From f160cb6566c17945f7ebc4f3a752b2cc6a051685 Mon Sep 17 00:00:00 2001 From: Robert Gemmell Date: Tue, 5 Jul 2016 21:55:35 +0000 Subject: QPID-7207: remove cpp and python subdirs from svn trunk, they have migrated to their own git repositories git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1751566 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/cpp/src/CMakeLists.txt | 1317 ------- qpid/cpp/src/CMakeWinVersions.cmake | 57 - qpid/cpp/src/QpidConfig.cmake.in | 30 - qpid/cpp/src/QpidConfigVersion.cmake.in | 30 - qpid/cpp/src/amqp.cmake | 156 - qpid/cpp/src/check-abi | 62 - qpid/cpp/src/config.h.cmake | 63 - qpid/cpp/src/cppabi.cpp | 32 - qpid/cpp/src/expand_types.cpp | 58 - qpid/cpp/src/finddb.cmake | 76 - qpid/cpp/src/legacystore.cmake | 172 - qpid/cpp/src/libqpidmessaging-api-symbols.txt | 243 -- qpid/cpp/src/libqpidtypes-api-symbols.txt | 141 - qpid/cpp/src/linearstore.cmake | 176 - qpid/cpp/src/msvc.cmake | 138 - qpid/cpp/src/posix/QpiddBroker.cpp | 250 -- qpid/cpp/src/prof | 39 - qpid/cpp/src/qmf/Agent.cpp | 640 ---- qpid/cpp/src/qmf/AgentEvent.cpp | 85 - qpid/cpp/src/qmf/AgentEventImpl.h | 96 - qpid/cpp/src/qmf/AgentImpl.h | 122 - qpid/cpp/src/qmf/AgentSession.cpp | 1031 ----- qpid/cpp/src/qmf/AgentSessionImpl.h | 168 - qpid/cpp/src/qmf/AgentSubscription.cpp | 51 - qpid/cpp/src/qmf/AgentSubscription.h | 52 - qpid/cpp/src/qmf/ConsoleEvent.cpp | 82 - qpid/cpp/src/qmf/ConsoleEventImpl.h | 84 - qpid/cpp/src/qmf/ConsoleSession.cpp | 683 ---- qpid/cpp/src/qmf/ConsoleSessionImpl.h | 127 - qpid/cpp/src/qmf/Data.cpp | 130 - qpid/cpp/src/qmf/DataAddr.cpp | 108 - qpid/cpp/src/qmf/DataAddrImpl.h | 73 - qpid/cpp/src/qmf/DataImpl.h | 84 - qpid/cpp/src/qmf/EventNotifierImpl.cpp | 60 - qpid/cpp/src/qmf/EventNotifierImpl.h | 48 - qpid/cpp/src/qmf/Expression.cpp | 441 --- qpid/cpp/src/qmf/Expression.h | 73 - qpid/cpp/src/qmf/Hash.cpp | 45 - qpid/cpp/src/qmf/Hash.h | 44 - qpid/cpp/src/qmf/PosixEventNotifier.cpp | 65 - qpid/cpp/src/qmf/PosixEventNotifierImpl.cpp | 112 - qpid/cpp/src/qmf/PosixEventNotifierImpl.h | 61 - qpid/cpp/src/qmf/PrivateImplRef.h | 93 - qpid/cpp/src/qmf/Query.cpp | 153 - qpid/cpp/src/qmf/QueryImpl.h | 77 - qpid/cpp/src/qmf/Schema.cpp | 358 -- qpid/cpp/src/qmf/SchemaCache.cpp | 91 - qpid/cpp/src/qmf/SchemaCache.h | 56 - qpid/cpp/src/qmf/SchemaId.cpp | 96 - qpid/cpp/src/qmf/SchemaIdImpl.h | 83 - qpid/cpp/src/qmf/SchemaImpl.h | 95 - qpid/cpp/src/qmf/SchemaMethod.cpp | 186 - qpid/cpp/src/qmf/SchemaMethodImpl.h | 75 - qpid/cpp/src/qmf/SchemaProperty.cpp | 434 --- qpid/cpp/src/qmf/SchemaPropertyImpl.h | 93 - qpid/cpp/src/qmf/Subscription.cpp | 88 - qpid/cpp/src/qmf/SubscriptionImpl.h | 57 - qpid/cpp/src/qmf/agentCapability.h | 39 - qpid/cpp/src/qmf/constants.cpp | 77 - qpid/cpp/src/qmf/constants.h | 83 - qpid/cpp/src/qmf/exceptions.cpp | 37 - qpid/cpp/src/qmf2.pc.in | 30 - qpid/cpp/src/qpid.linkmap | 31 - qpid/cpp/src/qpid.pc.in | 30 - qpid/cpp/src/qpid/AclHost.cpp | 151 - qpid/cpp/src/qpid/AclHost.h | 95 - qpid/cpp/src/qpid/Address.cpp | 44 - qpid/cpp/src/qpid/Address.h | 56 - qpid/cpp/src/qpid/BufferRef.h | 70 - qpid/cpp/src/qpid/CommonImportExport.h | 35 - qpid/cpp/src/qpid/DataDir.cpp | 47 - qpid/cpp/src/qpid/DataDir.h | 54 - qpid/cpp/src/qpid/DisableExceptionLogging.h | 39 - qpid/cpp/src/qpid/Exception.cpp | 71 - qpid/cpp/src/qpid/Exception.h | 95 - qpid/cpp/src/qpid/InlineAllocator.h | 101 - qpid/cpp/src/qpid/InlineVector.h | 68 - qpid/cpp/src/qpid/Modules.cpp | 94 - qpid/cpp/src/qpid/Modules.h | 44 - qpid/cpp/src/qpid/Msg.h | 79 - qpid/cpp/src/qpid/NullSaslClient.cpp | 64 - qpid/cpp/src/qpid/NullSaslClient.h | 45 - qpid/cpp/src/qpid/NullSaslServer.cpp | 85 - qpid/cpp/src/qpid/NullSaslServer.h | 50 - qpid/cpp/src/qpid/Options.cpp | 335 -- qpid/cpp/src/qpid/Options.h | 203 - qpid/cpp/src/qpid/OptionsTemplates.h | 52 - qpid/cpp/src/qpid/Plugin.cpp | 94 - qpid/cpp/src/qpid/Plugin.h | 129 - qpid/cpp/src/qpid/RangeSet.h | 330 -- qpid/cpp/src/qpid/RefCounted.h | 59 - qpid/cpp/src/qpid/RefCountedBuffer.cpp | 46 - qpid/cpp/src/qpid/RefCountedBuffer.h | 44 - qpid/cpp/src/qpid/Sasl.h | 61 - qpid/cpp/src/qpid/SaslFactory.cpp | 646 ---- qpid/cpp/src/qpid/SaslFactory.h | 49 - qpid/cpp/src/qpid/SaslServer.h | 48 - qpid/cpp/src/qpid/Serializer.h | 197 - qpid/cpp/src/qpid/SessionId.cpp | 47 - qpid/cpp/src/qpid/SessionId.h | 60 - qpid/cpp/src/qpid/SessionState.cpp | 287 -- qpid/cpp/src/qpid/SessionState.h | 235 -- qpid/cpp/src/qpid/SharedObject.h | 55 - qpid/cpp/src/qpid/StringUtils.cpp | 50 - qpid/cpp/src/qpid/StringUtils.h | 45 - qpid/cpp/src/qpid/Url.cpp | 281 -- qpid/cpp/src/qpid/Url.h | 96 - qpid/cpp/src/qpid/UrlArray.cpp | 43 - qpid/cpp/src/qpid/UrlArray.h | 36 - qpid/cpp/src/qpid/Version.h | 36 - qpid/cpp/src/qpid/acl/Acl.cpp | 450 --- qpid/cpp/src/qpid/acl/Acl.h | 134 - qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp | 320 -- qpid/cpp/src/qpid/acl/AclConnectionCounter.h | 106 - qpid/cpp/src/qpid/acl/AclData.cpp | 890 ----- qpid/cpp/src/qpid/acl/AclData.h | 323 -- qpid/cpp/src/qpid/acl/AclLexer.cpp | 141 - qpid/cpp/src/qpid/acl/AclLexer.h | 200 - qpid/cpp/src/qpid/acl/AclPlugin.cpp | 98 - qpid/cpp/src/qpid/acl/AclReader.cpp | 827 ---- qpid/cpp/src/qpid/acl/AclReader.h | 150 - qpid/cpp/src/qpid/acl/AclResourceCounter.cpp | 174 - qpid/cpp/src/qpid/acl/AclResourceCounter.h | 78 - qpid/cpp/src/qpid/acl/AclTopicMatch.h | 89 - qpid/cpp/src/qpid/acl/AclValidator.cpp | 536 --- qpid/cpp/src/qpid/acl/AclValidator.h | 106 - qpid/cpp/src/qpid/acl/management-schema.xml | 85 - qpid/cpp/src/qpid/amqp/CharSequence.cpp | 65 - qpid/cpp/src/qpid/amqp/CharSequence.h | 52 - qpid/cpp/src/qpid/amqp/Codec.h | 83 - qpid/cpp/src/qpid/amqp/Constructor.h | 42 - qpid/cpp/src/qpid/amqp/DataBuilder.cpp | 196 - qpid/cpp/src/qpid/amqp/DataBuilder.h | 79 - qpid/cpp/src/qpid/amqp/Decoder.cpp | 448 --- qpid/cpp/src/qpid/amqp/Decoder.h | 100 - qpid/cpp/src/qpid/amqp/Descriptor.cpp | 148 - qpid/cpp/src/qpid/amqp/Descriptor.h | 60 - qpid/cpp/src/qpid/amqp/Encoder.cpp | 523 --- qpid/cpp/src/qpid/amqp/Encoder.h | 181 - qpid/cpp/src/qpid/amqp/ListBuilder.cpp | 33 - qpid/cpp/src/qpid/amqp/ListBuilder.h | 41 - qpid/cpp/src/qpid/amqp/ListReader.h | 103 - qpid/cpp/src/qpid/amqp/LoggingReader.h | 64 - qpid/cpp/src/qpid/amqp/MapBuilder.cpp | 30 - qpid/cpp/src/qpid/amqp/MapBuilder.h | 41 - qpid/cpp/src/qpid/amqp/MapEncoder.cpp | 142 - qpid/cpp/src/qpid/amqp/MapEncoder.h | 58 - qpid/cpp/src/qpid/amqp/MapHandler.h | 53 - qpid/cpp/src/qpid/amqp/MapReader.cpp | 309 -- qpid/cpp/src/qpid/amqp/MapReader.h | 110 - qpid/cpp/src/qpid/amqp/MapSizeCalculator.cpp | 151 - qpid/cpp/src/qpid/amqp/MapSizeCalculator.h | 73 - qpid/cpp/src/qpid/amqp/MessageEncoder.cpp | 312 -- qpid/cpp/src/qpid/amqp/MessageEncoder.h | 117 - qpid/cpp/src/qpid/amqp/MessageId.cpp | 82 - qpid/cpp/src/qpid/amqp/MessageId.h | 57 - qpid/cpp/src/qpid/amqp/MessageReader.cpp | 685 ---- qpid/cpp/src/qpid/amqp/MessageReader.h | 161 - qpid/cpp/src/qpid/amqp/Reader.h | 80 - qpid/cpp/src/qpid/amqp/Sasl.cpp | 141 - qpid/cpp/src/qpid/amqp/Sasl.h | 55 - qpid/cpp/src/qpid/amqp/SaslClient.cpp | 154 - qpid/cpp/src/qpid/amqp/SaslClient.h | 55 - qpid/cpp/src/qpid/amqp/SaslServer.cpp | 183 - qpid/cpp/src/qpid/amqp/SaslServer.h | 50 - qpid/cpp/src/qpid/amqp/descriptors.h | 142 - qpid/cpp/src/qpid/amqp/typecodes.h | 115 - qpid/cpp/src/qpid/amqp_0_10/Codecs.cpp | 586 --- qpid/cpp/src/qpid/amqp_0_10/Codecs.h | 87 - qpid/cpp/src/qpid/amqp_0_10/CodecsInternal.h | 42 - qpid/cpp/src/qpid/amqp_0_10/Connection.cpp | 150 - qpid/cpp/src/qpid/amqp_0_10/Connection.h | 78 - qpid/cpp/src/qpid/amqp_0_10/SessionHandler.cpp | 333 -- qpid/cpp/src/qpid/amqp_0_10/SessionHandler.h | 118 - qpid/cpp/src/qpid/assert.cpp | 47 - qpid/cpp/src/qpid/assert.h | 38 - qpid/cpp/src/qpid/broker/AclModule.h | 75 - qpid/cpp/src/qpid/broker/AsyncCommandCallback.cpp | 70 - qpid/cpp/src/qpid/broker/AsyncCommandCallback.h | 68 - qpid/cpp/src/qpid/broker/AsyncCompletion.h | 209 -- qpid/cpp/src/qpid/broker/Bridge.cpp | 474 --- qpid/cpp/src/qpid/broker/Bridge.h | 158 - qpid/cpp/src/qpid/broker/Broker.cpp | 1683 --------- qpid/cpp/src/qpid/broker/Broker.h | 350 -- qpid/cpp/src/qpid/broker/BrokerImportExport.h | 42 - qpid/cpp/src/qpid/broker/BrokerObserver.h | 68 - qpid/cpp/src/qpid/broker/BrokerObservers.h | 73 - qpid/cpp/src/qpid/broker/BrokerOptions.h | 88 - qpid/cpp/src/qpid/broker/Connection.h | 53 - qpid/cpp/src/qpid/broker/ConnectionHandler.cpp | 471 --- qpid/cpp/src/qpid/broker/ConnectionHandler.h | 118 - qpid/cpp/src/qpid/broker/ConnectionObserver.h | 59 - qpid/cpp/src/qpid/broker/ConnectionObservers.h | 56 - qpid/cpp/src/qpid/broker/Consumer.h | 108 - qpid/cpp/src/qpid/broker/ConsumerFactory.h | 73 - qpid/cpp/src/qpid/broker/Credit.cpp | 151 - qpid/cpp/src/qpid/broker/Credit.h | 96 - qpid/cpp/src/qpid/broker/Daemon.cpp | 217 -- qpid/cpp/src/qpid/broker/Daemon.h | 83 - qpid/cpp/src/qpid/broker/Deliverable.h | 47 - qpid/cpp/src/qpid/broker/DeliverableMessage.cpp | 38 - qpid/cpp/src/qpid/broker/DeliverableMessage.h | 45 - qpid/cpp/src/qpid/broker/DeliveryId.h | 35 - qpid/cpp/src/qpid/broker/DeliveryRecord.cpp | 168 - qpid/cpp/src/qpid/broker/DeliveryRecord.h | 152 - qpid/cpp/src/qpid/broker/DirectExchange.cpp | 214 -- qpid/cpp/src/qpid/broker/DirectExchange.h | 74 - qpid/cpp/src/qpid/broker/DtxAck.cpp | 77 - qpid/cpp/src/qpid/broker/DtxAck.h | 51 - qpid/cpp/src/qpid/broker/DtxBuffer.cpp | 91 - qpid/cpp/src/qpid/broker/DtxBuffer.h | 59 - qpid/cpp/src/qpid/broker/DtxManager.cpp | 220 -- qpid/cpp/src/qpid/broker/DtxManager.h | 75 - qpid/cpp/src/qpid/broker/DtxTimeout.cpp | 37 - qpid/cpp/src/qpid/broker/DtxTimeout.h | 50 - qpid/cpp/src/qpid/broker/DtxWorkRecord.cpp | 187 - qpid/cpp/src/qpid/broker/DtxWorkRecord.h | 86 - qpid/cpp/src/qpid/broker/Exchange.cpp | 504 --- qpid/cpp/src/qpid/broker/Exchange.h | 268 -- qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp | 177 - qpid/cpp/src/qpid/broker/ExchangeRegistry.h | 127 - qpid/cpp/src/qpid/broker/Fairshare.cpp | 125 - qpid/cpp/src/qpid/broker/Fairshare.h | 60 - qpid/cpp/src/qpid/broker/FanOutExchange.cpp | 132 - qpid/cpp/src/qpid/broker/FanOutExchange.h | 74 - qpid/cpp/src/qpid/broker/FedOps.h | 38 - qpid/cpp/src/qpid/broker/FifoDistributor.cpp | 45 - qpid/cpp/src/qpid/broker/FifoDistributor.h | 50 - qpid/cpp/src/qpid/broker/HandlerImpl.h | 53 - qpid/cpp/src/qpid/broker/HeadersExchange.cpp | 417 --- qpid/cpp/src/qpid/broker/HeadersExchange.h | 119 - qpid/cpp/src/qpid/broker/IndexedDeque.h | 226 -- qpid/cpp/src/qpid/broker/IngressCompletion.cpp | 48 - qpid/cpp/src/qpid/broker/IngressCompletion.h | 52 - qpid/cpp/src/qpid/broker/Link.cpp | 799 ---- qpid/cpp/src/qpid/broker/Link.h | 208 - qpid/cpp/src/qpid/broker/LinkRegistry.cpp | 435 --- qpid/cpp/src/qpid/broker/LinkRegistry.h | 155 - qpid/cpp/src/qpid/broker/LossyLvq.cpp | 30 - qpid/cpp/src/qpid/broker/LossyLvq.h | 52 - qpid/cpp/src/qpid/broker/LossyQueue.cpp | 97 - qpid/cpp/src/qpid/broker/LossyQueue.h | 41 - qpid/cpp/src/qpid/broker/Lvq.cpp | 64 - qpid/cpp/src/qpid/broker/Lvq.h | 45 - qpid/cpp/src/qpid/broker/Message.cpp | 386 -- qpid/cpp/src/qpid/broker/Message.h | 237 -- qpid/cpp/src/qpid/broker/MessageAdapter.cpp | 81 - qpid/cpp/src/qpid/broker/MessageAdapter.h | 62 - qpid/cpp/src/qpid/broker/MessageBuilder.cpp | 125 - qpid/cpp/src/qpid/broker/MessageBuilder.h | 62 - qpid/cpp/src/qpid/broker/MessageDeque.cpp | 89 - qpid/cpp/src/qpid/broker/MessageDeque.h | 55 - qpid/cpp/src/qpid/broker/MessageDistributor.h | 53 - qpid/cpp/src/qpid/broker/MessageGroupManager.cpp | 313 -- qpid/cpp/src/qpid/broker/MessageGroupManager.h | 129 - qpid/cpp/src/qpid/broker/MessageInterceptor.h | 58 - qpid/cpp/src/qpid/broker/MessageMap.cpp | 161 - qpid/cpp/src/qpid/broker/MessageMap.h | 71 - qpid/cpp/src/qpid/broker/MessageStore.h | 189 - qpid/cpp/src/qpid/broker/MessageStoreModule.cpp | 173 - qpid/cpp/src/qpid/broker/MessageStoreModule.h | 85 - qpid/cpp/src/qpid/broker/Messages.h | 108 - qpid/cpp/src/qpid/broker/NameGenerator.cpp | 32 - qpid/cpp/src/qpid/broker/NameGenerator.h | 40 - qpid/cpp/src/qpid/broker/NullMessageStore.cpp | 163 - qpid/cpp/src/qpid/broker/NullMessageStore.h | 98 - qpid/cpp/src/qpid/broker/ObjectFactory.cpp | 75 - qpid/cpp/src/qpid/broker/ObjectFactory.h | 68 - qpid/cpp/src/qpid/broker/Observers.h | 94 - qpid/cpp/src/qpid/broker/OwnershipToken.h | 36 - qpid/cpp/src/qpid/broker/PagedQueue.cpp | 465 --- qpid/cpp/src/qpid/broker/PagedQueue.h | 103 - qpid/cpp/src/qpid/broker/Persistable.h | 63 - qpid/cpp/src/qpid/broker/PersistableConfig.h | 45 - qpid/cpp/src/qpid/broker/PersistableExchange.h | 45 - qpid/cpp/src/qpid/broker/PersistableMessage.cpp | 71 - qpid/cpp/src/qpid/broker/PersistableMessage.h | 95 - qpid/cpp/src/qpid/broker/PersistableObject.cpp | 89 - qpid/cpp/src/qpid/broker/PersistableObject.h | 73 - qpid/cpp/src/qpid/broker/PersistableQueue.h | 77 - qpid/cpp/src/qpid/broker/PriorityQueue.cpp | 234 -- qpid/cpp/src/qpid/broker/PriorityQueue.h | 109 - qpid/cpp/src/qpid/broker/Protocol.cpp | 141 - qpid/cpp/src/qpid/broker/Protocol.h | 96 - qpid/cpp/src/qpid/broker/Queue.cpp | 1793 --------- qpid/cpp/src/qpid/broker/Queue.h | 552 --- qpid/cpp/src/qpid/broker/QueueBindings.cpp | 53 - qpid/cpp/src/qpid/broker/QueueBindings.h | 70 - qpid/cpp/src/qpid/broker/QueueCleaner.cpp | 98 - qpid/cpp/src/qpid/broker/QueueCleaner.h | 70 - qpid/cpp/src/qpid/broker/QueueCursor.cpp | 44 - qpid/cpp/src/qpid/broker/QueueCursor.h | 72 - qpid/cpp/src/qpid/broker/QueueDepth.cpp | 127 - qpid/cpp/src/qpid/broker/QueueDepth.h | 74 - qpid/cpp/src/qpid/broker/QueueFactory.cpp | 142 - qpid/cpp/src/qpid/broker/QueueFactory.h | 76 - qpid/cpp/src/qpid/broker/QueueFlowLimit.cpp | 307 -- qpid/cpp/src/qpid/broker/QueueFlowLimit.h | 127 - qpid/cpp/src/qpid/broker/QueueListeners.cpp | 93 - qpid/cpp/src/qpid/broker/QueueListeners.h | 85 - qpid/cpp/src/qpid/broker/QueueObserver.h | 76 - qpid/cpp/src/qpid/broker/QueueObservers.h | 77 - qpid/cpp/src/qpid/broker/QueueRegistry.cpp | 183 - qpid/cpp/src/qpid/broker/QueueRegistry.h | 131 - qpid/cpp/src/qpid/broker/QueueSettings.cpp | 332 -- qpid/cpp/src/qpid/broker/QueueSettings.h | 124 - qpid/cpp/src/qpid/broker/QueuedMessage.cpp | 34 - qpid/cpp/src/qpid/broker/QueuedMessage.h | 55 - qpid/cpp/src/qpid/broker/RecoverableConfig.h | 45 - qpid/cpp/src/qpid/broker/RecoverableExchange.h | 55 - qpid/cpp/src/qpid/broker/RecoverableMessage.h | 62 - qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h | 50 - qpid/cpp/src/qpid/broker/RecoverableQueue.h | 63 - qpid/cpp/src/qpid/broker/RecoverableTransaction.h | 49 - qpid/cpp/src/qpid/broker/RecoveredDequeue.cpp | 47 - qpid/cpp/src/qpid/broker/RecoveredDequeue.h | 55 - qpid/cpp/src/qpid/broker/RecoveredEnqueue.cpp | 44 - qpid/cpp/src/qpid/broker/RecoveredEnqueue.h | 55 - qpid/cpp/src/qpid/broker/RecoveryManager.h | 61 - qpid/cpp/src/qpid/broker/RecoveryManagerImpl.cpp | 288 -- qpid/cpp/src/qpid/broker/RecoveryManagerImpl.h | 65 - qpid/cpp/src/qpid/broker/RetryList.cpp | 56 - qpid/cpp/src/qpid/broker/RetryList.h | 53 - qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp | 566 --- qpid/cpp/src/qpid/broker/SaslAuthenticator.h | 66 - qpid/cpp/src/qpid/broker/SecureConnection.cpp | 90 - qpid/cpp/src/qpid/broker/SecureConnection.h | 60 - qpid/cpp/src/qpid/broker/Selector.cpp | 280 -- qpid/cpp/src/qpid/broker/Selector.h | 80 - qpid/cpp/src/qpid/broker/SelectorExpression.cpp | 1114 ------ qpid/cpp/src/qpid/broker/SelectorExpression.h | 44 - qpid/cpp/src/qpid/broker/SelectorToken.cpp | 345 -- qpid/cpp/src/qpid/broker/SelectorToken.h | 126 - qpid/cpp/src/qpid/broker/SelectorValue.cpp | 212 -- qpid/cpp/src/qpid/broker/SelectorValue.h | 125 - qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp | 44 - qpid/cpp/src/qpid/broker/SelfDestructQueue.h | 45 - qpid/cpp/src/qpid/broker/SemanticState.cpp | 896 ----- qpid/cpp/src/qpid/broker/SemanticState.h | 295 -- qpid/cpp/src/qpid/broker/SessionAdapter.cpp | 680 ---- qpid/cpp/src/qpid/broker/SessionAdapter.h | 272 -- qpid/cpp/src/qpid/broker/SessionContext.h | 61 - qpid/cpp/src/qpid/broker/SessionHandler.cpp | 163 - qpid/cpp/src/qpid/broker/SessionHandler.h | 121 - qpid/cpp/src/qpid/broker/SessionHandlerObserver.h | 51 - qpid/cpp/src/qpid/broker/SessionManager.cpp | 104 - qpid/cpp/src/qpid/broker/SessionManager.h | 87 - qpid/cpp/src/qpid/broker/SessionOutputException.h | 47 - qpid/cpp/src/qpid/broker/SessionState.cpp | 527 --- qpid/cpp/src/qpid/broker/SessionState.h | 332 -- qpid/cpp/src/qpid/broker/SignalHandler.cpp | 54 - qpid/cpp/src/qpid/broker/SignalHandler.h | 50 - qpid/cpp/src/qpid/broker/System.cpp | 88 - qpid/cpp/src/qpid/broker/System.h | 70 - qpid/cpp/src/qpid/broker/ThresholdAlerts.cpp | 113 - qpid/cpp/src/qpid/broker/ThresholdAlerts.h | 77 - qpid/cpp/src/qpid/broker/TopicExchange.cpp | 350 -- qpid/cpp/src/qpid/broker/TopicExchange.h | 122 - qpid/cpp/src/qpid/broker/TopicKeyNode.h | 371 -- qpid/cpp/src/qpid/broker/TransactionObserver.h | 82 - qpid/cpp/src/qpid/broker/TransactionalStore.h | 60 - qpid/cpp/src/qpid/broker/TxAccept.cpp | 95 - qpid/cpp/src/qpid/broker/TxAccept.h | 64 - qpid/cpp/src/qpid/broker/TxBuffer.cpp | 103 - qpid/cpp/src/qpid/broker/TxBuffer.h | 148 - qpid/cpp/src/qpid/broker/TxDequeue.cpp | 68 - qpid/cpp/src/qpid/broker/TxDequeue.h | 54 - qpid/cpp/src/qpid/broker/TxOp.h | 45 - qpid/cpp/src/qpid/broker/Vhost.cpp | 54 - qpid/cpp/src/qpid/broker/Vhost.h | 52 - qpid/cpp/src/qpid/broker/amqp/Authorise.cpp | 157 - qpid/cpp/src/qpid/broker/amqp/Authorise.h | 66 - qpid/cpp/src/qpid/broker/amqp/BrokerContext.cpp | 33 - qpid/cpp/src/qpid/broker/amqp/BrokerContext.h | 55 - qpid/cpp/src/qpid/broker/amqp/Connection.cpp | 697 ---- qpid/cpp/src/qpid/broker/amqp/Connection.h | 111 - qpid/cpp/src/qpid/broker/amqp/DataReader.cpp | 193 - qpid/cpp/src/qpid/broker/amqp/DataReader.h | 59 - qpid/cpp/src/qpid/broker/amqp/Domain.cpp | 307 -- qpid/cpp/src/qpid/broker/amqp/Domain.h | 82 - qpid/cpp/src/qpid/broker/amqp/Exception.cpp | 30 - qpid/cpp/src/qpid/broker/amqp/Exception.h | 46 - qpid/cpp/src/qpid/broker/amqp/Filter.cpp | 417 --- qpid/cpp/src/qpid/broker/amqp/Filter.h | 128 - qpid/cpp/src/qpid/broker/amqp/Header.cpp | 65 - qpid/cpp/src/qpid/broker/amqp/Header.h | 50 - qpid/cpp/src/qpid/broker/amqp/Incoming.cpp | 156 - qpid/cpp/src/qpid/broker/amqp/Incoming.h | 87 - qpid/cpp/src/qpid/broker/amqp/Interconnect.cpp | 163 - qpid/cpp/src/qpid/broker/amqp/Interconnect.h | 65 - qpid/cpp/src/qpid/broker/amqp/Interconnects.cpp | 176 - qpid/cpp/src/qpid/broker/amqp/Interconnects.h | 66 - .../cpp/src/qpid/broker/amqp/ManagedConnection.cpp | 214 -- qpid/cpp/src/qpid/broker/amqp/ManagedConnection.h | 80 - .../src/qpid/broker/amqp/ManagedIncomingLink.cpp | 58 - .../cpp/src/qpid/broker/amqp/ManagedIncomingLink.h | 50 - .../src/qpid/broker/amqp/ManagedOutgoingLink.cpp | 68 - .../cpp/src/qpid/broker/amqp/ManagedOutgoingLink.h | 52 - qpid/cpp/src/qpid/broker/amqp/ManagedSession.cpp | 158 - qpid/cpp/src/qpid/broker/amqp/ManagedSession.h | 66 - qpid/cpp/src/qpid/broker/amqp/Message.cpp | 569 --- qpid/cpp/src/qpid/broker/amqp/Message.h | 165 - qpid/cpp/src/qpid/broker/amqp/NodePolicy.cpp | 326 -- qpid/cpp/src/qpid/broker/amqp/NodePolicy.h | 117 - qpid/cpp/src/qpid/broker/amqp/NodeProperties.cpp | 388 -- qpid/cpp/src/qpid/broker/amqp/NodeProperties.h | 90 - qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp | 373 -- qpid/cpp/src/qpid/broker/amqp/Outgoing.h | 175 - qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.cpp | 171 - qpid/cpp/src/qpid/broker/amqp/Relay.cpp | 301 -- qpid/cpp/src/qpid/broker/amqp/Relay.h | 130 - qpid/cpp/src/qpid/broker/amqp/Sasl.cpp | 171 - qpid/cpp/src/qpid/broker/amqp/Sasl.h | 71 - qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp | 181 - qpid/cpp/src/qpid/broker/amqp/SaslClient.h | 81 - qpid/cpp/src/qpid/broker/amqp/Session.cpp | 1053 ------ qpid/cpp/src/qpid/broker/amqp/Session.h | 150 - qpid/cpp/src/qpid/broker/amqp/Topic.cpp | 209 -- qpid/cpp/src/qpid/broker/amqp/Topic.h | 91 - qpid/cpp/src/qpid/broker/amqp/Translation.cpp | 343 -- qpid/cpp/src/qpid/broker/amqp/Translation.h | 60 - qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp | 549 --- qpid/cpp/src/qpid/broker/amqp_0_10/Connection.h | 250 -- .../src/qpid/broker/amqp_0_10/MessageTransfer.cpp | 477 --- .../src/qpid/broker/amqp_0_10/MessageTransfer.h | 143 - qpid/cpp/src/qpid/broker/management-schema.xml | 624 --- qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp | 42 - qpid/cpp/src/qpid/broker/posix/SocketFDPlugin.cpp | 93 - .../cpp/src/qpid/broker/windows/BrokerDefaults.cpp | 49 - .../src/qpid/broker/windows/SaslAuthenticator.cpp | 209 -- .../src/qpid/broker/windows/SslProtocolFactory.cpp | 312 -- qpid/cpp/src/qpid/client/AsyncSession.h | 38 - qpid/cpp/src/qpid/client/Bounds.cpp | 71 - qpid/cpp/src/qpid/client/Bounds.h | 49 - qpid/cpp/src/qpid/client/ChainableFrameHandler.h | 47 - qpid/cpp/src/qpid/client/ClientImportExport.h | 35 - qpid/cpp/src/qpid/client/Completion.cpp | 43 - qpid/cpp/src/qpid/client/Completion.h | 71 - qpid/cpp/src/qpid/client/CompletionImpl.cpp | 34 - qpid/cpp/src/qpid/client/CompletionImpl.h | 52 - qpid/cpp/src/qpid/client/Connection.cpp | 161 - qpid/cpp/src/qpid/client/Connection.h | 227 -- qpid/cpp/src/qpid/client/ConnectionAccess.h | 42 - qpid/cpp/src/qpid/client/ConnectionHandler.cpp | 392 -- qpid/cpp/src/qpid/client/ConnectionHandler.h | 139 - qpid/cpp/src/qpid/client/ConnectionImpl.cpp | 455 --- qpid/cpp/src/qpid/client/ConnectionImpl.h | 107 - qpid/cpp/src/qpid/client/ConnectionSettings.cpp | 58 - qpid/cpp/src/qpid/client/ConnectionSettings.h | 145 - qpid/cpp/src/qpid/client/Connector.cpp | 94 - qpid/cpp/src/qpid/client/Connector.h | 89 - qpid/cpp/src/qpid/client/Demux.cpp | 132 - qpid/cpp/src/qpid/client/Demux.h | 103 - qpid/cpp/src/qpid/client/Dispatcher.cpp | 151 - qpid/cpp/src/qpid/client/Dispatcher.h | 87 - qpid/cpp/src/qpid/client/Execution.h | 53 - qpid/cpp/src/qpid/client/FailoverListener.cpp | 93 - qpid/cpp/src/qpid/client/FailoverListener.h | 88 - qpid/cpp/src/qpid/client/FailoverManager.cpp | 133 - qpid/cpp/src/qpid/client/FailoverManager.h | 138 - qpid/cpp/src/qpid/client/FlowControl.h | 75 - qpid/cpp/src/qpid/client/Future.cpp | 46 - qpid/cpp/src/qpid/client/Future.h | 59 - qpid/cpp/src/qpid/client/FutureCompletion.cpp | 48 - qpid/cpp/src/qpid/client/FutureCompletion.h | 49 - qpid/cpp/src/qpid/client/FutureResult.cpp | 43 - qpid/cpp/src/qpid/client/FutureResult.h | 49 - qpid/cpp/src/qpid/client/Handle.h | 72 - qpid/cpp/src/qpid/client/LoadPlugins.cpp | 66 - qpid/cpp/src/qpid/client/LoadPlugins.h | 35 - qpid/cpp/src/qpid/client/LocalQueue.cpp | 52 - qpid/cpp/src/qpid/client/LocalQueue.h | 120 - qpid/cpp/src/qpid/client/LocalQueueImpl.cpp | 78 - qpid/cpp/src/qpid/client/LocalQueueImpl.h | 108 - qpid/cpp/src/qpid/client/Message.cpp | 62 - qpid/cpp/src/qpid/client/Message.h | 175 - qpid/cpp/src/qpid/client/MessageImpl.cpp | 71 - qpid/cpp/src/qpid/client/MessageImpl.h | 80 - qpid/cpp/src/qpid/client/MessageListener.cpp | 24 - qpid/cpp/src/qpid/client/MessageListener.h | 101 - qpid/cpp/src/qpid/client/MessageReplayTracker.cpp | 78 - qpid/cpp/src/qpid/client/MessageReplayTracker.h | 73 - qpid/cpp/src/qpid/client/PrivateImplRef.h | 94 - qpid/cpp/src/qpid/client/QueueOptions.cpp | 105 - qpid/cpp/src/qpid/client/QueueOptions.h | 95 - qpid/cpp/src/qpid/client/RdmaConnector.cpp | 420 --- qpid/cpp/src/qpid/client/Results.cpp | 75 - qpid/cpp/src/qpid/client/Results.h | 56 - qpid/cpp/src/qpid/client/Session.h | 39 - qpid/cpp/src/qpid/client/SessionBase_0_10.cpp | 85 - qpid/cpp/src/qpid/client/SessionBase_0_10.h | 109 - qpid/cpp/src/qpid/client/SessionBase_0_10Access.h | 42 - qpid/cpp/src/qpid/client/SessionImpl.cpp | 714 ---- qpid/cpp/src/qpid/client/SessionImpl.h | 220 -- qpid/cpp/src/qpid/client/SslConnector.cpp | 428 --- qpid/cpp/src/qpid/client/StateManager.cpp | 100 - qpid/cpp/src/qpid/client/StateManager.h | 50 - qpid/cpp/src/qpid/client/Subscription.cpp | 55 - qpid/cpp/src/qpid/client/Subscription.h | 123 - qpid/cpp/src/qpid/client/SubscriptionImpl.cpp | 169 - qpid/cpp/src/qpid/client/SubscriptionImpl.h | 125 - qpid/cpp/src/qpid/client/SubscriptionManager.cpp | 106 - qpid/cpp/src/qpid/client/SubscriptionManager.h | 292 -- .../src/qpid/client/SubscriptionManagerImpl.cpp | 182 - qpid/cpp/src/qpid/client/SubscriptionManagerImpl.h | 279 -- qpid/cpp/src/qpid/client/SubscriptionSettings.h | 135 - qpid/cpp/src/qpid/client/TCPConnector.cpp | 323 -- qpid/cpp/src/qpid/client/TCPConnector.h | 116 - qpid/cpp/src/qpid/client/TypedResult.h | 65 - .../cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp | 153 - qpid/cpp/src/qpid/client/amqp0_10/AcceptTracker.h | 88 - .../src/qpid/client/amqp0_10/AddressResolution.cpp | 1058 ------ .../src/qpid/client/amqp0_10/AddressResolution.h | 64 - .../src/qpid/client/amqp0_10/ConnectionImpl.cpp | 432 --- qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h | 88 - .../src/qpid/client/amqp0_10/IncomingMessages.cpp | 468 --- .../src/qpid/client/amqp0_10/IncomingMessages.h | 109 - qpid/cpp/src/qpid/client/amqp0_10/MessageSink.h | 52 - qpid/cpp/src/qpid/client/amqp0_10/MessageSource.h | 47 - .../src/qpid/client/amqp0_10/OutgoingMessage.cpp | 170 - .../cpp/src/qpid/client/amqp0_10/OutgoingMessage.h | 60 - qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp | 263 -- qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h | 152 - qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp | 206 - qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.h | 162 - qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp | 616 --- qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.h | 259 -- qpid/cpp/src/qpid/client/ssl.h | 30 - qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp | 22 - qpid/cpp/src/qpid/client/windows/SaslFactory.cpp | 202 - qpid/cpp/src/qpid/client/windows/SslConnector.cpp | 147 - qpid/cpp/src/qpid/framing/AMQBody.cpp | 64 - qpid/cpp/src/qpid/framing/AMQBody.h | 86 - qpid/cpp/src/qpid/framing/AMQContentBody.cpp | 46 - qpid/cpp/src/qpid/framing/AMQContentBody.h | 55 - qpid/cpp/src/qpid/framing/AMQDataBlock.h | 42 - qpid/cpp/src/qpid/framing/AMQFrame.cpp | 158 - qpid/cpp/src/qpid/framing/AMQFrame.h | 116 - qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp | 63 - qpid/cpp/src/qpid/framing/AMQHeaderBody.h | 113 - qpid/cpp/src/qpid/framing/AMQHeartbeatBody.cpp | 29 - qpid/cpp/src/qpid/framing/AMQHeartbeatBody.h | 48 - qpid/cpp/src/qpid/framing/AMQMethodBody.cpp | 28 - qpid/cpp/src/qpid/framing/AMQMethodBody.h | 72 - qpid/cpp/src/qpid/framing/AMQP_HighestVersion.h | 40 - qpid/cpp/src/qpid/framing/AccumulatedAck.cpp | 164 - qpid/cpp/src/qpid/framing/AccumulatedAck.h | 77 - qpid/cpp/src/qpid/framing/Array.cpp | 137 - qpid/cpp/src/qpid/framing/Array.h | 99 - qpid/cpp/src/qpid/framing/Blob.cpp | 31 - qpid/cpp/src/qpid/framing/Blob.h | 21 - qpid/cpp/src/qpid/framing/BodyFactory.h | 47 - qpid/cpp/src/qpid/framing/Buffer.cpp | 342 -- qpid/cpp/src/qpid/framing/Buffer.h | 115 - qpid/cpp/src/qpid/framing/BufferTypes.h | 106 - qpid/cpp/src/qpid/framing/ChannelHandler.h | 53 - qpid/cpp/src/qpid/framing/Endian.h | 78 - qpid/cpp/src/qpid/framing/FieldTable.cpp | 433 --- qpid/cpp/src/qpid/framing/FieldTable.h | 139 - qpid/cpp/src/qpid/framing/FieldValue.cpp | 267 -- qpid/cpp/src/qpid/framing/FieldValue.h | 482 --- qpid/cpp/src/qpid/framing/FrameDecoder.cpp | 81 - qpid/cpp/src/qpid/framing/FrameDecoder.h | 52 - qpid/cpp/src/qpid/framing/FrameDefaultVisitor.h | 60 - qpid/cpp/src/qpid/framing/FrameHandler.h | 33 - qpid/cpp/src/qpid/framing/FrameSet.cpp | 128 - qpid/cpp/src/qpid/framing/FrameSet.h | 130 - qpid/cpp/src/qpid/framing/Handler.h | 103 - qpid/cpp/src/qpid/framing/HeaderProperties.h | 44 - qpid/cpp/src/qpid/framing/InitiationHandler.cpp | 24 - qpid/cpp/src/qpid/framing/InitiationHandler.h | 41 - qpid/cpp/src/qpid/framing/InputHandler.h | 41 - qpid/cpp/src/qpid/framing/Invoker.h | 86 - qpid/cpp/src/qpid/framing/IsInSequenceSet.h | 51 - qpid/cpp/src/qpid/framing/List.cpp | 90 - qpid/cpp/src/qpid/framing/List.h | 78 - qpid/cpp/src/qpid/framing/MethodBodyFactory.h | 45 - qpid/cpp/src/qpid/framing/MethodContent.h | 40 - qpid/cpp/src/qpid/framing/ModelMethod.h | 49 - qpid/cpp/src/qpid/framing/ProtocolInitiation.cpp | 83 - qpid/cpp/src/qpid/framing/ProtocolInitiation.h | 60 - qpid/cpp/src/qpid/framing/ProtocolVersion.cpp | 52 - qpid/cpp/src/qpid/framing/ProtocolVersion.h | 67 - qpid/cpp/src/qpid/framing/Proxy.cpp | 51 - qpid/cpp/src/qpid/framing/Proxy.h | 64 - qpid/cpp/src/qpid/framing/ResizableBuffer.h | 60 - qpid/cpp/src/qpid/framing/SendContent.cpp | 66 - qpid/cpp/src/qpid/framing/SendContent.h | 56 - qpid/cpp/src/qpid/framing/SequenceNumber.cpp | 50 - qpid/cpp/src/qpid/framing/SequenceNumber.h | 85 - qpid/cpp/src/qpid/framing/SequenceNumberSet.cpp | 90 - qpid/cpp/src/qpid/framing/SequenceNumberSet.h | 69 - qpid/cpp/src/qpid/framing/SequenceSet.cpp | 127 - qpid/cpp/src/qpid/framing/SequenceSet.h | 69 - qpid/cpp/src/qpid/framing/StructHelper.h | 57 - qpid/cpp/src/qpid/framing/TransferContent.cpp | 102 - qpid/cpp/src/qpid/framing/TransferContent.h | 64 - qpid/cpp/src/qpid/framing/TypeFilter.h | 51 - qpid/cpp/src/qpid/framing/Uuid.cpp | 52 - qpid/cpp/src/qpid/framing/Uuid.h | 57 - qpid/cpp/src/qpid/framing/amqp_framing.h | 30 - qpid/cpp/src/qpid/framing/amqp_types.h | 63 - qpid/cpp/src/qpid/framing/amqp_types_full.h | 38 - qpid/cpp/src/qpid/framing/frame_functors.h | 116 - qpid/cpp/src/qpid/framing/variant.h | 91 - qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h | 74 - qpid/cpp/src/qpid/ha/Backup.cpp | 128 - qpid/cpp/src/qpid/ha/Backup.h | 82 - qpid/cpp/src/qpid/ha/BackupConnectionExcluder.h | 54 - qpid/cpp/src/qpid/ha/BrokerInfo.cpp | 120 - qpid/cpp/src/qpid/ha/BrokerInfo.h | 89 - qpid/cpp/src/qpid/ha/BrokerReplicator.cpp | 900 ----- qpid/cpp/src/qpid/ha/BrokerReplicator.h | 177 - qpid/cpp/src/qpid/ha/ConnectionObserver.cpp | 121 - qpid/cpp/src/qpid/ha/ConnectionObserver.h | 83 - qpid/cpp/src/qpid/ha/Event.cpp | 78 - qpid/cpp/src/qpid/ha/Event.h | 99 - qpid/cpp/src/qpid/ha/FailoverExchange.cpp | 133 - qpid/cpp/src/qpid/ha/FailoverExchange.h | 72 - qpid/cpp/src/qpid/ha/HaBroker.cpp | 240 -- qpid/cpp/src/qpid/ha/HaBroker.h | 137 - qpid/cpp/src/qpid/ha/HaPlugin.cpp | 103 - qpid/cpp/src/qpid/ha/IdSetter.h | 76 - qpid/cpp/src/qpid/ha/LogPrefix.cpp | 35 - qpid/cpp/src/qpid/ha/LogPrefix.h | 75 - qpid/cpp/src/qpid/ha/Membership.cpp | 228 -- qpid/cpp/src/qpid/ha/Membership.h | 103 - qpid/cpp/src/qpid/ha/Primary.cpp | 439 --- qpid/cpp/src/qpid/ha/Primary.h | 143 - qpid/cpp/src/qpid/ha/PrimaryQueueLimits.h | 108 - qpid/cpp/src/qpid/ha/QueueGuard.cpp | 123 - qpid/cpp/src/qpid/ha/QueueGuard.h | 108 - qpid/cpp/src/qpid/ha/QueueReplicator.cpp | 414 -- qpid/cpp/src/qpid/ha/QueueReplicator.h | 156 - qpid/cpp/src/qpid/ha/QueueSnapshot.h | 68 - qpid/cpp/src/qpid/ha/README.h | 149 - qpid/cpp/src/qpid/ha/RemoteBackup.cpp | 115 - qpid/cpp/src/qpid/ha/RemoteBackup.h | 118 - qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp | 324 -- qpid/cpp/src/qpid/ha/ReplicatingSubscription.h | 169 - qpid/cpp/src/qpid/ha/ReplicationTest.cpp | 75 - qpid/cpp/src/qpid/ha/ReplicationTest.h | 76 - qpid/cpp/src/qpid/ha/Role.h | 54 - qpid/cpp/src/qpid/ha/Settings.h | 61 - qpid/cpp/src/qpid/ha/StandAlone.h | 41 - qpid/cpp/src/qpid/ha/StatusCheck.cpp | 159 - qpid/cpp/src/qpid/ha/StatusCheck.h | 79 - qpid/cpp/src/qpid/ha/hash.h | 75 - qpid/cpp/src/qpid/ha/management-schema.xml | 63 - qpid/cpp/src/qpid/ha/types.cpp | 138 - qpid/cpp/src/qpid/ha/types.h | 147 - qpid/cpp/src/qpid/legacystore/BindingDbt.cpp | 50 - qpid/cpp/src/qpid/legacystore/BindingDbt.h | 56 - qpid/cpp/src/qpid/legacystore/BufferValue.cpp | 56 - qpid/cpp/src/qpid/legacystore/BufferValue.h | 46 - qpid/cpp/src/qpid/legacystore/Cursor.h | 50 - qpid/cpp/src/qpid/legacystore/DataTokenImpl.cpp | 28 - qpid/cpp/src/qpid/legacystore/DataTokenImpl.h | 47 - qpid/cpp/src/qpid/legacystore/IdDbt.cpp | 42 - qpid/cpp/src/qpid/legacystore/IdDbt.h | 42 - qpid/cpp/src/qpid/legacystore/IdSequence.cpp | 40 - qpid/cpp/src/qpid/legacystore/IdSequence.h | 44 - qpid/cpp/src/qpid/legacystore/JournalImpl.cpp | 633 ---- qpid/cpp/src/qpid/legacystore/JournalImpl.h | 265 -- qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp | 1730 --------- qpid/cpp/src/qpid/legacystore/MessageStoreImpl.h | 383 -- .../src/qpid/legacystore/PreparedTransaction.cpp | 81 - .../cpp/src/qpid/legacystore/PreparedTransaction.h | 74 - qpid/cpp/src/qpid/legacystore/StoreException.h | 56 - qpid/cpp/src/qpid/legacystore/StorePlugin.cpp | 81 - qpid/cpp/src/qpid/legacystore/TxnCtxt.cpp | 184 - qpid/cpp/src/qpid/legacystore/TxnCtxt.h | 117 - qpid/cpp/src/qpid/legacystore/jrnl/aio.cpp | 41 - qpid/cpp/src/qpid/legacystore/jrnl/aio.h | 153 - qpid/cpp/src/qpid/legacystore/jrnl/aio_callback.h | 57 - qpid/cpp/src/qpid/legacystore/jrnl/cvar.cpp | 33 - qpid/cpp/src/qpid/legacystore/jrnl/cvar.h | 87 - qpid/cpp/src/qpid/legacystore/jrnl/data_tok.cpp | 194 - qpid/cpp/src/qpid/legacystore/jrnl/data_tok.h | 172 - qpid/cpp/src/qpid/legacystore/jrnl/deq_hdr.h | 141 - qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.cpp | 461 --- qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.h | 103 - qpid/cpp/src/qpid/legacystore/jrnl/enq_hdr.h | 165 - qpid/cpp/src/qpid/legacystore/jrnl/enq_map.cpp | 183 - qpid/cpp/src/qpid/legacystore/jrnl/enq_map.h | 127 - qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.cpp | 640 ---- qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.h | 116 - qpid/cpp/src/qpid/legacystore/jrnl/enums.h | 108 - qpid/cpp/src/qpid/legacystore/jrnl/fcntl.cpp | 375 -- qpid/cpp/src/qpid/legacystore/jrnl/fcntl.h | 156 - qpid/cpp/src/qpid/legacystore/jrnl/file_hdr.h | 211 -- qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h | 91 - qpid/cpp/src/qpid/legacystore/jrnl/jcntl.cpp | 984 ----- qpid/cpp/src/qpid/legacystore/jrnl/jcntl.h | 722 ---- qpid/cpp/src/qpid/legacystore/jrnl/jdir.cpp | 463 --- qpid/cpp/src/qpid/legacystore/jrnl/jdir.h | 379 -- qpid/cpp/src/qpid/legacystore/jrnl/jerrno.cpp | 253 -- qpid/cpp/src/qpid/legacystore/jrnl/jerrno.h | 173 - qpid/cpp/src/qpid/legacystore/jrnl/jexception.cpp | 183 - qpid/cpp/src/qpid/legacystore/jrnl/jexception.h | 142 - qpid/cpp/src/qpid/legacystore/jrnl/jinf.cpp | 540 --- qpid/cpp/src/qpid/legacystore/jrnl/jinf.h | 133 - qpid/cpp/src/qpid/legacystore/jrnl/jrec.cpp | 119 - qpid/cpp/src/qpid/legacystore/jrnl/jrec.h | 183 - qpid/cpp/src/qpid/legacystore/jrnl/lp_map.cpp | 82 - qpid/cpp/src/qpid/legacystore/jrnl/lp_map.h | 83 - qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.cpp | 226 -- qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.h | 303 -- qpid/cpp/src/qpid/legacystore/jrnl/pmgr.cpp | 215 -- qpid/cpp/src/qpid/legacystore/jrnl/pmgr.h | 142 - qpid/cpp/src/qpid/legacystore/jrnl/rcvdat.h | 181 - qpid/cpp/src/qpid/legacystore/jrnl/rec_hdr.h | 143 - qpid/cpp/src/qpid/legacystore/jrnl/rec_tail.h | 98 - qpid/cpp/src/qpid/legacystore/jrnl/rfc.cpp | 82 - qpid/cpp/src/qpid/legacystore/jrnl/rfc.h | 193 - qpid/cpp/src/qpid/legacystore/jrnl/rmgr.cpp | 698 ---- qpid/cpp/src/qpid/legacystore/jrnl/rmgr.h | 114 - qpid/cpp/src/qpid/legacystore/jrnl/rrfc.cpp | 125 - qpid/cpp/src/qpid/legacystore/jrnl/rrfc.h | 179 - qpid/cpp/src/qpid/legacystore/jrnl/slock.cpp | 33 - qpid/cpp/src/qpid/legacystore/jrnl/slock.h | 85 - qpid/cpp/src/qpid/legacystore/jrnl/smutex.cpp | 33 - qpid/cpp/src/qpid/legacystore/jrnl/smutex.h | 64 - qpid/cpp/src/qpid/legacystore/jrnl/time_ns.cpp | 55 - qpid/cpp/src/qpid/legacystore/jrnl/time_ns.h | 105 - qpid/cpp/src/qpid/legacystore/jrnl/txn_hdr.h | 125 - qpid/cpp/src/qpid/legacystore/jrnl/txn_map.cpp | 256 -- qpid/cpp/src/qpid/legacystore/jrnl/txn_map.h | 159 - qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.cpp | 448 --- qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.h | 101 - qpid/cpp/src/qpid/legacystore/jrnl/wmgr.cpp | 1051 ------ qpid/cpp/src/qpid/legacystore/jrnl/wmgr.h | 147 - qpid/cpp/src/qpid/legacystore/jrnl/wrfc.cpp | 164 - qpid/cpp/src/qpid/legacystore/jrnl/wrfc.h | 154 - .../cpp/src/qpid/legacystore/management-schema.xml | 99 - qpid/cpp/src/qpid/linearstore/BindingDbt.cpp | 50 - qpid/cpp/src/qpid/linearstore/BindingDbt.h | 56 - qpid/cpp/src/qpid/linearstore/BufferValue.cpp | 56 - qpid/cpp/src/qpid/linearstore/BufferValue.h | 46 - qpid/cpp/src/qpid/linearstore/Cursor.h | 50 - qpid/cpp/src/qpid/linearstore/DataTokenImpl.cpp | 28 - qpid/cpp/src/qpid/linearstore/DataTokenImpl.h | 47 - qpid/cpp/src/qpid/linearstore/ISSUES | 260 -- qpid/cpp/src/qpid/linearstore/IdDbt.cpp | 42 - qpid/cpp/src/qpid/linearstore/IdDbt.h | 42 - qpid/cpp/src/qpid/linearstore/IdSequence.cpp | 40 - qpid/cpp/src/qpid/linearstore/IdSequence.h | 43 - qpid/cpp/src/qpid/linearstore/JournalImpl.cpp | 516 --- qpid/cpp/src/qpid/linearstore/JournalImpl.h | 252 -- qpid/cpp/src/qpid/linearstore/JournalLogImpl.cpp | 61 - qpid/cpp/src/qpid/linearstore/JournalLogImpl.h | 47 - qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp | 1562 -------- qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h | 355 -- .../src/qpid/linearstore/PreparedTransaction.cpp | 81 - .../cpp/src/qpid/linearstore/PreparedTransaction.h | 73 - qpid/cpp/src/qpid/linearstore/StoreException.h | 56 - qpid/cpp/src/qpid/linearstore/StorePlugin.cpp | 97 - qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp | 185 - qpid/cpp/src/qpid/linearstore/TxnCtxt.h | 115 - .../src/qpid/linearstore/journal/AtomicCounter.h | 133 - qpid/cpp/src/qpid/linearstore/journal/Checksum.cpp | 45 - qpid/cpp/src/qpid/linearstore/journal/Checksum.h | 54 - .../src/qpid/linearstore/journal/EmptyFilePool.cpp | 479 --- .../src/qpid/linearstore/journal/EmptyFilePool.h | 119 - .../linearstore/journal/EmptyFilePoolManager.cpp | 211 -- .../linearstore/journal/EmptyFilePoolManager.h | 83 - .../linearstore/journal/EmptyFilePoolPartition.cpp | 199 - .../linearstore/journal/EmptyFilePoolPartition.h | 82 - .../qpid/linearstore/journal/EmptyFilePoolTypes.h | 57 - .../src/qpid/linearstore/journal/JournalFile.cpp | 349 -- .../cpp/src/qpid/linearstore/journal/JournalFile.h | 132 - .../src/qpid/linearstore/journal/JournalLog.cpp | 63 - qpid/cpp/src/qpid/linearstore/journal/JournalLog.h | 60 - .../linearstore/journal/LinearFileController.cpp | 243 -- .../linearstore/journal/LinearFileController.h | 119 - .../qpid/linearstore/journal/RecoveryManager.cpp | 949 ----- .../src/qpid/linearstore/journal/RecoveryManager.h | 157 - qpid/cpp/src/qpid/linearstore/journal/aio.h | 201 - .../src/qpid/linearstore/journal/aio_callback.h | 44 - qpid/cpp/src/qpid/linearstore/journal/data_tok.cpp | 136 - qpid/cpp/src/qpid/linearstore/journal/data_tok.h | 133 - qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp | 313 -- qpid/cpp/src/qpid/linearstore/journal/deq_rec.h | 70 - qpid/cpp/src/qpid/linearstore/journal/enq_map.cpp | 181 - qpid/cpp/src/qpid/linearstore/journal/enq_map.h | 101 - qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp | 397 -- qpid/cpp/src/qpid/linearstore/journal/enq_rec.h | 74 - qpid/cpp/src/qpid/linearstore/journal/enums.h | 58 - qpid/cpp/src/qpid/linearstore/journal/jcfg.h | 72 - qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp | 440 --- qpid/cpp/src/qpid/linearstore/journal/jcntl.h | 570 --- qpid/cpp/src/qpid/linearstore/journal/jdir.cpp | 457 --- qpid/cpp/src/qpid/linearstore/journal/jdir.h | 362 -- qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp | 236 -- qpid/cpp/src/qpid/linearstore/journal/jerrno.h | 157 - .../src/qpid/linearstore/journal/jexception.cpp | 168 - qpid/cpp/src/qpid/linearstore/journal/jexception.h | 125 - qpid/cpp/src/qpid/linearstore/journal/jrec.h | 122 - qpid/cpp/src/qpid/linearstore/journal/pmgr.cpp | 192 - qpid/cpp/src/qpid/linearstore/journal/pmgr.h | 119 - qpid/cpp/src/qpid/linearstore/journal/slock.h | 71 - qpid/cpp/src/qpid/linearstore/journal/smutex.h | 51 - qpid/cpp/src/qpid/linearstore/journal/time_ns.cpp | 41 - qpid/cpp/src/qpid/linearstore/journal/time_ns.h | 92 - qpid/cpp/src/qpid/linearstore/journal/txn_map.cpp | 263 -- qpid/cpp/src/qpid/linearstore/journal/txn_map.h | 150 - qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp | 305 -- qpid/cpp/src/qpid/linearstore/journal/txn_rec.h | 68 - .../src/qpid/linearstore/journal/utils/deq_hdr.c | 46 - .../src/qpid/linearstore/journal/utils/deq_hdr.h | 83 - .../src/qpid/linearstore/journal/utils/enq_hdr.c | 63 - .../src/qpid/linearstore/journal/utils/enq_hdr.h | 83 - .../src/qpid/linearstore/journal/utils/file_hdr.c | 115 - .../src/qpid/linearstore/journal/utils/file_hdr.h | 111 - .../src/qpid/linearstore/journal/utils/rec_hdr.c | 51 - .../src/qpid/linearstore/journal/utils/rec_hdr.h | 72 - .../src/qpid/linearstore/journal/utils/rec_tail.c | 46 - .../src/qpid/linearstore/journal/utils/rec_tail.h | 82 - .../src/qpid/linearstore/journal/utils/txn_hdr.c | 33 - .../src/qpid/linearstore/journal/utils/txn_hdr.h | 72 - qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp | 1086 ------ qpid/cpp/src/qpid/linearstore/journal/wmgr.h | 156 - .../cpp/src/qpid/linearstore/management-schema.xml | 54 - qpid/cpp/src/qpid/log/Helpers.h | 79 - qpid/cpp/src/qpid/log/Logger.cpp | 200 - qpid/cpp/src/qpid/log/Logger.h | 122 - qpid/cpp/src/qpid/log/Options.cpp | 148 - qpid/cpp/src/qpid/log/Options.h | 57 - qpid/cpp/src/qpid/log/OstreamOutput.cpp | 41 - qpid/cpp/src/qpid/log/OstreamOutput.h | 41 - qpid/cpp/src/qpid/log/Selector.cpp | 237 -- qpid/cpp/src/qpid/log/Selector.h | 99 - qpid/cpp/src/qpid/log/SinkOptions.h | 64 - qpid/cpp/src/qpid/log/Statement.cpp | 218 -- qpid/cpp/src/qpid/log/Statement.h | 244 -- qpid/cpp/src/qpid/log/posix/SinkOptions.cpp | 222 -- qpid/cpp/src/qpid/log/posix/SinkOptions.h | 64 - qpid/cpp/src/qpid/log/windows/SinkOptions.cpp | 148 - qpid/cpp/src/qpid/log/windows/SinkOptions.h | 54 - qpid/cpp/src/qpid/management/Args.h | 44 - qpid/cpp/src/qpid/management/Buffer.cpp | 105 - qpid/cpp/src/qpid/management/Buffer.h | 105 - .../cpp/src/qpid/management/ConnectionSettings.cpp | 40 - qpid/cpp/src/qpid/management/ConnectionSettings.h | 118 - qpid/cpp/src/qpid/management/Manageable.cpp | 53 - qpid/cpp/src/qpid/management/Manageable.h | 79 - qpid/cpp/src/qpid/management/ManagementAgent.cpp | 2832 -------------- qpid/cpp/src/qpid/management/ManagementAgent.h | 388 -- .../qpid/management/ManagementDirectExchange.cpp | 65 - .../src/qpid/management/ManagementDirectExchange.h | 57 - qpid/cpp/src/qpid/management/ManagementEvent.h | 53 - qpid/cpp/src/qpid/management/ManagementObject.cpp | 413 -- qpid/cpp/src/qpid/management/ManagementObject.h | 256 -- .../qpid/management/ManagementTopicExchange.cpp | 73 - .../src/qpid/management/ManagementTopicExchange.h | 61 - qpid/cpp/src/qpid/management/Mutex.cpp | 29 - qpid/cpp/src/qpid/management/Mutex.h | 67 - qpid/cpp/src/qpid/memory.h | 32 - qpid/cpp/src/qpid/messaging/Address.cpp | 111 - qpid/cpp/src/qpid/messaging/AddressImpl.h | 45 - qpid/cpp/src/qpid/messaging/AddressParser.cpp | 271 -- qpid/cpp/src/qpid/messaging/AddressParser.h | 67 - qpid/cpp/src/qpid/messaging/Connection.cpp | 111 - qpid/cpp/src/qpid/messaging/ConnectionImpl.h | 60 - qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp | 135 - qpid/cpp/src/qpid/messaging/ConnectionOptions.h | 57 - qpid/cpp/src/qpid/messaging/Duration.cpp | 55 - qpid/cpp/src/qpid/messaging/FailoverUpdates.cpp | 85 - qpid/cpp/src/qpid/messaging/Logger.cpp | 200 - qpid/cpp/src/qpid/messaging/Message.cpp | 171 - qpid/cpp/src/qpid/messaging/MessageImpl.cpp | 253 -- qpid/cpp/src/qpid/messaging/MessageImpl.h | 122 - qpid/cpp/src/qpid/messaging/Message_io.cpp | 45 - qpid/cpp/src/qpid/messaging/PrivateImplRef.h | 94 - qpid/cpp/src/qpid/messaging/ProtocolRegistry.cpp | 219 -- qpid/cpp/src/qpid/messaging/ProtocolRegistry.h | 50 - qpid/cpp/src/qpid/messaging/Receiver.cpp | 62 - qpid/cpp/src/qpid/messaging/ReceiverImpl.h | 56 - qpid/cpp/src/qpid/messaging/Sender.cpp | 49 - qpid/cpp/src/qpid/messaging/SenderImpl.h | 50 - qpid/cpp/src/qpid/messaging/Session.cpp | 113 - qpid/cpp/src/qpid/messaging/SessionImpl.h | 63 - qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp | 788 ---- qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h | 96 - .../src/qpid/messaging/amqp/ConnectionContext.cpp | 1323 ------- .../src/qpid/messaging/amqp/ConnectionContext.h | 233 -- .../src/qpid/messaging/amqp/ConnectionHandle.cpp | 108 - .../cpp/src/qpid/messaging/amqp/ConnectionHandle.h | 61 - qpid/cpp/src/qpid/messaging/amqp/DriverImpl.cpp | 78 - qpid/cpp/src/qpid/messaging/amqp/DriverImpl.h | 64 - .../cpp/src/qpid/messaging/amqp/EncodedMessage.cpp | 366 -- qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.h | 190 - qpid/cpp/src/qpid/messaging/amqp/PnData.cpp | 246 -- qpid/cpp/src/qpid/messaging/amqp/PnData.h | 61 - .../src/qpid/messaging/amqp/ReceiverContext.cpp | 140 - qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h | 77 - .../cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp | 111 - qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.h | 64 - qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp | 186 - qpid/cpp/src/qpid/messaging/amqp/Sasl.h | 77 - qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp | 643 ---- qpid/cpp/src/qpid/messaging/amqp/SenderContext.h | 119 - qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp | 81 - qpid/cpp/src/qpid/messaging/amqp/SenderHandle.h | 59 - .../cpp/src/qpid/messaging/amqp/SessionContext.cpp | 258 -- qpid/cpp/src/qpid/messaging/amqp/SessionContext.h | 95 - qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp | 147 - qpid/cpp/src/qpid/messaging/amqp/SessionHandle.h | 64 - qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp | 186 - qpid/cpp/src/qpid/messaging/amqp/SslTransport.h | 78 - qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp | 185 - qpid/cpp/src/qpid/messaging/amqp/TcpTransport.h | 78 - qpid/cpp/src/qpid/messaging/amqp/Transaction.cpp | 155 - qpid/cpp/src/qpid/messaging/amqp/Transaction.h | 95 - qpid/cpp/src/qpid/messaging/amqp/Transport.cpp | 50 - qpid/cpp/src/qpid/messaging/amqp/Transport.h | 52 - .../cpp/src/qpid/messaging/amqp/TransportContext.h | 50 - qpid/cpp/src/qpid/messaging/amqp/util.cpp | 43 - qpid/cpp/src/qpid/messaging/amqp/util.h | 36 - .../qpid/messaging/amqp/windows/SslTransport.cpp | 136 - qpid/cpp/src/qpid/messaging/exceptions.cpp | 65 - qpid/cpp/src/qpid/pointer_to_other.h | 62 - qpid/cpp/src/qpid/ptr_map.h | 57 - qpid/cpp/src/qpid/store/CMakeLists.txt | 116 - qpid/cpp/src/qpid/store/MessageStorePlugin.cpp | 463 --- qpid/cpp/src/qpid/store/MessageStorePlugin.h | 280 -- qpid/cpp/src/qpid/store/StorageProvider.h | 329 -- qpid/cpp/src/qpid/store/StoreException.h | 49 - qpid/cpp/src/qpid/store/ms-clfs/Log.cpp | 182 - qpid/cpp/src/qpid/store/ms-clfs/Log.h | 78 - qpid/cpp/src/qpid/store/ms-clfs/Lsn.h | 36 - .../src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp | 1102 ------ qpid/cpp/src/qpid/store/ms-clfs/MessageLog.cpp | 406 -- qpid/cpp/src/qpid/store/ms-clfs/MessageLog.h | 107 - qpid/cpp/src/qpid/store/ms-clfs/Messages.cpp | 472 --- qpid/cpp/src/qpid/store/ms-clfs/Messages.h | 144 - qpid/cpp/src/qpid/store/ms-clfs/Transaction.cpp | 83 - qpid/cpp/src/qpid/store/ms-clfs/Transaction.h | 147 - qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.cpp | 428 --- qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.h | 104 - qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.cpp | 67 - qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.h | 85 - .../cpp/src/qpid/store/ms-sql/BindingRecordset.cpp | 165 - qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.h | 88 - qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.cpp | 64 - qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.h | 62 - qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.cpp | 133 - qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.h | 61 - qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.cpp | 86 - qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.h | 54 - .../src/qpid/store/ms-sql/DatabaseConnection.cpp | 91 - .../cpp/src/qpid/store/ms-sql/DatabaseConnection.h | 64 - qpid/cpp/src/qpid/store/ms-sql/Exception.h | 66 - qpid/cpp/src/qpid/store/ms-sql/MSSqlProvider.cpp | 1286 ------- .../src/qpid/store/ms-sql/MessageMapRecordset.cpp | 267 -- .../src/qpid/store/ms-sql/MessageMapRecordset.h | 100 - .../cpp/src/qpid/store/ms-sql/MessageRecordset.cpp | 184 - qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.h | 85 - qpid/cpp/src/qpid/store/ms-sql/Recordset.cpp | 92 - qpid/cpp/src/qpid/store/ms-sql/Recordset.h | 75 - qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.cpp | 71 - qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.h | 67 - qpid/cpp/src/qpid/store/ms-sql/State.cpp | 45 - qpid/cpp/src/qpid/store/ms-sql/State.h | 52 - qpid/cpp/src/qpid/store/ms-sql/TplRecordset.cpp | 128 - qpid/cpp/src/qpid/store/ms-sql/TplRecordset.h | 58 - qpid/cpp/src/qpid/store/ms-sql/VariantHelper.cpp | 71 - qpid/cpp/src/qpid/store/ms-sql/VariantHelper.h | 61 - qpid/cpp/src/qpid/sys/AggregateOutput.cpp | 89 - qpid/cpp/src/qpid/sys/AggregateOutput.h | 76 - qpid/cpp/src/qpid/sys/AsynchIO.h | 175 - qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp | 235 -- qpid/cpp/src/qpid/sys/AsynchIOHandler.h | 82 - qpid/cpp/src/qpid/sys/AtomicCount.h | 52 - qpid/cpp/src/qpid/sys/AtomicValue.h | 39 - qpid/cpp/src/qpid/sys/AtomicValue_gcc.h | 71 - qpid/cpp/src/qpid/sys/AtomicValue_mutex.h | 83 - qpid/cpp/src/qpid/sys/BlockingQueue.h | 129 - qpid/cpp/src/qpid/sys/Codec.h | 52 - qpid/cpp/src/qpid/sys/Condition.h | 33 - qpid/cpp/src/qpid/sys/ConnectionCodec.h | 70 - qpid/cpp/src/qpid/sys/ConnectionInputHandler.h | 51 - .../src/qpid/sys/ConnectionInputHandlerFactory.h | 54 - qpid/cpp/src/qpid/sys/ConnectionOutputHandler.h | 42 - qpid/cpp/src/qpid/sys/CopyOnWriteArray.h | 162 - qpid/cpp/src/qpid/sys/DeletionManager.h | 162 - qpid/cpp/src/qpid/sys/DispatchHandle.cpp | 352 -- qpid/cpp/src/qpid/sys/DispatchHandle.h | 150 - qpid/cpp/src/qpid/sys/Dispatcher.cpp | 40 - qpid/cpp/src/qpid/sys/Dispatcher.h | 44 - qpid/cpp/src/qpid/sys/ExceptionHolder.h | 71 - qpid/cpp/src/qpid/sys/FileSysDir.h | 71 - qpid/cpp/src/qpid/sys/Fork.h | 24 - qpid/cpp/src/qpid/sys/FreeBSD/uuid.cpp | 44 - qpid/cpp/src/qpid/sys/IOHandle.h | 36 - qpid/cpp/src/qpid/sys/LockFile.h | 64 - qpid/cpp/src/qpid/sys/LockPtr.h | 89 - qpid/cpp/src/qpid/sys/MemStat.cpp | 31 - qpid/cpp/src/qpid/sys/MemStat.h | 38 - qpid/cpp/src/qpid/sys/MemoryMappedFile.h | 79 - qpid/cpp/src/qpid/sys/Monitor.h | 49 - qpid/cpp/src/qpid/sys/Mutex.h | 91 - qpid/cpp/src/qpid/sys/OutputControl.h | 43 - qpid/cpp/src/qpid/sys/OutputTask.h | 41 - qpid/cpp/src/qpid/sys/Path.h | 61 - qpid/cpp/src/qpid/sys/PipeHandle.h | 51 - qpid/cpp/src/qpid/sys/PollableCondition.h | 64 - qpid/cpp/src/qpid/sys/PollableQueue.h | 177 - qpid/cpp/src/qpid/sys/Poller.h | 135 - qpid/cpp/src/qpid/sys/Probes.h | 65 - qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp | 393 -- qpid/cpp/src/qpid/sys/Runnable.cpp | 32 - qpid/cpp/src/qpid/sys/Runnable.h | 51 - qpid/cpp/src/qpid/sys/ScopedIncrement.h | 67 - qpid/cpp/src/qpid/sys/SecurityLayer.h | 46 - qpid/cpp/src/qpid/sys/SecuritySettings.h | 60 - qpid/cpp/src/qpid/sys/Semaphore.h | 79 - qpid/cpp/src/qpid/sys/Shlib.cpp | 38 - qpid/cpp/src/qpid/sys/Shlib.h | 77 - qpid/cpp/src/qpid/sys/ShutdownHandler.h | 37 - qpid/cpp/src/qpid/sys/Socket.h | 121 - qpid/cpp/src/qpid/sys/SocketAddress.h | 82 - qpid/cpp/src/qpid/sys/SocketTransport.cpp | 221 -- qpid/cpp/src/qpid/sys/SocketTransport.h | 91 - qpid/cpp/src/qpid/sys/SslPlugin.cpp | 143 - qpid/cpp/src/qpid/sys/StateMonitor.h | 78 - qpid/cpp/src/qpid/sys/StrError.h | 36 - qpid/cpp/src/qpid/sys/SystemInfo.h | 109 - qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp | 61 - qpid/cpp/src/qpid/sys/Thread.h | 73 - qpid/cpp/src/qpid/sys/Time.h | 181 - qpid/cpp/src/qpid/sys/Timer.cpp | 235 -- qpid/cpp/src/qpid/sys/Timer.h | 166 - qpid/cpp/src/qpid/sys/TimerWarnings.cpp | 82 - qpid/cpp/src/qpid/sys/TimerWarnings.h | 81 - qpid/cpp/src/qpid/sys/TransportFactory.h | 65 - qpid/cpp/src/qpid/sys/Waitable.h | 114 - qpid/cpp/src/qpid/sys/aix/SystemInfo.cpp | 201 - qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp | 129 - qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h | 68 - qpid/cpp/src/qpid/sys/epoll/EpollPoller.cpp | 677 ---- qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp | 655 ---- qpid/cpp/src/qpid/sys/posix/BSDSocket.cpp | 284 -- qpid/cpp/src/qpid/sys/posix/BSDSocket.h | 91 - qpid/cpp/src/qpid/sys/posix/Condition.cpp | 45 - qpid/cpp/src/qpid/sys/posix/Condition.h | 82 - qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp | 80 - qpid/cpp/src/qpid/sys/posix/Fork.cpp | 129 - qpid/cpp/src/qpid/sys/posix/Fork.h | 82 - qpid/cpp/src/qpid/sys/posix/IOHandle.cpp | 29 - qpid/cpp/src/qpid/sys/posix/LockFile.cpp | 107 - qpid/cpp/src/qpid/sys/posix/MemStat.cpp | 38 - qpid/cpp/src/qpid/sys/posix/MemoryMappedFile.cpp | 125 - qpid/cpp/src/qpid/sys/posix/Mutex.cpp | 46 - qpid/cpp/src/qpid/sys/posix/Mutex.h | 158 - qpid/cpp/src/qpid/sys/posix/Path.cpp | 60 - qpid/cpp/src/qpid/sys/posix/PidFile.h | 62 - qpid/cpp/src/qpid/sys/posix/PipeHandle.cpp | 64 - qpid/cpp/src/qpid/sys/posix/PollableCondition.cpp | 118 - qpid/cpp/src/qpid/sys/posix/PosixPoller.cpp | 793 ---- qpid/cpp/src/qpid/sys/posix/PrivatePosix.h | 65 - qpid/cpp/src/qpid/sys/posix/Shlib.cpp | 60 - qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp | 353 -- qpid/cpp/src/qpid/sys/posix/StrError.cpp | 41 - qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp | 201 - qpid/cpp/src/qpid/sys/posix/Thread.cpp | 88 - qpid/cpp/src/qpid/sys/posix/Time.cpp | 162 - qpid/cpp/src/qpid/sys/posix/Time.h | 34 - qpid/cpp/src/qpid/sys/posix/check.h | 53 - qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp | 247 -- qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp | 724 ---- qpid/cpp/src/qpid/sys/rdma/RdmaIO.h | 250 -- qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp | 210 -- qpid/cpp/src/qpid/sys/rdma/rdma_exception.h | 69 - qpid/cpp/src/qpid/sys/rdma/rdma_factories.cpp | 105 - qpid/cpp/src/qpid/sys/rdma/rdma_factories.h | 40 - qpid/cpp/src/qpid/sys/rdma/rdma_wrap.cpp | 576 --- qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h | 305 -- qpid/cpp/src/qpid/sys/regex.h | 81 - qpid/cpp/src/qpid/sys/solaris/ECFPoller.cpp | 444 --- qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp | 110 - qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp | 409 -- qpid/cpp/src/qpid/sys/ssl/SslSocket.h | 98 - qpid/cpp/src/qpid/sys/ssl/check.cpp | 85 - qpid/cpp/src/qpid/sys/ssl/check.h | 57 - qpid/cpp/src/qpid/sys/ssl/util.cpp | 132 - qpid/cpp/src/qpid/sys/ssl/util.h | 50 - qpid/cpp/src/qpid/sys/unordered_map.h | 41 - qpid/cpp/src/qpid/sys/urlAdd.h | 62 - qpid/cpp/src/qpid/sys/uuid.h | 37 - qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp | 713 ---- qpid/cpp/src/qpid/sys/windows/AsynchIO.h | 235 -- qpid/cpp/src/qpid/sys/windows/AsynchIoResult.h | 204 - qpid/cpp/src/qpid/sys/windows/Condition.h | 77 - qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp | 90 - qpid/cpp/src/qpid/sys/windows/IOHandle.cpp | 29 - qpid/cpp/src/qpid/sys/windows/IoHandlePrivate.h | 58 - qpid/cpp/src/qpid/sys/windows/IocpPoller.cpp | 220 -- qpid/cpp/src/qpid/sys/windows/LockFile.cpp | 64 - qpid/cpp/src/qpid/sys/windows/MemoryMappedFile.cpp | 58 - qpid/cpp/src/qpid/sys/windows/Mutex.h | 188 - qpid/cpp/src/qpid/sys/windows/Path.cpp | 65 - qpid/cpp/src/qpid/sys/windows/PipeHandle.cpp | 101 - .../cpp/src/qpid/sys/windows/PollableCondition.cpp | 114 - qpid/cpp/src/qpid/sys/windows/QpidDllMain.h | 72 - qpid/cpp/src/qpid/sys/windows/Shlib.cpp | 54 - qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp | 346 -- qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp | 735 ---- qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h | 192 - qpid/cpp/src/qpid/sys/windows/SslCredential.cpp | 279 -- qpid/cpp/src/qpid/sys/windows/SslCredential.h | 84 - qpid/cpp/src/qpid/sys/windows/StrError.cpp | 52 - qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp | 208 - qpid/cpp/src/qpid/sys/windows/Thread.cpp | 340 -- qpid/cpp/src/qpid/sys/windows/Time.cpp | 217 -- qpid/cpp/src/qpid/sys/windows/Time.h | 36 - qpid/cpp/src/qpid/sys/windows/WinSocket.cpp | 286 -- qpid/cpp/src/qpid/sys/windows/WinSocket.h | 121 - qpid/cpp/src/qpid/sys/windows/check.h | 49 - qpid/cpp/src/qpid/sys/windows/mingw32_compat.h | 39 - qpid/cpp/src/qpid/sys/windows/util.cpp | 70 - qpid/cpp/src/qpid/sys/windows/util.h | 50 - qpid/cpp/src/qpid/sys/windows/uuid.cpp | 68 - qpid/cpp/src/qpid/types/Exception.cpp | 30 - qpid/cpp/src/qpid/types/Uuid.cpp | 208 - qpid/cpp/src/qpid/types/Variant.cpp | 962 ----- qpid/cpp/src/qpid/types/encodings.h | 35 - qpid/cpp/src/qpid/xml/XmlExchange.cpp | 474 --- qpid/cpp/src/qpid/xml/XmlExchange.h | 124 - qpid/cpp/src/qpid/xml/XmlExchangePlugin.cpp | 70 - qpid/cpp/src/qpidd.cpp | 115 - qpid/cpp/src/qpidd.h | 78 - qpid/cpp/src/rdma.cmake | 117 - qpid/cpp/src/tests/.valgrind.supp | 242 -- qpid/cpp/src/tests/AccumulatedAckTest.cpp | 237 -- qpid/cpp/src/tests/Acl.cpp | 166 - qpid/cpp/src/tests/AclHost.cpp | 166 - qpid/cpp/src/tests/Address.cpp | 135 - qpid/cpp/src/tests/Array.cpp | 84 - qpid/cpp/src/tests/AsyncCompletion.cpp | 153 - qpid/cpp/src/tests/AtomicValue.cpp | 54 - qpid/cpp/src/tests/Blob.cpp | 21 - qpid/cpp/src/tests/BrokerFixture.h | 168 - qpid/cpp/src/tests/BrokerMgmtAgent.cpp | 387 -- qpid/cpp/src/tests/BrokerMgmtAgent.xml | 38 - qpid/cpp/src/tests/BrokerOptions.cpp | 79 - qpid/cpp/src/tests/CMakeLists.txt | 323 -- qpid/cpp/src/tests/ClientMessage.cpp | 46 - qpid/cpp/src/tests/ClientMessageTest.cpp | 51 - qpid/cpp/src/tests/ClientSessionTest.cpp | 663 ---- qpid/cpp/src/tests/ConnectionOptions.h | 62 - qpid/cpp/src/tests/DeliveryRecordTest.cpp | 67 - qpid/cpp/src/tests/DispatcherTest.cpp | 240 -- qpid/cpp/src/tests/DtxWorkRecordTest.cpp | 193 - qpid/cpp/src/tests/ExchangeTest.cpp | 267 -- qpid/cpp/src/tests/FieldTable.cpp | 215 -- qpid/cpp/src/tests/FieldValue.cpp | 98 - qpid/cpp/src/tests/Frame.cpp | 84 - qpid/cpp/src/tests/FrameDecoder.cpp | 78 - qpid/cpp/src/tests/FramingTest.cpp | 168 - qpid/cpp/src/tests/HeaderTest.cpp | 114 - qpid/cpp/src/tests/HeadersExchangeTest.cpp | 194 - qpid/cpp/src/tests/InlineAllocator.cpp | 68 - qpid/cpp/src/tests/InlineVector.cpp | 128 - qpid/cpp/src/tests/ManagementTest.cpp | 97 - qpid/cpp/src/tests/MessageReplayTracker.cpp | 104 - qpid/cpp/src/tests/MessageTest.cpp | 89 - qpid/cpp/src/tests/MessageUtils.h | 117 - qpid/cpp/src/tests/MessagingFixture.h | 352 -- qpid/cpp/src/tests/MessagingLogger.cpp | 149 - qpid/cpp/src/tests/MessagingSessionTests.cpp | 1628 -------- qpid/cpp/src/tests/MessagingThreadTests.cpp | 144 - qpid/cpp/src/tests/PollableCondition.cpp | 109 - qpid/cpp/src/tests/PollerTest.cpp | 262 -- qpid/cpp/src/tests/ProxyTest.cpp | 56 - qpid/cpp/src/tests/Qmf2.cpp | 422 --- qpid/cpp/src/tests/QueueDepth.cpp | 105 - qpid/cpp/src/tests/QueueFlowLimitTest.cpp | 457 --- qpid/cpp/src/tests/QueueOptionsTest.cpp | 85 - qpid/cpp/src/tests/QueuePolicyTest.cpp | 300 -- qpid/cpp/src/tests/QueueRegistryTest.cpp | 91 - qpid/cpp/src/tests/QueueTest.cpp | 629 ---- qpid/cpp/src/tests/README.txt | 30 - qpid/cpp/src/tests/RangeSet.cpp | 154 - qpid/cpp/src/tests/RefCounted.cpp | 55 - qpid/cpp/src/tests/RetryList.cpp | 111 - qpid/cpp/src/tests/Selector.cpp | 501 --- qpid/cpp/src/tests/SequenceNumberTest.cpp | 209 -- qpid/cpp/src/tests/SequenceSet.cpp | 187 - qpid/cpp/src/tests/SessionState.cpp | 303 -- qpid/cpp/src/tests/Shlib.cpp | 67 - qpid/cpp/src/tests/Statistics.cpp | 131 - qpid/cpp/src/tests/Statistics.h | 111 - qpid/cpp/src/tests/StringUtils.cpp | 81 - qpid/cpp/src/tests/SystemInfo.cpp | 36 - qpid/cpp/src/tests/TestMessageStore.h | 63 - qpid/cpp/src/tests/TestOptions.h | 79 - qpid/cpp/src/tests/TimerTest.cpp | 176 - qpid/cpp/src/tests/TopicExchangeTest.cpp | 408 -- qpid/cpp/src/tests/TransactionObserverTest.cpp | 147 - qpid/cpp/src/tests/TxBufferTest.cpp | 188 - qpid/cpp/src/tests/TxMocks.h | 236 -- qpid/cpp/src/tests/Url.cpp | 116 - qpid/cpp/src/tests/Uuid.cpp | 150 - qpid/cpp/src/tests/Variant.cpp | 834 ----- qpid/cpp/src/tests/XmlClientSessionTest.cpp | 301 -- qpid/cpp/src/tests/acl.py | 3959 -------------------- qpid/cpp/src/tests/acl_1.py | 396 -- qpid/cpp/src/tests/assertions.py | 194 - qpid/cpp/src/tests/background.ps1 | 55 - qpid/cpp/src/tests/brokertest.py | 739 ---- qpid/cpp/src/tests/check_dependencies.py.in | 53 - qpid/cpp/src/tests/cli_tests.py | 482 --- qpid/cpp/src/tests/common.py | 298 -- qpid/cpp/src/tests/consume.cpp | 131 - qpid/cpp/src/tests/datagen.cpp | 103 - qpid/cpp/src/tests/declare_queues.cpp | 101 - qpid/cpp/src/tests/dlclose_noop.c | 30 - qpid/cpp/src/tests/dynamic_log_hires_timestamp | 75 - qpid/cpp/src/tests/dynamic_log_level_test | 90 - qpid/cpp/src/tests/echotest.cpp | 157 - qpid/cpp/src/tests/env.ps1.in | 77 - qpid/cpp/src/tests/env.py.in | 116 - qpid/cpp/src/tests/env.sh.in | 76 - qpid/cpp/src/tests/exception_test.cpp | 125 - qpid/cpp/src/tests/failing-amqp0-10-python-tests | 32 - qpid/cpp/src/tests/failing-amqp1.0-python-tests | 25 - qpid/cpp/src/tests/federated_topic_test | 127 - qpid/cpp/src/tests/federation.py | 2793 -------------- qpid/cpp/src/tests/federation_sys.py | 977 ----- qpid/cpp/src/tests/find_prog.ps1 | 36 - qpid/cpp/src/tests/ha_test.py | 401 -- qpid/cpp/src/tests/ha_test_max_queues.cpp | 67 - qpid/cpp/src/tests/ha_tests.py | 1458 ------- qpid/cpp/src/tests/header_test.cpp | 59 - qpid/cpp/src/tests/header_test.py | 86 - qpid/cpp/src/tests/headers_federation.py | 99 - qpid/cpp/src/tests/idle_timeout_tests.py | 96 - qpid/cpp/src/tests/interlink_tests.py | 331 -- qpid/cpp/src/tests/interop_tests.py | 217 -- qpid/cpp/src/tests/legacystore/.valgrind.supp | 35 - qpid/cpp/src/tests/legacystore/.valgrindrc | 7 - qpid/cpp/src/tests/legacystore/CMakeLists.txt | 130 - qpid/cpp/src/tests/legacystore/MessageUtils.h | 105 - qpid/cpp/src/tests/legacystore/TestFramework.cpp | 30 - qpid/cpp/src/tests/legacystore/TestFramework.h | 37 - qpid/cpp/src/tests/legacystore/clean.sh | 32 - .../src/tests/legacystore/federation/Makefile.am | 46 - .../legacystore/federation/federation_tests_env.sh | 313 -- .../federation/run_federation_sys_tests | 96 - .../federation/run_long_federation_sys_tests | 24 - .../src/tests/legacystore/jrnl/_st_auto_expand.cpp | 140 - qpid/cpp/src/tests/legacystore/jrnl/_st_basic.cpp | 558 --- .../src/tests/legacystore/jrnl/_st_basic_txn.cpp | 239 -- .../src/tests/legacystore/jrnl/_st_helper_fns.h | 882 ----- qpid/cpp/src/tests/legacystore/jrnl/_st_read.cpp | 460 --- .../src/tests/legacystore/jrnl/_st_read_txn.cpp | 353 -- .../cpp/src/tests/legacystore/jrnl/_ut_enq_map.cpp | 320 -- qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp | 416 -- qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp | 47 - .../src/tests/legacystore/jrnl/_ut_jexception.cpp | 346 -- qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp | 402 -- qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp | 886 ----- .../cpp/src/tests/legacystore/jrnl/_ut_rec_hdr.cpp | 438 --- .../cpp/src/tests/legacystore/jrnl/_ut_time_ns.cpp | 163 - .../cpp/src/tests/legacystore/jrnl/_ut_txn_map.cpp | 106 - qpid/cpp/src/tests/legacystore/jrnl/chk_jdata | 32 - qpid/cpp/src/tests/legacystore/jrnl/cp_rtest_jrnl | 59 - qpid/cpp/src/tests/legacystore/jrnl/jhexdump | 41 - .../tests/legacystore/jrnl/jtt/_ut_data_src.cpp | 207 - .../legacystore/jrnl/jtt/_ut_jrnl_init_params.cpp | 100 - .../legacystore/jrnl/jtt/_ut_jrnl_instance.cpp | 178 - .../tests/legacystore/jrnl/jtt/_ut_read_arg.cpp | 146 - .../tests/legacystore/jrnl/jtt/_ut_test_case.cpp | 113 - .../legacystore/jrnl/jtt/_ut_test_case_result.cpp | 206 - .../jrnl/jtt/_ut_test_case_result_agregation.cpp | 178 - .../legacystore/jrnl/jtt/_ut_test_case_set.cpp | 147 - .../legacystore/jrnl/jtt/_ut_test_case_set.csv | 74 - qpid/cpp/src/tests/legacystore/jrnl/jtt/args.cpp | 226 -- qpid/cpp/src/tests/legacystore/jrnl/jtt/args.h | 66 - .../src/tests/legacystore/jrnl/jtt/data_src.cpp | 87 - qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.h | 66 - .../src/tests/legacystore/jrnl/jtt/jfile_chk.py | 838 ----- .../legacystore/jrnl/jtt/jrnl_init_params.cpp | 77 - .../tests/legacystore/jrnl/jtt/jrnl_init_params.h | 80 - .../tests/legacystore/jrnl/jtt/jrnl_instance.cpp | 439 --- .../src/tests/legacystore/jrnl/jtt/jrnl_instance.h | 121 - qpid/cpp/src/tests/legacystore/jrnl/jtt/jtt.csv | 234 -- qpid/cpp/src/tests/legacystore/jrnl/jtt/main.cpp | 57 - .../src/tests/legacystore/jrnl/jtt/read_arg.cpp | 93 - qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.h | 62 - .../src/tests/legacystore/jrnl/jtt/test_case.cpp | 179 - .../cpp/src/tests/legacystore/jrnl/jtt/test_case.h | 110 - .../legacystore/jrnl/jtt/test_case_result.cpp | 201 - .../tests/legacystore/jrnl/jtt/test_case_result.h | 100 - .../jrnl/jtt/test_case_result_agregation.cpp | 185 - .../jrnl/jtt/test_case_result_agregation.h | 81 - .../tests/legacystore/jrnl/jtt/test_case_set.cpp | 169 - .../src/tests/legacystore/jrnl/jtt/test_case_set.h | 99 - .../src/tests/legacystore/jrnl/jtt/test_mgr.cpp | 218 -- qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.h | 68 - qpid/cpp/src/tests/legacystore/jrnl/prof | 32 - .../src/tests/legacystore/jrnl/run-journal-tests | 47 - qpid/cpp/src/tests/legacystore/jrnl/tests.ods | Bin 91064 -> 0 bytes qpid/cpp/src/tests/legacystore/persistence.py | 574 --- .../src/tests/legacystore/python_tests/__init__.py | 24 - .../legacystore/python_tests/client_persistence.py | 239 -- .../src/tests/legacystore/python_tests/resize.py | 170 - .../tests/legacystore/python_tests/store_test.py | 417 --- .../src/tests/legacystore/run_long_python_tests | 21 - qpid/cpp/src/tests/legacystore/run_python_tests | 47 - .../src/tests/legacystore/run_short_python_tests | 21 - qpid/cpp/src/tests/legacystore/system_test.sh | 51 - qpid/cpp/src/tests/legacystore/unit_test.cpp | 28 - qpid/cpp/src/tests/legacystore/unit_test.h | 69 - qpid/cpp/src/tests/linearstore/CMakeLists.txt | 26 - .../src/tests/linearstore/linearstoredirsetup.sh | 55 - .../src/tests/linearstore/python_tests/__init__.py | 23 - .../linearstore/python_tests/client_persistence.py | 239 -- .../tests/linearstore/python_tests/store_test.py | 417 --- .../src/tests/linearstore/run_long_python_tests | 21 - qpid/cpp/src/tests/linearstore/run_python_tests | 47 - .../src/tests/linearstore/run_short_python_tests | 21 - qpid/cpp/src/tests/linearstore/tx-test-soak.sh | 275 -- qpid/cpp/src/tests/logging.cpp | 512 --- qpid/cpp/src/tests/mgmt_1.py | 99 - qpid/cpp/src/tests/misc.py | 119 - qpid/cpp/src/tests/msg_group_test.cpp | 641 ---- qpid/cpp/src/tests/perfdist | 87 - qpid/cpp/src/tests/ping_broker | 134 - qpid/cpp/src/tests/plano.py | 559 --- qpid/cpp/src/tests/policies.py | 136 - qpid/cpp/src/tests/policy.acl | 20 - qpid/cpp/src/tests/publish.cpp | 135 - qpid/cpp/src/tests/qpid-analyze-trace | 258 -- qpid/cpp/src/tests/qpid-client-test.cpp | 139 - qpid/cpp/src/tests/qpid-cluster-benchmark | 64 - qpid/cpp/src/tests/qpid-cpp-benchmark | 366 -- qpid/cpp/src/tests/qpid-ctrl | 120 - qpid/cpp/src/tests/qpid-latency-test.cpp | 480 --- qpid/cpp/src/tests/qpid-perftest.cpp | 760 ---- qpid/cpp/src/tests/qpid-ping.cpp | 94 - qpid/cpp/src/tests/qpid-receive.cpp | 299 -- qpid/cpp/src/tests/qpid-send.cpp | 469 --- qpid/cpp/src/tests/qpid-src-rinstall | 31 - qpid/cpp/src/tests/qpid-stream.cpp | 193 - qpid/cpp/src/tests/qpid-topic-listener.cpp | 209 -- qpid/cpp/src/tests/qpid-topic-publisher.cpp | 230 -- qpid/cpp/src/tests/qpid-txtest.cpp | 342 -- qpid/cpp/src/tests/qpid-txtest2.cpp | 363 -- qpid/cpp/src/tests/qpidd-empty.conf | 22 - qpid/cpp/src/tests/qpidd-p0 | 46 - qpid/cpp/src/tests/qpidd_qmfv2_tests.py | 278 -- qpid/cpp/src/tests/queue_flow_limit_tests.py | 376 -- qpid/cpp/src/tests/queue_redirect.py | 317 -- qpid/cpp/src/tests/receiver.cpp | 140 - qpid/cpp/src/tests/reject_release.py | 65 - qpid/cpp/src/tests/replaying_sender.cpp | 165 - qpid/cpp/src/tests/resuming_receiver.cpp | 193 - qpid/cpp/src/tests/ring_queue_test | 174 - qpid/cpp/src/tests/run.py | 6 - qpid/cpp/src/tests/run_acl_tests | 70 - qpid/cpp/src/tests/run_cli_tests | 63 - qpid/cpp/src/tests/run_client_tests | 30 - qpid/cpp/src/tests/run_federation_tests | 60 - qpid/cpp/src/tests/run_flow_control_tests | 28 - qpid/cpp/src/tests/run_ha_tests | 37 - qpid/cpp/src/tests/run_idle_timeout_tests | 26 - qpid/cpp/src/tests/run_interlink_tests | 26 - qpid/cpp/src/tests/run_interop_tests | 35 - qpid/cpp/src/tests/run_ipv6_tests | 116 - qpid/cpp/src/tests/run_logging_tests | 38 - qpid/cpp/src/tests/run_long_federation_sys_tests | 24 - qpid/cpp/src/tests/run_msg_group_tests | 47 - qpid/cpp/src/tests/run_msg_group_tests_soak | 61 - qpid/cpp/src/tests/run_paged_queue_tests | 45 - qpid/cpp/src/tests/run_performance_tests | 28 - qpid/cpp/src/tests/run_python_tests | 67 - qpid/cpp/src/tests/run_qmf_tests | 26 - qpid/cpp/src/tests/run_queue_redirect_tests | 30 - qpid/cpp/src/tests/run_ring_queue_tests | 30 - qpid/cpp/src/tests/run_sasl_tests | 64 - qpid/cpp/src/tests/run_ssl_tests | 329 -- qpid/cpp/src/tests/run_store_tests.ps1 | 132 - qpid/cpp/src/tests/run_topic_tests | 30 - qpid/cpp/src/tests/run_transaction_tests | 30 - qpid/cpp/src/tests/run_unit_tests | 39 - qpid/cpp/src/tests/run_windows_store_tests | 61 - qpid/cpp/src/tests/sasl_fed | 122 - qpid/cpp/src/tests/sasl_fed_ex | 223 -- qpid/cpp/src/tests/sasl_no_dir | 58 - qpid/cpp/src/tests/sasl_test_setup.sh | 43 - qpid/cpp/src/tests/sasl_version.cpp | 48 - qpid/cpp/src/tests/sender.cpp | 157 - qpid/cpp/src/tests/shlibtest.cpp | 34 - qpid/cpp/src/tests/ssl_test | 335 -- qpid/cpp/src/tests/store.py | 214 -- qpid/cpp/src/tests/test_store.cpp | 339 -- qpid/cpp/src/tests/test_tools.h | 106 - qpid/cpp/src/tests/topictest | 61 - qpid/cpp/src/tests/topictest.ps1 | 73 - qpid/cpp/src/tests/txjob.cpp | 102 - qpid/cpp/src/tests/txshift.cpp | 193 - qpid/cpp/src/tests/unit_test.cpp | 23 - qpid/cpp/src/tests/unit_test.h | 74 - .../src/tests/windows/DisableWin32ErrorWindows.cpp | 78 - qpid/cpp/src/versions.cmake | 51 - qpid/cpp/src/windows/QpiddBroker.cpp | 512 --- qpid/cpp/src/windows/SCM.cpp | 332 -- qpid/cpp/src/windows/SCM.h | 109 - qpid/cpp/src/windows/resources/qpid-icon.ico | Bin 52972 -> 0 bytes .../cpp/src/windows/resources/template-resource.rc | 122 - qpid/cpp/src/windows/resources/version-resource.h | 35 - 1413 files changed, 235713 deletions(-) delete mode 100644 qpid/cpp/src/CMakeLists.txt delete mode 100644 qpid/cpp/src/CMakeWinVersions.cmake delete mode 100644 qpid/cpp/src/QpidConfig.cmake.in delete mode 100644 qpid/cpp/src/QpidConfigVersion.cmake.in delete mode 100644 qpid/cpp/src/amqp.cmake delete mode 100755 qpid/cpp/src/check-abi delete mode 100644 qpid/cpp/src/config.h.cmake delete mode 100644 qpid/cpp/src/cppabi.cpp delete mode 100644 qpid/cpp/src/expand_types.cpp delete mode 100644 qpid/cpp/src/finddb.cmake delete mode 100644 qpid/cpp/src/legacystore.cmake delete mode 100644 qpid/cpp/src/libqpidmessaging-api-symbols.txt delete mode 100644 qpid/cpp/src/libqpidtypes-api-symbols.txt delete mode 100644 qpid/cpp/src/linearstore.cmake delete mode 100644 qpid/cpp/src/msvc.cmake delete mode 100644 qpid/cpp/src/posix/QpiddBroker.cpp delete mode 100755 qpid/cpp/src/prof delete mode 100644 qpid/cpp/src/qmf/Agent.cpp delete mode 100644 qpid/cpp/src/qmf/AgentEvent.cpp delete mode 100644 qpid/cpp/src/qmf/AgentEventImpl.h delete mode 100644 qpid/cpp/src/qmf/AgentImpl.h delete mode 100644 qpid/cpp/src/qmf/AgentSession.cpp delete mode 100644 qpid/cpp/src/qmf/AgentSessionImpl.h delete mode 100644 qpid/cpp/src/qmf/AgentSubscription.cpp delete mode 100644 qpid/cpp/src/qmf/AgentSubscription.h delete mode 100644 qpid/cpp/src/qmf/ConsoleEvent.cpp delete mode 100644 qpid/cpp/src/qmf/ConsoleEventImpl.h delete mode 100644 qpid/cpp/src/qmf/ConsoleSession.cpp delete mode 100644 qpid/cpp/src/qmf/ConsoleSessionImpl.h delete mode 100644 qpid/cpp/src/qmf/Data.cpp delete mode 100644 qpid/cpp/src/qmf/DataAddr.cpp delete mode 100644 qpid/cpp/src/qmf/DataAddrImpl.h delete mode 100644 qpid/cpp/src/qmf/DataImpl.h delete mode 100644 qpid/cpp/src/qmf/EventNotifierImpl.cpp delete mode 100644 qpid/cpp/src/qmf/EventNotifierImpl.h delete mode 100644 qpid/cpp/src/qmf/Expression.cpp delete mode 100644 qpid/cpp/src/qmf/Expression.h delete mode 100644 qpid/cpp/src/qmf/Hash.cpp delete mode 100644 qpid/cpp/src/qmf/Hash.h delete mode 100644 qpid/cpp/src/qmf/PosixEventNotifier.cpp delete mode 100644 qpid/cpp/src/qmf/PosixEventNotifierImpl.cpp delete mode 100644 qpid/cpp/src/qmf/PosixEventNotifierImpl.h delete mode 100644 qpid/cpp/src/qmf/PrivateImplRef.h delete mode 100644 qpid/cpp/src/qmf/Query.cpp delete mode 100644 qpid/cpp/src/qmf/QueryImpl.h delete mode 100644 qpid/cpp/src/qmf/Schema.cpp delete mode 100644 qpid/cpp/src/qmf/SchemaCache.cpp delete mode 100644 qpid/cpp/src/qmf/SchemaCache.h delete mode 100644 qpid/cpp/src/qmf/SchemaId.cpp delete mode 100644 qpid/cpp/src/qmf/SchemaIdImpl.h delete mode 100644 qpid/cpp/src/qmf/SchemaImpl.h delete mode 100644 qpid/cpp/src/qmf/SchemaMethod.cpp delete mode 100644 qpid/cpp/src/qmf/SchemaMethodImpl.h delete mode 100644 qpid/cpp/src/qmf/SchemaProperty.cpp delete mode 100644 qpid/cpp/src/qmf/SchemaPropertyImpl.h delete mode 100644 qpid/cpp/src/qmf/Subscription.cpp delete mode 100644 qpid/cpp/src/qmf/SubscriptionImpl.h delete mode 100644 qpid/cpp/src/qmf/agentCapability.h delete mode 100644 qpid/cpp/src/qmf/constants.cpp delete mode 100644 qpid/cpp/src/qmf/constants.h delete mode 100644 qpid/cpp/src/qmf/exceptions.cpp delete mode 100644 qpid/cpp/src/qmf2.pc.in delete mode 100644 qpid/cpp/src/qpid.linkmap delete mode 100644 qpid/cpp/src/qpid.pc.in delete mode 100644 qpid/cpp/src/qpid/AclHost.cpp delete mode 100644 qpid/cpp/src/qpid/AclHost.h delete mode 100644 qpid/cpp/src/qpid/Address.cpp delete mode 100755 qpid/cpp/src/qpid/Address.h delete mode 100644 qpid/cpp/src/qpid/BufferRef.h delete mode 100644 qpid/cpp/src/qpid/CommonImportExport.h delete mode 100644 qpid/cpp/src/qpid/DataDir.cpp delete mode 100644 qpid/cpp/src/qpid/DataDir.h delete mode 100644 qpid/cpp/src/qpid/DisableExceptionLogging.h delete mode 100644 qpid/cpp/src/qpid/Exception.cpp delete mode 100644 qpid/cpp/src/qpid/Exception.h delete mode 100644 qpid/cpp/src/qpid/InlineAllocator.h delete mode 100644 qpid/cpp/src/qpid/InlineVector.h delete mode 100644 qpid/cpp/src/qpid/Modules.cpp delete mode 100644 qpid/cpp/src/qpid/Modules.h delete mode 100644 qpid/cpp/src/qpid/Msg.h delete mode 100644 qpid/cpp/src/qpid/NullSaslClient.cpp delete mode 100644 qpid/cpp/src/qpid/NullSaslClient.h delete mode 100644 qpid/cpp/src/qpid/NullSaslServer.cpp delete mode 100644 qpid/cpp/src/qpid/NullSaslServer.h delete mode 100644 qpid/cpp/src/qpid/Options.cpp delete mode 100644 qpid/cpp/src/qpid/Options.h delete mode 100644 qpid/cpp/src/qpid/OptionsTemplates.h delete mode 100644 qpid/cpp/src/qpid/Plugin.cpp delete mode 100644 qpid/cpp/src/qpid/Plugin.h delete mode 100644 qpid/cpp/src/qpid/RangeSet.h delete mode 100644 qpid/cpp/src/qpid/RefCounted.h delete mode 100644 qpid/cpp/src/qpid/RefCountedBuffer.cpp delete mode 100644 qpid/cpp/src/qpid/RefCountedBuffer.h delete mode 100644 qpid/cpp/src/qpid/Sasl.h delete mode 100644 qpid/cpp/src/qpid/SaslFactory.cpp delete mode 100644 qpid/cpp/src/qpid/SaslFactory.h delete mode 100644 qpid/cpp/src/qpid/SaslServer.h delete mode 100644 qpid/cpp/src/qpid/Serializer.h delete mode 100644 qpid/cpp/src/qpid/SessionId.cpp delete mode 100644 qpid/cpp/src/qpid/SessionId.h delete mode 100644 qpid/cpp/src/qpid/SessionState.cpp delete mode 100644 qpid/cpp/src/qpid/SessionState.h delete mode 100644 qpid/cpp/src/qpid/SharedObject.h delete mode 100644 qpid/cpp/src/qpid/StringUtils.cpp delete mode 100644 qpid/cpp/src/qpid/StringUtils.h delete mode 100644 qpid/cpp/src/qpid/Url.cpp delete mode 100644 qpid/cpp/src/qpid/Url.h delete mode 100644 qpid/cpp/src/qpid/UrlArray.cpp delete mode 100644 qpid/cpp/src/qpid/UrlArray.h delete mode 100755 qpid/cpp/src/qpid/Version.h delete mode 100644 qpid/cpp/src/qpid/acl/Acl.cpp delete mode 100644 qpid/cpp/src/qpid/acl/Acl.h delete mode 100644 qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp delete mode 100644 qpid/cpp/src/qpid/acl/AclConnectionCounter.h delete mode 100644 qpid/cpp/src/qpid/acl/AclData.cpp delete mode 100644 qpid/cpp/src/qpid/acl/AclData.h delete mode 100644 qpid/cpp/src/qpid/acl/AclLexer.cpp delete mode 100644 qpid/cpp/src/qpid/acl/AclLexer.h delete mode 100644 qpid/cpp/src/qpid/acl/AclPlugin.cpp delete mode 100644 qpid/cpp/src/qpid/acl/AclReader.cpp delete mode 100644 qpid/cpp/src/qpid/acl/AclReader.h delete mode 100644 qpid/cpp/src/qpid/acl/AclResourceCounter.cpp delete mode 100644 qpid/cpp/src/qpid/acl/AclResourceCounter.h delete mode 100644 qpid/cpp/src/qpid/acl/AclTopicMatch.h delete mode 100644 qpid/cpp/src/qpid/acl/AclValidator.cpp delete mode 100644 qpid/cpp/src/qpid/acl/AclValidator.h delete mode 100644 qpid/cpp/src/qpid/acl/management-schema.xml delete mode 100644 qpid/cpp/src/qpid/amqp/CharSequence.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/CharSequence.h delete mode 100644 qpid/cpp/src/qpid/amqp/Codec.h delete mode 100644 qpid/cpp/src/qpid/amqp/Constructor.h delete mode 100644 qpid/cpp/src/qpid/amqp/DataBuilder.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/DataBuilder.h delete mode 100644 qpid/cpp/src/qpid/amqp/Decoder.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/Decoder.h delete mode 100644 qpid/cpp/src/qpid/amqp/Descriptor.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/Descriptor.h delete mode 100644 qpid/cpp/src/qpid/amqp/Encoder.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/Encoder.h delete mode 100644 qpid/cpp/src/qpid/amqp/ListBuilder.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/ListBuilder.h delete mode 100644 qpid/cpp/src/qpid/amqp/ListReader.h delete mode 100644 qpid/cpp/src/qpid/amqp/LoggingReader.h delete mode 100644 qpid/cpp/src/qpid/amqp/MapBuilder.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/MapBuilder.h delete mode 100644 qpid/cpp/src/qpid/amqp/MapEncoder.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/MapEncoder.h delete mode 100644 qpid/cpp/src/qpid/amqp/MapHandler.h delete mode 100644 qpid/cpp/src/qpid/amqp/MapReader.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/MapReader.h delete mode 100644 qpid/cpp/src/qpid/amqp/MapSizeCalculator.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/MapSizeCalculator.h delete mode 100644 qpid/cpp/src/qpid/amqp/MessageEncoder.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/MessageEncoder.h delete mode 100644 qpid/cpp/src/qpid/amqp/MessageId.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/MessageId.h delete mode 100644 qpid/cpp/src/qpid/amqp/MessageReader.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/MessageReader.h delete mode 100644 qpid/cpp/src/qpid/amqp/Reader.h delete mode 100644 qpid/cpp/src/qpid/amqp/Sasl.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/Sasl.h delete mode 100644 qpid/cpp/src/qpid/amqp/SaslClient.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/SaslClient.h delete mode 100644 qpid/cpp/src/qpid/amqp/SaslServer.cpp delete mode 100644 qpid/cpp/src/qpid/amqp/SaslServer.h delete mode 100644 qpid/cpp/src/qpid/amqp/descriptors.h delete mode 100644 qpid/cpp/src/qpid/amqp/typecodes.h delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/Codecs.cpp delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/Codecs.h delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/CodecsInternal.h delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/Connection.cpp delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/Connection.h delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/SessionHandler.cpp delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/SessionHandler.h delete mode 100644 qpid/cpp/src/qpid/assert.cpp delete mode 100644 qpid/cpp/src/qpid/assert.h delete mode 100644 qpid/cpp/src/qpid/broker/AclModule.h delete mode 100644 qpid/cpp/src/qpid/broker/AsyncCommandCallback.cpp delete mode 100644 qpid/cpp/src/qpid/broker/AsyncCommandCallback.h delete mode 100644 qpid/cpp/src/qpid/broker/AsyncCompletion.h delete mode 100644 qpid/cpp/src/qpid/broker/Bridge.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Bridge.h delete mode 100644 qpid/cpp/src/qpid/broker/Broker.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Broker.h delete mode 100644 qpid/cpp/src/qpid/broker/BrokerImportExport.h delete mode 100644 qpid/cpp/src/qpid/broker/BrokerObserver.h delete mode 100644 qpid/cpp/src/qpid/broker/BrokerObservers.h delete mode 100644 qpid/cpp/src/qpid/broker/BrokerOptions.h delete mode 100644 qpid/cpp/src/qpid/broker/Connection.h delete mode 100644 qpid/cpp/src/qpid/broker/ConnectionHandler.cpp delete mode 100644 qpid/cpp/src/qpid/broker/ConnectionHandler.h delete mode 100644 qpid/cpp/src/qpid/broker/ConnectionObserver.h delete mode 100644 qpid/cpp/src/qpid/broker/ConnectionObservers.h delete mode 100644 qpid/cpp/src/qpid/broker/Consumer.h delete mode 100644 qpid/cpp/src/qpid/broker/ConsumerFactory.h delete mode 100644 qpid/cpp/src/qpid/broker/Credit.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Credit.h delete mode 100644 qpid/cpp/src/qpid/broker/Daemon.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Daemon.h delete mode 100644 qpid/cpp/src/qpid/broker/Deliverable.h delete mode 100644 qpid/cpp/src/qpid/broker/DeliverableMessage.cpp delete mode 100644 qpid/cpp/src/qpid/broker/DeliverableMessage.h delete mode 100644 qpid/cpp/src/qpid/broker/DeliveryId.h delete mode 100644 qpid/cpp/src/qpid/broker/DeliveryRecord.cpp delete mode 100644 qpid/cpp/src/qpid/broker/DeliveryRecord.h delete mode 100644 qpid/cpp/src/qpid/broker/DirectExchange.cpp delete mode 100644 qpid/cpp/src/qpid/broker/DirectExchange.h delete mode 100644 qpid/cpp/src/qpid/broker/DtxAck.cpp delete mode 100644 qpid/cpp/src/qpid/broker/DtxAck.h delete mode 100644 qpid/cpp/src/qpid/broker/DtxBuffer.cpp delete mode 100644 qpid/cpp/src/qpid/broker/DtxBuffer.h delete mode 100644 qpid/cpp/src/qpid/broker/DtxManager.cpp delete mode 100644 qpid/cpp/src/qpid/broker/DtxManager.h delete mode 100644 qpid/cpp/src/qpid/broker/DtxTimeout.cpp delete mode 100644 qpid/cpp/src/qpid/broker/DtxTimeout.h delete mode 100644 qpid/cpp/src/qpid/broker/DtxWorkRecord.cpp delete mode 100644 qpid/cpp/src/qpid/broker/DtxWorkRecord.h delete mode 100644 qpid/cpp/src/qpid/broker/Exchange.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Exchange.h delete mode 100644 qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp delete mode 100644 qpid/cpp/src/qpid/broker/ExchangeRegistry.h delete mode 100644 qpid/cpp/src/qpid/broker/Fairshare.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Fairshare.h delete mode 100644 qpid/cpp/src/qpid/broker/FanOutExchange.cpp delete mode 100644 qpid/cpp/src/qpid/broker/FanOutExchange.h delete mode 100644 qpid/cpp/src/qpid/broker/FedOps.h delete mode 100644 qpid/cpp/src/qpid/broker/FifoDistributor.cpp delete mode 100644 qpid/cpp/src/qpid/broker/FifoDistributor.h delete mode 100644 qpid/cpp/src/qpid/broker/HandlerImpl.h delete mode 100644 qpid/cpp/src/qpid/broker/HeadersExchange.cpp delete mode 100644 qpid/cpp/src/qpid/broker/HeadersExchange.h delete mode 100644 qpid/cpp/src/qpid/broker/IndexedDeque.h delete mode 100644 qpid/cpp/src/qpid/broker/IngressCompletion.cpp delete mode 100644 qpid/cpp/src/qpid/broker/IngressCompletion.h delete mode 100644 qpid/cpp/src/qpid/broker/Link.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Link.h delete mode 100644 qpid/cpp/src/qpid/broker/LinkRegistry.cpp delete mode 100644 qpid/cpp/src/qpid/broker/LinkRegistry.h delete mode 100644 qpid/cpp/src/qpid/broker/LossyLvq.cpp delete mode 100644 qpid/cpp/src/qpid/broker/LossyLvq.h delete mode 100644 qpid/cpp/src/qpid/broker/LossyQueue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/LossyQueue.h delete mode 100644 qpid/cpp/src/qpid/broker/Lvq.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Lvq.h delete mode 100644 qpid/cpp/src/qpid/broker/Message.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Message.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageAdapter.cpp delete mode 100644 qpid/cpp/src/qpid/broker/MessageAdapter.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageBuilder.cpp delete mode 100644 qpid/cpp/src/qpid/broker/MessageBuilder.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageDeque.cpp delete mode 100644 qpid/cpp/src/qpid/broker/MessageDeque.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageDistributor.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageGroupManager.cpp delete mode 100644 qpid/cpp/src/qpid/broker/MessageGroupManager.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageInterceptor.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageMap.cpp delete mode 100644 qpid/cpp/src/qpid/broker/MessageMap.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageStore.h delete mode 100644 qpid/cpp/src/qpid/broker/MessageStoreModule.cpp delete mode 100644 qpid/cpp/src/qpid/broker/MessageStoreModule.h delete mode 100644 qpid/cpp/src/qpid/broker/Messages.h delete mode 100644 qpid/cpp/src/qpid/broker/NameGenerator.cpp delete mode 100644 qpid/cpp/src/qpid/broker/NameGenerator.h delete mode 100644 qpid/cpp/src/qpid/broker/NullMessageStore.cpp delete mode 100644 qpid/cpp/src/qpid/broker/NullMessageStore.h delete mode 100644 qpid/cpp/src/qpid/broker/ObjectFactory.cpp delete mode 100644 qpid/cpp/src/qpid/broker/ObjectFactory.h delete mode 100644 qpid/cpp/src/qpid/broker/Observers.h delete mode 100644 qpid/cpp/src/qpid/broker/OwnershipToken.h delete mode 100644 qpid/cpp/src/qpid/broker/PagedQueue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/PagedQueue.h delete mode 100644 qpid/cpp/src/qpid/broker/Persistable.h delete mode 100644 qpid/cpp/src/qpid/broker/PersistableConfig.h delete mode 100644 qpid/cpp/src/qpid/broker/PersistableExchange.h delete mode 100644 qpid/cpp/src/qpid/broker/PersistableMessage.cpp delete mode 100644 qpid/cpp/src/qpid/broker/PersistableMessage.h delete mode 100644 qpid/cpp/src/qpid/broker/PersistableObject.cpp delete mode 100644 qpid/cpp/src/qpid/broker/PersistableObject.h delete mode 100644 qpid/cpp/src/qpid/broker/PersistableQueue.h delete mode 100644 qpid/cpp/src/qpid/broker/PriorityQueue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/PriorityQueue.h delete mode 100644 qpid/cpp/src/qpid/broker/Protocol.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Protocol.h delete mode 100644 qpid/cpp/src/qpid/broker/Queue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Queue.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueBindings.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueBindings.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueCleaner.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueCleaner.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueCursor.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueCursor.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueDepth.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueDepth.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueFactory.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueFactory.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueFlowLimit.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueFlowLimit.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueListeners.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueListeners.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueObserver.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueObservers.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueRegistry.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueRegistry.h delete mode 100644 qpid/cpp/src/qpid/broker/QueueSettings.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueueSettings.h delete mode 100644 qpid/cpp/src/qpid/broker/QueuedMessage.cpp delete mode 100644 qpid/cpp/src/qpid/broker/QueuedMessage.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoverableConfig.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoverableExchange.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoverableMessage.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoverableQueue.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoverableTransaction.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoveredDequeue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/RecoveredDequeue.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoveredEnqueue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/RecoveredEnqueue.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoveryManager.h delete mode 100644 qpid/cpp/src/qpid/broker/RecoveryManagerImpl.cpp delete mode 100644 qpid/cpp/src/qpid/broker/RecoveryManagerImpl.h delete mode 100644 qpid/cpp/src/qpid/broker/RetryList.cpp delete mode 100644 qpid/cpp/src/qpid/broker/RetryList.h delete mode 100644 qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SaslAuthenticator.h delete mode 100644 qpid/cpp/src/qpid/broker/SecureConnection.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SecureConnection.h delete mode 100644 qpid/cpp/src/qpid/broker/Selector.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Selector.h delete mode 100644 qpid/cpp/src/qpid/broker/SelectorExpression.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SelectorExpression.h delete mode 100644 qpid/cpp/src/qpid/broker/SelectorToken.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SelectorToken.h delete mode 100644 qpid/cpp/src/qpid/broker/SelectorValue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SelectorValue.h delete mode 100644 qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SelfDestructQueue.h delete mode 100644 qpid/cpp/src/qpid/broker/SemanticState.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SemanticState.h delete mode 100644 qpid/cpp/src/qpid/broker/SessionAdapter.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SessionAdapter.h delete mode 100644 qpid/cpp/src/qpid/broker/SessionContext.h delete mode 100644 qpid/cpp/src/qpid/broker/SessionHandler.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SessionHandler.h delete mode 100644 qpid/cpp/src/qpid/broker/SessionHandlerObserver.h delete mode 100644 qpid/cpp/src/qpid/broker/SessionManager.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SessionManager.h delete mode 100644 qpid/cpp/src/qpid/broker/SessionOutputException.h delete mode 100644 qpid/cpp/src/qpid/broker/SessionState.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SessionState.h delete mode 100644 qpid/cpp/src/qpid/broker/SignalHandler.cpp delete mode 100644 qpid/cpp/src/qpid/broker/SignalHandler.h delete mode 100644 qpid/cpp/src/qpid/broker/System.cpp delete mode 100644 qpid/cpp/src/qpid/broker/System.h delete mode 100644 qpid/cpp/src/qpid/broker/ThresholdAlerts.cpp delete mode 100644 qpid/cpp/src/qpid/broker/ThresholdAlerts.h delete mode 100644 qpid/cpp/src/qpid/broker/TopicExchange.cpp delete mode 100644 qpid/cpp/src/qpid/broker/TopicExchange.h delete mode 100644 qpid/cpp/src/qpid/broker/TopicKeyNode.h delete mode 100644 qpid/cpp/src/qpid/broker/TransactionObserver.h delete mode 100644 qpid/cpp/src/qpid/broker/TransactionalStore.h delete mode 100644 qpid/cpp/src/qpid/broker/TxAccept.cpp delete mode 100644 qpid/cpp/src/qpid/broker/TxAccept.h delete mode 100644 qpid/cpp/src/qpid/broker/TxBuffer.cpp delete mode 100644 qpid/cpp/src/qpid/broker/TxBuffer.h delete mode 100644 qpid/cpp/src/qpid/broker/TxDequeue.cpp delete mode 100644 qpid/cpp/src/qpid/broker/TxDequeue.h delete mode 100644 qpid/cpp/src/qpid/broker/TxOp.h delete mode 100644 qpid/cpp/src/qpid/broker/Vhost.cpp delete mode 100644 qpid/cpp/src/qpid/broker/Vhost.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Authorise.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Authorise.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/BrokerContext.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/BrokerContext.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Connection.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Connection.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/DataReader.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/DataReader.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Domain.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Domain.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Exception.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Exception.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Filter.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Filter.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Header.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Header.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Incoming.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Incoming.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Interconnect.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Interconnect.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Interconnects.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Interconnects.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ManagedConnection.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ManagedConnection.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ManagedIncomingLink.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ManagedIncomingLink.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ManagedOutgoingLink.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ManagedOutgoingLink.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ManagedSession.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ManagedSession.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Message.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Message.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/NodePolicy.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/NodePolicy.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/NodeProperties.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/NodeProperties.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Outgoing.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Relay.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Relay.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Sasl.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Sasl.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/SaslClient.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Session.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Session.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Topic.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Topic.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Translation.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp/Translation.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp_0_10/Connection.h delete mode 100644 qpid/cpp/src/qpid/broker/amqp_0_10/MessageTransfer.cpp delete mode 100644 qpid/cpp/src/qpid/broker/amqp_0_10/MessageTransfer.h delete mode 100644 qpid/cpp/src/qpid/broker/management-schema.xml delete mode 100644 qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp delete mode 100644 qpid/cpp/src/qpid/broker/posix/SocketFDPlugin.cpp delete mode 100644 qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp delete mode 100644 qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp delete mode 100644 qpid/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp delete mode 100644 qpid/cpp/src/qpid/client/AsyncSession.h delete mode 100644 qpid/cpp/src/qpid/client/Bounds.cpp delete mode 100644 qpid/cpp/src/qpid/client/Bounds.h delete mode 100644 qpid/cpp/src/qpid/client/ChainableFrameHandler.h delete mode 100644 qpid/cpp/src/qpid/client/ClientImportExport.h delete mode 100644 qpid/cpp/src/qpid/client/Completion.cpp delete mode 100644 qpid/cpp/src/qpid/client/Completion.h delete mode 100644 qpid/cpp/src/qpid/client/CompletionImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/CompletionImpl.h delete mode 100644 qpid/cpp/src/qpid/client/Connection.cpp delete mode 100644 qpid/cpp/src/qpid/client/Connection.h delete mode 100644 qpid/cpp/src/qpid/client/ConnectionAccess.h delete mode 100644 qpid/cpp/src/qpid/client/ConnectionHandler.cpp delete mode 100644 qpid/cpp/src/qpid/client/ConnectionHandler.h delete mode 100644 qpid/cpp/src/qpid/client/ConnectionImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/ConnectionImpl.h delete mode 100644 qpid/cpp/src/qpid/client/ConnectionSettings.cpp delete mode 100644 qpid/cpp/src/qpid/client/ConnectionSettings.h delete mode 100644 qpid/cpp/src/qpid/client/Connector.cpp delete mode 100644 qpid/cpp/src/qpid/client/Connector.h delete mode 100644 qpid/cpp/src/qpid/client/Demux.cpp delete mode 100644 qpid/cpp/src/qpid/client/Demux.h delete mode 100644 qpid/cpp/src/qpid/client/Dispatcher.cpp delete mode 100644 qpid/cpp/src/qpid/client/Dispatcher.h delete mode 100644 qpid/cpp/src/qpid/client/Execution.h delete mode 100644 qpid/cpp/src/qpid/client/FailoverListener.cpp delete mode 100644 qpid/cpp/src/qpid/client/FailoverListener.h delete mode 100644 qpid/cpp/src/qpid/client/FailoverManager.cpp delete mode 100644 qpid/cpp/src/qpid/client/FailoverManager.h delete mode 100644 qpid/cpp/src/qpid/client/FlowControl.h delete mode 100644 qpid/cpp/src/qpid/client/Future.cpp delete mode 100644 qpid/cpp/src/qpid/client/Future.h delete mode 100644 qpid/cpp/src/qpid/client/FutureCompletion.cpp delete mode 100644 qpid/cpp/src/qpid/client/FutureCompletion.h delete mode 100644 qpid/cpp/src/qpid/client/FutureResult.cpp delete mode 100644 qpid/cpp/src/qpid/client/FutureResult.h delete mode 100644 qpid/cpp/src/qpid/client/Handle.h delete mode 100644 qpid/cpp/src/qpid/client/LoadPlugins.cpp delete mode 100644 qpid/cpp/src/qpid/client/LoadPlugins.h delete mode 100644 qpid/cpp/src/qpid/client/LocalQueue.cpp delete mode 100644 qpid/cpp/src/qpid/client/LocalQueue.h delete mode 100644 qpid/cpp/src/qpid/client/LocalQueueImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/LocalQueueImpl.h delete mode 100644 qpid/cpp/src/qpid/client/Message.cpp delete mode 100644 qpid/cpp/src/qpid/client/Message.h delete mode 100644 qpid/cpp/src/qpid/client/MessageImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/MessageImpl.h delete mode 100644 qpid/cpp/src/qpid/client/MessageListener.cpp delete mode 100644 qpid/cpp/src/qpid/client/MessageListener.h delete mode 100644 qpid/cpp/src/qpid/client/MessageReplayTracker.cpp delete mode 100644 qpid/cpp/src/qpid/client/MessageReplayTracker.h delete mode 100644 qpid/cpp/src/qpid/client/PrivateImplRef.h delete mode 100644 qpid/cpp/src/qpid/client/QueueOptions.cpp delete mode 100644 qpid/cpp/src/qpid/client/QueueOptions.h delete mode 100644 qpid/cpp/src/qpid/client/RdmaConnector.cpp delete mode 100644 qpid/cpp/src/qpid/client/Results.cpp delete mode 100644 qpid/cpp/src/qpid/client/Results.h delete mode 100644 qpid/cpp/src/qpid/client/Session.h delete mode 100644 qpid/cpp/src/qpid/client/SessionBase_0_10.cpp delete mode 100644 qpid/cpp/src/qpid/client/SessionBase_0_10.h delete mode 100644 qpid/cpp/src/qpid/client/SessionBase_0_10Access.h delete mode 100644 qpid/cpp/src/qpid/client/SessionImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/SessionImpl.h delete mode 100644 qpid/cpp/src/qpid/client/SslConnector.cpp delete mode 100644 qpid/cpp/src/qpid/client/StateManager.cpp delete mode 100644 qpid/cpp/src/qpid/client/StateManager.h delete mode 100644 qpid/cpp/src/qpid/client/Subscription.cpp delete mode 100644 qpid/cpp/src/qpid/client/Subscription.h delete mode 100644 qpid/cpp/src/qpid/client/SubscriptionImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/SubscriptionImpl.h delete mode 100644 qpid/cpp/src/qpid/client/SubscriptionManager.cpp delete mode 100644 qpid/cpp/src/qpid/client/SubscriptionManager.h delete mode 100644 qpid/cpp/src/qpid/client/SubscriptionManagerImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/SubscriptionManagerImpl.h delete mode 100644 qpid/cpp/src/qpid/client/SubscriptionSettings.h delete mode 100644 qpid/cpp/src/qpid/client/TCPConnector.cpp delete mode 100644 qpid/cpp/src/qpid/client/TCPConnector.h delete mode 100644 qpid/cpp/src/qpid/client/TypedResult.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/AcceptTracker.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/MessageSink.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/MessageSource.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.h delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp delete mode 100644 qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.h delete mode 100644 qpid/cpp/src/qpid/client/ssl.h delete mode 100644 qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp delete mode 100644 qpid/cpp/src/qpid/client/windows/SaslFactory.cpp delete mode 100644 qpid/cpp/src/qpid/client/windows/SslConnector.cpp delete mode 100644 qpid/cpp/src/qpid/framing/AMQBody.cpp delete mode 100644 qpid/cpp/src/qpid/framing/AMQBody.h delete mode 100644 qpid/cpp/src/qpid/framing/AMQContentBody.cpp delete mode 100644 qpid/cpp/src/qpid/framing/AMQContentBody.h delete mode 100644 qpid/cpp/src/qpid/framing/AMQDataBlock.h delete mode 100644 qpid/cpp/src/qpid/framing/AMQFrame.cpp delete mode 100644 qpid/cpp/src/qpid/framing/AMQFrame.h delete mode 100644 qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp delete mode 100644 qpid/cpp/src/qpid/framing/AMQHeaderBody.h delete mode 100644 qpid/cpp/src/qpid/framing/AMQHeartbeatBody.cpp delete mode 100644 qpid/cpp/src/qpid/framing/AMQHeartbeatBody.h delete mode 100644 qpid/cpp/src/qpid/framing/AMQMethodBody.cpp delete mode 100644 qpid/cpp/src/qpid/framing/AMQMethodBody.h delete mode 100644 qpid/cpp/src/qpid/framing/AMQP_HighestVersion.h delete mode 100644 qpid/cpp/src/qpid/framing/AccumulatedAck.cpp delete mode 100644 qpid/cpp/src/qpid/framing/AccumulatedAck.h delete mode 100644 qpid/cpp/src/qpid/framing/Array.cpp delete mode 100644 qpid/cpp/src/qpid/framing/Array.h delete mode 100644 qpid/cpp/src/qpid/framing/Blob.cpp delete mode 100644 qpid/cpp/src/qpid/framing/Blob.h delete mode 100644 qpid/cpp/src/qpid/framing/BodyFactory.h delete mode 100644 qpid/cpp/src/qpid/framing/Buffer.cpp delete mode 100644 qpid/cpp/src/qpid/framing/Buffer.h delete mode 100644 qpid/cpp/src/qpid/framing/BufferTypes.h delete mode 100644 qpid/cpp/src/qpid/framing/ChannelHandler.h delete mode 100644 qpid/cpp/src/qpid/framing/Endian.h delete mode 100644 qpid/cpp/src/qpid/framing/FieldTable.cpp delete mode 100644 qpid/cpp/src/qpid/framing/FieldTable.h delete mode 100644 qpid/cpp/src/qpid/framing/FieldValue.cpp delete mode 100644 qpid/cpp/src/qpid/framing/FieldValue.h delete mode 100644 qpid/cpp/src/qpid/framing/FrameDecoder.cpp delete mode 100644 qpid/cpp/src/qpid/framing/FrameDecoder.h delete mode 100644 qpid/cpp/src/qpid/framing/FrameDefaultVisitor.h delete mode 100644 qpid/cpp/src/qpid/framing/FrameHandler.h delete mode 100644 qpid/cpp/src/qpid/framing/FrameSet.cpp delete mode 100644 qpid/cpp/src/qpid/framing/FrameSet.h delete mode 100644 qpid/cpp/src/qpid/framing/Handler.h delete mode 100644 qpid/cpp/src/qpid/framing/HeaderProperties.h delete mode 100644 qpid/cpp/src/qpid/framing/InitiationHandler.cpp delete mode 100644 qpid/cpp/src/qpid/framing/InitiationHandler.h delete mode 100644 qpid/cpp/src/qpid/framing/InputHandler.h delete mode 100644 qpid/cpp/src/qpid/framing/Invoker.h delete mode 100644 qpid/cpp/src/qpid/framing/IsInSequenceSet.h delete mode 100644 qpid/cpp/src/qpid/framing/List.cpp delete mode 100644 qpid/cpp/src/qpid/framing/List.h delete mode 100644 qpid/cpp/src/qpid/framing/MethodBodyFactory.h delete mode 100644 qpid/cpp/src/qpid/framing/MethodContent.h delete mode 100644 qpid/cpp/src/qpid/framing/ModelMethod.h delete mode 100644 qpid/cpp/src/qpid/framing/ProtocolInitiation.cpp delete mode 100644 qpid/cpp/src/qpid/framing/ProtocolInitiation.h delete mode 100644 qpid/cpp/src/qpid/framing/ProtocolVersion.cpp delete mode 100644 qpid/cpp/src/qpid/framing/ProtocolVersion.h delete mode 100644 qpid/cpp/src/qpid/framing/Proxy.cpp delete mode 100644 qpid/cpp/src/qpid/framing/Proxy.h delete mode 100644 qpid/cpp/src/qpid/framing/ResizableBuffer.h delete mode 100644 qpid/cpp/src/qpid/framing/SendContent.cpp delete mode 100644 qpid/cpp/src/qpid/framing/SendContent.h delete mode 100644 qpid/cpp/src/qpid/framing/SequenceNumber.cpp delete mode 100644 qpid/cpp/src/qpid/framing/SequenceNumber.h delete mode 100644 qpid/cpp/src/qpid/framing/SequenceNumberSet.cpp delete mode 100644 qpid/cpp/src/qpid/framing/SequenceNumberSet.h delete mode 100644 qpid/cpp/src/qpid/framing/SequenceSet.cpp delete mode 100644 qpid/cpp/src/qpid/framing/SequenceSet.h delete mode 100644 qpid/cpp/src/qpid/framing/StructHelper.h delete mode 100644 qpid/cpp/src/qpid/framing/TransferContent.cpp delete mode 100644 qpid/cpp/src/qpid/framing/TransferContent.h delete mode 100644 qpid/cpp/src/qpid/framing/TypeFilter.h delete mode 100644 qpid/cpp/src/qpid/framing/Uuid.cpp delete mode 100644 qpid/cpp/src/qpid/framing/Uuid.h delete mode 100644 qpid/cpp/src/qpid/framing/amqp_framing.h delete mode 100644 qpid/cpp/src/qpid/framing/amqp_types.h delete mode 100644 qpid/cpp/src/qpid/framing/amqp_types_full.h delete mode 100644 qpid/cpp/src/qpid/framing/frame_functors.h delete mode 100644 qpid/cpp/src/qpid/framing/variant.h delete mode 100644 qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h delete mode 100644 qpid/cpp/src/qpid/ha/Backup.cpp delete mode 100644 qpid/cpp/src/qpid/ha/Backup.h delete mode 100644 qpid/cpp/src/qpid/ha/BackupConnectionExcluder.h delete mode 100644 qpid/cpp/src/qpid/ha/BrokerInfo.cpp delete mode 100644 qpid/cpp/src/qpid/ha/BrokerInfo.h delete mode 100644 qpid/cpp/src/qpid/ha/BrokerReplicator.cpp delete mode 100644 qpid/cpp/src/qpid/ha/BrokerReplicator.h delete mode 100644 qpid/cpp/src/qpid/ha/ConnectionObserver.cpp delete mode 100644 qpid/cpp/src/qpid/ha/ConnectionObserver.h delete mode 100644 qpid/cpp/src/qpid/ha/Event.cpp delete mode 100644 qpid/cpp/src/qpid/ha/Event.h delete mode 100644 qpid/cpp/src/qpid/ha/FailoverExchange.cpp delete mode 100644 qpid/cpp/src/qpid/ha/FailoverExchange.h delete mode 100644 qpid/cpp/src/qpid/ha/HaBroker.cpp delete mode 100644 qpid/cpp/src/qpid/ha/HaBroker.h delete mode 100644 qpid/cpp/src/qpid/ha/HaPlugin.cpp delete mode 100644 qpid/cpp/src/qpid/ha/IdSetter.h delete mode 100644 qpid/cpp/src/qpid/ha/LogPrefix.cpp delete mode 100644 qpid/cpp/src/qpid/ha/LogPrefix.h delete mode 100644 qpid/cpp/src/qpid/ha/Membership.cpp delete mode 100644 qpid/cpp/src/qpid/ha/Membership.h delete mode 100644 qpid/cpp/src/qpid/ha/Primary.cpp delete mode 100644 qpid/cpp/src/qpid/ha/Primary.h delete mode 100644 qpid/cpp/src/qpid/ha/PrimaryQueueLimits.h delete mode 100644 qpid/cpp/src/qpid/ha/QueueGuard.cpp delete mode 100644 qpid/cpp/src/qpid/ha/QueueGuard.h delete mode 100644 qpid/cpp/src/qpid/ha/QueueReplicator.cpp delete mode 100644 qpid/cpp/src/qpid/ha/QueueReplicator.h delete mode 100644 qpid/cpp/src/qpid/ha/QueueSnapshot.h delete mode 100644 qpid/cpp/src/qpid/ha/README.h delete mode 100644 qpid/cpp/src/qpid/ha/RemoteBackup.cpp delete mode 100644 qpid/cpp/src/qpid/ha/RemoteBackup.h delete mode 100644 qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp delete mode 100644 qpid/cpp/src/qpid/ha/ReplicatingSubscription.h delete mode 100644 qpid/cpp/src/qpid/ha/ReplicationTest.cpp delete mode 100644 qpid/cpp/src/qpid/ha/ReplicationTest.h delete mode 100644 qpid/cpp/src/qpid/ha/Role.h delete mode 100644 qpid/cpp/src/qpid/ha/Settings.h delete mode 100644 qpid/cpp/src/qpid/ha/StandAlone.h delete mode 100644 qpid/cpp/src/qpid/ha/StatusCheck.cpp delete mode 100644 qpid/cpp/src/qpid/ha/StatusCheck.h delete mode 100644 qpid/cpp/src/qpid/ha/hash.h delete mode 100644 qpid/cpp/src/qpid/ha/management-schema.xml delete mode 100644 qpid/cpp/src/qpid/ha/types.cpp delete mode 100644 qpid/cpp/src/qpid/ha/types.h delete mode 100644 qpid/cpp/src/qpid/legacystore/BindingDbt.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/BindingDbt.h delete mode 100644 qpid/cpp/src/qpid/legacystore/BufferValue.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/BufferValue.h delete mode 100644 qpid/cpp/src/qpid/legacystore/Cursor.h delete mode 100644 qpid/cpp/src/qpid/legacystore/DataTokenImpl.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/DataTokenImpl.h delete mode 100644 qpid/cpp/src/qpid/legacystore/IdDbt.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/IdDbt.h delete mode 100644 qpid/cpp/src/qpid/legacystore/IdSequence.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/IdSequence.h delete mode 100644 qpid/cpp/src/qpid/legacystore/JournalImpl.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/JournalImpl.h delete mode 100644 qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/MessageStoreImpl.h delete mode 100644 qpid/cpp/src/qpid/legacystore/PreparedTransaction.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/PreparedTransaction.h delete mode 100644 qpid/cpp/src/qpid/legacystore/StoreException.h delete mode 100644 qpid/cpp/src/qpid/legacystore/StorePlugin.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/TxnCtxt.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/TxnCtxt.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/aio.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/aio.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/aio_callback.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/cvar.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/cvar.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/data_tok.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/data_tok.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/deq_hdr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/enq_hdr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/enq_map.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/enq_map.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/enums.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/fcntl.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/fcntl.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/file_hdr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jcntl.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jcntl.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jdir.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jdir.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jerrno.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jerrno.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jexception.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jexception.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jinf.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jinf.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jrec.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/jrec.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/lp_map.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/lp_map.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/pmgr.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/pmgr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rcvdat.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rec_hdr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rec_tail.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rfc.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rfc.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rmgr.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rmgr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rrfc.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/rrfc.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/slock.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/slock.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/smutex.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/smutex.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/time_ns.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/time_ns.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/txn_hdr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/txn_map.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/txn_map.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/wmgr.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/wmgr.h delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/wrfc.cpp delete mode 100644 qpid/cpp/src/qpid/legacystore/jrnl/wrfc.h delete mode 100644 qpid/cpp/src/qpid/legacystore/management-schema.xml delete mode 100644 qpid/cpp/src/qpid/linearstore/BindingDbt.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/BindingDbt.h delete mode 100644 qpid/cpp/src/qpid/linearstore/BufferValue.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/BufferValue.h delete mode 100644 qpid/cpp/src/qpid/linearstore/Cursor.h delete mode 100644 qpid/cpp/src/qpid/linearstore/DataTokenImpl.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/DataTokenImpl.h delete mode 100644 qpid/cpp/src/qpid/linearstore/ISSUES delete mode 100644 qpid/cpp/src/qpid/linearstore/IdDbt.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/IdDbt.h delete mode 100644 qpid/cpp/src/qpid/linearstore/IdSequence.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/IdSequence.h delete mode 100644 qpid/cpp/src/qpid/linearstore/JournalImpl.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/JournalImpl.h delete mode 100644 qpid/cpp/src/qpid/linearstore/JournalLogImpl.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/JournalLogImpl.h delete mode 100644 qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h delete mode 100644 qpid/cpp/src/qpid/linearstore/PreparedTransaction.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/PreparedTransaction.h delete mode 100644 qpid/cpp/src/qpid/linearstore/StoreException.h delete mode 100644 qpid/cpp/src/qpid/linearstore/StorePlugin.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/TxnCtxt.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/AtomicCounter.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/Checksum.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/Checksum.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolTypes.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/JournalFile.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/JournalLog.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/JournalLog.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/aio.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/aio_callback.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/data_tok.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/data_tok.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/deq_rec.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/enq_map.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/enq_map.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/enq_rec.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/enums.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jcfg.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jcntl.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jdir.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jdir.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jerrno.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jexception.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jexception.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/jrec.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/pmgr.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/pmgr.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/slock.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/smutex.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/time_ns.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/time_ns.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/txn_map.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/txn_map.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/txn_rec.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/deq_hdr.c delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/deq_hdr.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/enq_hdr.c delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/enq_hdr.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/file_hdr.c delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/file_hdr.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/rec_hdr.c delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/rec_hdr.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/rec_tail.c delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/rec_tail.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/txn_hdr.c delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/utils/txn_hdr.h delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp delete mode 100644 qpid/cpp/src/qpid/linearstore/journal/wmgr.h delete mode 100644 qpid/cpp/src/qpid/linearstore/management-schema.xml delete mode 100644 qpid/cpp/src/qpid/log/Helpers.h delete mode 100644 qpid/cpp/src/qpid/log/Logger.cpp delete mode 100644 qpid/cpp/src/qpid/log/Logger.h delete mode 100644 qpid/cpp/src/qpid/log/Options.cpp delete mode 100644 qpid/cpp/src/qpid/log/Options.h delete mode 100644 qpid/cpp/src/qpid/log/OstreamOutput.cpp delete mode 100644 qpid/cpp/src/qpid/log/OstreamOutput.h delete mode 100644 qpid/cpp/src/qpid/log/Selector.cpp delete mode 100644 qpid/cpp/src/qpid/log/Selector.h delete mode 100644 qpid/cpp/src/qpid/log/SinkOptions.h delete mode 100644 qpid/cpp/src/qpid/log/Statement.cpp delete mode 100644 qpid/cpp/src/qpid/log/Statement.h delete mode 100644 qpid/cpp/src/qpid/log/posix/SinkOptions.cpp delete mode 100644 qpid/cpp/src/qpid/log/posix/SinkOptions.h delete mode 100644 qpid/cpp/src/qpid/log/windows/SinkOptions.cpp delete mode 100644 qpid/cpp/src/qpid/log/windows/SinkOptions.h delete mode 100644 qpid/cpp/src/qpid/management/Args.h delete mode 100644 qpid/cpp/src/qpid/management/Buffer.cpp delete mode 100644 qpid/cpp/src/qpid/management/Buffer.h delete mode 100644 qpid/cpp/src/qpid/management/ConnectionSettings.cpp delete mode 100644 qpid/cpp/src/qpid/management/ConnectionSettings.h delete mode 100644 qpid/cpp/src/qpid/management/Manageable.cpp delete mode 100644 qpid/cpp/src/qpid/management/Manageable.h delete mode 100644 qpid/cpp/src/qpid/management/ManagementAgent.cpp delete mode 100644 qpid/cpp/src/qpid/management/ManagementAgent.h delete mode 100644 qpid/cpp/src/qpid/management/ManagementDirectExchange.cpp delete mode 100644 qpid/cpp/src/qpid/management/ManagementDirectExchange.h delete mode 100644 qpid/cpp/src/qpid/management/ManagementEvent.h delete mode 100644 qpid/cpp/src/qpid/management/ManagementObject.cpp delete mode 100644 qpid/cpp/src/qpid/management/ManagementObject.h delete mode 100644 qpid/cpp/src/qpid/management/ManagementTopicExchange.cpp delete mode 100644 qpid/cpp/src/qpid/management/ManagementTopicExchange.h delete mode 100644 qpid/cpp/src/qpid/management/Mutex.cpp delete mode 100644 qpid/cpp/src/qpid/management/Mutex.h delete mode 100644 qpid/cpp/src/qpid/memory.h delete mode 100644 qpid/cpp/src/qpid/messaging/Address.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/AddressImpl.h delete mode 100644 qpid/cpp/src/qpid/messaging/AddressParser.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/AddressParser.h delete mode 100644 qpid/cpp/src/qpid/messaging/Connection.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/ConnectionImpl.h delete mode 100644 qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/ConnectionOptions.h delete mode 100644 qpid/cpp/src/qpid/messaging/Duration.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/FailoverUpdates.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/Logger.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/Message.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/MessageImpl.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/MessageImpl.h delete mode 100644 qpid/cpp/src/qpid/messaging/Message_io.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/PrivateImplRef.h delete mode 100644 qpid/cpp/src/qpid/messaging/ProtocolRegistry.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/ProtocolRegistry.h delete mode 100644 qpid/cpp/src/qpid/messaging/Receiver.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/ReceiverImpl.h delete mode 100644 qpid/cpp/src/qpid/messaging/Sender.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/SenderImpl.h delete mode 100644 qpid/cpp/src/qpid/messaging/Session.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/SessionImpl.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/DriverImpl.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/DriverImpl.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/PnData.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/PnData.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/Sasl.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SenderContext.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SenderHandle.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SessionContext.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SessionHandle.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/SslTransport.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/TcpTransport.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/Transaction.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/Transaction.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/Transport.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/Transport.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/TransportContext.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/util.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/util.h delete mode 100644 qpid/cpp/src/qpid/messaging/amqp/windows/SslTransport.cpp delete mode 100644 qpid/cpp/src/qpid/messaging/exceptions.cpp delete mode 100644 qpid/cpp/src/qpid/pointer_to_other.h delete mode 100644 qpid/cpp/src/qpid/ptr_map.h delete mode 100644 qpid/cpp/src/qpid/store/CMakeLists.txt delete mode 100644 qpid/cpp/src/qpid/store/MessageStorePlugin.cpp delete mode 100644 qpid/cpp/src/qpid/store/MessageStorePlugin.h delete mode 100644 qpid/cpp/src/qpid/store/StorageProvider.h delete mode 100644 qpid/cpp/src/qpid/store/StoreException.h delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/Log.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/Log.h delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/Lsn.h delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/MessageLog.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/MessageLog.h delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/Messages.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/Messages.h delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/Transaction.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/Transaction.h delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/DatabaseConnection.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/DatabaseConnection.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/Exception.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/MSSqlProvider.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/MessageMapRecordset.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/MessageMapRecordset.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/Recordset.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/Recordset.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/State.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/State.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/TplRecordset.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/TplRecordset.h delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/VariantHelper.cpp delete mode 100644 qpid/cpp/src/qpid/store/ms-sql/VariantHelper.h delete mode 100644 qpid/cpp/src/qpid/sys/AggregateOutput.cpp delete mode 100644 qpid/cpp/src/qpid/sys/AggregateOutput.h delete mode 100644 qpid/cpp/src/qpid/sys/AsynchIO.h delete mode 100644 qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp delete mode 100644 qpid/cpp/src/qpid/sys/AsynchIOHandler.h delete mode 100644 qpid/cpp/src/qpid/sys/AtomicCount.h delete mode 100644 qpid/cpp/src/qpid/sys/AtomicValue.h delete mode 100644 qpid/cpp/src/qpid/sys/AtomicValue_gcc.h delete mode 100644 qpid/cpp/src/qpid/sys/AtomicValue_mutex.h delete mode 100644 qpid/cpp/src/qpid/sys/BlockingQueue.h delete mode 100644 qpid/cpp/src/qpid/sys/Codec.h delete mode 100644 qpid/cpp/src/qpid/sys/Condition.h delete mode 100644 qpid/cpp/src/qpid/sys/ConnectionCodec.h delete mode 100644 qpid/cpp/src/qpid/sys/ConnectionInputHandler.h delete mode 100644 qpid/cpp/src/qpid/sys/ConnectionInputHandlerFactory.h delete mode 100644 qpid/cpp/src/qpid/sys/ConnectionOutputHandler.h delete mode 100644 qpid/cpp/src/qpid/sys/CopyOnWriteArray.h delete mode 100644 qpid/cpp/src/qpid/sys/DeletionManager.h delete mode 100644 qpid/cpp/src/qpid/sys/DispatchHandle.cpp delete mode 100644 qpid/cpp/src/qpid/sys/DispatchHandle.h delete mode 100644 qpid/cpp/src/qpid/sys/Dispatcher.cpp delete mode 100644 qpid/cpp/src/qpid/sys/Dispatcher.h delete mode 100644 qpid/cpp/src/qpid/sys/ExceptionHolder.h delete mode 100755 qpid/cpp/src/qpid/sys/FileSysDir.h delete mode 100644 qpid/cpp/src/qpid/sys/Fork.h delete mode 100644 qpid/cpp/src/qpid/sys/FreeBSD/uuid.cpp delete mode 100644 qpid/cpp/src/qpid/sys/IOHandle.h delete mode 100644 qpid/cpp/src/qpid/sys/LockFile.h delete mode 100644 qpid/cpp/src/qpid/sys/LockPtr.h delete mode 100644 qpid/cpp/src/qpid/sys/MemStat.cpp delete mode 100644 qpid/cpp/src/qpid/sys/MemStat.h delete mode 100644 qpid/cpp/src/qpid/sys/MemoryMappedFile.h delete mode 100644 qpid/cpp/src/qpid/sys/Monitor.h delete mode 100644 qpid/cpp/src/qpid/sys/Mutex.h delete mode 100644 qpid/cpp/src/qpid/sys/OutputControl.h delete mode 100644 qpid/cpp/src/qpid/sys/OutputTask.h delete mode 100644 qpid/cpp/src/qpid/sys/Path.h delete mode 100755 qpid/cpp/src/qpid/sys/PipeHandle.h delete mode 100644 qpid/cpp/src/qpid/sys/PollableCondition.h delete mode 100644 qpid/cpp/src/qpid/sys/PollableQueue.h delete mode 100644 qpid/cpp/src/qpid/sys/Poller.h delete mode 100644 qpid/cpp/src/qpid/sys/Probes.h delete mode 100644 qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp delete mode 100644 qpid/cpp/src/qpid/sys/Runnable.cpp delete mode 100644 qpid/cpp/src/qpid/sys/Runnable.h delete mode 100644 qpid/cpp/src/qpid/sys/ScopedIncrement.h delete mode 100644 qpid/cpp/src/qpid/sys/SecurityLayer.h delete mode 100644 qpid/cpp/src/qpid/sys/SecuritySettings.h delete mode 100644 qpid/cpp/src/qpid/sys/Semaphore.h delete mode 100644 qpid/cpp/src/qpid/sys/Shlib.cpp delete mode 100644 qpid/cpp/src/qpid/sys/Shlib.h delete mode 100644 qpid/cpp/src/qpid/sys/ShutdownHandler.h delete mode 100644 qpid/cpp/src/qpid/sys/Socket.h delete mode 100644 qpid/cpp/src/qpid/sys/SocketAddress.h delete mode 100644 qpid/cpp/src/qpid/sys/SocketTransport.cpp delete mode 100644 qpid/cpp/src/qpid/sys/SocketTransport.h delete mode 100644 qpid/cpp/src/qpid/sys/SslPlugin.cpp delete mode 100644 qpid/cpp/src/qpid/sys/StateMonitor.h delete mode 100644 qpid/cpp/src/qpid/sys/StrError.h delete mode 100644 qpid/cpp/src/qpid/sys/SystemInfo.h delete mode 100644 qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp delete mode 100644 qpid/cpp/src/qpid/sys/Thread.h delete mode 100644 qpid/cpp/src/qpid/sys/Time.h delete mode 100644 qpid/cpp/src/qpid/sys/Timer.cpp delete mode 100644 qpid/cpp/src/qpid/sys/Timer.h delete mode 100644 qpid/cpp/src/qpid/sys/TimerWarnings.cpp delete mode 100644 qpid/cpp/src/qpid/sys/TimerWarnings.h delete mode 100644 qpid/cpp/src/qpid/sys/TransportFactory.h delete mode 100644 qpid/cpp/src/qpid/sys/Waitable.h delete mode 100644 qpid/cpp/src/qpid/sys/aix/SystemInfo.cpp delete mode 100644 qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp delete mode 100644 qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h delete mode 100644 qpid/cpp/src/qpid/sys/epoll/EpollPoller.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/BSDSocket.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/BSDSocket.h delete mode 100644 qpid/cpp/src/qpid/sys/posix/Condition.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/Condition.h delete mode 100755 qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/Fork.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/Fork.h delete mode 100644 qpid/cpp/src/qpid/sys/posix/IOHandle.cpp delete mode 100755 qpid/cpp/src/qpid/sys/posix/LockFile.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/MemStat.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/MemoryMappedFile.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/Mutex.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/Mutex.h delete mode 100644 qpid/cpp/src/qpid/sys/posix/Path.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/PidFile.h delete mode 100755 qpid/cpp/src/qpid/sys/posix/PipeHandle.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/PollableCondition.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/PosixPoller.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/PrivatePosix.h delete mode 100644 qpid/cpp/src/qpid/sys/posix/Shlib.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/StrError.cpp delete mode 100755 qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/Thread.cpp delete mode 100644 qpid/cpp/src/qpid/sys/posix/Time.cpp delete mode 100755 qpid/cpp/src/qpid/sys/posix/Time.h delete mode 100644 qpid/cpp/src/qpid/sys/posix/check.h delete mode 100644 qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp delete mode 100644 qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp delete mode 100644 qpid/cpp/src/qpid/sys/rdma/RdmaIO.h delete mode 100644 qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp delete mode 100644 qpid/cpp/src/qpid/sys/rdma/rdma_exception.h delete mode 100644 qpid/cpp/src/qpid/sys/rdma/rdma_factories.cpp delete mode 100644 qpid/cpp/src/qpid/sys/rdma/rdma_factories.h delete mode 100644 qpid/cpp/src/qpid/sys/rdma/rdma_wrap.cpp delete mode 100644 qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h delete mode 100644 qpid/cpp/src/qpid/sys/regex.h delete mode 100644 qpid/cpp/src/qpid/sys/solaris/ECFPoller.cpp delete mode 100755 qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp delete mode 100644 qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp delete mode 100644 qpid/cpp/src/qpid/sys/ssl/SslSocket.h delete mode 100644 qpid/cpp/src/qpid/sys/ssl/check.cpp delete mode 100644 qpid/cpp/src/qpid/sys/ssl/check.h delete mode 100644 qpid/cpp/src/qpid/sys/ssl/util.cpp delete mode 100644 qpid/cpp/src/qpid/sys/ssl/util.h delete mode 100644 qpid/cpp/src/qpid/sys/unordered_map.h delete mode 100644 qpid/cpp/src/qpid/sys/urlAdd.h delete mode 100644 qpid/cpp/src/qpid/sys/uuid.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/AsynchIO.h delete mode 100755 qpid/cpp/src/qpid/sys/windows/AsynchIoResult.h delete mode 100755 qpid/cpp/src/qpid/sys/windows/Condition.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp delete mode 100755 qpid/cpp/src/qpid/sys/windows/IOHandle.cpp delete mode 100755 qpid/cpp/src/qpid/sys/windows/IoHandlePrivate.h delete mode 100755 qpid/cpp/src/qpid/sys/windows/IocpPoller.cpp delete mode 100755 qpid/cpp/src/qpid/sys/windows/LockFile.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/MemoryMappedFile.cpp delete mode 100755 qpid/cpp/src/qpid/sys/windows/Mutex.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/Path.cpp delete mode 100755 qpid/cpp/src/qpid/sys/windows/PipeHandle.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/PollableCondition.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/QpidDllMain.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/Shlib.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/SslCredential.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/SslCredential.h delete mode 100755 qpid/cpp/src/qpid/sys/windows/StrError.cpp delete mode 100755 qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp delete mode 100755 qpid/cpp/src/qpid/sys/windows/Thread.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/Time.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/Time.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/WinSocket.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/WinSocket.h delete mode 100755 qpid/cpp/src/qpid/sys/windows/check.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/mingw32_compat.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/util.cpp delete mode 100644 qpid/cpp/src/qpid/sys/windows/util.h delete mode 100644 qpid/cpp/src/qpid/sys/windows/uuid.cpp delete mode 100644 qpid/cpp/src/qpid/types/Exception.cpp delete mode 100644 qpid/cpp/src/qpid/types/Uuid.cpp delete mode 100644 qpid/cpp/src/qpid/types/Variant.cpp delete mode 100644 qpid/cpp/src/qpid/types/encodings.h delete mode 100644 qpid/cpp/src/qpid/xml/XmlExchange.cpp delete mode 100644 qpid/cpp/src/qpid/xml/XmlExchange.h delete mode 100644 qpid/cpp/src/qpid/xml/XmlExchangePlugin.cpp delete mode 100644 qpid/cpp/src/qpidd.cpp delete mode 100644 qpid/cpp/src/qpidd.h delete mode 100644 qpid/cpp/src/rdma.cmake delete mode 100644 qpid/cpp/src/tests/.valgrind.supp delete mode 100644 qpid/cpp/src/tests/AccumulatedAckTest.cpp delete mode 100644 qpid/cpp/src/tests/Acl.cpp delete mode 100644 qpid/cpp/src/tests/AclHost.cpp delete mode 100644 qpid/cpp/src/tests/Address.cpp delete mode 100644 qpid/cpp/src/tests/Array.cpp delete mode 100644 qpid/cpp/src/tests/AsyncCompletion.cpp delete mode 100644 qpid/cpp/src/tests/AtomicValue.cpp delete mode 100644 qpid/cpp/src/tests/Blob.cpp delete mode 100644 qpid/cpp/src/tests/BrokerFixture.h delete mode 100644 qpid/cpp/src/tests/BrokerMgmtAgent.cpp delete mode 100644 qpid/cpp/src/tests/BrokerMgmtAgent.xml delete mode 100644 qpid/cpp/src/tests/BrokerOptions.cpp delete mode 100644 qpid/cpp/src/tests/CMakeLists.txt delete mode 100644 qpid/cpp/src/tests/ClientMessage.cpp delete mode 100644 qpid/cpp/src/tests/ClientMessageTest.cpp delete mode 100644 qpid/cpp/src/tests/ClientSessionTest.cpp delete mode 100644 qpid/cpp/src/tests/ConnectionOptions.h delete mode 100644 qpid/cpp/src/tests/DeliveryRecordTest.cpp delete mode 100644 qpid/cpp/src/tests/DispatcherTest.cpp delete mode 100644 qpid/cpp/src/tests/DtxWorkRecordTest.cpp delete mode 100644 qpid/cpp/src/tests/ExchangeTest.cpp delete mode 100644 qpid/cpp/src/tests/FieldTable.cpp delete mode 100644 qpid/cpp/src/tests/FieldValue.cpp delete mode 100644 qpid/cpp/src/tests/Frame.cpp delete mode 100644 qpid/cpp/src/tests/FrameDecoder.cpp delete mode 100644 qpid/cpp/src/tests/FramingTest.cpp delete mode 100644 qpid/cpp/src/tests/HeaderTest.cpp delete mode 100644 qpid/cpp/src/tests/HeadersExchangeTest.cpp delete mode 100644 qpid/cpp/src/tests/InlineAllocator.cpp delete mode 100644 qpid/cpp/src/tests/InlineVector.cpp delete mode 100644 qpid/cpp/src/tests/ManagementTest.cpp delete mode 100644 qpid/cpp/src/tests/MessageReplayTracker.cpp delete mode 100644 qpid/cpp/src/tests/MessageTest.cpp delete mode 100644 qpid/cpp/src/tests/MessageUtils.h delete mode 100644 qpid/cpp/src/tests/MessagingFixture.h delete mode 100644 qpid/cpp/src/tests/MessagingLogger.cpp delete mode 100644 qpid/cpp/src/tests/MessagingSessionTests.cpp delete mode 100644 qpid/cpp/src/tests/MessagingThreadTests.cpp delete mode 100644 qpid/cpp/src/tests/PollableCondition.cpp delete mode 100644 qpid/cpp/src/tests/PollerTest.cpp delete mode 100644 qpid/cpp/src/tests/ProxyTest.cpp delete mode 100644 qpid/cpp/src/tests/Qmf2.cpp delete mode 100644 qpid/cpp/src/tests/QueueDepth.cpp delete mode 100644 qpid/cpp/src/tests/QueueFlowLimitTest.cpp delete mode 100644 qpid/cpp/src/tests/QueueOptionsTest.cpp delete mode 100644 qpid/cpp/src/tests/QueuePolicyTest.cpp delete mode 100644 qpid/cpp/src/tests/QueueRegistryTest.cpp delete mode 100644 qpid/cpp/src/tests/QueueTest.cpp delete mode 100644 qpid/cpp/src/tests/README.txt delete mode 100644 qpid/cpp/src/tests/RangeSet.cpp delete mode 100644 qpid/cpp/src/tests/RefCounted.cpp delete mode 100644 qpid/cpp/src/tests/RetryList.cpp delete mode 100644 qpid/cpp/src/tests/Selector.cpp delete mode 100644 qpid/cpp/src/tests/SequenceNumberTest.cpp delete mode 100644 qpid/cpp/src/tests/SequenceSet.cpp delete mode 100644 qpid/cpp/src/tests/SessionState.cpp delete mode 100644 qpid/cpp/src/tests/Shlib.cpp delete mode 100644 qpid/cpp/src/tests/Statistics.cpp delete mode 100644 qpid/cpp/src/tests/Statistics.h delete mode 100644 qpid/cpp/src/tests/StringUtils.cpp delete mode 100644 qpid/cpp/src/tests/SystemInfo.cpp delete mode 100644 qpid/cpp/src/tests/TestMessageStore.h delete mode 100644 qpid/cpp/src/tests/TestOptions.h delete mode 100644 qpid/cpp/src/tests/TimerTest.cpp delete mode 100644 qpid/cpp/src/tests/TopicExchangeTest.cpp delete mode 100644 qpid/cpp/src/tests/TransactionObserverTest.cpp delete mode 100644 qpid/cpp/src/tests/TxBufferTest.cpp delete mode 100644 qpid/cpp/src/tests/TxMocks.h delete mode 100644 qpid/cpp/src/tests/Url.cpp delete mode 100644 qpid/cpp/src/tests/Uuid.cpp delete mode 100644 qpid/cpp/src/tests/Variant.cpp delete mode 100644 qpid/cpp/src/tests/XmlClientSessionTest.cpp delete mode 100755 qpid/cpp/src/tests/acl.py delete mode 100644 qpid/cpp/src/tests/acl_1.py delete mode 100644 qpid/cpp/src/tests/assertions.py delete mode 100644 qpid/cpp/src/tests/background.ps1 delete mode 100644 qpid/cpp/src/tests/brokertest.py delete mode 100755 qpid/cpp/src/tests/check_dependencies.py.in delete mode 100755 qpid/cpp/src/tests/cli_tests.py delete mode 100644 qpid/cpp/src/tests/common.py delete mode 100644 qpid/cpp/src/tests/consume.cpp delete mode 100644 qpid/cpp/src/tests/datagen.cpp delete mode 100644 qpid/cpp/src/tests/declare_queues.cpp delete mode 100644 qpid/cpp/src/tests/dlclose_noop.c delete mode 100755 qpid/cpp/src/tests/dynamic_log_hires_timestamp delete mode 100755 qpid/cpp/src/tests/dynamic_log_level_test delete mode 100644 qpid/cpp/src/tests/echotest.cpp delete mode 100644 qpid/cpp/src/tests/env.ps1.in delete mode 100644 qpid/cpp/src/tests/env.py.in delete mode 100644 qpid/cpp/src/tests/env.sh.in delete mode 100644 qpid/cpp/src/tests/exception_test.cpp delete mode 100644 qpid/cpp/src/tests/failing-amqp0-10-python-tests delete mode 100644 qpid/cpp/src/tests/failing-amqp1.0-python-tests delete mode 100755 qpid/cpp/src/tests/federated_topic_test delete mode 100755 qpid/cpp/src/tests/federation.py delete mode 100755 qpid/cpp/src/tests/federation_sys.py delete mode 100644 qpid/cpp/src/tests/find_prog.ps1 delete mode 100755 qpid/cpp/src/tests/ha_test.py delete mode 100644 qpid/cpp/src/tests/ha_test_max_queues.cpp delete mode 100755 qpid/cpp/src/tests/ha_tests.py delete mode 100644 qpid/cpp/src/tests/header_test.cpp delete mode 100755 qpid/cpp/src/tests/header_test.py delete mode 100644 qpid/cpp/src/tests/headers_federation.py delete mode 100755 qpid/cpp/src/tests/idle_timeout_tests.py delete mode 100755 qpid/cpp/src/tests/interlink_tests.py delete mode 100755 qpid/cpp/src/tests/interop_tests.py delete mode 100644 qpid/cpp/src/tests/legacystore/.valgrind.supp delete mode 100644 qpid/cpp/src/tests/legacystore/.valgrindrc delete mode 100644 qpid/cpp/src/tests/legacystore/CMakeLists.txt delete mode 100644 qpid/cpp/src/tests/legacystore/MessageUtils.h delete mode 100644 qpid/cpp/src/tests/legacystore/TestFramework.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/TestFramework.h delete mode 100644 qpid/cpp/src/tests/legacystore/clean.sh delete mode 100644 qpid/cpp/src/tests/legacystore/federation/Makefile.am delete mode 100755 qpid/cpp/src/tests/legacystore/federation/federation_tests_env.sh delete mode 100755 qpid/cpp/src/tests/legacystore/federation/run_federation_sys_tests delete mode 100755 qpid/cpp/src/tests/legacystore/federation/run_long_federation_sys_tests delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_st_auto_expand.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_st_basic.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_st_basic_txn.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_st_helper_fns.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_st_read.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_st_read_txn.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_enq_map.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_jexception.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_rec_hdr.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_time_ns.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/_ut_txn_map.cpp delete mode 100755 qpid/cpp/src/tests/legacystore/jrnl/chk_jdata delete mode 100755 qpid/cpp/src/tests/legacystore/jrnl/cp_rtest_jrnl delete mode 100755 qpid/cpp/src/tests/legacystore/jrnl/jhexdump delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_data_src.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_jrnl_init_params.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_jrnl_instance.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_read_arg.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_result.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_result_agregation.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_set.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_set.csv delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/args.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/args.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.h delete mode 100755 qpid/cpp/src/tests/legacystore/jrnl/jtt/jfile_chk.py delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_init_params.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_init_params.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_instance.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_instance.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/jtt.csv delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/main.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result_agregation.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result_agregation.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_set.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_set.h delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.h delete mode 100755 qpid/cpp/src/tests/legacystore/jrnl/prof delete mode 100755 qpid/cpp/src/tests/legacystore/jrnl/run-journal-tests delete mode 100644 qpid/cpp/src/tests/legacystore/jrnl/tests.ods delete mode 100644 qpid/cpp/src/tests/legacystore/persistence.py delete mode 100644 qpid/cpp/src/tests/legacystore/python_tests/__init__.py delete mode 100644 qpid/cpp/src/tests/legacystore/python_tests/client_persistence.py delete mode 100644 qpid/cpp/src/tests/legacystore/python_tests/resize.py delete mode 100644 qpid/cpp/src/tests/legacystore/python_tests/store_test.py delete mode 100644 qpid/cpp/src/tests/legacystore/run_long_python_tests delete mode 100755 qpid/cpp/src/tests/legacystore/run_python_tests delete mode 100644 qpid/cpp/src/tests/legacystore/run_short_python_tests delete mode 100644 qpid/cpp/src/tests/legacystore/system_test.sh delete mode 100644 qpid/cpp/src/tests/legacystore/unit_test.cpp delete mode 100644 qpid/cpp/src/tests/legacystore/unit_test.h delete mode 100644 qpid/cpp/src/tests/linearstore/CMakeLists.txt delete mode 100755 qpid/cpp/src/tests/linearstore/linearstoredirsetup.sh delete mode 100644 qpid/cpp/src/tests/linearstore/python_tests/__init__.py delete mode 100644 qpid/cpp/src/tests/linearstore/python_tests/client_persistence.py delete mode 100644 qpid/cpp/src/tests/linearstore/python_tests/store_test.py delete mode 100644 qpid/cpp/src/tests/linearstore/run_long_python_tests delete mode 100755 qpid/cpp/src/tests/linearstore/run_python_tests delete mode 100644 qpid/cpp/src/tests/linearstore/run_short_python_tests delete mode 100755 qpid/cpp/src/tests/linearstore/tx-test-soak.sh delete mode 100644 qpid/cpp/src/tests/logging.cpp delete mode 100644 qpid/cpp/src/tests/mgmt_1.py delete mode 100644 qpid/cpp/src/tests/misc.py delete mode 100644 qpid/cpp/src/tests/msg_group_test.cpp delete mode 100755 qpid/cpp/src/tests/perfdist delete mode 100755 qpid/cpp/src/tests/ping_broker delete mode 100644 qpid/cpp/src/tests/plano.py delete mode 100644 qpid/cpp/src/tests/policies.py delete mode 100644 qpid/cpp/src/tests/policy.acl delete mode 100644 qpid/cpp/src/tests/publish.cpp delete mode 100755 qpid/cpp/src/tests/qpid-analyze-trace delete mode 100644 qpid/cpp/src/tests/qpid-client-test.cpp delete mode 100755 qpid/cpp/src/tests/qpid-cluster-benchmark delete mode 100755 qpid/cpp/src/tests/qpid-cpp-benchmark delete mode 100755 qpid/cpp/src/tests/qpid-ctrl delete mode 100644 qpid/cpp/src/tests/qpid-latency-test.cpp delete mode 100644 qpid/cpp/src/tests/qpid-perftest.cpp delete mode 100644 qpid/cpp/src/tests/qpid-ping.cpp delete mode 100644 qpid/cpp/src/tests/qpid-receive.cpp delete mode 100644 qpid/cpp/src/tests/qpid-send.cpp delete mode 100755 qpid/cpp/src/tests/qpid-src-rinstall delete mode 100644 qpid/cpp/src/tests/qpid-stream.cpp delete mode 100644 qpid/cpp/src/tests/qpid-topic-listener.cpp delete mode 100644 qpid/cpp/src/tests/qpid-topic-publisher.cpp delete mode 100644 qpid/cpp/src/tests/qpid-txtest.cpp delete mode 100644 qpid/cpp/src/tests/qpid-txtest2.cpp delete mode 100644 qpid/cpp/src/tests/qpidd-empty.conf delete mode 100755 qpid/cpp/src/tests/qpidd-p0 delete mode 100755 qpid/cpp/src/tests/qpidd_qmfv2_tests.py delete mode 100644 qpid/cpp/src/tests/queue_flow_limit_tests.py delete mode 100644 qpid/cpp/src/tests/queue_redirect.py delete mode 100644 qpid/cpp/src/tests/receiver.cpp delete mode 100644 qpid/cpp/src/tests/reject_release.py delete mode 100644 qpid/cpp/src/tests/replaying_sender.cpp delete mode 100644 qpid/cpp/src/tests/resuming_receiver.cpp delete mode 100755 qpid/cpp/src/tests/ring_queue_test delete mode 100755 qpid/cpp/src/tests/run.py delete mode 100755 qpid/cpp/src/tests/run_acl_tests delete mode 100755 qpid/cpp/src/tests/run_cli_tests delete mode 100755 qpid/cpp/src/tests/run_client_tests delete mode 100755 qpid/cpp/src/tests/run_federation_tests delete mode 100755 qpid/cpp/src/tests/run_flow_control_tests delete mode 100755 qpid/cpp/src/tests/run_ha_tests delete mode 100755 qpid/cpp/src/tests/run_idle_timeout_tests delete mode 100755 qpid/cpp/src/tests/run_interlink_tests delete mode 100755 qpid/cpp/src/tests/run_interop_tests delete mode 100755 qpid/cpp/src/tests/run_ipv6_tests delete mode 100755 qpid/cpp/src/tests/run_logging_tests delete mode 100644 qpid/cpp/src/tests/run_long_federation_sys_tests delete mode 100755 qpid/cpp/src/tests/run_msg_group_tests delete mode 100755 qpid/cpp/src/tests/run_msg_group_tests_soak delete mode 100755 qpid/cpp/src/tests/run_paged_queue_tests delete mode 100755 qpid/cpp/src/tests/run_performance_tests delete mode 100755 qpid/cpp/src/tests/run_python_tests delete mode 100755 qpid/cpp/src/tests/run_qmf_tests delete mode 100644 qpid/cpp/src/tests/run_queue_redirect_tests delete mode 100755 qpid/cpp/src/tests/run_ring_queue_tests delete mode 100755 qpid/cpp/src/tests/run_sasl_tests delete mode 100755 qpid/cpp/src/tests/run_ssl_tests delete mode 100644 qpid/cpp/src/tests/run_store_tests.ps1 delete mode 100755 qpid/cpp/src/tests/run_topic_tests delete mode 100755 qpid/cpp/src/tests/run_transaction_tests delete mode 100755 qpid/cpp/src/tests/run_unit_tests delete mode 100644 qpid/cpp/src/tests/run_windows_store_tests delete mode 100755 qpid/cpp/src/tests/sasl_fed delete mode 100755 qpid/cpp/src/tests/sasl_fed_ex delete mode 100755 qpid/cpp/src/tests/sasl_no_dir delete mode 100755 qpid/cpp/src/tests/sasl_test_setup.sh delete mode 100644 qpid/cpp/src/tests/sasl_version.cpp delete mode 100644 qpid/cpp/src/tests/sender.cpp delete mode 100644 qpid/cpp/src/tests/shlibtest.cpp delete mode 100755 qpid/cpp/src/tests/ssl_test delete mode 100755 qpid/cpp/src/tests/store.py delete mode 100644 qpid/cpp/src/tests/test_store.cpp delete mode 100644 qpid/cpp/src/tests/test_tools.h delete mode 100755 qpid/cpp/src/tests/topictest delete mode 100644 qpid/cpp/src/tests/topictest.ps1 delete mode 100644 qpid/cpp/src/tests/txjob.cpp delete mode 100644 qpid/cpp/src/tests/txshift.cpp delete mode 100644 qpid/cpp/src/tests/unit_test.cpp delete mode 100644 qpid/cpp/src/tests/unit_test.h delete mode 100644 qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp delete mode 100644 qpid/cpp/src/versions.cmake delete mode 100644 qpid/cpp/src/windows/QpiddBroker.cpp delete mode 100644 qpid/cpp/src/windows/SCM.cpp delete mode 100644 qpid/cpp/src/windows/SCM.h delete mode 100644 qpid/cpp/src/windows/resources/qpid-icon.ico delete mode 100644 qpid/cpp/src/windows/resources/template-resource.rc delete mode 100644 qpid/cpp/src/windows/resources/version-resource.h (limited to 'qpid/cpp/src') diff --git a/qpid/cpp/src/CMakeLists.txt b/qpid/cpp/src/CMakeLists.txt deleted file mode 100644 index ef203e53b6..0000000000 --- a/qpid/cpp/src/CMakeLists.txt +++ /dev/null @@ -1,1317 +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. -# - -# library versions -include (versions.cmake) - -# Option to require building optional plugins -foreach (r ${REQUIRE}) - set(${r}_force ON) - message(STATUS "Forcing ${r} to ${${r}_force}") -endforeach(r) - -include(CheckFunctionExists) -include(CheckIncludeFileCXX) -include(CheckIncludeFiles) -include(CheckIncludeFileCXX) -include(CheckLibraryExists) -include(CheckSymbolExists) -include(CheckSizetDistinct) - -find_package(PkgConfig) -find_package(Ruby) - -find_package(Doxygen) - -find_program(VALGRIND_EXECUTABLE valgrind DOC "Location of the valgrind program") -mark_as_advanced(VALGRIND_EXECUTABLE) -find_package_handle_standard_args(VALGRIND DEFAULT_MSG VALGRIND_EXECUTABLE) - -find_program(SASLPASSWD2_EXECUTABLE saslpasswd2 DOC "Location of the saslpasswd2 program") -mark_as_advanced(SASLPASSWD2_EXECUTABLE) - -# See if Cyrus SASL is desired and available -CHECK_LIBRARY_EXISTS (sasl2 sasl_checkpass "" FOUND_SASL_LIB) -CHECK_INCLUDE_FILES (sasl/sasl.h FOUND_SASL_H) -find_package_handle_standard_args(SASL DEFAULT_MSG FOUND_SASL_LIB FOUND_SASL_H) - -#set (CMAKE_VERBOSE_MAKEFILE ON) # for debugging - -if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows AND BUILD_TESTING) - # Executables used in testing the library ABIs - add_executable(cppabi cppabi.cpp) - add_executable(expand_types expand_types.cpp) - - # Add a test to check the exported library API against expected API symbols - MACRO (add_api_test libname) - add_test(api_check_${libname} ${CMAKE_CURRENT_SOURCE_DIR}/check-abi ${CMAKE_CURRENT_BINARY_DIR}/lib${libname}.so ${CMAKE_CURRENT_SOURCE_DIR}/lib${libname}-api-symbols.txt) - ENDMACRO (add_api_test libname) -else (NOT CMAKE_SYSTEM_NAME STREQUAL Windows AND BUILD_TESTING) - # If the test isn't applicable use a dummy macro - MACRO (add_api_test libname) - ENDMACRO (add_api_test libname) -endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows AND BUILD_TESTING) - - -# check if we generate source as part of the build -# - rubygen generates the amqp spec -# - managementgen generates the broker management code -# -# rubygen subdir is excluded from stable distributions -# If the main AMQP spec is present, then check if ruby and python are -# present, and if any sources have changed, forcing a re-gen of source code. -find_file(QPID_AMQP_SPEC NAMES amqp.0-10-qpid-errata.stripped.xml PATHS ${qpid-cpp_SOURCE_DIR}/specs ${qpid-cpp_SOURCE_DIR}/../specs NO_DEFAULT_PATH) -mark_as_advanced(QPID_AMQP_SPEC) -if (NOT QPID_AMQP_SPEC) - message(FATAL_ERROR "Can't find amqp 0-10 spec for framing code generation") -endif (NOT QPID_AMQP_SPEC) -if (NOT RUBY_EXECUTABLE) - message(FATAL_ERROR "Can't locate ruby, needed to generate amqp 0-10 framing code.") -endif (NOT RUBY_EXECUTABLE) - -set(specs ${QPID_AMQP_SPEC}) -set(regen_amqp OFF) -set(rgen_dir ${qpid-cpp_SOURCE_DIR}/rubygen) -file(GLOB_RECURSE rgen_progs ${rgen_dir}/*.rb) -# If any of the specs, or any of the sources used to generate code, change -# then regenerate the sources. -foreach (spec_file ${specs} ${rgen_progs}) - if (${spec_file} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/rubygen.cmake) - set(regen_amqp ON) - endif (${spec_file} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/rubygen.cmake) -endforeach (spec_file ${specs}) -if (regen_amqp) - message(STATUS "Regenerating AMQP protocol sources") - execute_process(COMMAND ${RUBY_EXECUTABLE} -I ${rgen_dir} ${rgen_dir}/generate ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/../include ${specs} all rubygen.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -else (regen_amqp) - message(STATUS "No need to generate AMQP protocol sources") -endif (regen_amqp) - -find_file(QPID_BROKER_MANAGEMENT_SPEC NAMES management-schema.xml PATHS ${CMAKE_CURRENT_SOURCE_DIR}/qpid/broker ${qpid-cpp_SOURCE_DIR}/../specs NO_DEFAULT_PATH) -mark_as_advanced(QPID_BROKER_MANAGEMENT_SPEC) -if (NOT QPID_BROKER_MANAGEMENT_SPEC) - message(FATAL_ERROR "Can't find broker management spec for code generation") -endif (NOT QPID_BROKER_MANAGEMENT_SPEC) -if (NOT PYTHON_EXECUTABLE) - message(FATAL_ERROR "Can't locate python, needed to generate broker management code.") -endif (NOT PYTHON_EXECUTABLE) -set(mgmt_specs ${QPID_BROKER_MANAGEMENT_SPEC} - ${CMAKE_CURRENT_SOURCE_DIR}/qpid/acl/management-schema.xml - ${CMAKE_CURRENT_SOURCE_DIR}/qpid/ha/management-schema.xml - ${CMAKE_CURRENT_SOURCE_DIR}/qpid/legacystore/management-schema.xml - ${CMAKE_CURRENT_SOURCE_DIR}/qpid/linearstore/management-schema.xml -) -set(mgen_dir ${qpid-cpp_SOURCE_DIR}/managementgen) -set(regen_mgmt OFF) -foreach (spec_file ${mgmt_specs}) - if (${spec_file} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/managementgen.cmake) - message(STATUS "${spec_file} is newer") - set(regen_mgmt ON) - endif (${spec_file} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/managementgen.cmake) -endforeach (spec_file ${mgmt_specs}) -if (regen_mgmt) - message(STATUS "Regenerating Qpid Management Framework sources") - execute_process(COMMAND ${PYTHON_EXECUTABLE} ${mgen_dir}/qmf-gen -c managementgen.cmake -b -l -q -o ${CMAKE_CURRENT_BINARY_DIR}/qmf ${mgmt_specs} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -else (regen_mgmt) - message(STATUS "No need to generate Qpid Management Framework sources") -endif (regen_mgmt) - -# Pull in the names of the generated files, i.e. ${rgen_framing_srcs} -include (${CMAKE_CURRENT_BINARY_DIR}/rubygen.cmake) -include (${CMAKE_CURRENT_BINARY_DIR}/managementgen.cmake) - -# FindDoxygen module tries to locate doxygen and Graphviz dot -if (DOXYGEN_FOUND) - option(BUILD_DOCS "Build user documentation" ON) -else (DOXYGEN_FOUND) - message(STATUS "Can't locate the doxygen command; user documentation cannot be generated") -endif (DOXYGEN_FOUND) - -if (VALGRIND_FOUND) - option(ENABLE_VALGRIND "Use valgrind to detect run-time problems" ON) -endif (VALGRIND_FOUND) - -option(ENABLE_WARNINGS "Enable lots of compiler warnings (recommended)" ON) -if (NOT ENABLE_WARNINGS) - set (WARNING_FLAGS "") -endif (NOT ENABLE_WARNINGS) - -if (GCC_VERSION AND NOT GCC_VERSION VERSION_LESS 5.1) - option(ENABLE_GLIBCXX_OLD_ABI "Enable old (pre GCC 5.1) C++ ABI" OFF) -endif () - -if (ENABLE_GLIBCXX_OLD_ABI) - set (ABI_DEF "-D_GLIBCXX_USE_CXX11_ABI=0") -endif (ENABLE_GLIBCXX_OLD_ABI) - -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ABI_DEF} ${COMPILER_FLAGS} ${WARNING_FLAGS}") - -# Expand a bit from the basic Find_Boost; be specific about what's needed. -# Boost.system is sometimes needed; it's handled separately, below. -# There may be different minimum versions of boost for Windows and Unix -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - set (Boost_components program_options date_time thread) - set (Boost_minversion 1.44) -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - set (Boost_components program_options) - set (Boost_minversion 1.33) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -# Visual Studio 2010 requires boost 1.45 or better. -# The choice here is to fail demanding the user to update CMake to version N -# 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 - "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" - "1.54" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" - "1.57" "1.57.0" "1.58" "1.58.0") -endif (NOT DEFINED Boost_ADDITIONAL_VERSIONS) - -# Discover Boost version -find_package(Boost ${Boost_minversion} QUIET REQUIRED) - -# Boost.system was introduced at Boost 1.35; it's needed secondarily by other -# Boost libs Qpid needs, so be sure it's there. -if (Boost_VERSION GREATER 103499) - list(APPEND Boost_components system) -endif (Boost_VERSION GREATER 103499) - -# Boost.chrono was introduced at Boost 1.47; it's needed secondarily by other -# Boost libs Qpid needs on Windows, so be sure it's there on Windows. -if (Boost_VERSION GREATER 104699 AND CMAKE_SYSTEM_NAME STREQUAL Windows) - list(APPEND Boost_components chrono) -endif (Boost_VERSION GREATER 104699 AND CMAKE_SYSTEM_NAME STREQUAL Windows) - -find_package(Boost ${Boost_minversion} REQUIRED COMPONENTS ${Boost_components}) -if(NOT Boost_FOUND) - message(FATAL_ERROR "Required Boost C++ libraries not found. Please install or try setting BOOST_ROOT") -endif(NOT Boost_FOUND) - -if (BUILD_TESTING) - set (BUILD_TESTING_UNITTESTS ON) - find_package(Boost ${Boost_minversion} QUIET COMPONENTS unit_test_framework) - if(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY) - message(STATUS "Could not find unit testing library - will not build unit tests") - set (BUILD_TESTING_UNITTESTS OFF) - endif(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY) -endif (BUILD_TESTING) - -# The Windows install also wants the Boost DLLs, libs and headers that the -# release is built with. The DLLs enable everything to run, and the headers -# and libs ensure that users building Qpid C++ client programs can compile -# (the C++ API still exposes Boost headers, but hopefully this will be fixed -# in the future). -# -# On Windows you can pick whether the static or dynamic versions of the libs -# are used; allow this choice to the user. Since we also install the Boost -# DLLs that are needed for the Windows package, none are needed for the -# static link case; else drop them into the install. Do this all first, since -# Boost on Windows can use automatic linking to pick up the correct -# Boost libs based on compile-time touching of the headers. Since we don't -# really need to add them to the link lines, set the names to blanks. -option(QPID_LINK_BOOST_DYNAMIC "Link with dynamic Boost libs (OFF to link static)" ON) -mark_as_advanced(QPID_LINK_BOOST_DYNAMIC) - -if (MSVC) - if (QPID_LINK_BOOST_DYNAMIC) - add_definitions( /D BOOST_ALL_DYN_LINK) - string (REPLACE .lib .dll - _boost_date_time_debug ${Boost_DATE_TIME_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_date_time_release ${Boost_DATE_TIME_LIBRARY_RELEASE}) - string (REPLACE .lib .dll - _boost_program_options_debug ${Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_program_options_release ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}) - string (REPLACE .lib .dll - _boost_thread_debug ${Boost_THREAD_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_thread_release ${Boost_THREAD_LIBRARY_RELEASE}) - if (NOT Boost_VERSION LESS 103500) - string (REPLACE .lib .dll - _boost_system_debug ${Boost_SYSTEM_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_system_release ${Boost_SYSTEM_LIBRARY_RELEASE}) - endif (NOT Boost_VERSION LESS 103500) - if (NOT Boost_VERSION LESS 104700) - string (REPLACE .lib .dll - _boost_chrono_debug ${Boost_CHRONO_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_chrono_release ${Boost_CHRONO_LIBRARY_RELEASE}) - endif (NOT Boost_VERSION LESS 104700) - install (PROGRAMS - ${_boost_date_time_debug} ${_boost_date_time_release} - ${_boost_program_options_debug} ${_boost_program_options_release} - ${_boost_thread_debug} ${_boost_thread_release} - ${_boost_chrono_debug} ${_boost_chrono_release} - ${_boost_system_debug} ${_boost_system_release} - DESTINATION ${QPID_INSTALL_BINDIR} - COMPONENT ${QPID_COMPONENT_COMMON}) - endif (QPID_LINK_BOOST_DYNAMIC) - - set(Boost_DATE_TIME_LIBRARY "") - set(Boost_THREAD_LIBRARY "") - set(Boost_PROGRAM_OPTIONS_LIBRARY "") - set(Boost_UNIT_TEST_FRAMEWORK_LIBRARY "") - set(Boost_SYSTEM_LIBRARY "") - set(Boost_CHRONO_LIBRARY "") - include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/windows/resources ) -endif (MSVC) - -include_directories( ${Boost_INCLUDE_DIR} ) - -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../include ) -include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../include ) - -link_directories( ${Boost_LIBRARY_DIRS} ) - -CHECK_SYMBOL_EXISTS(uuid_generate "uuid/uuid.h" UUID_GENERATE_IN_LIBC) -if (UUID_GENERATE_IN_LIBC) - set(uuid_SRC "") - set(uuid_LIB "") -else (UUID_GENERATE_IN_LIBC) - CHECK_LIBRARY_EXISTS (uuid uuid_generate "" UUID_GENERATE_IN_UUID) - if (UUID_GENERATE_IN_UUID) - set(uuid_SRC "") - set(uuid_LIB uuid) - else (UUID_GENERATE_IN_UUID) - CHECK_SYMBOL_EXISTS(uuid_create "uuid.h" UUID_CREATE_IN_LIBC) - if (UUID_CREATE_IN_LIBC) - set(uuid_SRC qpid/sys/FreeBSD/uuid.cpp) - set(uuid_LIB "") - else (UUID_CREATE_IN_LIBC) - CHECK_SYMBOL_EXISTS(UuidToString "rpc.h" WIN_UUID) - if (WIN_UUID) - set(uuid_SRC qpid/sys/windows/uuid.cpp) - set(uuid_LIB rpcrt4) - else (WIN_UUID) - message(FATAL_ERROR "No Uuid API found") - endif (WIN_UUID) - endif (UUID_CREATE_IN_LIBC) - endif (UUID_GENERATE_IN_UUID) -endif (UUID_GENERATE_IN_LIBC) - -# 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) - - # Check for header file for dtrace static probes - check_include_files(sys/sdt.h HAVE_SDT) - if (HAVE_SDT) - # Only enable by default on Linux - if (CMAKE_SYSTEM_NAME STREQUAL Linux) - set(probes_default ON) - endif (CMAKE_SYSTEM_NAME STREQUAL Linux) - option(BUILD_PROBES "Build with DTrace/systemtap static probes" "${probes_default}") - endif (HAVE_SDT) - if (BUILD_PROBES) - set (HAVE_SYS_SDT_H 1) - else (HAVE_SDT) - set (HAVE_SYS_SDT_H 0) - endif (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(QPID_POLLER ${poller_default} CACHE STRING "Poller implementation (poll/epoll)") - mark_as_advanced(QPID_POLLER) -endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) - -check_size_t_distinct (QPID_SIZE_T_DISTINCT) - -option(BUILD_SASL "Build with Cyrus SASL support" ${SASL_FOUND}) -if (BUILD_SASL) - if (NOT SASL_FOUND) - message(FATAL_ERROR "Cyrus SASL support requested but libsasl2 libraryor headers not found") - endif (NOT SASL_FOUND) - - set(qpidcommon_sasl_source - qpid/sys/cyrus/CyrusSecurityLayer.h - qpid/sys/cyrus/CyrusSecurityLayer.cpp - ) - set(sasl_LIB sasl2) - set(HAVE_SASL 1) -else (BUILD_SASL) - set(HAVE_SASL 0) -endif (BUILD_SASL) -set(QPID_BROKER_SASL_NAME "qpidd" CACHE STRING "SASL app name for the qpid broker") -mark_as_advanced(QPID_BROKER_SASL_NAME) - -# Optional SSL/TLS support. Requires Netscape Portable Runtime on Linux. - -# According to some cmake docs this is not a reliable way to detect -# pkg-configed libraries, but it's no worse than what we did under -# autotools -pkg_check_modules(NSS nss) - -set (ssl_default ${ssl_force}) -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - set (ssl_default ON) -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (NSS_FOUND) - set (ssl_default ON) - endif (NSS_FOUND) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -option(BUILD_SSL "Build with support for SSL" ${ssl_default}) - -if (BUILD_SSL) - if (CMAKE_SYSTEM_NAME STREQUAL Windows) - set (sslcommon_SOURCES - qpid/sys/windows/SslAsynchIO.cpp - qpid/sys/windows/SslCredential.cpp - qpid/sys/windows/SslCredential.h - qpid/sys/windows/util.cpp - qpid/sys/windows/util.h - ) - - set (ssl_SOURCES - qpid/broker/windows/SslProtocolFactory.cpp - ) - - set (sslconnector_SOURCES - qpid/client/windows/SslConnector.cpp - ) - set (ssl_INCLUDES "") - set (ssl_LIBDIRS "") - set (ssl_LIBS Crypt32.lib 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) - - set (sslcommon_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 - ) - - set (ssl_SOURCES - qpid/sys/SslPlugin.cpp - ) - - set (sslconnector_SOURCES - qpid/client/SslConnector.cpp - qpid/messaging/amqp/SslTransport.cpp - ) - - 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 -CHECK_LIBRARY_EXISTS (xerces-c _init "" HAVE_XERCES) -CHECK_INCLUDE_FILE_CXX (xercesc/framework/MemBufInputSource.hpp HAVE_XERCES_H) -CHECK_INCLUDE_FILE_CXX (xqilla/xqilla-simple.hpp HAVE_XQILLA_H) -CHECK_INCLUDE_FILE_CXX (xqilla/ast/XQEffectiveBooleanValue.hpp HAVE_XQ_EBV) - -set (xml_default ${xml_force}) -if (CMAKE_SYSTEM_NAME STREQUAL Windows) -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (HAVE_XERCES AND HAVE_XERCES_H) - if (HAVE_XQILLA_H) - set (xml_default ON) - endif (HAVE_XQILLA_H) - endif (HAVE_XERCES AND HAVE_XERCES_H) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -option(BUILD_XML "Build with XML Exchange" ${xml_default}) - -if (BUILD_XML) - if (NOT HAVE_XERCES) - message(FATAL_ERROR "XML Exchange support requested but xerces-c library not found") - endif (NOT HAVE_XERCES) - if (NOT HAVE_XERCES_H) - message(FATAL_ERROR "XML Exchange support requested but Xerces-C headers not found") - endif (NOT HAVE_XERCES_H) - if (NOT HAVE_XQILLA_H) - message(FATAL_ERROR "XML Exchange support requested but XQilla headers not found") - endif (NOT HAVE_XQILLA_H) - - if (HAVE_XQ_EBV) - add_definitions(-DXQ_EFFECTIVE_BOOLEAN_VALUE_HPP) - endif (HAVE_XQ_EBV) - - add_library (xml MODULE - qpid/xml/XmlExchange.cpp - qpid/xml/XmlExchange.h - qpid/xml/XmlExchangePlugin.cpp) - target_link_libraries (xml xerces-c xqilla qpidbroker qpidcommon) - set_target_properties (xml PROPERTIES - PREFIX "") - install (TARGETS xml - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - - set(xml_tests XmlClientSessionTest) - -endif (BUILD_XML) - -set (acl_SOURCES - 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/AclLexer.cpp - qpid/acl/AclLexer.h - qpid/acl/AclPlugin.cpp - qpid/acl/AclReader.cpp - qpid/acl/AclReader.h - qpid/acl/AclResourceCounter.cpp - qpid/acl/AclResourceCounter.h - qpid/acl/AclValidator.cpp - qpid/acl/AclValidator.h - ) - -set (ha_default ON) - -option(BUILD_HA "Build Active-Passive HA plugin" ${ha_default}) - -if (BUILD_HA) - set (ha_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/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/IdSetter.h - qpid/ha/LogPrefix.cpp - qpid/ha/LogPrefix.h - qpid/ha/Membership.cpp - qpid/ha/Membership.h - qpid/ha/Primary.cpp - qpid/ha/Primary.h - qpid/ha/PrimaryQueueLimits.h - qpid/ha/QueueGuard.cpp - qpid/ha/QueueGuard.h - qpid/ha/QueueReplicator.cpp - qpid/ha/QueueReplicator.h - qpid/ha/QueueSnapshot.h - qpid/ha/QueueSnapshot.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 - ) - - add_library (ha MODULE ${ha_SOURCES}) - target_link_libraries (ha - qpidtypes qpidcommon qpidbroker qpidmessaging - ${Boost_PROGRAM_OPTIONS_LIBRARY}) - set_target_properties (ha PROPERTIES - PREFIX "") - install (TARGETS ha - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) -endif (BUILD_HA) - -# Check for optional RDMA support requirements -include (rdma.cmake) - -# Check for optional AMQP 1.0 support requirements -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 -) - -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - - set (qpidcommon_platform_SOURCES - qpid/log/windows/SinkOptions.cpp - qpid/sys/windows/AsynchIO.cpp - qpid/sys/windows/Path.cpp - qpid/sys/windows/FileSysDir.cpp - qpid/sys/windows/IocpPoller.cpp - qpid/sys/windows/IOHandle.cpp - qpid/sys/windows/LockFile.cpp - qpid/sys/windows/MemoryMappedFile.cpp - qpid/sys/windows/PipeHandle.cpp - qpid/sys/windows/PollableCondition.cpp - qpid/sys/windows/Shlib.cpp - qpid/sys/windows/WinSocket.cpp - qpid/sys/windows/SocketAddress.cpp - qpid/sys/windows/StrError.cpp - qpid/sys/windows/SystemInfo.cpp - qpid/sys/windows/Thread.cpp - qpid/sys/windows/Time.cpp - qpid/client/windows/SaslFactory.cpp - ) - - set (qpidcommon_platform_LIBS - ${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 (qpidclient_platform_SOURCES - qpid/client/windows/ClientDllMain.cpp - ) - - set (qpidd_platform_SOURCES - windows/QpiddBroker.cpp - windows/SCM.cpp - ) - -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - - # POSIX (Non-Windows) platforms have a lot of overlap in sources; the only - # major difference is the poller module. - if (QPID_POLLER STREQUAL poll) - set (qpid_poller_module - qpid/sys/posix/PosixPoller.cpp - ) - elseif (QPID_POLLER STREQUAL epoll) - set (qpid_poller_module - qpid/sys/epoll/EpollPoller.cpp - ) - endif (QPID_POLLER STREQUAL poll) - - # Set default System Info module - set (qpid_system_module - qpid/sys/posix/SystemInfo.cpp - ) - - if (CMAKE_SYSTEM_NAME STREQUAL Linux) - # 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) - # On Solaris override the system info module - set (qpid_system_module - qpid/sys/solaris/SystemInfo.cpp - ) - # On Sun we want -lpthread -lthread as the 2nd last and last libs passed to linker - set (qpidtypes_platform_LIBS ${qpidtypes_platform_LIBS} - pthread - thread - ) - endif (CMAKE_SYSTEM_NAME STREQUAL SunOS) - - if (CMAKE_SYSTEM_NAME STREQUAL AIX) - set (qpid_system_module - qpid/sys/aix/SystemInfo.cpp - ) - endif (CMAKE_SYSTEM_NAME STREQUAL AIX) - - if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro) - # -lmalloc needed for mallinfo. - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lmalloc") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lmalloc") - endif (CMAKE_CXX_COMPILER_ID STREQUAL SunPro) - - set (qpidcommon_platform_SOURCES - qpid/sys/posix/AsynchIO.cpp - qpid/sys/posix/Condition.cpp - qpid/sys/posix/Fork.cpp - qpid/sys/posix/Path.cpp - qpid/sys/posix/FileSysDir.cpp - qpid/sys/posix/IOHandle.cpp - qpid/sys/posix/LockFile.cpp - qpid/sys/posix/MemoryMappedFile.cpp - qpid/sys/posix/Mutex.cpp - qpid/sys/posix/PipeHandle.cpp - qpid/sys/posix/PollableCondition.cpp - qpid/sys/posix/Shlib.cpp - qpid/log/posix/SinkOptions.cpp - qpid/sys/posix/BSDSocket.cpp - qpid/sys/posix/SocketAddress.cpp - qpid/sys/posix/StrError.cpp - qpid/sys/posix/Thread.cpp - qpid/sys/posix/Time.cpp - qpid/SaslFactory.cpp - - ${qpid_system_module} - ${qpid_poller_module} - ) - - set (qpidcommon_platform_LIBS - "${CMAKE_DL_LIBS}" - "${clock_gettime_LIB}" - ) - - set (qpidbroker_platform_SOURCES - qpid/broker/Daemon.cpp - qpid/broker/SaslAuthenticator.cpp - qpid/broker/SignalHandler.h - qpid/broker/SignalHandler.cpp - qpid/broker/posix/BrokerDefaults.cpp - qpid/broker/posix/SocketFDPlugin.cpp - ) - - set (qpidclient_platform_SOURCES - ) - - set (qpidd_platform_SOURCES - posix/QpiddBroker.cpp - ) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -set (qpidcommon_SOURCES - ${rgen_framing_srcs} - ${qpidcommon_platform_SOURCES} - ${qpidcommon_sasl_source} - ${sslcommon_SOURCES} - qpid/assert.cpp - qpid/AclHost.cpp - qpid/Address.cpp - qpid/DataDir.cpp - qpid/Exception.cpp - qpid/Modules.cpp - qpid/Options.cpp - qpid/Plugin.cpp - qpid/RefCountedBuffer.cpp - qpid/SessionState.cpp - qpid/SessionId.cpp - 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 - qpid/framing/AMQBody.cpp - qpid/framing/AMQMethodBody.cpp - qpid/framing/AMQContentBody.cpp - qpid/framing/AMQFrame.cpp - qpid/framing/AMQHeaderBody.cpp - qpid/framing/AMQHeartbeatBody.cpp - qpid/framing/Array.cpp - qpid/framing/Buffer.cpp - qpid/framing/FieldTable.cpp - qpid/framing/FieldValue.cpp - qpid/framing/FrameSet.cpp - qpid/framing/FrameDecoder.cpp - qpid/framing/List.cpp - qpid/framing/ProtocolInitiation.cpp - qpid/framing/ProtocolVersion.cpp - qpid/framing/SendContent.cpp - qpid/framing/SequenceNumber.cpp - qpid/framing/SequenceNumberSet.cpp - qpid/framing/SequenceSet.cpp - qpid/framing/Proxy.cpp - qpid/framing/Uuid.cpp - qpid/framing/TransferContent.cpp - qpid/log/Logger.cpp - qpid/log/Options.cpp - qpid/log/OstreamOutput.cpp - qpid/log/Selector.cpp - qpid/log/Statement.cpp - qpid/management/Buffer.cpp - qpid/management/ConnectionSettings.cpp - qpid/management/Mutex.cpp - qpid/management/Manageable.cpp - qpid/management/ManagementObject.cpp - qpid/sys/AggregateOutput.cpp - qpid/sys/AsynchIOHandler.cpp - qpid/sys/Dispatcher.cpp - qpid/sys/DispatchHandle.cpp - qpid/sys/Runnable.cpp - qpid/sys/Shlib.cpp - qpid/sys/Timer.cpp - qpid/sys/TimerWarnings.cpp - 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 - 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/messaging/amqp/Transport.h - qpid/messaging/amqp/Transport.cpp - qpid/messaging/amqp/TransportContext.h - ${qpid_memstat_module} -) -add_msvc_version (qpidcommon library dll) - -add_library (qpidcommon SHARED ${qpidcommon_SOURCES}) - -target_link_libraries (qpidcommon qpidtypes - ${qpidcommon_platform_LIBS} - ${Boost_PROGRAM_OPTIONS_LIBRARY} - "${sasl_LIB}" - ${ssl_LIBS}) - -set_target_properties (qpidcommon PROPERTIES - VERSION ${qpidcommon_version} - SOVERSION ${qpidcommon_version_major}) - -install (TARGETS qpidcommon - RUNTIME DESTINATION ${QPID_INSTALL_BINDIR} COMPONENT ${QPID_COMPONENT_COMMON} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_COMMON} - ARCHIVE DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_COMMON}) -install_pdb (qpidcommon ${QPID_COMPONENT_COMMON}) - -set(qpidtypes_SOURCES - qpid/types/Exception.cpp - qpid/types/Uuid.cpp - qpid/types/Variant.cpp - ${uuid_SRC} -) -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 "${uuid_LIB}") -set_target_properties (qpidtypes PROPERTIES - LINK_FLAGS "${HIDE_SYMBOL_FLAGS} ${LINK_VERSION_SCRIPT_FLAG}" - VERSION ${qpidtypes_version} - SOVERSION ${qpidtypes_version_major}) - -install(TARGETS qpidtypes - RUNTIME DESTINATION ${QPID_INSTALL_BINDIR} COMPONENT ${QPID_COMPONENT_COMMON} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_COMMON} - ARCHIVE 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} - ${sslconnector_SOURCES} - qpid/client/Bounds.cpp - qpid/client/Completion.cpp - qpid/client/CompletionImpl.cpp - qpid/client/Connection.cpp - qpid/client/ConnectionHandler.cpp - qpid/client/ConnectionImpl.cpp - qpid/client/ConnectionSettings.cpp - qpid/client/Connector.cpp - qpid/client/Demux.cpp - qpid/client/Dispatcher.cpp - qpid/client/FailoverManager.cpp - qpid/client/FailoverListener.cpp - qpid/client/Future.cpp - qpid/client/FutureCompletion.cpp - qpid/client/FutureResult.cpp - qpid/client/LoadPlugins.cpp - qpid/client/LocalQueue.cpp - qpid/client/LocalQueueImpl.cpp - qpid/client/Message.cpp - qpid/client/MessageImpl.cpp - qpid/client/MessageListener.cpp - qpid/client/MessageReplayTracker.cpp - qpid/client/QueueOptions.cpp - qpid/client/Results.cpp - qpid/client/SessionBase_0_10.cpp - qpid/client/SessionBase_0_10Access.h - qpid/client/ConnectionAccess.h - qpid/client/SessionImpl.cpp - qpid/client/StateManager.cpp - qpid/client/Subscription.cpp - qpid/client/SubscriptionImpl.cpp - qpid/client/SubscriptionManager.cpp - qpid/client/SubscriptionManagerImpl.cpp - qpid/client/TCPConnector.cpp -) -add_msvc_version (qpidclient library dll) - -add_library (qpidclient SHARED ${qpidclient_SOURCES}) - -target_link_libraries (qpidclient qpidcommon qpidtypes - ${ssl_LIBS}) - -set_target_properties (qpidclient PROPERTIES - VERSION ${qpidclient_version} - SOVERSION ${qpidclient_version_major}) - -install (TARGETS qpidclient - RUNTIME DESTINATION ${QPID_INSTALL_BINDIR} COMPONENT ${QPID_COMPONENT_CLIENT} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_CLIENT} - ARCHIVE DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_CLIENT}) -install (DIRECTORY ../include/qpid - DESTINATION ${QPID_INSTALL_INCLUDEDIR} - COMPONENT ${QPID_COMPONENT_CLIENT_INCLUDE} - PATTERN ".svn" EXCLUDE) -install_pdb (qpidclient ${QPID_COMPONENT_CLIENT}) - -set (qpidmessaging_SOURCES - ${amqpc_SOURCES} - qpid/messaging/AddressImpl.h - qpid/messaging/ConnectionImpl.h - qpid/messaging/ReceiverImpl.h - qpid/messaging/SessionImpl.h - qpid/messaging/SenderImpl.h - 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 - qpid/messaging/Address.cpp - qpid/messaging/AddressParser.h - qpid/messaging/AddressParser.cpp # The functions in here are not in the public interface, but qmf uses them - qpid/messaging/Connection.cpp - qpid/messaging/Duration.cpp - qpid/messaging/exceptions.cpp - qpid/messaging/FailoverUpdates.cpp - qpid/messaging/Logger.cpp - qpid/messaging/Message.cpp - qpid/messaging/Receiver.cpp - qpid/messaging/Session.cpp - qpid/messaging/Sender.cpp - #functions from the following are not in the public interface but are used by the AMQP 1.0 client module - qpid/messaging/ConnectionOptions.h - qpid/messaging/ConnectionOptions.cpp - qpid/messaging/MessageImpl.h - qpid/messaging/MessageImpl.cpp - qpid/messaging/Message_io.cpp - qpid/messaging/ProtocolRegistry.cpp - qpid/messaging/amqp/EncodedMessage.h - qpid/messaging/amqp/EncodedMessage.cpp -) - -add_msvc_version (qpidmessaging library dll) - -add_library (qpidmessaging SHARED ${qpidmessaging_SOURCES}) -target_link_libraries (qpidmessaging qpidtypes qpidclient qpidcommon ${Proton_LIBRARIES}) -set_target_properties (qpidmessaging PROPERTIES - LINK_FLAGS "${HIDE_SYMBOL_FLAGS} ${LINK_VERSION_SCRIPT_FLAG}" - COMPILE_FLAGS "${HIDE_SYMBOL_FLAGS}" - VERSION ${qpidmessaging_version} - SOVERSION ${qpidmessaging_version_major}) -install (TARGETS qpidmessaging - RUNTIME DESTINATION ${QPID_INSTALL_BINDIR} COMPONENT ${QPID_COMPONENT_CLIENT} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_CLIENT} - ARCHIVE DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_CLIENT}) -install_pdb (qpidmessaging ${QPID_COMPONENT_CLIENT}) - -add_api_test(qpidmessaging) - -if (MSVC) - # Install the DtcPlugin project and call it qpidxarm. - set(AMQP_WCF_DIR ${qpid-cpp_SOURCE_DIR}/../wcf) - set(qpidxarm_SOURCES ${AMQP_WCF_DIR}/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp) - if (EXISTS ${qpidxarm_SOURCES}) - add_msvc_version (qpidxarm library dll) - add_library (qpidxarm SHARED ${qpidxarm_SOURCES}) - target_link_libraries (qpidxarm qpidclient qpidcommon) - install (TARGETS qpidxarm - RUNTIME DESTINATION ${QPID_INSTALL_BINDIR} COMPONENT ${QPID_COMPONENT_CLIENT} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_CLIENT} - ARCHIVE DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_CLIENT}) - install_pdb (qpidxarm ${QPID_COMPONENT_CLIENT}) - endif (EXISTS ${qpidxarm_SOURCES}) -endif (MSVC) - -set (qpidbroker_SOURCES - ${mgen_broker_cpp} - ${qpidbroker_platform_SOURCES} - ${acl_SOURCES} - ${ssl_SOURCES} - qpid/amqp_0_10/Connection.h - qpid/amqp_0_10/Connection.cpp - qpid/broker/AsyncCommandCallback.h - qpid/broker/AsyncCommandCallback.cpp - qpid/broker/Broker.cpp - qpid/broker/Credit.cpp - qpid/broker/Exchange.cpp - qpid/broker/Fairshare.cpp - qpid/broker/MessageDeque.cpp - qpid/broker/MessageMap.cpp - qpid/broker/ObjectFactory.h - qpid/broker/ObjectFactory.cpp - qpid/broker/PriorityQueue.cpp - qpid/broker/Protocol.cpp - qpid/broker/Queue.cpp - qpid/broker/QueueCleaner.cpp - qpid/broker/QueueListeners.cpp - qpid/broker/FifoDistributor.cpp - qpid/broker/MessageGroupManager.cpp - qpid/broker/PersistableMessage.cpp - qpid/broker/PersistableObject.cpp - qpid/broker/Bridge.cpp - qpid/broker/amqp_0_10/Connection.cpp - qpid/broker/ConnectionHandler.cpp - qpid/broker/DeliverableMessage.cpp - qpid/broker/DeliveryRecord.cpp - qpid/broker/DirectExchange.cpp - qpid/broker/DtxAck.cpp - qpid/broker/DtxBuffer.cpp - qpid/broker/DtxManager.cpp - qpid/broker/DtxTimeout.cpp - qpid/broker/DtxWorkRecord.cpp - qpid/broker/ExchangeRegistry.cpp - qpid/broker/FanOutExchange.cpp - qpid/broker/HeadersExchange.cpp - qpid/broker/IngressCompletion.cpp - qpid/broker/Link.cpp - qpid/broker/LinkRegistry.cpp - qpid/broker/LossyLvq.cpp - qpid/broker/LossyQueue.cpp - qpid/broker/Lvq.cpp - qpid/broker/Message.cpp - qpid/broker/MessageAdapter.cpp - qpid/broker/MessageBuilder.cpp - qpid/broker/MessageStoreModule.cpp - qpid/broker/NameGenerator.cpp - qpid/broker/NullMessageStore.cpp - qpid/broker/PagedQueue.cpp - qpid/broker/QueueBindings.cpp - qpid/broker/QueuedMessage.cpp - qpid/broker/QueueCursor.cpp - qpid/broker/QueueDepth.cpp - qpid/broker/QueueFactory.cpp - qpid/broker/QueueRegistry.cpp - qpid/broker/QueueSettings.cpp - qpid/broker/QueueFlowLimit.cpp - qpid/broker/RecoveryManagerImpl.cpp - qpid/broker/RecoveredEnqueue.cpp - qpid/broker/RecoveredDequeue.cpp - qpid/broker/RetryList.cpp - qpid/broker/SecureConnection.cpp - qpid/broker/Selector.h - qpid/broker/Selector.cpp - qpid/broker/SelectorExpression.h - qpid/broker/SelectorExpression.cpp - qpid/broker/SelectorToken.h - 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 - qpid/broker/SessionState.h - qpid/broker/SessionState.cpp - qpid/broker/SessionManager.h - qpid/broker/SessionManager.cpp - qpid/broker/SessionContext.h - qpid/broker/SessionHandler.h - qpid/broker/SessionHandler.cpp - qpid/broker/System.cpp - qpid/broker/ThresholdAlerts.cpp - qpid/broker/TopicExchange.cpp - qpid/broker/TxAccept.cpp - qpid/broker/TxBuffer.cpp - qpid/broker/TxDequeue.h - qpid/broker/TxDequeue.cpp - qpid/broker/Vhost.cpp - qpid/broker/amqp_0_10/MessageTransfer.cpp - qpid/management/ManagementAgent.cpp - qpid/management/ManagementDirectExchange.cpp - qpid/management/ManagementTopicExchange.cpp - qpid/sys/SocketTransport.cpp - qpid/sys/TCPIOPlugin.cpp -) -add_msvc_version (qpidbroker library dll) -add_library (qpidbroker SHARED ${qpidbroker_SOURCES}) - -target_link_libraries (qpidbroker qpidcommon qpidtypes - "${sasl_LIB}" - ${ssl_server_LIBS}) - -set_target_properties (qpidbroker PROPERTIES - VERSION ${qpidbroker_version} - SOVERSION ${qpidbroker_version_major}) - -if (CMAKE_CXX_COMPILER_ID MATCHES XL) - set_target_properties (qpidbroker PROPERTIES LINK_FLAGS -Wl,-bbigtoc) -endif (CMAKE_CXX_COMPILER_ID MATCHES XL) - -if (MSVC) - set_target_properties (qpidbroker PROPERTIES COMPILE_FLAGS /wd4290) -endif (MSVC) -install (TARGETS qpidbroker - RUNTIME DESTINATION ${QPID_INSTALL_BINDIR} COMPONENT ${QPID_COMPONENT_BROKER} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_BROKER} - ARCHIVE DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_BROKER}) -install_pdb (qpidbroker ${QPID_COMPONENT_BROKER}) - - -set (qpidd_SOURCES - ${qpidd_platform_SOURCES} - qpidd.cpp - qpidd.h -) -add_msvc_version (qpidd application exe) -add_executable (qpidd ${qpidd_SOURCES}) -target_link_libraries (qpidd qpidbroker qpidcommon) -install (TARGETS qpidd - RUNTIME DESTINATION ${QPID_INSTALL_SBINDIR} COMPONENT ${QPID_COMPONENT_BROKER} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_BROKER} - ARCHIVE DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_BROKER}) -if (CPACK_GENERATOR STREQUAL "NSIS") - set (CPACK_NSIS_MENU_LINKS - "qpidd" "Start Qpid Broker") -endif (CPACK_GENERATOR STREQUAL "NSIS") - -if (NOT WIN32) - set (qmf2_platform_headers - ../include/qmf/posix/EventNotifier.h - ) - set (qmf2_platform_sources - qmf/PosixEventNotifier.cpp - qmf/PosixEventNotifierImpl.cpp - ) -endif (NOT WIN32) - - set (qmf2_HEADERS - ../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/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 - ${qmf2_platform_headers} - ) - - set (qmf2_SOURCES - ${qmf2_HEADERS} - qmf/agentCapability.h - qmf/Agent.cpp - qmf/AgentEvent.cpp - qmf/AgentEventImpl.h - qmf/AgentImpl.h - qmf/AgentSession.cpp - 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.h - qmf/EventNotifierImpl.cpp - qmf/exceptions.cpp - qmf/Expression.cpp - qmf/Expression.h - qmf/Hash.cpp - qmf/Hash.h - qmf/PrivateImplRef.h - qmf/Query.cpp - qmf/QueryImpl.h - qmf/Schema.cpp - qmf/SchemaCache.cpp - qmf/SchemaCache.h - 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 - ${qmf2_platform_sources} - ) - - add_msvc_version (qmf2 library dll) - add_library (qmf2 SHARED ${qmf2_SOURCES}) - target_link_libraries (qmf2 qpidmessaging qpidtypes qpidclient qpidcommon) - set_target_properties (qmf2 PROPERTIES - VERSION ${qmf2_version} - SOVERSION ${qmf2_version_major}) - install (TARGETS qmf2 OPTIONAL - RUNTIME DESTINATION ${QPID_INSTALL_BINDIR} COMPONENT ${QPID_COMPONENT_QMF} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_QMF} - ARCHIVE DESTINATION ${QPID_INSTALL_LIBDIR} COMPONENT ${QPID_COMPONENT_QMF}) - install (FILES ${qmf2_HEADERS} - DESTINATION ${QPID_INSTALL_INCLUDEDIR}/qmf - COMPONENT ${QPID_COMPONENT_QMF}) - install_pdb (qmf2 ${QPID_COMPONENT_QMF}) - -# -# Legacy store -# -include (legacystore.cmake) -# -# Linear store -# -include (linearstore.cmake) - -# Now create the config file from all the info learned above. -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/config.h) -add_subdirectory(qpid/store) -add_subdirectory(tests) -add_subdirectory(tests/legacystore) -add_subdirectory(tests/linearstore) - -# Support for pkg-config - -# Compatible variable names used in the pkg config files also for autoconf -set (prefix ${CMAKE_INSTALL_PREFIX}) -set (exec_prefix ${CMAKE_INSTALL_PREFIX}) -set_absolute_install_path (libdir ${QPID_INSTALL_LIBDIR}) -set_absolute_install_path (includedir ${QPID_INSTALL_INCLUDEDIR}) -set (VERSION ${QPID_VERSION_FULL}) - -#add_custom_target(pkgconfig ALL echo DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/qpid.pc) -#add_dependencies(pkgconfig ${CMAKE_CURRENT_BINARY_DIR}/qmf2.pc) -configure_file(qpid.pc.in ${CMAKE_CURRENT_BINARY_DIR}/qpid.pc @ONLY) -configure_file(qmf2.pc.in ${CMAKE_CURRENT_BINARY_DIR}/qmf2.pc @ONLY) -install (FILES ${CMAKE_CURRENT_BINARY_DIR}/qpid.pc ${CMAKE_CURRENT_BINARY_DIR}/qmf2.pc - DESTINATION ${QPID_INSTALL_LIBDIR}/pkgconfig - COMPONENT ${QPID_COMPONENT_COMMON}) - -if (DEFINED CMAKE_IMPORT_LIBRARY_PREFIX) -set(QPIDMSGLIB ${CMAKE_IMPORT_LIBRARY_PREFIX}qpidmessaging${CMAKE_IMPORT_LIBRARY_SUFFIX}) -set(QPIDMSGLIBDEBUG ${CMAKE_IMPORT_LIBRARY_PREFIX}qpidmessaging${CMAKE_DEBUG_POSTFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}) -set(QPIDTYPESLIB ${CMAKE_IMPORT_LIBRARY_PREFIX}qpidtypes${CMAKE_IMPORT_LIBRARY_SUFFIX}) -set(QPIDTYPESLIBDEBUG ${CMAKE_IMPORT_LIBRARY_PREFIX}qpidtypes${CMAKE_DEBUG_POSTFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}) -else () -set(QPIDMSGLIB ${CMAKE_SHARED_LIBRARY_PREFIX}qpidmessaging${CMAKE_SHARED_LIBRARY_SUFFIX}) -set(QPIDMSGLIBDEBUG ${CMAKE_SHARED_LIBRARY_PREFIX}qpidmessaging${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}) -set(QPIDTYPESLIB ${CMAKE_SHARED_LIBRARY_PREFIX}qpidtypes${CMAKE_SHARED_LIBRARY_SUFFIX}) -set(QPIDTYPESLIBDEBUG ${CMAKE_SHARED_LIBRARY_PREFIX}qpidtypes${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}) -endif () - -configure_file(QpidConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/QpidConfig.cmake @ONLY) -configure_file(QpidConfigVersion.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/QpidConfigVersion.cmake @ONLY) -install (FILES - ${CMAKE_CURRENT_BINARY_DIR}/QpidConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/QpidConfigVersion.cmake - DESTINATION ${QPID_INSTALL_LIBDIR}/cmake/Qpid - COMPONENT ${QPID_COMPONENT_COMMON}) - diff --git a/qpid/cpp/src/CMakeWinVersions.cmake b/qpid/cpp/src/CMakeWinVersions.cmake deleted file mode 100644 index 0bac7cab47..0000000000 --- a/qpid/cpp/src/CMakeWinVersions.cmake +++ /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. -# - -# -# Versions settings overrides for Windows dll/exe file version resource. -# These values are compiled into the dll and exe files. -# -# The settings override precedence from lowest to highest: -# 1. CPACK settings from cpp/CMakeLists.txt -# 2. Global settings from this file -# 3. Command line version number (only) from add_msvc_version_full call -# 4. Per-project settings from this file -# - -# -# Specification of global settings for all projects. -# -# set ("winver_PACKAGE_NAME" "qpid-cpp") -# set ("winver_DESCRIPTION_SUMMARY" "Apache Qpid C++") -# set ("winver_FILE_VERSION_N1" "0") -# set ("winver_FILE_VERSION_N2" "11") -# set ("winver_FILE_VERSION_N3" "0") -# set ("winver_FILE_VERSION_N4" "0") -# set ("winver_PRODUCT_VERSION_N1" "0") -# set ("winver_PRODUCT_VERSION_N2" "11") -# set ("winver_PRODUCT_VERSION_N3" "0") -# set ("winver_PRODUCT_VERSION_N4" "0") -# set ("winver_LEGAL_COPYRIGHT" "") - -# -# Specification of per-project settings: -# -# set ("winver_${projectName}_FileVersionBinary" "0,11,0,0") -# set ("winver_${projectName}_ProductVersionBinary" "0,11,0,0") -# set ("winver_${projectName}_FileVersionString" "0, 11, 0, 0") -# set ("winver_${projectName}_ProductVersionString" "0, 11, 0, 0") -# set ("winver_${projectName}_FileDescription" "qpid-cpp-qpidcommon Library") -# set ("winver_${projectName}_LegalCopyright" "") -# set ("winver_${projectName}_InternalName" "qpidcommon") -# set ("winver_${projectName}_OriginalFilename" "qpidcommon.dll") -# set ("winver_${projectName}_ProductName" "Apache Qpid C++") diff --git a/qpid/cpp/src/QpidConfig.cmake.in b/qpid/cpp/src/QpidConfig.cmake.in deleted file mode 100644 index 3f84e3b6b0..0000000000 --- a/qpid/cpp/src/QpidConfig.cmake.in +++ /dev/null @@ -1,30 +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. -# - -# Name: Qpid -# Description: Qpid Client C library -# Version: @VERSION@ -# URL: http://qpid.apache.org/ - -set (Qpid_VERSION @VERSION@) - -set (Qpid_INCLUDE_DIRS @includedir@) -set (Qpid_LIBRARIES optimized @libdir@/@QPIDMSGLIB@ @libdir@/@QPIDTYPESLIB@ debug @libdir@/@QPIDMSGLIBDEBUG@ @libdir@/@QPIDTYPESLIBDEBUG@) - -set (Qpid_FOUND True) diff --git a/qpid/cpp/src/QpidConfigVersion.cmake.in b/qpid/cpp/src/QpidConfigVersion.cmake.in deleted file mode 100644 index d85924ab7e..0000000000 --- a/qpid/cpp/src/QpidConfigVersion.cmake.in +++ /dev/null @@ -1,30 +0,0 @@ -# This is a basic version file for the Config-mode of find_package(). -# It is used by write_basic_package_version_file() as input file for configure_file() -# to create a version-file which can be installed along a config.cmake file. -# -# The created file sets PACKAGE_VERSION_EXACT if the current version string and -# the requested version string are exactly the same and it sets -# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version. - -set(PACKAGE_VERSION "@VERSION@") - -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif() -endif() - -# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: -if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") - return() -endif() - -# check that the installed version has the same 32/64bit-ness as the one which is currently searching: -if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "@CMAKE_SIZEOF_VOID_P@") - math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") - set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") - set(PACKAGE_VERSION_UNSUITABLE TRUE) -endif() diff --git a/qpid/cpp/src/amqp.cmake b/qpid/cpp/src/amqp.cmake deleted file mode 100644 index ea36a92904..0000000000 --- a/qpid/cpp/src/amqp.cmake +++ /dev/null @@ -1,156 +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. -# - -# Optional AMQP1.0 support. Requires proton toolkit. - -find_package(Proton 0.7) - -set (amqp_default ${amqp_force}) -set (maximum_version 0.9) -if (Proton_FOUND) - if (Proton_VERSION VERSION_GREATER ${maximum_version}) - message(WARNING "Qpid proton ${Proton_VERSION} is not a tested version and might not be compatible, ${maximum_version} is highest tested; build may not work") - endif (Proton_VERSION VERSION_GREATER ${maximum_version}) - message(STATUS "Qpid proton found, amqp 1.0 support enabled") - set (amqp_default ON) - if (Proton_VERSION VERSION_GREATER 0.7) - set (USE_PROTON_TRANSPORT_CONDITION 1) - set (HAVE_PROTON_EVENTS 1) - endif (Proton_VERSION VERSION_GREATER 0.7) - if (Proton_VERSION VERSION_GREATER 0.8) - set (NO_PROTON_DELIVERY_TAG_T 1) - endif (Proton_VERSION VERSION_GREATER 0.8) -else () - message(STATUS "Qpid proton not found, amqp 1.0 support not enabled") -endif () - -option(BUILD_AMQP "Build with support for AMQP 1.0" ${amqp_default}) -if (BUILD_AMQP) - - if (NOT Proton_FOUND) - message(FATAL_ERROR "Qpid proton not found, required for amqp 1.0 support") - endif () - - set (amqp_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/NodePolicy.h - qpid/broker/amqp/NodePolicy.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 - ) - - include_directories(${Proton_INCLUDE_DIRS}) - - add_library (amqp MODULE ${amqp_SOURCES}) - target_link_libraries (amqp qpidtypes qpidbroker qpidcommon ${Proton_LIBRARIES}) - set_target_properties (amqp PROPERTIES - PREFIX "") - - install (TARGETS amqp - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - - set (amqpc_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/PnData.h - qpid/messaging/amqp/PnData.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 - qpid/messaging/amqp/Transaction.h - qpid/messaging/amqp/Transaction.cpp - qpid/messaging/amqp/util.h - qpid/messaging/amqp/util.cpp - ) - - if (WIN32) - list (APPEND amqp_SOURCES qpid/messaging/amqp/windows/SslTransport.cpp) - list (APPEND amqpc_SOURCES qpid/messaging/amqp/windows/SslTransport.cpp) - endif (WIN32) -else (BUILD_AMQP) - # ensure that qpid build ignores proton - UNSET( amqpc_SOURCES ) - UNSET( PROTON_LIBRARIES ) -endif (BUILD_AMQP) diff --git a/qpid/cpp/src/check-abi b/qpid/cpp/src/check-abi deleted file mode 100755 index 498c6bd322..0000000000 --- a/qpid/cpp/src/check-abi +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env 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. -# - -MKTEMP="mktemp /tmp/tmp.XXXXXXXXXX" - -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 - -LC_ALL=C -export LC_ALL - -# Extract exported symbols from library -nm -DC --defined-only -f s $1 | cut -f1 -d'|' -s | sed -e "$(./cppabi)" | sort -u > $syms_library - -# Process API syms (substitute in some typedefs etc.) -sed -e " - $(./expand_types) - /^\$/d - /^#.*\$/d -" $2 | 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/config.h.cmake b/qpid/cpp/src/config.h.cmake deleted file mode 100644 index 1e1f4087ee..0000000000 --- a/qpid/cpp/src/config.h.cmake +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * 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. - * - */ - -/* - * This file is automatically generated and will be overwritten by the - * next CMake invocation. - */ - -#ifndef QPID_CONFIG_H -#define QPID_CONFIG_H - -// PACKAGE_NAME and PACKAGE_VERSION are carry-overs from the autoconf world. -// They tend to cause confusion and problems when mixing headers from multiple -// autoconf-configured packages, so it's best to remove these in favor of -// Qpid-specific names as soon as the autoconf stuff is removed. -#define PACKAGE_NAME "${CMAKE_PROJECT_NAME}" -#define PACKAGE_VERSION "${qpidc_version}" - -#cmakedefine QPIDC_CONF_FILE "${QPIDC_CONF_FILE}" -#cmakedefine QPIDD_CONF_FILE "${QPIDD_CONF_FILE}" - -#cmakedefine QPIDC_MODULE_DIR "${QPIDC_MODULE_DIR}" -#cmakedefine QPIDD_MODULE_DIR "${QPIDD_MODULE_DIR}" - -#define QPID_SHLIB_PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}" -#define QPID_MODULE_PREFIX -#cmakedefine QPID_DEBUG_POSTFIX "${QPID_DEBUG_POSTFIX}" -#if defined(QPID_DEBUG_POSTFIX) && defined (_DEBUG) -# define QPID_SHLIB_POSTFIX QPID_DEBUG_POSTFIX -# define QPID_MODULE_POSTFIX QPID_DEBUG_POSTFIX -#else -# define QPID_SHLIB_POSTFIX -# define QPID_MODULE_POSTFIX -#endif -#define QPID_SHLIB_SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}" -#define QPID_MODULE_SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}" - -#define BROKER_SASL_NAME "${QPID_BROKER_SASL_NAME}" -#cmakedefine HAVE_SASL ${HAVE_SASL} - -#cmakedefine HAVE_SYS_SDT_H ${HAVE_SYS_SDT_H} -#cmakedefine HAVE_LOG_AUTHPRIV -#cmakedefine HAVE_LOG_FTP -#cmakedefine QPID_SIZE_T_DISTINCT -#cmakedefine USE_PROTON_TRANSPORT_CONDITION -#cmakedefine HAVE_PROTON_EVENTS -#cmakedefine NO_PROTON_DELIVERY_TAG_T -#endif /* QPID_CONFIG_H */ diff --git a/qpid/cpp/src/cppabi.cpp b/qpid/cpp/src/cppabi.cpp deleted file mode 100644 index 5767d6084c..0000000000 --- a/qpid/cpp/src/cppabi.cpp +++ /dev/null @@ -1,32 +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 - -#include - -int main() { -#if _GLIBCXX_USE_CXX11_ABI - std::cout << "s/\\[abi:cxx11\\]//"; - return 0; -#else - return 1; -#endif -} diff --git a/qpid/cpp/src/expand_types.cpp b/qpid/cpp/src/expand_types.cpp deleted file mode 100644 index 9e8cd1ee69..0000000000 --- a/qpid/cpp/src/expand_types.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include -#include -#include -#include -#include -#include - -#include "qpid/types/Variant.h" - -void print_type(const char* type, const char* mangled_type) -{ - int status; - char* demangled_type = - abi::__cxa_demangle(mangled_type, 0, 0, &status); - if (demangled_type) { - std::cout << "s/" << type << "/" << demangled_type << "/g\n"; - } - ::free(demangled_type); -} - -#define mangle_name(x) typeid(x).name() - -#define print_subst(x) print_type(#x, mangle_name(x)) - -int main() { - print_subst(uint64_t); - print_subst(uint32_t); - print_subst(uint16_t); - print_subst(uint8_t); - print_subst(size_t); - print_subst(int64_t); - print_subst(int32_t); - print_subst(int16_t); - print_subst(int8_t); - print_subst(std::string); - print_subst(qpid::types::Variant::Map); - print_subst(qpid::types::Variant::List); -} diff --git a/qpid/cpp/src/finddb.cmake b/qpid/cpp/src/finddb.cmake deleted file mode 100644 index 2f2f94f469..0000000000 --- a/qpid/cpp/src/finddb.cmake +++ /dev/null @@ -1,76 +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. -# -# - -if(UNIX) -# - Find BerkeleyDB -# Find the BerkeleyDB includes and library -# This module defines -# 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_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 db_cxx-4) -FIND_LIBRARY(DB_LIBRARY - NAMES ${DB_NAMES} - PATHS /usr/lib /usr/local/lib -) - -IF (DB_LIBRARY AND DB_CXX_INCLUDE_DIR) - SET(DB_LIBRARIES ${DB_LIBRARY}) - SET(DB_FOUND "YES") -ELSE (DB_LIBRARY AND DB_CXX_INCLUDE_DIR) - UNSET( DB_FOUND ) -ENDIF (DB_LIBRARY AND DB_CXX_INCLUDE_DIR) - - -IF (DB_FOUND) - IF (NOT DB_FIND_QUIETLY) - MESSAGE(STATUS "Found BerkeleyDB: ${DB_LIBRARIES}") - ENDIF (NOT DB_FIND_QUIETLY) -ELSE (DB_FOUND) - IF (DB_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find BerkeleyDB library") - ENDIF (DB_FIND_REQUIRED) -ENDIF (DB_FOUND) - -# Deprecated declarations. -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_CXX_INCLUDE_DIR -) - -else(UNIX) - MESSAGE(STATUS "BerkeleyDB is ignored on non-Unix platforms") - UNSET( DB_FOUND ) -endif(UNIX) diff --git a/qpid/cpp/src/legacystore.cmake b/qpid/cpp/src/legacystore.cmake deleted file mode 100644 index ef5df28c41..0000000000 --- a/qpid/cpp/src/legacystore.cmake +++ /dev/null @@ -1,172 +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 library CMake fragment, to be included in CMakeLists.txt -# - -if (DEFINED legacystore_force) - set (legacystore_default ${legacystore_force}) -else (DEFINED legacystore_force) - set (legacystore_default OFF) - if (UNIX) - # - # Find required BerkeleyDB - # - include (finddb.cmake) - if (DB_FOUND) - # - # find libaio - # - CHECK_LIBRARY_EXISTS (aio io_queue_init "" HAVE_AIO) - CHECK_INCLUDE_FILES (libaio.h HAVE_AIO_H) - if (HAVE_AIO AND HAVE_AIO_H) - # - # allow legacystore to be built - # - message(STATUS "BerkeleyDB for C++ and libaio found, Legacystore support disabled by default (deprecated, use linearstore instead).") - set (legacystore_default OFF) # Disabled, deprecated. Use linearstore instead. - else (HAVE_AIO AND HAVE_AIO_H) - if (NOT HAVE_AIO) - message(STATUS "Legacystore requires libaio which is absent.") - endif (NOT HAVE_AIO) - if (NOT HAVE_AIO_H) - message(STATUS "Legacystore requires libaio.h which is absent.") - endif (NOT HAVE_AIO_H) - endif (HAVE_AIO AND HAVE_AIO_H) - else (DB_FOUND) - message(STATUS "Legacystore requires BerkeleyDB for C++ which is absent.") - endif (DB_FOUND) - endif (UNIX) -endif (DEFINED legacystore_force) - -option(BUILD_LEGACYSTORE "Build legacystore persistent store" ${legacystore_default}) - -if (BUILD_LEGACYSTORE) - if (NOT UNIX) - message(FATAL_ERROR "Legacystore produced only on Unix platforms") - endif (NOT UNIX) - if (NOT DB_FOUND) - message(FATAL_ERROR "Legacystore requires BerkeleyDB for C++ which is absent.") - endif (NOT DB_FOUND) - if (NOT HAVE_AIO) - message(FATAL_ERROR "Legacystore requires libaio which is absent.") - endif (NOT HAVE_AIO) - if (NOT HAVE_AIO_H) - message(FATAL_ERROR "Legacystore requires libaio.h which is absent.") - endif (NOT HAVE_AIO_H) - - # Journal source files - set (legacy_jrnl_SOURCES - qpid/legacystore/jrnl/aio.cpp - qpid/legacystore/jrnl/cvar.cpp - qpid/legacystore/jrnl/data_tok.cpp - qpid/legacystore/jrnl/deq_rec.cpp - qpid/legacystore/jrnl/enq_map.cpp - qpid/legacystore/jrnl/enq_rec.cpp - qpid/legacystore/jrnl/fcntl.cpp - qpid/legacystore/jrnl/jcntl.cpp - qpid/legacystore/jrnl/jdir.cpp - qpid/legacystore/jrnl/jerrno.cpp - qpid/legacystore/jrnl/jexception.cpp - qpid/legacystore/jrnl/jinf.cpp - qpid/legacystore/jrnl/jrec.cpp - qpid/legacystore/jrnl/lp_map.cpp - qpid/legacystore/jrnl/lpmgr.cpp - qpid/legacystore/jrnl/pmgr.cpp - qpid/legacystore/jrnl/rmgr.cpp - qpid/legacystore/jrnl/rfc.cpp - qpid/legacystore/jrnl/rrfc.cpp - qpid/legacystore/jrnl/slock.cpp - qpid/legacystore/jrnl/smutex.cpp - qpid/legacystore/jrnl/time_ns.cpp - qpid/legacystore/jrnl/txn_map.cpp - qpid/legacystore/jrnl/txn_rec.cpp - qpid/legacystore/jrnl/wmgr.cpp - qpid/legacystore/jrnl/wrfc.cpp - ) - - # legacyStore source files - set (legacy_store_SOURCES - qpid/legacystore/StorePlugin.cpp - qpid/legacystore/BindingDbt.cpp - qpid/legacystore/BufferValue.cpp - qpid/legacystore/DataTokenImpl.cpp - qpid/legacystore/IdDbt.cpp - qpid/legacystore/IdSequence.cpp - qpid/legacystore/JournalImpl.cpp - qpid/legacystore/MessageStoreImpl.cpp - qpid/legacystore/PreparedTransaction.cpp - qpid/legacystore/TxnCtxt.cpp - ) - - set (legacystore_defines RHM_CLEAN) - - if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/db-inc.h) - message(STATUS "Including BDB from ${DB_CXX_INCLUDE_DIR}/db_cxx.h") - file(WRITE - ${CMAKE_CURRENT_BINARY_DIR}/db-inc.h - "#include <${DB_CXX_INCLUDE_DIR}/db_cxx.h>\n") - endif() - - add_library (legacystore MODULE - ${legacy_jrnl_SOURCES} - ${legacy_store_SOURCES} - ${legacy_qmf_SOURCES} - ) - - set_target_properties (legacystore PROPERTIES - PREFIX "" - COMPILE_DEFINITIONS "${legacystore_defines}" - OUTPUT_NAME legacystore - ) - - target_link_libraries (legacystore - ${clock_gettime_LIB} - aio - uuid - qpidcommon qpidtypes qpidbroker - ${DB_LIBRARY} - ) - - # For use in the store tests only - add_library (legacystore_shared SHARED - ${legacy_jrnl_SOURCES} - ${legacy_store_SOURCES} - ${legacy_qmf_SOURCES} - ) - - set_target_properties (legacystore_shared PROPERTIES - COMPILE_DEFINITIONS "${legacystore_defines}" - ) - - target_link_libraries (legacystore_shared - ${clock_gettime_LIB} - aio - uuid - qpidcommon qpidtypes qpidbroker - ${DB_LIBRARY} - ) - -install(TARGETS legacystore - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - -else (BUILD_LEGACYSTORE) - message(STATUS "Legacystore is excluded from build.") -endif (BUILD_LEGACYSTORE) diff --git a/qpid/cpp/src/libqpidmessaging-api-symbols.txt b/qpid/cpp/src/libqpidmessaging-api-symbols.txt deleted file mode 100644 index 23634857c2..0000000000 --- a/qpid/cpp/src/libqpidmessaging-api-symbols.txt +++ /dev/null @@ -1,243 +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. -# - -# 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&) - -# Logger -qpid::messaging::Logger::configure(int, char const**, std::string const&) -qpid::messaging::Logger::log(qpid::messaging::Level, char const*, int, char const*, std::string const&) -qpid::messaging::Logger::setOutput(qpid::messaging::LoggerOutput&) -qpid::messaging::Logger::usage() - -qpid::messaging::LoggerOutput::~LoggerOutput() - -# 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::TransactionUnknown::TransactionUnknown(std::string const&) -qpid::messaging::TransactionUnknown::~TransactionUnknown() -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 deleted file mode 100644 index 04e7a6775e..0000000000 --- a/qpid/cpp/src/libqpidtypes-api-symbols.txt +++ /dev/null @@ -1,141 +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. -# - -# 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/linearstore.cmake b/qpid/cpp/src/linearstore.cmake deleted file mode 100644 index 8c90e8a1eb..0000000000 --- a/qpid/cpp/src/linearstore.cmake +++ /dev/null @@ -1,176 +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. -# -# -# Linear store library CMake fragment, to be included in CMakeLists.txt -# - -if (DEFINED linearstore_force) - set (linearstore_default ${linearstore_force}) -else (DEFINED linearstore_force) - set (linearstore_default OFF) - if (UNIX) - # - # Find required BerkeleyDB - # - include (finddb.cmake) - if (DB_FOUND) - # - # find libaio - # - CHECK_LIBRARY_EXISTS (aio io_queue_init "" HAVE_AIO) - CHECK_INCLUDE_FILES (libaio.h HAVE_AIO_H) - if (HAVE_AIO AND HAVE_AIO_H) - # - # allow linearstore to be built - # - message(STATUS "BerkeleyDB for C++ and libaio found, Linearstore support enabled.") - set (linearstore_default ON) - else (HAVE_AIO AND HAVE_AIO_H) - if (NOT HAVE_AIO) - message(STATUS "Linearstore requires libaio which is absent.") - endif (NOT HAVE_AIO) - if (NOT HAVE_AIO_H) - message(STATUS "Linearstore requires libaio.h which is absent.") - endif (NOT HAVE_AIO_H) - endif (HAVE_AIO AND HAVE_AIO_H) - else (DB_FOUND) - message(STATUS "Linearstore requires BerkeleyDB for C++ which is absent.") - endif (DB_FOUND) - endif (UNIX) -endif (DEFINED linearstore_force) - -option(BUILD_LINEARSTORE "Build linearstore persistent store" ${linearstore_default}) - -if (BUILD_LINEARSTORE) - if (NOT UNIX) - message(FATAL_ERROR "Linearstore produced only on Unix platforms") - endif (NOT UNIX) - if (NOT DB_FOUND) - message(FATAL_ERROR "Linearstore requires BerkeleyDB for C++ which is absent.") - endif (NOT DB_FOUND) - if (NOT HAVE_AIO) - message(FATAL_ERROR "Linearstore requires libaio which is absent.") - endif (NOT HAVE_AIO) - if (NOT HAVE_AIO_H) - message(FATAL_ERROR "Linearstore requires libaio.h which is absent.") - endif (NOT HAVE_AIO_H) - - # Journal source files - set (linear_jrnl_SOURCES - qpid/linearstore/journal/Checksum.cpp - qpid/linearstore/journal/data_tok.cpp - qpid/linearstore/journal/deq_rec.cpp - qpid/linearstore/journal/EmptyFilePool.cpp - qpid/linearstore/journal/EmptyFilePoolManager.cpp - qpid/linearstore/journal/EmptyFilePoolPartition.cpp - qpid/linearstore/journal/enq_map.cpp - qpid/linearstore/journal/enq_rec.cpp - qpid/linearstore/journal/jcntl.cpp - qpid/linearstore/journal/jdir.cpp - qpid/linearstore/journal/jerrno.cpp - qpid/linearstore/journal/jexception.cpp - qpid/linearstore/journal/JournalFile.cpp - qpid/linearstore/journal/JournalLog.cpp - qpid/linearstore/journal/LinearFileController.cpp - qpid/linearstore/journal/pmgr.cpp - qpid/linearstore/journal/RecoveryManager.cpp - qpid/linearstore/journal/time_ns.cpp - qpid/linearstore/journal/txn_map.cpp - qpid/linearstore/journal/txn_rec.cpp - qpid/linearstore/journal/wmgr.cpp - ) - - # linearstore source files - set (linear_store_SOURCES - qpid/linearstore/StorePlugin.cpp - qpid/linearstore/BindingDbt.cpp - qpid/linearstore/BufferValue.cpp - qpid/linearstore/DataTokenImpl.cpp - qpid/linearstore/IdDbt.cpp - qpid/linearstore/IdSequence.cpp - qpid/linearstore/JournalImpl.cpp - qpid/linearstore/MessageStoreImpl.cpp - qpid/linearstore/PreparedTransaction.cpp - qpid/linearstore/JournalLogImpl.cpp - qpid/linearstore/TxnCtxt.cpp - ) - - set (util_SOURCES - qpid/linearstore/journal/utils/deq_hdr.c - qpid/linearstore/journal/utils/enq_hdr.c - qpid/linearstore/journal/utils/file_hdr.c - qpid/linearstore/journal/utils/rec_hdr.c - qpid/linearstore/journal/utils/rec_tail.c - qpid/linearstore/journal/utils/txn_hdr.c - ) - - # linearstore include directories - get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) - set (linear_include_DIRECTORIES - ${dirs} - ${CMAKE_CURRENT_SOURCE_DIR}/qpid/linearstore - ) - - if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/db-inc.h) - message(STATUS "Including BDB from ${DB_CXX_INCLUDE_DIR}/db_cxx.h") - file(WRITE - ${CMAKE_CURRENT_BINARY_DIR}/db-inc.h - "#include <${DB_CXX_INCLUDE_DIR}/db_cxx.h>\n") - endif() - - add_library (linearstoreutils SHARED - ${util_SOURCES} - ) - - target_link_libraries (linearstoreutils - rt - ) - - add_library (linearstore MODULE - ${linear_jrnl_SOURCES} - ${linear_store_SOURCES} - ${linear_qmf_SOURCES} - ) - - set_target_properties (linearstore PROPERTIES - PREFIX "" - OUTPUT_NAME linearstore - INCLUDE_DIRECTORIES "${linear_include_DIRECTORIES}" - ) - - target_link_libraries (linearstore - aio - uuid - qpidcommon qpidtypes qpidbroker linearstoreutils - ${DB_LIBRARY} - ) - - install(TARGETS linearstore - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - - install (TARGETS linearstoreutils - RUNTIME DESTINATION ${QPID_INSTALL_BINDIR} - LIBRARY DESTINATION ${QPID_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - -else (BUILD_LINEARSTORE) - message(STATUS "Linearstore is excluded from build.") -endif (BUILD_LINEARSTORE) diff --git a/qpid/cpp/src/msvc.cmake b/qpid/cpp/src/msvc.cmake deleted file mode 100644 index 4aa2f71513..0000000000 --- a/qpid/cpp/src/msvc.cmake +++ /dev/null @@ -1,138 +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. -# - -# This file provides library support for MSVC builds. -# * Allows for detailed specification of file/product versions. -# * Installs PDB files. - -# -# If the compiler is Visual Studio set up installation of .pdb files -# -# Sample: install_pdb (qpidcommon ${QPID_COMPONENT_COMMON}) -# -MACRO (install_pdb theLibrary theComponent) - if (MSVC) - install (FILES - $ - DESTINATION ${QPID_INSTALL_LIBDIR}/ReleasePDB - COMPONENT ${theComponent} - OPTIONAL - CONFIGURATIONS Release MinSizeRel RelWithDebInfo) - install (FILES - $ - DESTINATION ${QPID_INSTALL_LIBDIR}/DebugPDB - COMPONENT ${theComponent} - CONFIGURATIONS Debug) - endif (MSVC) -ENDMACRO (install_pdb) - -# -# inherit_value - if the symbol is undefined then set it to the given value. -# Set flag to indicate this symbol was defined here. -# -MACRO (inherit_value theSymbol theValue) - if (NOT DEFINED ${theSymbol}) - set (${theSymbol} ${theValue}) - # message ("Set symbol '${theSymbol}' to value '${theValue}'") - set (${theSymbol}_inherited = "true") - endif (NOT DEFINED ${theSymbol}) -ENDMACRO (inherit_value) - -# -# If compiler is Visual Studio then create a "version resource" for the project. -# Use this call to override CPACK and file global settings but not file per-project settings. -# Two groups of four version numbers specify "file" and "product" versions separately. -# -# Sample: add_msvc_version_full (qmfengine library dll 1 0 0 1 1 0 0 1) -# -MACRO (add_msvc_version_full verProject verProjectType verProjectFileExt verFN1 verFN2 verFN3 verFN4 verPN1 verPN2 verPN3 verPN4) - if (MSVC) - # Create project-specific version strings - inherit_value ("winver_${verProject}_FileVersionBinary" "${verFN1},${verFN2},${verFN3},${verFN4}") - inherit_value ("winver_${verProject}_ProductVersionBinary" "${verPN1},${verPN2},${verPN3},${verPN4}") - inherit_value ("winver_${verProject}_FileVersionString" "${verFN1}, ${verFN2}, ${verFN3}, ${verFN4}") - inherit_value ("winver_${verProject}_ProductVersionString" "${verPN1}, ${verPN2}, ${verPN3}, ${verPN4}") - inherit_value ("winver_${verProject}_FileDescription" "${winver_PACKAGE_NAME}-${verProject} ${verProjectType}") - inherit_value ("winver_${verProject}_LegalCopyright" "${winver_LEGAL_COPYRIGHT}") - inherit_value ("winver_${verProject}_InternalName" "${verProject}") - inherit_value ("winver_${verProject}_OriginalFilename" "${verProject}.${verProjectFileExt}") - inherit_value ("winver_${verProject}_ProductName" "${winver_DESCRIPTION_SUMMARY}") - - # Create strings to be substituted into the template file - set ("winverFileVersionBinary" "${winver_${verProject}_FileVersionBinary}") - set ("winverProductVersionBinary" "${winver_${verProject}_ProductVersionBinary}") - set ("winverFileVersionString" "${winver_${verProject}_FileVersionString}") - set ("winverProductVersionString" "${winver_${verProject}_ProductVersionString}") - set ("winverFileDescription" "${winver_${verProject}_FileDescription}") - set ("winverLegalCopyright" "${winver_${verProject}_LegalCopyright}") - set ("winverInternalName" "${winver_${verProject}_InternalName}") - set ("winverOriginalFilename" "${winver_${verProject}_OriginalFilename}") - set ("winverProductName" "${winver_${verProject}_ProductName}") - - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/resources/template-resource.rc - ${CMAKE_CURRENT_BINARY_DIR}/windows/resources/${verProject}-resource.rc) - set (${verProject}_SOURCES - ${${verProject}_SOURCES} - ${CMAKE_CURRENT_BINARY_DIR}/windows/resources/${verProject}-resource.rc - ) - endif (MSVC) -ENDMACRO (add_msvc_version_full) - -# -# If compiler is Visual Studio then create a "version resource" for the project. -# Use this call to accept file override version settings or -# inherited CPACK_PACKAGE_VERSION version settings. -# -# Sample: add_msvc_version (qpidcommon library dll) -# -MACRO (add_msvc_version verProject verProjectType verProjectFileExt) - if (MSVC) - add_msvc_version_full (${verProject} - ${verProjectType} - ${verProjectFileExt} - ${winver_FILE_VERSION_N1} - ${winver_FILE_VERSION_N2} - ${winver_FILE_VERSION_N3} - ${winver_FILE_VERSION_N4} - ${winver_PRODUCT_VERSION_N1} - ${winver_PRODUCT_VERSION_N2} - ${winver_PRODUCT_VERSION_N3} - ${winver_PRODUCT_VERSION_N4}) - endif (MSVC) -ENDMACRO (add_msvc_version) - -# -# Install optional windows version settings. Override variables are specified in a file. -# -include (./CMakeWinVersions.cmake OPTIONAL) - -# -# Inherit global windows version settings from CPACK settings. -# -inherit_value ("winver_PACKAGE_NAME" "${CPACK_PACKAGE_NAME}") -inherit_value ("winver_DESCRIPTION_SUMMARY" "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") -inherit_value ("winver_FILE_VERSION_N1" "${CPACK_PACKAGE_VERSION_MAJOR}") -inherit_value ("winver_FILE_VERSION_N2" "${CPACK_PACKAGE_VERSION_MINOR}") -inherit_value ("winver_FILE_VERSION_N3" "${CPACK_PACKAGE_VERSION_PATCH}") -inherit_value ("winver_FILE_VERSION_N4" "1") -inherit_value ("winver_PRODUCT_VERSION_N1" "${winver_FILE_VERSION_N1}") -inherit_value ("winver_PRODUCT_VERSION_N2" "${winver_FILE_VERSION_N2}") -inherit_value ("winver_PRODUCT_VERSION_N3" "${winver_FILE_VERSION_N3}") -inherit_value ("winver_PRODUCT_VERSION_N4" "${winver_FILE_VERSION_N4}") -inherit_value ("winver_LEGAL_COPYRIGHT" "") diff --git a/qpid/cpp/src/posix/QpiddBroker.cpp b/qpid/cpp/src/posix/QpiddBroker.cpp deleted file mode 100644 index 7caffd570e..0000000000 --- a/qpid/cpp/src/posix/QpiddBroker.cpp +++ /dev/null @@ -1,250 +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 "config.h" -#include "qpidd.h" -#include "qpid/Exception.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Daemon.h" -#include "qpid/broker/SignalHandler.h" -#include "qpid/log/Logger.h" - -#include -#include -#include -#include -#include - -using std::cout; -using std::endl; -using std::ifstream; -using std::ofstream; - -namespace qpid { -namespace broker { - -BootstrapOptions::BootstrapOptions(const char* argv0) - : qpid::Options("Options"), - common("", QPIDD_CONF_FILE, QPIDC_CONF_FILE), - module(QPIDD_MODULE_DIR), - log(argv0) -{ - add(common); - add(module); - add(log); -} - -void BootstrapOptions::usage() const { - cout << "Usage: qpidd [OPTIONS]" << endl << endl << *this << endl; -} - -namespace { -const std::string TCP = "tcp"; -} - -struct DaemonOptions : public qpid::Options { - bool daemon; - bool quit; - bool kill; - bool check; - std::vector closeFd; - int wait; - std::string piddir; - std::string pidfile; - std::string transport; - - DaemonOptions() : qpid::Options("Daemon options"), daemon(false), quit(false), kill(false), check(false), wait(600), transport(TCP) - { - char *home = ::getenv("HOME"); - - if (home == 0) - piddir += "/tmp"; - else - piddir += home; - piddir += "/.qpidd"; - - addOptions() - ("daemon,d", pure_switch(daemon), "Run as a daemon. Logs to syslog by default in this mode.") - ("transport", optValue(transport, "TRANSPORT"), "The transport for which to return the port") - ("pid-dir", optValue(piddir, "DIR"), "Directory where port-specific PID file is stored") - ("pidfile", optValue(pidfile, "FILE"), "File name to store the PID in daemon mode. Used as-is, no directory or suffixes added.") - ("close-fd", optValue(closeFd, "FD"), "File descriptors that the daemon should close") - ("wait,w", optValue(wait, "SECONDS"), "Sets the maximum wait time to initialize or shutdown the daemon. If the daemon fails to initialize/shutdown, prints an error and returns 1") - ("check,c", pure_switch(check), "Prints the daemon's process ID to stdout and returns 0 if the daemon is running, otherwise returns 1") - ("quit,q", pure_switch(quit), "Tells the daemon to shut down with an INT signal") - ("kill,k", pure_switch(kill), "Kill the daemon with a KILL signal."); - } -}; - -struct QpiddPosixOptions : public QpiddOptionsPrivate { - DaemonOptions daemon; - QpiddOptions *parent; - - QpiddPosixOptions(QpiddOptions *parent_) : parent(parent_) { - parent->add(daemon); - } -}; - -QpiddOptions::QpiddOptions(const char* argv0) - : qpid::Options("Options"), - common("", QPIDD_CONF_FILE, QPIDC_CONF_FILE), - module(QPIDD_MODULE_DIR), - log(argv0) -{ - add(common); - add(module); - add(broker); - add(log); - - platform.reset(new QpiddPosixOptions(this)); - qpid::Plugin::addOptions(*this); -} - -void QpiddOptions::usage() const { - cout << "Usage: qpidd [OPTIONS]" << endl << endl << *this << endl; -} - -// Set the broker pointer on the signal handler, then reset at end of scope. -// This is to ensure that the signal handler doesn't keep a broker -// reference after main() has returned. -// -struct ScopedSetBroker { - ScopedSetBroker(const boost::intrusive_ptr& broker) { - qpid::broker::SignalHandler::setBroker(broker.get()); - } - ~ScopedSetBroker() { qpid::broker::SignalHandler::setBroker(0); } -}; - -namespace { - -/// Write a pid file if requested -void writePid(const std::string& filename) { - if (!filename.empty()) { - ofstream pidfile(filename.c_str()); - pidfile << ::getpid() << endl; - pidfile.close(); - } -} -} - -struct QpiddDaemon : public Daemon { - QpiddPosixOptions *options; - - QpiddDaemon(std::string pidDir, QpiddPosixOptions *opts) - : Daemon(pidDir), options(opts) {} - - /** Code for parent process */ - void parent() { - uint16_t port = wait(options->daemon.wait); - if (options->parent->broker.port == 0) - cout << port << endl; - } - - /** Code for forked child process */ - void child() { - // Close extra FDs requested in options. - for (size_t i = 0; i < options->daemon.closeFd.size(); ++i) - ::close(options->daemon.closeFd[i]); - boost::intrusive_ptr brokerPtr(new Broker(options->parent->broker)); - ScopedSetBroker ssb(brokerPtr); - brokerPtr->accept(); - uint16_t port=brokerPtr->getPort(options->daemon.transport); - ready(port); // Notify parent. - if (options->parent->broker.enableMgmt && (options->parent->broker.port == 0 || options->daemon.transport != TCP)) { - boost::dynamic_pointer_cast(brokerPtr->GetManagementObject())->set_port(port); - } - writePid(options->daemon.pidfile); - brokerPtr->run(); - } -}; - -int QpiddBroker::execute (QpiddOptions *options) { - // Options that affect a running daemon. - QpiddPosixOptions *myOptions = - static_cast(options->platform.get()); - if (myOptions == 0) - throw Exception("Internal error obtaining platform options"); - - if (myOptions->daemon.check || myOptions->daemon.quit || myOptions->daemon.kill) { - pid_t pid = 0; - if (!myOptions->daemon.pidfile.empty()) { - ifstream pidfile(myOptions->daemon.pidfile.c_str()); - pidfile >> pid; - pidfile.close(); - } - if (pid == 0) { - try { - pid = Daemon::getPid(myOptions->daemon.piddir, options->broker.port); - } catch (const Exception& e) { - // This is not a critical error, usually means broker is not running - QPID_LOG(notice, "Broker is not running: " << e.what()); - return 1; - } - } - if (pid < 0) - return 1; - if (myOptions->daemon.check) - cout << pid << endl; - if (myOptions->daemon.quit || myOptions->daemon.kill) { - int signal = myOptions->daemon.kill ? SIGKILL : SIGINT; - if (kill(pid, signal) < 0) - throw Exception("Failed to stop daemon: " + qpid::sys::strError(errno)); - // Wait for the process to die before returning - int retry=myOptions->daemon.wait*1000; // Try up to "--wait N" seconds, do retry every millisecond - while (kill(pid,0) == 0 && --retry) - sys::usleep(1000); - if (retry == 0) - throw Exception("Gave up waiting for daemon process to exit"); - } - return 0; - } - - // Starting the broker. - if (myOptions->daemon.daemon) { - // For daemon mode replace default stderr with syslog. - options->log.sinkOptions->detached(); - qpid::log::Logger::instance().configure(options->log); - // Fork the daemon - QpiddDaemon d(myOptions->daemon.piddir, myOptions); - d.fork(); // Broker is stared in QpiddDaemon::child() - } - else { // Non-daemon broker. - boost::intrusive_ptr brokerPtr(new Broker(options->broker)); - ScopedSetBroker ssb(brokerPtr); - brokerPtr->accept(); - if (options->broker.port == 0) { - uint16_t port = brokerPtr->getPort(myOptions->daemon.transport); - cout << port << endl; - if (options->broker.enableMgmt) { - boost::dynamic_pointer_cast(brokerPtr->GetManagementObject())->set_port(port); - } - } - writePid(myOptions->daemon.pidfile); - brokerPtr->run(); - } - return 0; -} - -}} // namespace qpid::Broker - -int main(int argc, char* argv[]) -{ - return qpid::broker::run_broker(argc, argv); -} diff --git a/qpid/cpp/src/prof b/qpid/cpp/src/prof deleted file mode 100755 index fa470f5f84..0000000000 --- a/qpid/cpp/src/prof +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env 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. -# -# - - -rm /var/lib/oprofile/oprofiled.log - -opcontrol --reset -opcontrol --setup --no-vmlinux --separate=library -opcontrol --start -# -- Do stuff here -- -./qpidd -# -- End of stuff -- -opcontrol --stop -opcontrol --dump -opcontrol --shutdown -opreport -l ./qpidd > stats.txt -opannotate --source --output-dir=qpidd-prof ./qpidd - -# clear the relusts -#opcontrol --reset diff --git a/qpid/cpp/src/qmf/Agent.cpp b/qpid/cpp/src/qmf/Agent.cpp deleted file mode 100644 index fa3987e0c9..0000000000 --- a/qpid/cpp/src/qmf/Agent.cpp +++ /dev/null @@ -1,640 +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/AgentImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/ConsoleEventImpl.h" -#include "qmf/ConsoleSession.h" -#include "qmf/DataImpl.h" -#include "qmf/Query.h" -#include "qmf/SchemaImpl.h" -#include "qmf/agentCapability.h" -#include "qmf/constants.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/management/Buffer.h" -#include "qpid/log/Statement.h" -#include - -using qpid::types::Variant; -using qpid::messaging::Duration; -using qpid::messaging::Message; -using qpid::messaging::Sender; -using namespace std; -using namespace qmf; - -typedef PrivateImplRef PI; - -Agent::Agent(AgentImpl* impl) { PI::ctor(*this, impl); } -Agent::Agent(const Agent& s) : qmf::Handle() { PI::copy(*this, s); } -Agent::~Agent() { PI::dtor(*this); } -Agent& Agent::operator=(const Agent& s) { return PI::assign(*this, s); } -string Agent::getName() const { return isValid() ? impl->getName() : ""; } -uint32_t Agent::getEpoch() const { return isValid() ? impl->getEpoch() : 0; } -string Agent::getVendor() const { return isValid() ? impl->getVendor() : ""; } -string Agent::getProduct() const { return isValid() ? impl->getProduct() : ""; } -string Agent::getInstance() const { return isValid() ? impl->getInstance() : ""; } -const Variant& Agent::getAttribute(const string& k) const { return impl->getAttribute(k); } -const Variant::Map& Agent::getAttributes() const { return impl->getAttributes(); } -ConsoleEvent Agent::querySchema(Duration t) { return impl->querySchema(t); } -uint32_t Agent::querySchemaAsync() { return impl->querySchemaAsync(); } -ConsoleEvent Agent::query(const Query& q, Duration t) { return impl->query(q, t); } -ConsoleEvent Agent::query(const string& q, Duration t) { return impl->query(q, t); } -uint32_t Agent::queryAsync(const Query& q) { return impl->queryAsync(q); } -uint32_t Agent::queryAsync(const string& q) { return impl->queryAsync(q); } -ConsoleEvent Agent::callMethod(const string& m, const Variant::Map& a, const DataAddr& d, Duration t) { return impl->callMethod(m, a, d, t); } -uint32_t Agent::callMethodAsync(const string& m, const Variant::Map& a, const DataAddr& d) { return impl->callMethodAsync(m, a, d); } -uint32_t Agent::getPackageCount() const { return impl->getPackageCount(); } -const string& Agent::getPackage(uint32_t i) const { return impl->getPackage(i); } -uint32_t Agent::getSchemaIdCount(const string& p) const { return impl->getSchemaIdCount(p); } -SchemaId Agent::getSchemaId(const string& p, uint32_t i) const { return impl->getSchemaId(p, i); } -Schema Agent::getSchema(const SchemaId& s, Duration t) { return impl->getSchema(s, t); } - - - -AgentImpl::AgentImpl(const std::string& n, uint32_t e, ConsoleSessionImpl& s) : - name(n), directSubject(n), epoch(e), session(s), touched(true), untouchedCount(0), capability(0), - sender(session.directSender), schemaCache(s.schemaCache) -{ -} - -void AgentImpl::setAttribute(const std::string& k, const qpid::types::Variant& v) -{ - attributes[k] = v; - if (k == "qmf.agent_capability") - try { - capability = v.asUint32(); - } catch (std::exception&) {} - if (k == "_direct_subject") - try { - directSubject = v.asString(); - sender = session.topicSender; - } catch (std::exception&) {} -} - -const Variant& AgentImpl::getAttribute(const string& k) const -{ - Variant::Map::const_iterator iter = attributes.find(k); - if (iter == attributes.end()) - throw KeyNotFound(k); - return iter->second; -} - - -ConsoleEvent AgentImpl::query(const Query& query, Duration timeout) -{ - boost::shared_ptr context(new SyncContext()); - uint32_t correlator(session.correlator()); - ConsoleEvent result; - - { - qpid::sys::Mutex::ScopedLock l(lock); - contextMap[correlator] = context; - } - try { - sendQuery(query, correlator); - { - uint64_t milliseconds = timeout.getMilliseconds(); - qpid::sys::Mutex::ScopedLock cl(context->lock); - if (!context->response.isValid() || !context->response.isFinal()) - context->cond.wait(context->lock, - qpid::sys::AbsTime(qpid::sys::now(), - qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC))); - if (context->response.isValid() && - ((context->response.getType() == CONSOLE_QUERY_RESPONSE && context->response.isFinal()) || - (context->response.getType() == CONSOLE_EXCEPTION))) - result = context->response; - else { - auto_ptr impl(new ConsoleEventImpl(CONSOLE_EXCEPTION)); - Data exception(new DataImpl()); - exception.setProperty("error_text", "Timed out waiting for the agent to respond"); - impl->addData(exception); - result = ConsoleEvent(impl.release()); - } - } - } catch (qpid::types::Exception&) { - } - - { - qpid::sys::Mutex::ScopedLock l(lock); - contextMap.erase(correlator); - } - - return result; -} - - -ConsoleEvent AgentImpl::query(const string& text, Duration timeout) -{ - return query(stringToQuery(text), timeout); -} - - -uint32_t AgentImpl::queryAsync(const Query& query) -{ - uint32_t correlator(session.correlator()); - - sendQuery(query, correlator); - return correlator; -} - - -uint32_t AgentImpl::queryAsync(const string& text) -{ - return queryAsync(stringToQuery(text)); -} - - -ConsoleEvent AgentImpl::callMethod(const string& method, const Variant::Map& args, const DataAddr& addr, Duration timeout) -{ - boost::shared_ptr context(new SyncContext()); - uint32_t correlator(session.correlator()); - ConsoleEvent result; - - { - qpid::sys::Mutex::ScopedLock l(lock); - contextMap[correlator] = context; - } - try { - sendMethod(method, args, addr, correlator); - { - uint64_t milliseconds = timeout.getMilliseconds(); - qpid::sys::Mutex::ScopedLock cl(context->lock); - if (!context->response.isValid()) - context->cond.wait(context->lock, - qpid::sys::AbsTime(qpid::sys::now(), - qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC))); - if (context->response.isValid()) - result = context->response; - else { - auto_ptr impl(new ConsoleEventImpl(CONSOLE_EXCEPTION)); - Data exception(new DataImpl()); - exception.setProperty("error_text", "Timed out waiting for the agent to respond"); - impl->addData(exception); - result = ConsoleEvent(impl.release()); - } - } - } catch (qpid::types::Exception&) { - } - - { - qpid::sys::Mutex::ScopedLock l(lock); - contextMap.erase(correlator); - } - - return result; -} - - -uint32_t AgentImpl::callMethodAsync(const string& method, const Variant::Map& args, const DataAddr& addr) -{ - uint32_t correlator(session.correlator()); - - sendMethod(method, args, addr, correlator); - return correlator; -} - - -uint32_t AgentImpl::getPackageCount() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - - // - // Populate the package set. - // - for (set::const_iterator iter = schemaIdSet.begin(); iter != schemaIdSet.end(); iter++) - packageSet.insert(iter->getPackageName()); - - return packageSet.size(); -} - - -const string& AgentImpl::getPackage(uint32_t idx) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - uint32_t count(0); - for (set::const_iterator iter = packageSet.begin(); iter != packageSet.end(); iter++) { - if (idx == count) - return *iter; - count++; - } - throw IndexOutOfRange(); -} - - -uint32_t AgentImpl::getSchemaIdCount(const string& pname) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - uint32_t count(0); - for (set::const_iterator iter = schemaIdSet.begin(); iter != schemaIdSet.end(); iter++) - if (iter->getPackageName() == pname) - count++; - return count; -} - - -SchemaId AgentImpl::getSchemaId(const string& pname, uint32_t idx) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - uint32_t count(0); - for (set::const_iterator iter = schemaIdSet.begin(); iter != schemaIdSet.end(); iter++) { - if (iter->getPackageName() == pname) { - if (idx == count) - return *iter; - count++; - } - } - throw IndexOutOfRange(); -} - - -Schema AgentImpl::getSchema(const SchemaId& id, Duration timeout) -{ - if (!schemaCache->haveSchema(id)) - // - // The desired schema is not in the cache. We need to asynchronously query the remote - // agent for the information. The call to schemaCache->getSchema will block waiting for - // the response to be received. - // - sendSchemaRequest(id); - - return schemaCache->getSchema(id, timeout); -} - - -void AgentImpl::handleException(const Variant::Map& content, const Message& msg) -{ - const string& cid(msg.getCorrelationId()); - Variant::Map::const_iterator aIter; - uint32_t correlator; - boost::shared_ptr context; - - try { correlator = boost::lexical_cast(cid); } - catch(const boost::bad_lexical_cast&) { correlator = 0; } - - { - qpid::sys::Mutex::ScopedLock l(lock); - map >::iterator iter = contextMap.find(correlator); - if (iter != contextMap.end()) - context = iter->second; - } - - if (context.get() != 0) { - // - // This exception is associated with a synchronous request. - // - qpid::sys::Mutex::ScopedLock cl(context->lock); - context->response = ConsoleEvent(new ConsoleEventImpl(CONSOLE_EXCEPTION)); - ConsoleEventImplAccess::get(context->response).addData(new DataImpl(content, this)); - ConsoleEventImplAccess::get(context->response).setAgent(this); - context->cond.notify(); - } else { - // - // This exception is associated with an asynchronous request. - // - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_EXCEPTION)); - eventImpl->setCorrelator(correlator); - eventImpl->setAgent(this); - eventImpl->addData(new DataImpl(content, this)); - session.enqueueEvent(eventImpl.release()); - } -} - - -void AgentImpl::handleMethodResponse(const Variant::Map& response, const Message& msg) -{ - const string& cid(msg.getCorrelationId()); - Variant::Map::const_iterator aIter; - Variant::Map argMap; - uint32_t correlator; - boost::shared_ptr context; - - QPID_LOG(trace, "RCVD MethodResponse cid=" << cid << " map=" << response); - - aIter = response.find("_arguments"); - if (aIter != response.end()) - argMap = aIter->second.asMap(); - - try { correlator = boost::lexical_cast(cid); } - catch(const boost::bad_lexical_cast&) { correlator = 0; } - - { - qpid::sys::Mutex::ScopedLock l(lock); - map >::iterator iter = contextMap.find(correlator); - if (iter != contextMap.end()) - context = iter->second; - } - - if (context.get() != 0) { - // - // This response is associated with a synchronous request. - // - qpid::sys::Mutex::ScopedLock cl(context->lock); - context->response = ConsoleEvent(new ConsoleEventImpl(CONSOLE_METHOD_RESPONSE)); - ConsoleEventImplAccess::get(context->response).setArguments(argMap); - ConsoleEventImplAccess::get(context->response).setAgent(this); - context->cond.notify(); - } else { - // - // This response is associated with an asynchronous request. - // - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_METHOD_RESPONSE)); - eventImpl->setCorrelator(correlator); - eventImpl->setAgent(this); - eventImpl->setArguments(argMap); - session.enqueueEvent(eventImpl.release()); - } -} - - -void AgentImpl::handleDataIndication(const Variant::List& list, const Message& msg) -{ - Variant::Map::const_iterator aIter; - const Variant::Map& props(msg.getProperties()); - boost::shared_ptr context; - - aIter = props.find("qmf.content"); - if (aIter == props.end()) - return; - - string content_type(aIter->second.asString()); - if (content_type != "_event") - return; - - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - const Variant::Map& eventMap(lIter->asMap()); - Data data(new DataImpl(eventMap, this)); - int severity(SEV_NOTICE); - uint64_t timestamp(0); - - aIter = eventMap.find("_severity"); - if (aIter != eventMap.end()) - severity = int(aIter->second.asInt8()); - - aIter = eventMap.find("_timestamp"); - if (aIter != eventMap.end()) - timestamp = aIter->second.asUint64(); - - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_EVENT)); - eventImpl->setAgent(this); - eventImpl->addData(data); - eventImpl->setSeverity(severity); - eventImpl->setTimestamp(timestamp); - if (data.hasSchema()) - learnSchemaId(data.getSchemaId()); - session.enqueueEvent(eventImpl.release()); - } -} - - -void AgentImpl::handleQueryResponse(const Variant::List& list, const Message& msg) -{ - const string& cid(msg.getCorrelationId()); - Variant::Map::const_iterator aIter; - const Variant::Map& props(msg.getProperties()); - uint32_t correlator; - bool final(false); - boost::shared_ptr context; - - aIter = props.find("partial"); - if (aIter == props.end()) - final = true; - - aIter = props.find("qmf.content"); - if (aIter == props.end()) - return; - - string content_type(aIter->second.asString()); - if (content_type != "_schema" && content_type != "_schema_id" && content_type != "_data") - return; - - try { correlator = boost::lexical_cast(cid); } - catch(const boost::bad_lexical_cast&) { correlator = 0; } - - { - qpid::sys::Mutex::ScopedLock l(lock); - map >::iterator iter = contextMap.find(correlator); - if (iter != contextMap.end()) - context = iter->second; - } - - if (context.get() != 0) { - // - // This response is associated with a synchronous request. - // - qpid::sys::Mutex::ScopedLock cl(context->lock); - if (!context->response.isValid()) - context->response = ConsoleEvent(new ConsoleEventImpl(CONSOLE_QUERY_RESPONSE)); - - if (content_type == "_data") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - Data data(new DataImpl(lIter->asMap(), this)); - ConsoleEventImplAccess::get(context->response).addData(data); - if (data.hasSchema()) - learnSchemaId(data.getSchemaId()); - } - else if (content_type == "_schema_id") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - SchemaId schemaId(new SchemaIdImpl(lIter->asMap())); - ConsoleEventImplAccess::get(context->response).addSchemaId(schemaId); - learnSchemaId(schemaId); - } - else if (content_type == "_schema") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - Schema schema(new SchemaImpl(lIter->asMap())); - schemaCache->declareSchema(schema); - } - - if (final) { - ConsoleEventImplAccess::get(context->response).setFinal(); - ConsoleEventImplAccess::get(context->response).setAgent(this); - context->cond.notify(); - } - } else { - // - // This response is associated with an asynchronous request. - // - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_QUERY_RESPONSE)); - eventImpl->setCorrelator(correlator); - eventImpl->setAgent(this); - - if (content_type == "_data") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - Data data(new DataImpl(lIter->asMap(), this)); - eventImpl->addData(data); - if (data.hasSchema()) - learnSchemaId(data.getSchemaId()); - } - else if (content_type == "_schema_id") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - SchemaId schemaId(new SchemaIdImpl(lIter->asMap())); - eventImpl->addSchemaId(schemaId); - learnSchemaId(schemaId); - } - else if (content_type == "_schema") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - Schema schema(new SchemaImpl(lIter->asMap())); - schemaCache->declareSchema(schema); - } - - if (final) - eventImpl->setFinal(); - if (content_type != "_schema") - session.enqueueEvent(eventImpl.release()); - } -} - - -Query AgentImpl::stringToQuery(const std::string& text) -{ - qpid::messaging::AddressParser parser(text); - Variant::Map map; - Variant::Map::const_iterator iter; - string className; - string packageName; - - parser.parseMap(map); - - iter = map.find("class"); - if (iter != map.end()) - className = iter->second.asString(); - - iter = map.find("package"); - if (iter != map.end()) - packageName = iter->second.asString(); - - Query query(QUERY_OBJECT, className, packageName); - - iter = map.find("where"); - if (iter != map.end()) - query.setPredicate(iter->second.asList()); - - return query; -} - - -void AgentImpl::sendQuery(const Query& query, uint32_t correlator) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_REQUEST; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_QUERY_REQUEST; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - msg.setReplyTo(session.replyAddress); - msg.setCorrelationId(boost::lexical_cast(correlator)); - msg.setSubject(directSubject); - string userId(session.connection.getAuthenticatedUsername()); - if (!userId.empty()) - msg.setUserId(userId); - encode(QueryImplAccess::get(query).asMap(), msg); - if (sender.isValid()) { - sender.send(msg); - QPID_LOG(trace, "SENT QueryRequest to=" << sender.getName() << "/" << directSubject << " cid=" << correlator); - } -} - - -void AgentImpl::sendMethod(const string& method, const Variant::Map& args, const DataAddr& addr, uint32_t correlator) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_REQUEST; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_METHOD_REQUEST; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - map["_method_name"] = method; - map["_object_id"] = addr.asMap(); - map["_arguments"] = args; - - msg.setReplyTo(session.replyAddress); - msg.setCorrelationId(boost::lexical_cast(correlator)); - msg.setSubject(directSubject); - string userId(session.connection.getAuthenticatedUsername()); - if (!userId.empty()) - msg.setUserId(userId); - encode(map, msg); - if (sender.isValid()) { - sender.send(msg); - QPID_LOG(trace, "SENT MethodRequest method=" << method << " to=" << sender.getName() << "/" << directSubject << " content=" << map << " cid=" << correlator); - } -} - -void AgentImpl::sendSchemaRequest(const SchemaId& id) -{ - uint32_t correlator(session.correlator()); - - if (capability >= AGENT_CAPABILITY_V2_SCHEMA) { - Query query(QUERY_SCHEMA, id); - sendQuery(query, correlator); - return; - } - -#define RAW_BUFFER_SIZE 1024 - char rawBuffer[RAW_BUFFER_SIZE]; - qpid::management::Buffer buffer(rawBuffer, RAW_BUFFER_SIZE); - - buffer.putOctet('A'); - buffer.putOctet('M'); - buffer.putOctet('2'); - buffer.putOctet('S'); - buffer.putLong(correlator); - buffer.putShortString(id.getPackageName()); - buffer.putShortString(id.getName()); - buffer.putBin128(id.getHash().data()); - - string content(rawBuffer, buffer.getPosition()); - - Message msg; - msg.setReplyTo(session.replyAddress); - msg.setContent(content); - msg.setSubject(directSubject); - string userId(session.connection.getAuthenticatedUsername()); - if (!userId.empty()) - msg.setUserId(userId); - if (sender.isValid()) { - sender.send(msg); - QPID_LOG(trace, "SENT V1SchemaRequest to=" << sender.getName() << "/" << directSubject); - } -} - - -void AgentImpl::learnSchemaId(const SchemaId& id) -{ - schemaCache->declareSchemaId(id); - schemaIdSet.insert(id); -} - - -AgentImpl& AgentImplAccess::get(Agent& item) -{ - return *item.impl; -} - - -const AgentImpl& AgentImplAccess::get(const Agent& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/AgentEvent.cpp b/qpid/cpp/src/qmf/AgentEvent.cpp deleted file mode 100644 index 2dc24ecac1..0000000000 --- a/qpid/cpp/src/qmf/AgentEvent.cpp +++ /dev/null @@ -1,85 +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/AgentEventImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/SchemaImpl.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef PI; - -AgentEvent::AgentEvent(AgentEventImpl* impl) { PI::ctor(*this, impl); } -AgentEvent::AgentEvent(const AgentEvent& s) : qmf::Handle() { PI::copy(*this, s); } -AgentEvent::~AgentEvent() { PI::dtor(*this); } -AgentEvent& AgentEvent::operator=(const AgentEvent& s) { return PI::assign(*this, s); } - -AgentEventCode AgentEvent::getType() const { return impl->getType(); } -const string& AgentEvent::getUserId() const { return impl->getUserId(); } -Query AgentEvent::getQuery() const { return impl->getQuery(); } -bool AgentEvent::hasDataAddr() const { return impl->hasDataAddr(); } -DataAddr AgentEvent::getDataAddr() const { return impl->getDataAddr(); } -const string& AgentEvent::getMethodName() const { return impl->getMethodName(); } -qpid::types::Variant::Map& AgentEvent::getArguments() { return impl->getArguments(); } -qpid::types::Variant::Map& AgentEvent::getArgumentSubtypes() { return impl->getArgumentSubtypes(); } -void AgentEvent::addReturnArgument(const std::string& k, const qpid::types::Variant& v, const std::string& s) { impl->addReturnArgument(k, v, s); } - -uint32_t AgentEventImpl::enqueueData(const Data& data) -{ - qpid::sys::Mutex::ScopedLock l(lock); - dataQueue.push(data); - return dataQueue.size(); -} - - -Data AgentEventImpl::dequeueData() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (dataQueue.empty()) - return Data(); - Data data(dataQueue.front()); - dataQueue.pop(); - return data; -} - - -void AgentEventImpl::addReturnArgument(const string& key, const Variant& val, const string& subtype) -{ - if (schema.isValid() && !SchemaImplAccess::get(schema).isValidMethodOutArg(methodName, key, val)) - throw QmfException("Output argument is unknown or the type is incompatible"); - outArguments[key] = val; - if (!subtype.empty()) - outArgumentSubtypes[key] = subtype; -} - - -AgentEventImpl& AgentEventImplAccess::get(AgentEvent& item) -{ - return *item.impl; -} - - -const AgentEventImpl& AgentEventImplAccess::get(const AgentEvent& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/AgentEventImpl.h b/qpid/cpp/src/qmf/AgentEventImpl.h deleted file mode 100644 index 1ecb41775a..0000000000 --- a/qpid/cpp/src/qmf/AgentEventImpl.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef _QMF_AGENT_EVENT_IMPL_H_ -#define _QMF_AGENT_EVENT_IMPL_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/RefCounted.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/messaging/Address.h" -#include "qmf/AgentEvent.h" -#include "qmf/Query.h" -#include "qmf/DataAddr.h" -#include "qmf/Data.h" -#include "qmf/Schema.h" -#include - -namespace qmf { - class AgentEventImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only methods - // - AgentEventImpl(AgentEventCode e) : eventType(e) {} - void setUserId(const std::string& u) { userId = u; } - void setQuery(const Query& q) { query = q; } - void setDataAddr(const DataAddr& d) { dataAddr = d; } - void setMethodName(const std::string& m) { methodName = m; } - void setArguments(const qpid::types::Variant::Map& a) { arguments = a; } - void setArgumentSubtypes(const qpid::types::Variant::Map& a) { argumentSubtypes = a; } - void setReplyTo(const qpid::messaging::Address& r) { replyTo = r; } - void setSchema(const Schema& s) { schema = s; } - const qpid::messaging::Address& getReplyTo() { return replyTo; } - void setCorrelationId(const std::string& c) { correlationId = c; } - const std::string& getCorrelationId() { return correlationId; } - const qpid::types::Variant::Map& getReturnArguments() const { return outArguments; } - const qpid::types::Variant::Map& getReturnArgumentSubtypes() const { return outArgumentSubtypes; } - uint32_t enqueueData(const Data&); - Data dequeueData(); - - // - // Methods from API handle - // - AgentEventCode getType() const { return eventType; } - const std::string& getUserId() const { return userId; } - Query getQuery() const { return query; } - bool hasDataAddr() const { return dataAddr.isValid(); } - DataAddr getDataAddr() const { return dataAddr; } - const std::string& getMethodName() const { return methodName; } - qpid::types::Variant::Map& getArguments() { return arguments; } - qpid::types::Variant::Map& getArgumentSubtypes() { return argumentSubtypes; } - void addReturnArgument(const std::string&, const qpid::types::Variant&, const std::string&); - - private: - const AgentEventCode eventType; - std::string userId; - qpid::messaging::Address replyTo; - std::string correlationId; - Query query; - DataAddr dataAddr; - Schema schema; - std::string methodName; - qpid::types::Variant::Map arguments; - qpid::types::Variant::Map argumentSubtypes; - qpid::types::Variant::Map outArguments; - qpid::types::Variant::Map outArgumentSubtypes; - - qpid::sys::Mutex lock; - std::queue dataQueue; - }; - - struct AgentEventImplAccess - { - static AgentEventImpl& get(AgentEvent&); - static const AgentEventImpl& get(const AgentEvent&); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/AgentImpl.h b/qpid/cpp/src/qmf/AgentImpl.h deleted file mode 100644 index 09754a3a7e..0000000000 --- a/qpid/cpp/src/qmf/AgentImpl.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef _QMF_AGENT_IMPL_H_ -#define _QMF_AGENT_IMPL_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/RefCounted.h" -#include "qmf/Agent.h" -#include "qmf/ConsoleEventImpl.h" -#include "qmf/ConsoleSessionImpl.h" -#include "qmf/QueryImpl.h" -#include "qmf/SchemaCache.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Sender.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Condition.h" -#include -#include -#include - -namespace qmf { - class AgentImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only methods - // - AgentImpl(const std::string& n, uint32_t e, ConsoleSessionImpl& s); - void setAttribute(const std::string& k, const qpid::types::Variant& v); - void setAttribute(const std::string& k, const std::string& v) { attributes[k] = v; } - void touch() { touched = true; } - uint32_t age() { untouchedCount = touched ? 0 : untouchedCount + 1; touched = false; return untouchedCount; } - uint32_t getCapability() const { return capability; } - void handleException(const qpid::types::Variant::Map&, const qpid::messaging::Message&); - void handleMethodResponse(const qpid::types::Variant::Map&, const qpid::messaging::Message&); - void handleDataIndication(const qpid::types::Variant::List&, const qpid::messaging::Message&); - void handleQueryResponse(const qpid::types::Variant::List&, const qpid::messaging::Message&); - - // - // Methods from API handle - // - const std::string& getName() const { return name; } - uint32_t getEpoch() const { return epoch; } - void setEpoch(uint32_t e) { epoch = e; } - std::string getVendor() const { return getAttribute("_vendor").asString(); } - std::string getProduct() const { return getAttribute("_product").asString(); } - std::string getInstance() const { return getAttribute("_instance").asString(); } - const qpid::types::Variant& getAttribute(const std::string& k) const; - const qpid::types::Variant::Map& getAttributes() const { return attributes; } - - ConsoleEvent querySchema(qpid::messaging::Duration t) { return query(Query(QUERY_SCHEMA_ID), t); } - uint32_t querySchemaAsync() { return queryAsync(Query(QUERY_SCHEMA_ID)); } - - ConsoleEvent query(const Query& q, qpid::messaging::Duration t); - ConsoleEvent query(const std::string& q, qpid::messaging::Duration t); - uint32_t queryAsync(const Query& q); - uint32_t queryAsync(const std::string& q); - - ConsoleEvent callMethod(const std::string& m, const qpid::types::Variant::Map& a, const DataAddr&, qpid::messaging::Duration t); - uint32_t callMethodAsync(const std::string& m, const qpid::types::Variant::Map& a, const DataAddr&); - - uint32_t getPackageCount() const; - const std::string& getPackage(uint32_t i) const; - uint32_t getSchemaIdCount(const std::string& p) const; - SchemaId getSchemaId(const std::string& p, uint32_t i) const; - Schema getSchema(const SchemaId& s, qpid::messaging::Duration t); - - private: - struct SyncContext { - qpid::sys::Mutex lock; - qpid::sys::Condition cond; - ConsoleEvent response; - }; - - mutable qpid::sys::Mutex lock; - std::string name; - std::string directSubject; - uint32_t epoch; - ConsoleSessionImpl& session; - bool touched; - uint32_t untouchedCount; - uint32_t capability; - qpid::messaging::Sender sender; - qpid::types::Variant::Map attributes; - std::map > contextMap; - boost::shared_ptr schemaCache; - mutable std::set packageSet; - std::set schemaIdSet; - - Query stringToQuery(const std::string&); - void sendQuery(const Query&, uint32_t); - void sendSchemaIdQuery(uint32_t); - void sendMethod(const std::string&, const qpid::types::Variant::Map&, const DataAddr&, uint32_t); - void sendSchemaRequest(const SchemaId&); - void learnSchemaId(const SchemaId&); - }; - - struct AgentImplAccess - { - static AgentImpl& get(Agent&); - static const AgentImpl& get(const Agent&); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/AgentSession.cpp b/qpid/cpp/src/qmf/AgentSession.cpp deleted file mode 100644 index 4605285448..0000000000 --- a/qpid/cpp/src/qmf/AgentSession.cpp +++ /dev/null @@ -1,1031 +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/AgentSessionImpl.h" - -#include -#include - -namespace qmf { - -using std::string; -using std::map; - -using qpid::messaging::Address; -using qpid::messaging::Connection; -using qpid::messaging::Duration; -using qpid::messaging::Message; -using qpid::messaging::Receiver; -using qpid::messaging::Sender; -using qpid::types::Variant; - -AgentSession::AgentSession(AgentSessionImpl* impl) { PI::ctor(*this, impl); } -AgentSession::AgentSession(const AgentSession& s) : qmf::Handle() { PI::copy(*this, s); } -AgentSession::~AgentSession() { PI::dtor(*this); } -AgentSession& AgentSession::operator=(const AgentSession& s) { return PI::assign(*this, s); } - -AgentSession::AgentSession(Connection& c, const string& o) { PI::ctor(*this, new AgentSessionImpl(c, o)); } -void AgentSession::setDomain(const string& d) { impl->setDomain(d); } -void AgentSession::setVendor(const string& v) { impl->setVendor(v); } -void AgentSession::setProduct(const string& p) { impl->setProduct(p); } -void AgentSession::setInstance(const string& i) { impl->setInstance(i); } -void AgentSession::setAttribute(const string& k, const qpid::types::Variant& v) { impl->setAttribute(k, v); } -const string& AgentSession::getName() const { return impl->getName(); } -void AgentSession::open() { impl->open(); } -void AgentSession::close() { impl->close(); } -bool AgentSession::nextEvent(AgentEvent& e, Duration t) { return impl->nextEvent(e, t); } -int AgentSession::pendingEvents() const { return impl->pendingEvents(); } -void AgentSession::registerSchema(Schema& s) { impl->registerSchema(s); } -DataAddr AgentSession::addData(Data& d, const string& n, bool p) { return impl->addData(d, n, p); } -void AgentSession::delData(const DataAddr& a) { impl->delData(a); } -void AgentSession::authAccept(AgentEvent& e) { impl->authAccept(e); } -void AgentSession::authReject(AgentEvent& e, const string& m) { impl->authReject(e, m); } -void AgentSession::raiseException(AgentEvent& e, const string& s) { impl->raiseException(e, s); } -void AgentSession::raiseException(AgentEvent& e, const Data& d) { impl->raiseException(e, d); } -void AgentSession::response(AgentEvent& e, const Data& d) { impl->response(e, d); } -void AgentSession::complete(AgentEvent& e) { impl->complete(e); } -void AgentSession::methodSuccess(AgentEvent& e) { impl->methodSuccess(e); } -void AgentSession::raiseEvent(const Data& d) { impl->raiseEvent(d); } -void AgentSession::raiseEvent(const Data& d, int s) { impl->raiseEvent(d, s); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -AgentSessionImpl::AgentSessionImpl(Connection& c, const string& options) : - connection(c), domain("default"), opened(false), eventNotifier(0), thread(0), threadCanceled(false), - bootSequence(1), interval(60), lastHeartbeat(0), lastVisit(0), forceHeartbeat(false), - externalStorage(false), autoAllowQueries(true), autoAllowMethods(true), - maxSubscriptions(64), minSubInterval(3000), subLifetime(300), publicEvents(true), - listenOnDirect(true), strictSecurity(false), maxThreadWaitTime(5), - schemaUpdateTime(uint64_t(qpid::sys::Duration::FromEpoch())) -{ - // - // Set Agent Capability Level - // - attributes["qmf.agent_capability"] = AGENT_CAPABILITY_0_8; - - if (!options.empty()) { - qpid::messaging::AddressParser parser(options); - Variant::Map optMap; - Variant::Map::const_iterator iter; - - parser.parseMap(optMap); - - iter = optMap.find("domain"); - if (iter != optMap.end()) - domain = iter->second.asString(); - - iter = optMap.find("interval"); - if (iter != optMap.end()) { - interval = iter->second.asUint32(); - if (interval < 1) - interval = 1; - } - - iter = optMap.find("external"); - if (iter != optMap.end()) - externalStorage = iter->second.asBool(); - - iter = optMap.find("allow-queries"); - if (iter != optMap.end()) - autoAllowQueries = iter->second.asBool(); - - iter = optMap.find("allow-methods"); - if (iter != optMap.end()) - autoAllowMethods = iter->second.asBool(); - - iter = optMap.find("max-subscriptions"); - if (iter != optMap.end()) - maxSubscriptions = iter->second.asUint32(); - - iter = optMap.find("min-sub-interval"); - if (iter != optMap.end()) - minSubInterval = iter->second.asUint32(); - - iter = optMap.find("sub-lifetime"); - if (iter != optMap.end()) - subLifetime = iter->second.asUint32(); - - iter = optMap.find("public-events"); - if (iter != optMap.end()) - publicEvents = iter->second.asBool(); - - iter = optMap.find("listen-on-direct"); - if (iter != optMap.end()) - listenOnDirect = iter->second.asBool(); - - iter = optMap.find("strict-security"); - if (iter != optMap.end()) - strictSecurity = iter->second.asBool(); - - iter = optMap.find("max-thread-wait-time"); - if (iter != optMap.end()) - maxThreadWaitTime = iter->second.asUint32(); - } - - if (maxThreadWaitTime > interval) - maxThreadWaitTime = interval; -} - - -AgentSessionImpl::~AgentSessionImpl() -{ - if (opened) - close(); - - if (thread) { - thread->join(); - delete thread; - } -} - - -void AgentSessionImpl::open() -{ - if (opened) - throw QmfException("The session is already open"); - - // If the thread exists, join and delete it before creating a new one. - if (thread) { - thread->join(); - delete thread; - } - - const string addrArgs(";{create:never,node:{type:topic}}"); - const string routableAddr("direct-agent.route." + qpid::types::Uuid(true).str()); - attributes["_direct_subject"] = routableAddr; - - // Establish messaging addresses - setAgentName(); - directBase = "qmf." + domain + ".direct"; - topicBase = "qmf." + domain + ".topic"; - - // Create AMQP session, receivers, and senders - session = connection.createSession(); - Receiver directRx; - Receiver routableDirectRx = session.createReceiver(topicBase + "/" + routableAddr + addrArgs); - Receiver topicRx = session.createReceiver(topicBase + "/console.#" + addrArgs); - - if (listenOnDirect && !strictSecurity) { - directRx = session.createReceiver(directBase + "/" + agentName + addrArgs); - directRx.setCapacity(64); - } - - routableDirectRx.setCapacity(64); - topicRx.setCapacity(64); - - if (!strictSecurity) - directSender = session.createSender(directBase + addrArgs); - topicSender = session.createSender(topicBase + addrArgs); - - // Start the receiver thread - threadCanceled = false; - opened = true; - thread = new qpid::sys::Thread(*this); - - // Send an initial agent heartbeat message - sendHeartbeat(); -} - - -void AgentSessionImpl::closeAsync() -{ - if (!opened) - return; - - // Stop the receiver thread. Don't join it until the destructor is called or open() is called. - threadCanceled = true; - opened = false; -} - - -void AgentSessionImpl::close() -{ - closeAsync(); - - if (thread) { - thread->join(); - delete thread; - thread = 0; - } -} - - -bool AgentSessionImpl::nextEvent(AgentEvent& event, Duration timeout) -{ - uint64_t milliseconds = timeout.getMilliseconds(); - qpid::sys::Mutex::ScopedLock l(lock); - - if (eventQueue.empty() && milliseconds > 0) { - int64_t nsecs(qpid::sys::TIME_INFINITE); - if ((uint64_t)(nsecs / 1000000) > milliseconds) - nsecs = (int64_t) milliseconds * 1000000; - qpid::sys::Duration then(nsecs); - cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(), then)); - } - - if (!eventQueue.empty()) { - event = eventQueue.front(); - eventQueue.pop(); - if (eventQueue.empty()) - alertEventNotifierLH(false); - return true; - } - - return false; -} - - -int AgentSessionImpl::pendingEvents() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return eventQueue.size(); -} - - -void AgentSessionImpl::setEventNotifier(EventNotifierImpl* notifier) -{ - qpid::sys::Mutex::ScopedLock l(lock); - eventNotifier = notifier; -} - -EventNotifierImpl* AgentSessionImpl::getEventNotifier() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return eventNotifier; -} - - -void AgentSessionImpl::registerSchema(Schema& schema) -{ - if (!schema.isFinalized()) - schema.finalize(); - const SchemaId& schemaId(schema.getSchemaId()); - - qpid::sys::Mutex::ScopedLock l(lock); - schemata[schemaId] = schema; - schemaIndex[schemaId] = DataIndex(); - - // - // Get the news out at the next periodic interval that there is new schema information. - // - schemaUpdateTime = uint64_t(qpid::sys::Duration::FromEpoch()); - forceHeartbeat = true; -} - - -DataAddr AgentSessionImpl::addData(Data& data, const string& name, bool persistent) -{ - if (externalStorage) - throw QmfException("addData() must not be called when the 'external' option is enabled."); - - string dataName; - if (name.empty()) - dataName = qpid::types::Uuid(true).str(); - else - dataName = name; - - DataAddr addr(dataName, agentName, persistent ? 0 : bootSequence); - data.setAddr(addr); - - { - qpid::sys::Mutex::ScopedLock l(lock); - DataIndex::const_iterator iter = globalIndex.find(addr); - if (iter != globalIndex.end()) - throw QmfException("Duplicate Data Address"); - - globalIndex[addr] = data; - if (data.hasSchema()) - schemaIndex[data.getSchemaId()][addr] = data; - } - - // - // TODO: Survey active subscriptions to see if they need to hear about this new data. - // - - return addr; -} - - -void AgentSessionImpl::delData(const DataAddr& addr) -{ - { - qpid::sys::Mutex::ScopedLock l(lock); - DataIndex::iterator iter = globalIndex.find(addr); - if (iter == globalIndex.end()) - return; - if (iter->second.hasSchema()) { - const SchemaId& schemaId(iter->second.getSchemaId()); - schemaIndex[schemaId].erase(addr); - } - globalIndex.erase(iter); - } - - // - // TODO: Survey active subscriptions to see if they need to hear about this deleted data. - // -} - - -void AgentSessionImpl::authAccept(AgentEvent& authEvent) -{ - std::auto_ptr eventImpl(new AgentEventImpl(AGENT_QUERY)); - eventImpl->setQuery(authEvent.getQuery()); - eventImpl->setUserId(authEvent.getUserId()); - eventImpl->setReplyTo(AgentEventImplAccess::get(authEvent).getReplyTo()); - eventImpl->setCorrelationId(AgentEventImplAccess::get(authEvent).getCorrelationId()); - AgentEvent event(eventImpl.release()); - - if (externalStorage) { - enqueueEvent(event); - return; - } - - const Query& query(authEvent.getQuery()); - if (query.getDataAddr().isValid()) { - { - qpid::sys::Mutex::ScopedLock l(lock); - DataIndex::const_iterator iter = globalIndex.find(query.getDataAddr()); - if (iter != globalIndex.end()) - response(event, iter->second); - } - complete(event); - return; - } - - if (query.getSchemaId().isValid()) { - { - qpid::sys::Mutex::ScopedLock l(lock); - map::const_iterator iter = schemaIndex.find(query.getSchemaId()); - if (iter != schemaIndex.end()) - for (DataIndex::const_iterator dIter = iter->second.begin(); dIter != iter->second.end(); dIter++) - if (query.matchesPredicate(dIter->second.getProperties())) - response(event, dIter->second); - } - complete(event); - return; - } - - raiseException(event, "Query is Invalid"); -} - - -void AgentSessionImpl::authReject(AgentEvent& event, const string& error) -{ - raiseException(event, "Action Forbidden - " + error); -} - - -void AgentSessionImpl::raiseException(AgentEvent& event, const string& error) -{ - Data exception(new DataImpl()); - exception.setProperty("error_text", error); - raiseException(event, exception); -} - - -void AgentSessionImpl::raiseException(AgentEvent& event, const Data& data) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_EXCEPTION; - headers[protocol::HEADER_KEY_CONTENT] = protocol::HEADER_CONTENT_DATA; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - AgentEventImpl& eventImpl(AgentEventImplAccess::get(event)); - const DataImpl& dataImpl(DataImplAccess::get(data)); - - msg.setCorrelationId(eventImpl.getCorrelationId()); - encode(dataImpl.asMap(), msg); - send(msg, eventImpl.getReplyTo()); - - QPID_LOG(trace, "SENT Exception to=" << eventImpl.getReplyTo()); -} - - -void AgentSessionImpl::response(AgentEvent& event, const Data& data) -{ - AgentEventImpl& impl(AgentEventImplAccess::get(event)); - uint32_t count = impl.enqueueData(data); - if (count >= 8) - flushResponses(event, false); -} - - -void AgentSessionImpl::complete(AgentEvent& event) -{ - flushResponses(event, true); -} - - -void AgentSessionImpl::methodSuccess(AgentEvent& event) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - AgentEventImpl& eventImpl(AgentEventImplAccess::get(event)); - - const Variant::Map& outArgs(eventImpl.getReturnArguments()); - const Variant::Map& outSubtypes(eventImpl.getReturnArgumentSubtypes()); - - map["_arguments"] = outArgs; - if (!outSubtypes.empty()) - map["_subtypes"] = outSubtypes; - - msg.setCorrelationId(eventImpl.getCorrelationId()); - encode(map, msg); - send(msg, eventImpl.getReplyTo()); - - QPID_LOG(trace, "SENT MethodResponse to=" << eventImpl.getReplyTo()); -} - - -void AgentSessionImpl::raiseEvent(const Data& data) -{ - int severity(SEV_NOTICE); - if (data.hasSchema()) { - const Schema& schema(DataImplAccess::get(data).getSchema()); - if (schema.isValid()) - severity = schema.getDefaultSeverity(); - } - - raiseEvent(data, severity); -} - - -void AgentSessionImpl::raiseEvent(const Data& data, int severity) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - string subject("agent.ind.event"); - - if (data.hasSchema()) { - const SchemaId& schemaId(data.getSchemaId()); - if (schemaId.getType() != SCHEMA_TYPE_EVENT) - throw QmfException("Cannot call raiseEvent on data that is not an Event"); - subject = subject + "." + schemaId.getPackageName() + "." + schemaId.getName(); - } - - if (severity < SEV_EMERG || severity > SEV_DEBUG) - throw QmfException("Invalid severity value"); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_INDICATION; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_DATA_INDICATION; - headers[protocol::HEADER_KEY_CONTENT] = protocol::HEADER_CONTENT_EVENT; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - msg.setSubject(subject); - - Variant::List list; - Variant::Map dataAsMap(DataImplAccess::get(data).asMap()); - dataAsMap["_severity"] = severity; - dataAsMap["_timestamp"] = uint64_t(qpid::sys::Duration::FromEpoch()); - list.push_back(dataAsMap); - encode(list, msg); - topicSender.send(msg); - - QPID_LOG(trace, "SENT EventIndication to=" << topicSender.getName() << "/" << subject); -} - - -void AgentSessionImpl::checkOpen() -{ - if (opened) - throw QmfException("Operation must be performed before calling open()"); -} - - -void AgentSessionImpl::enqueueEvent(const AgentEvent& event) -{ - qpid::sys::Mutex::ScopedLock l(lock); - bool notify = eventQueue.empty(); - eventQueue.push(event); - if (notify) { - cond.notify(); - alertEventNotifierLH(true); - } -} - - -void AgentSessionImpl::setAgentName() -{ - Variant::Map::iterator iter; - string vendor; - string product; - string instance; - - iter = attributes.find("_vendor"); - if (iter == attributes.end()) - attributes["_vendor"] = vendor; - else - vendor = iter->second.asString(); - - iter = attributes.find("_product"); - if (iter == attributes.end()) - attributes["_product"] = product; - else - product = iter->second.asString(); - - iter = attributes.find("_instance"); - if (iter == attributes.end()) { - instance = qpid::types::Uuid(true).str(); - attributes["_instance"] = instance; - } else - instance = iter->second.asString(); - - agentName = vendor + ":" + product + ":" + instance; - attributes["_name"] = agentName; -} - - -void AgentSessionImpl::handleLocateRequest(const Variant::List& predicate, const Message& msg) -{ - QPID_LOG(trace, "RCVD AgentLocateRequest from=" << msg.getReplyTo()); - - if (!predicate.empty()) { - Query agentQuery(QUERY_OBJECT); - agentQuery.setPredicate(predicate); - if (!agentQuery.matchesPredicate(attributes)) { - QPID_LOG(trace, "AgentLocate predicate does not match this agent, ignoring"); - return; - } - } - - Message reply; - Variant::Map map; - Variant::Map& headers(reply.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_INDICATION; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_AGENT_LOCATE_RESPONSE; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - map["_values"] = attributes; - map["_values"].asMap()[protocol::AGENT_ATTR_TIMESTAMP] = uint64_t(qpid::sys::Duration::FromEpoch()); - map["_values"].asMap()[protocol::AGENT_ATTR_HEARTBEAT_INTERVAL] = interval; - map["_values"].asMap()[protocol::AGENT_ATTR_EPOCH] = bootSequence; - map["_values"].asMap()[protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP] = schemaUpdateTime; - - encode(map, reply); - send(reply, msg.getReplyTo()); - QPID_LOG(trace, "SENT AgentLocateResponse to=" << msg.getReplyTo()); -} - - -void AgentSessionImpl::handleMethodRequest(const Variant::Map& content, const Message& msg) -{ - QPID_LOG(trace, "RCVD MethodRequest map=" << content << " from=" << msg.getReplyTo() << " cid=" << msg.getCorrelationId()); - - // - // Construct an AgentEvent to be sent to the application. - // - std::auto_ptr eventImpl(new AgentEventImpl(AGENT_METHOD)); - eventImpl->setUserId(msg.getUserId()); - eventImpl->setReplyTo(msg.getReplyTo()); - eventImpl->setCorrelationId(msg.getCorrelationId()); - - Variant::Map::const_iterator iter; - - iter = content.find("_method_name"); - if (iter == content.end()) { - AgentEvent event(eventImpl.release()); - raiseException(event, "Malformed MethodRequest: missing _method_name field"); - return; - } - eventImpl->setMethodName(iter->second.asString()); - - iter = content.find("_arguments"); - if (iter != content.end()) - eventImpl->setArguments(iter->second.asMap()); - - iter = content.find("_subtypes"); - if (iter != content.end()) - eventImpl->setArgumentSubtypes(iter->second.asMap()); - - iter = content.find("_object_id"); - if (iter != content.end()) { - DataAddr addr(new DataAddrImpl(iter->second.asMap())); - eventImpl->setDataAddr(addr); - if (!externalStorage) { - DataIndex::const_iterator iter(globalIndex.find(addr)); - if (iter == globalIndex.end()) { - AgentEvent event(eventImpl.release()); - raiseException(event, "No data object found with the specified address"); - return; - } - - const Schema& schema(DataImplAccess::get(iter->second).getSchema()); - if (schema.isValid()) { - eventImpl->setSchema(schema); - for (Variant::Map::const_iterator aIter = eventImpl->getArguments().begin(); - aIter != eventImpl->getArguments().end(); aIter++) { - const Schema& schema(DataImplAccess::get(iter->second).getSchema()); - if (!SchemaImplAccess::get(schema).isValidMethodInArg(eventImpl->getMethodName(), aIter->first, aIter->second)) { - AgentEvent event(eventImpl.release()); - raiseException(event, "Invalid argument: " + aIter->first); - return; - } - } - } - } - } - - enqueueEvent(AgentEvent(eventImpl.release())); -} - - -void AgentSessionImpl::handleQueryRequest(const Variant::Map& content, const Message& msg) -{ - QPID_LOG(trace, "RCVD QueryRequest query=" << content << " from=" << msg.getReplyTo() << " cid=" << msg.getCorrelationId()); - - // - // Construct an AgentEvent to be sent to the application or directly handled by the agent. - // - std::auto_ptr queryImpl(new QueryImpl(content)); - std::auto_ptr eventImpl(new AgentEventImpl(AGENT_AUTH_QUERY)); - eventImpl->setUserId(msg.getUserId()); - eventImpl->setReplyTo(msg.getReplyTo()); - eventImpl->setCorrelationId(msg.getCorrelationId()); - eventImpl->setQuery(queryImpl.release()); - AgentEvent ae(eventImpl.release()); - - if (ae.getQuery().getTarget() == QUERY_SCHEMA_ID || ae.getQuery().getTarget() == QUERY_SCHEMA) { - handleSchemaRequest(ae); - return; - } - - if (autoAllowQueries) - authAccept(ae); - else - enqueueEvent(ae); -} - - -void AgentSessionImpl::handleSchemaRequest(AgentEvent& event) -{ - SchemaMap::const_iterator iter; - string error; - const Query& query(event.getQuery()); - - Message msg; - Variant::List content; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_QUERY_RESPONSE; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - { - qpid::sys::Mutex::ScopedLock l(lock); - if (query.getTarget() == QUERY_SCHEMA_ID) { - headers[protocol::HEADER_KEY_CONTENT] = "_schema_id"; - for (iter = schemata.begin(); iter != schemata.end(); iter++) - content.push_back(SchemaIdImplAccess::get(iter->first).asMap()); - } else if (query.getSchemaId().isValid()) { - headers[protocol::HEADER_KEY_CONTENT] = "_schema"; - iter = schemata.find(query.getSchemaId()); - if (iter != schemata.end()) - content.push_back(SchemaImplAccess::get(iter->second).asMap()); - } else { - error = "Invalid Schema Query: Requests for SCHEMA must supply a valid schema ID."; - } - } - - if (!error.empty()) { - raiseException(event, error); - return; - } - - AgentEventImpl& eventImpl(AgentEventImplAccess::get(event)); - - msg.setCorrelationId(eventImpl.getCorrelationId()); - encode(content, msg); - send(msg, eventImpl.getReplyTo()); - - QPID_LOG(trace, "SENT QueryResponse(Schema) to=" << eventImpl.getReplyTo()); -} - - -void AgentSessionImpl::handleV1SchemaRequest(qpid::management::Buffer& buffer, uint32_t seq, const Message& msg) -{ - string packageName; - string className; - uint8_t hashBits[16]; - - buffer.getShortString(packageName); - buffer.getShortString(className); - buffer.getBin128(hashBits); - - QPID_LOG(trace, "RCVD QMFv1 SchemaRequest for " << packageName << ":" << className); - - qpid::types::Uuid hash(hashBits); - map::const_iterator iter; - string replyContent; - - SchemaId dataId(SCHEMA_TYPE_DATA, packageName, className); - dataId.setHash(hash); - - { - qpid::sys::Mutex::ScopedLock l(lock); - iter = schemata.find(dataId); - if (iter != schemata.end()) - replyContent = SchemaImplAccess::get(iter->second).asV1Content(seq); - else { - SchemaId eventId(SCHEMA_TYPE_EVENT, packageName, className); - eventId.setHash(hash); - iter = schemata.find(dataId); - if (iter != schemata.end()) - replyContent = SchemaImplAccess::get(iter->second).asV1Content(seq); - else - return; - } - } - - Message reply; - Variant::Map& headers(reply.getProperties()); - - headers[protocol::HEADER_KEY_AGENT] = agentName; - reply.setContent(replyContent); - - send(reply, msg.getReplyTo()); - QPID_LOG(trace, "SENT QMFv1 SchemaResponse to=" << msg.getReplyTo()); -} - - -void AgentSessionImpl::dispatch(Message msg) -{ - const Variant::Map& properties(msg.getProperties()); - Variant::Map::const_iterator iter; - - // - // If strict-security is enabled, make sure that reply-to address complies with the - // strict-security addressing pattern (i.e. start with 'qmf..topic/direct-console.'). - // - if (strictSecurity && msg.getReplyTo()) { - if (msg.getReplyTo().getName() != topicBase || msg.getReplyTo().getSubject().find("direct-console.") != 0) { - QPID_LOG(warning, "Reply-to violates strict-security policy: " << msg.getReplyTo().str()); - return; - } - } - - iter = properties.find(protocol::HEADER_KEY_APP_ID); - if (iter != properties.end() && iter->second.asString() == protocol::HEADER_APP_ID_QMF) { - // - // Dispatch a QMFv2 formatted message - // - iter = properties.find(protocol::HEADER_KEY_OPCODE); - if (iter == properties.end()) { - QPID_LOG(trace, "Message received with no 'qmf.opcode' header"); - return; - } - - const string& opcode = iter->second.asString(); - - if (msg.getContentType() == "amqp/list") { - Variant::List content; - decode(msg, content); - - if (opcode == protocol::HEADER_OPCODE_AGENT_LOCATE_REQUEST) handleLocateRequest(content, msg); - else { - QPID_LOG(trace, "Unexpected QMFv2 opcode with 'amqp/list' content: " << opcode); - } - - } else if (msg.getContentType() == "amqp/map") { - Variant::Map content; - decode(msg, content); - - if (opcode == protocol::HEADER_OPCODE_METHOD_REQUEST) handleMethodRequest(content, msg); - else if (opcode == protocol::HEADER_OPCODE_QUERY_REQUEST) handleQueryRequest(content, msg); - else { - QPID_LOG(trace, "Unexpected QMFv2 opcode with 'amqp/map' content: " << opcode); - } - } else { - QPID_LOG(trace, "Unexpected QMFv2 content type. Expected amqp/list or amqp/map"); - } - - } else { - // - // Dispatch a QMFv1 formatted message - // - const string& body(msg.getContent()); - if (body.size() < 8) - return; - qpid::management::Buffer buffer(const_cast(body.c_str()), body.size()); - - if (buffer.getOctet() != 'A') return; - if (buffer.getOctet() != 'M') return; - if (buffer.getOctet() != '2') return; - char v1Opcode(buffer.getOctet()); - uint32_t seq(buffer.getLong()); - - if (v1Opcode == 'S') handleV1SchemaRequest(buffer, seq, msg); - else { - QPID_LOG(trace, "Unknown or Unsupported QMFv1 opcode: " << v1Opcode); - } - } -} - - -void AgentSessionImpl::sendHeartbeat() -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - std::stringstream address; - - address << "agent.ind.heartbeat"; - - // append .. to address key if present. - Variant::Map::const_iterator v; - if ((v = attributes.find("_vendor")) != attributes.end() && !v->second.getString().empty()) { - address << "." << v->second.getString(); - if ((v = attributes.find("_product")) != attributes.end() && !v->second.getString().empty()) { - address << "." << v->second.getString(); - } - } - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_INDICATION; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_AGENT_HEARTBEAT_INDICATION; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - msg.setSubject(address.str()); - - map["_values"] = attributes; - map["_values"].asMap()[protocol::AGENT_ATTR_TIMESTAMP] = uint64_t(qpid::sys::Duration::FromEpoch()); - map["_values"].asMap()[protocol::AGENT_ATTR_HEARTBEAT_INTERVAL] = interval; - map["_values"].asMap()[protocol::AGENT_ATTR_EPOCH] = bootSequence; - map["_values"].asMap()[protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP] = schemaUpdateTime; - - encode(map, msg); - topicSender.send(msg); - QPID_LOG(trace, "SENT AgentHeartbeat name=" << agentName); -} - - -void AgentSessionImpl::send(Message msg, const Address& to) -{ - Sender sender; - - if (strictSecurity && to.getName() != topicBase) { - QPID_LOG(warning, "Address violates strict-security policy: " << to); - return; - } - - if (to.getName() == directBase) { - msg.setSubject(to.getSubject()); - sender = directSender; - } else if (to.getName() == topicBase) { - msg.setSubject(to.getSubject()); - sender = topicSender; - } else - sender = session.createSender(to); - - sender.send(msg); -} - - -void AgentSessionImpl::flushResponses(AgentEvent& event, bool final) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_QUERY_RESPONSE; - headers[protocol::HEADER_KEY_CONTENT] = protocol::HEADER_CONTENT_DATA; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - if (!final) - headers[protocol::HEADER_KEY_PARTIAL] = Variant(); - - Variant::List body; - AgentEventImpl& eventImpl(AgentEventImplAccess::get(event)); - Data data(eventImpl.dequeueData()); - while (data.isValid()) { - DataImpl& dataImpl(DataImplAccess::get(data)); - body.push_back(dataImpl.asMap()); - data = eventImpl.dequeueData(); - } - - msg.setCorrelationId(eventImpl.getCorrelationId()); - encode(body, msg); - send(msg, eventImpl.getReplyTo()); - - QPID_LOG(trace, "SENT QueryResponse to=" << eventImpl.getReplyTo()); -} - - -void AgentSessionImpl::periodicProcessing(uint64_t seconds) -{ - // - // The granularity of this timer is seconds. Don't waste time looking for work if - // it's been less than a second since we last visited. - // - if (seconds == lastVisit) - return; - //uint64_t thisInterval(seconds - lastVisit); - lastVisit = seconds; - - // - // First time through, set lastHeartbeat to the current time. - // - if (lastHeartbeat == 0) - lastHeartbeat = seconds; - - // - // If the hearbeat interval has elapsed, send a heartbeat. - // - if (forceHeartbeat || (seconds - lastHeartbeat >= interval)) { - lastHeartbeat = seconds; - forceHeartbeat = false; - sendHeartbeat(); - } - - // - // TODO: process any active subscriptions on their intervals. - // -} - - -void AgentSessionImpl::alertEventNotifierLH(bool readable) -{ - if (eventNotifier) - eventNotifier->setReadable(readable); -} - - -void AgentSessionImpl::run() -{ - QPID_LOG(debug, "AgentSession thread started for agent " << agentName); - - try { - while (!threadCanceled) { - periodicProcessing((uint64_t) qpid::sys::Duration::FromEpoch() / qpid::sys::TIME_SEC); - - Receiver rx; - bool valid = session.nextReceiver(rx, Duration::SECOND * maxThreadWaitTime); - if (threadCanceled) - break; - if (valid) { - try { - dispatch(rx.fetch()); - } catch (qpid::types::Exception& e) { - QPID_LOG(error, "Exception caught in message dispatch: " << e.what()); - } - session.acknowledge(); - } - } - } catch (qpid::types::Exception& e) { - QPID_LOG(error, "Exception caught in message thread - exiting: " << e.what()); - enqueueEvent(AgentEvent(new AgentEventImpl(AGENT_THREAD_FAILED))); - } - - session.close(); - QPID_LOG(debug, "AgentSession thread exiting for agent " << agentName); -} - - -AgentSessionImpl& AgentSessionImplAccess::get(AgentSession& session) -{ - return *session.impl; -} - - -const AgentSessionImpl& AgentSessionImplAccess::get(const AgentSession& session) -{ - return *session.impl; -} - -} diff --git a/qpid/cpp/src/qmf/AgentSessionImpl.h b/qpid/cpp/src/qmf/AgentSessionImpl.h deleted file mode 100644 index 64a39ab2e8..0000000000 --- a/qpid/cpp/src/qmf/AgentSessionImpl.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef __QMF_AGENT_SESSION_IMPL_H -#define __QMF_AGENT_SESSION_IMPL_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/RefCounted.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/AgentSession.h" -#include "qmf/AgentEventImpl.h" -#include "qmf/EventNotifierImpl.h" -#include "qpid/messaging/Connection.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Condition.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/management/Buffer.h" -#include "qpid/RefCounted.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/AgentSession.h" -#include "qmf/exceptions.h" -#include "qmf/AgentSession.h" -#include "qmf/SchemaIdImpl.h" -#include "qmf/SchemaImpl.h" -#include "qmf/DataAddrImpl.h" -#include "qmf/DataImpl.h" -#include "qmf/QueryImpl.h" -#include "qmf/agentCapability.h" -#include "qmf/constants.h" - -#include -#include - -namespace qmf { - typedef qmf::PrivateImplRef PI; - - class AgentSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable { - public: - ~AgentSessionImpl(); - - // - // Methods from API handle - // - AgentSessionImpl(qpid::messaging::Connection& c, const std::string& o); - void setDomain(const std::string& d) { checkOpen(); domain = d; } - void setVendor(const std::string& v) { checkOpen(); attributes["_vendor"] = v; } - void setProduct(const std::string& p) { checkOpen(); attributes["_product"] = p; } - void setInstance(const std::string& i) { checkOpen(); attributes["_instance"] = i; } - void setAttribute(const std::string& k, const qpid::types::Variant& v) { checkOpen(); attributes[k] = v; } - const std::string& getName() const { return agentName; } - void open(); - void closeAsync(); - void close(); - bool nextEvent(AgentEvent& e, qpid::messaging::Duration t); - int pendingEvents() const; - - void setEventNotifier(EventNotifierImpl* eventNotifier); - EventNotifierImpl* getEventNotifier() const; - - void registerSchema(Schema& s); - DataAddr addData(Data& d, const std::string& n, bool persist); - void delData(const DataAddr&); - - void authAccept(AgentEvent& e); - void authReject(AgentEvent& e, const std::string& m); - void raiseException(AgentEvent& e, const std::string& s); - void raiseException(AgentEvent& e, const Data& d); - void response(AgentEvent& e, const Data& d); - void complete(AgentEvent& e); - void methodSuccess(AgentEvent& e); - void raiseEvent(const Data& d); - void raiseEvent(const Data& d, int s); - - private: - typedef std::map DataIndex; - typedef std::map SchemaMap; - - mutable qpid::sys::Mutex lock; - qpid::sys::Condition cond; - qpid::messaging::Connection connection; - qpid::messaging::Session session; - qpid::messaging::Sender directSender; - qpid::messaging::Sender topicSender; - std::string domain; - qpid::types::Variant::Map attributes; - qpid::types::Variant::Map options; - std::string agentName; - bool opened; - std::queue eventQueue; - EventNotifierImpl* eventNotifier; - qpid::sys::Thread* thread; - bool threadCanceled; - uint32_t bootSequence; - uint32_t interval; - uint64_t lastHeartbeat; - uint64_t lastVisit; - bool forceHeartbeat; - bool externalStorage; - bool autoAllowQueries; - bool autoAllowMethods; - uint32_t maxSubscriptions; - uint32_t minSubInterval; - uint32_t subLifetime; - bool publicEvents; - bool listenOnDirect; - bool strictSecurity; - uint32_t maxThreadWaitTime; - uint64_t schemaUpdateTime; - std::string directBase; - std::string topicBase; - - SchemaMap schemata; - DataIndex globalIndex; - std::map schemaIndex; - - void checkOpen(); - void setAgentName(); - void enqueueEvent(const AgentEvent&); - void alertEventNotifierLH(bool readable); - void handleLocateRequest(const qpid::types::Variant::List& content, const qpid::messaging::Message& msg); - void handleMethodRequest(const qpid::types::Variant::Map& content, const qpid::messaging::Message& msg); - void handleQueryRequest(const qpid::types::Variant::Map& content, const qpid::messaging::Message& msg); - void handleSchemaRequest(AgentEvent&); - void handleV1SchemaRequest(qpid::management::Buffer&, uint32_t, const qpid::messaging::Message&); - void dispatch(qpid::messaging::Message); - void sendHeartbeat(); - void send(qpid::messaging::Message, const qpid::messaging::Address&); - void flushResponses(AgentEvent&, bool); - void periodicProcessing(uint64_t); - void run(); - }; - - struct AgentSessionImplAccess { - static AgentSessionImpl& get(AgentSession& session); - static const AgentSessionImpl& get(const AgentSession& session); - }; -} - - -#endif - diff --git a/qpid/cpp/src/qmf/AgentSubscription.cpp b/qpid/cpp/src/qmf/AgentSubscription.cpp deleted file mode 100644 index 4dc5cb74a4..0000000000 --- a/qpid/cpp/src/qmf/AgentSubscription.cpp +++ /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. - * - */ - -#include "qmf/AgentSubscription.h" - -using namespace qmf; - -AgentSubscription::AgentSubscription(uint64_t _id, uint64_t _interval, uint64_t _life, - const std::string& _replyTo, const std::string& _cid, Query _query) : - id(_id), interval(_interval), lifetime(_life), timeSincePublish(0), timeSinceKeepalive(0), - replyTo(_replyTo), cid(_cid), query(_query) -{ -} - - -AgentSubscription::~AgentSubscription() -{ -} - - -bool AgentSubscription::tick(uint64_t seconds) -{ - timeSinceKeepalive += seconds; - if (timeSinceKeepalive >= lifetime) - return false; - - timeSincePublish += seconds; - if (timeSincePublish >= interval) { - } - - return true; -} - diff --git a/qpid/cpp/src/qmf/AgentSubscription.h b/qpid/cpp/src/qmf/AgentSubscription.h deleted file mode 100644 index 01e8f43e9f..0000000000 --- a/qpid/cpp/src/qmf/AgentSubscription.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _QMF_AGENT_SUBSCRIPTION_H_ -#define _QMF_AGENT_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/sys/IntegerTypes.h" -#include "qpid/types/Variant.h" -#include "qmf/Query.h" -#include "qmf/Data.h" -#include - -namespace qmf { - class AgentSubscription { - public: - AgentSubscription(uint64_t _id, uint64_t _interval, uint64_t _life, - const std::string& _replyTo, const std::string& _cid, Query _query); - ~AgentSubscription(); - bool tick(uint64_t seconds); - void keepalive() { timeSinceKeepalive = 0; } - - private: - uint64_t id; - uint64_t interval; - uint64_t lifetime; - uint64_t timeSincePublish; - uint64_t timeSinceKeepalive; - const std::string replyTo; - const std::string cid; - Query query; - }; - -} - -#endif diff --git a/qpid/cpp/src/qmf/ConsoleEvent.cpp b/qpid/cpp/src/qmf/ConsoleEvent.cpp deleted file mode 100644 index b2a5e321c7..0000000000 --- a/qpid/cpp/src/qmf/ConsoleEvent.cpp +++ /dev/null @@ -1,82 +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/ConsoleEventImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef PI; - -ConsoleEvent::ConsoleEvent(ConsoleEventImpl* impl) { PI::ctor(*this, impl); } -ConsoleEvent::ConsoleEvent(const ConsoleEvent& s) : qmf::Handle() { PI::copy(*this, s); } -ConsoleEvent::~ConsoleEvent() { PI::dtor(*this); } -ConsoleEvent& ConsoleEvent::operator=(const ConsoleEvent& s) { return PI::assign(*this, s); } - -ConsoleEventCode ConsoleEvent::getType() const { return impl->getType(); } -uint32_t ConsoleEvent::getCorrelator() const { return impl->getCorrelator(); } -Agent ConsoleEvent::getAgent() const { return impl->getAgent(); } -AgentDelReason ConsoleEvent::getAgentDelReason() const { return impl->getAgentDelReason(); } -uint32_t ConsoleEvent::getSchemaIdCount() const { return impl->getSchemaIdCount(); } -SchemaId ConsoleEvent::getSchemaId(uint32_t i) const { return impl->getSchemaId(i); } -uint32_t ConsoleEvent::getDataCount() const { return impl->getDataCount(); } -Data ConsoleEvent::getData(uint32_t i) const { return impl->getData(i); } -bool ConsoleEvent::isFinal() const { return impl->isFinal(); } -const Variant::Map& ConsoleEvent::getArguments() const { return impl->getArguments(); } -int ConsoleEvent::getSeverity() const { return impl->getSeverity(); } -uint64_t ConsoleEvent::getTimestamp() const { return impl->getTimestamp(); } - - -SchemaId ConsoleEventImpl::getSchemaId(uint32_t i) const -{ - uint32_t count = 0; - for (list::const_iterator iter = newSchemaIds.begin(); iter != newSchemaIds.end(); iter++) { - if (count++ == i) - return *iter; - } - throw IndexOutOfRange(); -} - - -Data ConsoleEventImpl::getData(uint32_t i) const -{ - uint32_t count = 0; - for (list::const_iterator iter = dataList.begin(); iter != dataList.end(); iter++) { - if (count++ == i) - return *iter; - } - throw IndexOutOfRange(); -} - - -ConsoleEventImpl& ConsoleEventImplAccess::get(ConsoleEvent& item) -{ - return *item.impl; -} - - -const ConsoleEventImpl& ConsoleEventImplAccess::get(const ConsoleEvent& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/ConsoleEventImpl.h b/qpid/cpp/src/qmf/ConsoleEventImpl.h deleted file mode 100644 index 9843971456..0000000000 --- a/qpid/cpp/src/qmf/ConsoleEventImpl.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _QMF_CONSOLE_EVENT_IMPL_H_ -#define _QMF_CONSOLE_EVENT_IMPL_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/RefCounted.h" -#include "qmf/ConsoleEvent.h" -#include "qmf/Agent.h" -#include "qmf/Data.h" -#include "qpid/types/Variant.h" -#include - -namespace qmf { - class ConsoleEventImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only methods - // - ConsoleEventImpl(ConsoleEventCode e, AgentDelReason r = AGENT_DEL_AGED) : - eventType(e), delReason(r), correlator(0), final(false) {} - void setCorrelator(uint32_t c) { correlator = c; } - void setAgent(const Agent& a) { agent = a; } - void addData(const Data& d) { dataList.push_back(Data(d)); } - void addSchemaId(const SchemaId& s) { newSchemaIds.push_back(SchemaId(s)); } - void setFinal() { final = true; } - void setArguments(const qpid::types::Variant::Map& a) { arguments = a; } - void setSeverity(int s) { severity = s; } - void setTimestamp(uint64_t t) { timestamp = t; } - - // - // Methods from API handle - // - ConsoleEventCode getType() const { return eventType; } - uint32_t getCorrelator() const { return correlator; } - Agent getAgent() const { return agent; } - AgentDelReason getAgentDelReason() const { return delReason; } - uint32_t getSchemaIdCount() const { return newSchemaIds.size(); } - SchemaId getSchemaId(uint32_t) const; - uint32_t getDataCount() const { return dataList.size(); } - Data getData(uint32_t i) const; - bool isFinal() const { return final; } - const qpid::types::Variant::Map& getArguments() const { return arguments; } - int getSeverity() const { return severity; } - uint64_t getTimestamp() const { return timestamp; } - - private: - const ConsoleEventCode eventType; - const AgentDelReason delReason; - uint32_t correlator; - Agent agent; - bool final; - std::list dataList; - std::list newSchemaIds; - qpid::types::Variant::Map arguments; - int severity; - uint64_t timestamp; - }; - - struct ConsoleEventImplAccess - { - static ConsoleEventImpl& get(ConsoleEvent&); - static const ConsoleEventImpl& get(const ConsoleEvent&); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/ConsoleSession.cpp b/qpid/cpp/src/qmf/ConsoleSession.cpp deleted file mode 100644 index c74d4de8db..0000000000 --- a/qpid/cpp/src/qmf/ConsoleSession.cpp +++ /dev/null @@ -1,683 +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/PrivateImplRef.h" -#include "qmf/ConsoleSessionImpl.h" -#include "qmf/AgentImpl.h" -#include "qmf/SchemaId.h" -#include "qmf/SchemaImpl.h" -#include "qmf/ConsoleEventImpl.h" -#include "qmf/constants.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" - -using namespace std; -using namespace qmf; -using qpid::messaging::Address; -using qpid::messaging::Connection; -using qpid::messaging::Receiver; -using qpid::messaging::Sender; -using qpid::messaging::Duration; -using qpid::messaging::Message; -using qpid::types::Variant; - -typedef qmf::PrivateImplRef PI; - -ConsoleSession::ConsoleSession(ConsoleSessionImpl* impl) { PI::ctor(*this, impl); } -ConsoleSession::ConsoleSession(const ConsoleSession& s) : qmf::Handle() { PI::copy(*this, s); } -ConsoleSession::~ConsoleSession() { PI::dtor(*this); } -ConsoleSession& ConsoleSession::operator=(const ConsoleSession& s) { return PI::assign(*this, s); } - -ConsoleSession::ConsoleSession(Connection& c, const string& o) { PI::ctor(*this, new ConsoleSessionImpl(c, o)); } -void ConsoleSession::setDomain(const string& d) { impl->setDomain(d); } -void ConsoleSession::setAgentFilter(const string& f) { impl->setAgentFilter(f); } -void ConsoleSession::open() { impl->open(); } -void ConsoleSession::close() { impl->close(); } -bool ConsoleSession::nextEvent(ConsoleEvent& e, Duration t) { return impl->nextEvent(e, t); } -int ConsoleSession::pendingEvents() const { return impl->pendingEvents(); } -uint32_t ConsoleSession::getAgentCount() const { return impl->getAgentCount(); } -Agent ConsoleSession::getAgent(uint32_t i) const { return impl->getAgent(i); } -Agent ConsoleSession::getConnectedBrokerAgent() const { return impl->getConnectedBrokerAgent(); } -Subscription ConsoleSession::subscribe(const Query& q, const string& f, const string& o) { return impl->subscribe(q, f, o); } -Subscription ConsoleSession::subscribe(const string& q, const string& f, const string& o) { return impl->subscribe(q, f, o); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -ConsoleSessionImpl::ConsoleSessionImpl(Connection& c, const string& options) : - connection(c), domain("default"), maxAgentAgeMinutes(5), listenOnDirect(true), strictSecurity(false), maxThreadWaitTime(5), - opened(false), eventNotifier(0), thread(0), threadCanceled(false), lastVisit(0), lastAgePass(0), - connectedBrokerInAgentList(false), schemaCache(new SchemaCache()), nextCorrelator(1) -{ - if (!options.empty()) { - qpid::messaging::AddressParser parser(options); - Variant::Map optMap; - Variant::Map::const_iterator iter; - - parser.parseMap(optMap); - - iter = optMap.find("domain"); - if (iter != optMap.end()) - domain = iter->second.asString(); - - iter = optMap.find("max-agent-age"); - if (iter != optMap.end()) - maxAgentAgeMinutes = iter->second.asUint32(); - - iter = optMap.find("listen-on-direct"); - if (iter != optMap.end()) - listenOnDirect = iter->second.asBool(); - - iter = optMap.find("strict-security"); - if (iter != optMap.end()) - strictSecurity = iter->second.asBool(); - - iter = optMap.find("max-thread-wait-time"); - if (iter != optMap.end()) - maxThreadWaitTime = iter->second.asUint32(); - } - - if (maxThreadWaitTime > 60) - maxThreadWaitTime = 60; -} - - -ConsoleSessionImpl::~ConsoleSessionImpl() -{ - if (opened) - close(); - - if (thread) { - thread->join(); - delete thread; - } -} - - -void ConsoleSessionImpl::setAgentFilter(const string& predicate) -{ - agentQuery = Query(QUERY_OBJECT, predicate); - - // - // Purge the agent list of any agents that don't match the filter. - // - { - qpid::sys::Mutex::ScopedLock l(lock); - map toDelete; - for (map::iterator iter = agents.begin(); iter != agents.end(); iter++) - if (!agentQuery.matchesPredicate(iter->second.getAttributes())) { - toDelete[iter->first] = iter->second; - if (iter->second.getName() == connectedBrokerAgent.getName()) - connectedBrokerInAgentList = false; - } - - for (map::iterator iter = toDelete.begin(); iter != toDelete.end(); iter++) { - agents.erase(iter->first); - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_DEL, AGENT_DEL_FILTER)); - eventImpl->setAgent(iter->second); - enqueueEventLH(eventImpl.release()); - } - - if (!connectedBrokerInAgentList && connectedBrokerAgent.isValid() && - agentQuery.matchesPredicate(connectedBrokerAgent.getAttributes())) { - agents[connectedBrokerAgent.getName()] = connectedBrokerAgent; - connectedBrokerInAgentList = true; - - // - // Enqueue a notification of the new agent. - // - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_ADD)); - eventImpl->setAgent(connectedBrokerAgent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - } - } - - // - // Broadcast an agent locate request with our new criteria. - // - if (opened) - sendAgentLocate(); -} - - -void ConsoleSessionImpl::open() -{ - if (opened) - throw QmfException("The session is already open"); - - // If the thread exists, join and delete it before creating a new one. - if (thread) { - thread->join(); - delete thread; - } - - // Establish messaging addresses - directBase = "qmf." + domain + ".direct"; - topicBase = "qmf." + domain + ".topic"; - - string myKey("direct-console." + qpid::types::Uuid(true).str()); - - replyAddress = Address(topicBase + "/" + myKey + ";{node:{type:topic}}"); - - // Create AMQP session, receivers, and senders - session = connection.createSession(); - Receiver directRx = session.createReceiver(replyAddress); - Receiver topicRx = session.createReceiver(topicBase + "/agent.#"); // TODO: be more discriminating - if (!strictSecurity) { - Receiver legacyRx = session.createReceiver("amq.direct/" + myKey + ";{node:{type:topic}}"); - legacyRx.setCapacity(64); - directSender = session.createSender(directBase + ";{create:never,node:{type:topic}}"); - directSender.setCapacity(128); - } - - directRx.setCapacity(64); - topicRx.setCapacity(128); - - topicSender = session.createSender(topicBase + ";{create:never,node:{type:topic}}"); - - topicSender.setCapacity(128); - - // Start the receiver thread - threadCanceled = false; - opened = true; - thread = new qpid::sys::Thread(*this); - - // Send an agent_locate to direct address 'broker' to identify the connected-broker-agent. - sendBrokerLocate(); - if (agentQuery) - sendAgentLocate(); -} - - -void ConsoleSessionImpl::closeAsync() -{ - if (!opened) - throw QmfException("The session is already closed"); - - // Stop the receiver thread. Don't join it until the destructor is called or open() is called. - threadCanceled = true; - opened = false; -} - - -void ConsoleSessionImpl::close() -{ - closeAsync(); - - if (thread) { - thread->join(); - delete thread; - thread = 0; - } -} - - -bool ConsoleSessionImpl::nextEvent(ConsoleEvent& event, Duration timeout) -{ - uint64_t milliseconds = timeout.getMilliseconds(); - qpid::sys::Mutex::ScopedLock l(lock); - - if (eventQueue.empty() && milliseconds > 0) { - int64_t nsecs(qpid::sys::TIME_INFINITE); - if ((uint64_t)(nsecs / 1000000) > milliseconds) - nsecs = (int64_t) milliseconds * 1000000; - qpid::sys::Duration then(nsecs); - cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(), then)); - } - - if (!eventQueue.empty()) { - event = eventQueue.front(); - eventQueue.pop(); - if (eventQueue.empty()) - alertEventNotifierLH(false); - return true; - } - - return false; -} - - -int ConsoleSessionImpl::pendingEvents() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return eventQueue.size(); -} - - -void ConsoleSessionImpl::setEventNotifier(EventNotifierImpl* notifier) -{ - qpid::sys::Mutex::ScopedLock l(lock); - eventNotifier = notifier; -} - - -EventNotifierImpl* ConsoleSessionImpl::getEventNotifier() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return eventNotifier; -} - - -uint32_t ConsoleSessionImpl::getAgentCount() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return agents.size(); -} - - -Agent ConsoleSessionImpl::getAgent(uint32_t i) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - uint32_t count = 0; - for (map::const_iterator iter = agents.begin(); iter != agents.end(); iter++) - if (count++ == i) - return iter->second; - throw IndexOutOfRange(); -} - - -Subscription ConsoleSessionImpl::subscribe(const Query&, const string&, const string&) -{ - return Subscription(); -} - - -Subscription ConsoleSessionImpl::subscribe(const string&, const string&, const string&) -{ - return Subscription(); -} - - -void ConsoleSessionImpl::enqueueEvent(const ConsoleEvent& event) -{ - qpid::sys::Mutex::ScopedLock l(lock); - enqueueEventLH(event); -} - - -void ConsoleSessionImpl::enqueueEventLH(const ConsoleEvent& event) -{ - bool notify = eventQueue.empty(); - eventQueue.push(event); - if (notify) { - cond.notify(); - alertEventNotifierLH(true); - } -} - - -void ConsoleSessionImpl::dispatch(Message msg) -{ - const Variant::Map& properties(msg.getProperties()); - Variant::Map::const_iterator iter; - Variant::Map::const_iterator oiter; - - oiter = properties.find(protocol::HEADER_KEY_OPCODE); - iter = properties.find(protocol::HEADER_KEY_APP_ID); - if (iter == properties.end()) - iter = properties.find("app_id"); - if (iter != properties.end() && iter->second.asString() == protocol::HEADER_APP_ID_QMF && oiter != properties.end()) { - // - // Dispatch a QMFv2 formatted message - // - const string& opcode = oiter->second.asString(); - - iter = properties.find(protocol::HEADER_KEY_AGENT); - if (iter == properties.end()) { - QPID_LOG(trace, "Message received with no 'qmf.agent' header"); - return; - } - const string& agentName = iter->second.asString(); - - Agent agent; - { - qpid::sys::Mutex::ScopedLock l(lock); - map::iterator aIter = agents.find(agentName); - if (aIter != agents.end()) { - agent = aIter->second; - AgentImplAccess::get(agent).touch(); - } - } - - if (msg.getContentType() == "amqp/map" && - (opcode == protocol::HEADER_OPCODE_AGENT_HEARTBEAT_INDICATION || opcode == protocol::HEADER_OPCODE_AGENT_LOCATE_RESPONSE)) { - // - // This is the one case where it's ok (necessary actually) to receive a QMFv2 - // message from an unknown agent (how else are they going to get known?) - // - Variant::Map content; - decode(msg, content); - handleAgentUpdate(agentName, content, msg); - return; - } - - if (!agent.isValid()) - return; - - AgentImpl& agentImpl(AgentImplAccess::get(agent)); - - if (msg.getContentType() == "amqp/map") { - Variant::Map content; - decode(msg, content); - - if (opcode == protocol::HEADER_OPCODE_EXCEPTION) agentImpl.handleException(content, msg); - else if (opcode == protocol::HEADER_OPCODE_METHOD_RESPONSE) agentImpl.handleMethodResponse(content, msg); - else - QPID_LOG(error, "Received a map-formatted QMFv2 message with opcode=" << opcode); - - return; - } - - if (msg.getContentType() == "amqp/list") { - Variant::List content; - decode(msg, content); - - if (opcode == protocol::HEADER_OPCODE_QUERY_RESPONSE) agentImpl.handleQueryResponse(content, msg); - else if (opcode == protocol::HEADER_OPCODE_DATA_INDICATION) agentImpl.handleDataIndication(content, msg); - else - QPID_LOG(error, "Received a list-formatted QMFv2 message with opcode=" << opcode); - - return; - } - } else { - // - // Dispatch a QMFv1 formatted message - // - const string& body(msg.getContent()); - if (body.size() < 8) - return; - qpid::management::Buffer buffer(const_cast(body.c_str()), body.size()); - - if (buffer.getOctet() != 'A') return; - if (buffer.getOctet() != 'M') return; - if (buffer.getOctet() != '2') return; - char v1Opcode(buffer.getOctet()); - uint32_t seq(buffer.getLong()); - - if (v1Opcode == 's') handleV1SchemaResponse(buffer, seq, msg); - else { - QPID_LOG(trace, "Unknown or Unsupported QMFv1 opcode: " << v1Opcode); - } - } -} - - -void ConsoleSessionImpl::sendBrokerLocate() -{ - Message msg; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_REQUEST; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_AGENT_LOCATE_REQUEST; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - msg.setReplyTo(replyAddress); - msg.setCorrelationId("broker-locate"); - msg.setSubject("broker"); - - Sender sender = session.createSender(directBase + ";{create:never,node:{type:topic}}"); - sender.send(msg); - sender.close(); - - QPID_LOG(trace, "SENT AgentLocate to broker"); -} - - -void ConsoleSessionImpl::sendAgentLocate() -{ - Message msg; - Variant::Map& headers(msg.getProperties()); - static const string subject("console.request.agent_locate"); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_REQUEST; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_AGENT_LOCATE_REQUEST; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - msg.setReplyTo(replyAddress); - msg.setCorrelationId("agent-locate"); - msg.setSubject(subject); - encode(agentQuery.getPredicate(), msg); - - topicSender.send(msg); - - QPID_LOG(trace, "SENT AgentLocate to=" << topicSender.getName() << "/" << subject); -} - - -void ConsoleSessionImpl::handleAgentUpdate(const string& agentName, const Variant::Map& content, const Message& msg) -{ - Variant::Map::const_iterator iter; - Agent agent; - uint32_t epoch(0); - string cid(msg.getCorrelationId()); - - iter = content.find("_values"); - if (iter == content.end()) - return; - const Variant::Map& in_attrs(iter->second.asMap()); - Variant::Map attrs; - - // - // Copy the map from the message to "attrs". Translate any old-style - // keys to their new key values in the process. - // - for (iter = in_attrs.begin(); iter != in_attrs.end(); iter++) { - if (iter->first == "epoch") - attrs[protocol::AGENT_ATTR_EPOCH] = iter->second; - else if (iter->first == "timestamp") - attrs[protocol::AGENT_ATTR_TIMESTAMP] = iter->second; - else if (iter->first == "heartbeat_interval") - attrs[protocol::AGENT_ATTR_HEARTBEAT_INTERVAL] = iter->second; - else - attrs[iter->first] = iter->second; - } - - iter = attrs.find(protocol::AGENT_ATTR_EPOCH); - if (iter != attrs.end()) - epoch = iter->second.asUint32(); - - if (cid == "broker-locate") { - qpid::sys::Mutex::ScopedLock l(lock); - auto_ptr impl(new AgentImpl(agentName, epoch, *this)); - for (iter = attrs.begin(); iter != attrs.end(); iter++) - if (iter->first != protocol::AGENT_ATTR_EPOCH) - impl->setAttribute(iter->first, iter->second); - agent = Agent(impl.release()); - connectedBrokerAgent = agent; - if (!agentQuery || agentQuery.matchesPredicate(attrs)) { - connectedBrokerInAgentList = true; - agents[agentName] = agent; - - // - // Enqueue a notification of the new agent. - // - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_ADD)); - eventImpl->setAgent(agent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - } - return; - } - - // - // Check this agent against the agent filter. Exit if it doesn't match. - // (only if this isn't the connected broker agent) - // - if (agentQuery && (!agentQuery.matchesPredicate(attrs))) - return; - - QPID_LOG(trace, "RCVD AgentHeartbeat from an agent matching our filter: " << agentName); - - { - qpid::sys::Mutex::ScopedLock l(lock); - map::iterator aIter = agents.find(agentName); - if (aIter == agents.end()) { - // - // This is a new agent. We have no current record of its existence. - // - auto_ptr impl(new AgentImpl(agentName, epoch, *this)); - for (iter = attrs.begin(); iter != attrs.end(); iter++) - if (iter->first != protocol::AGENT_ATTR_EPOCH) - impl->setAttribute(iter->first, iter->second); - agent = Agent(impl.release()); - agents[agentName] = agent; - - // - // Enqueue a notification of the new agent. - // - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_ADD)); - eventImpl->setAgent(agent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - } else { - // - // This is a refresh of an agent we are already tracking. - // - bool detectedRestart(false); - agent = aIter->second; - AgentImpl& impl(AgentImplAccess::get(agent)); - impl.touch(); - if (impl.getEpoch() != epoch) { - // - // The agent has restarted since the last time we heard from it. - // Enqueue a notification. - // - impl.setEpoch(epoch); - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_RESTART)); - eventImpl->setAgent(agent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - detectedRestart = true; - } - - iter = attrs.find(protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP); - if (iter != attrs.end()) { - uint64_t ts(iter->second.asUint64()); - if (ts > impl.getAttribute(protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP).asUint64()) { - // - // The agent has added new schema entries since we last heard from it. - // Update the attribute and, if this doesn't accompany a restart, enqueue a notification. - // - if (!detectedRestart) { - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_SCHEMA_UPDATE)); - eventImpl->setAgent(agent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - } - impl.setAttribute(protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP, iter->second); - } - } - } - } -} - - -void ConsoleSessionImpl::handleV1SchemaResponse(qpid::management::Buffer& buffer, uint32_t, const Message&) -{ - QPID_LOG(trace, "RCVD V1SchemaResponse"); - Schema schema(new SchemaImpl(buffer)); - schemaCache->declareSchema(schema); -} - - -void ConsoleSessionImpl::periodicProcessing(uint64_t seconds) -{ - // - // The granularity of this timer is seconds. Don't waste time looking for work if - // it's been less than a second since we last visited. - // - if (seconds == lastVisit) - return; - lastVisit = seconds; - - // - // Handle the aging of agent records - // - if (lastAgePass == 0) - lastAgePass = seconds; - if (seconds - lastAgePass >= 60) { - lastAgePass = seconds; - map toDelete; - qpid::sys::Mutex::ScopedLock l(lock); - - for (map::iterator iter = agents.begin(); iter != agents.end(); iter++) - if ((iter->second.getName() != connectedBrokerAgent.getName()) && - (AgentImplAccess::get(iter->second).age() > maxAgentAgeMinutes)) - toDelete[iter->first] = iter->second; - - for (map::iterator iter = toDelete.begin(); iter != toDelete.end(); iter++) { - agents.erase(iter->first); - auto_ptr eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_DEL, AGENT_DEL_AGED)); - eventImpl->setAgent(iter->second); - enqueueEventLH(eventImpl.release()); - } - } -} - - -void ConsoleSessionImpl::alertEventNotifierLH(bool readable) -{ - if (eventNotifier) - eventNotifier->setReadable(readable); -} - - -void ConsoleSessionImpl::run() -{ - QPID_LOG(debug, "ConsoleSession thread started"); - - try { - while (!threadCanceled) { - periodicProcessing((uint64_t) qpid::sys::Duration::FromEpoch() / - qpid::sys::TIME_SEC); - - Receiver rx; - bool valid = session.nextReceiver(rx, Duration::SECOND * maxThreadWaitTime); - if (threadCanceled) - break; - if (valid) { - try { - dispatch(rx.fetch()); - } catch (qpid::types::Exception& e) { - QPID_LOG(error, "Exception caught in message dispatch: " << e.what()); - } - session.acknowledge(); - } - } - } catch (qpid::types::Exception& e) { - QPID_LOG(error, "Exception caught in message thread - exiting: " << e.what()); - enqueueEvent(ConsoleEvent(new ConsoleEventImpl(CONSOLE_THREAD_FAILED))); - } - - session.close(); - QPID_LOG(debug, "ConsoleSession thread exiting"); -} - - -ConsoleSessionImpl& ConsoleSessionImplAccess::get(ConsoleSession& session) -{ - return *session.impl; -} - - -const ConsoleSessionImpl& ConsoleSessionImplAccess::get(const ConsoleSession& session) -{ - return *session.impl; -} diff --git a/qpid/cpp/src/qmf/ConsoleSessionImpl.h b/qpid/cpp/src/qmf/ConsoleSessionImpl.h deleted file mode 100644 index 2c06df030c..0000000000 --- a/qpid/cpp/src/qmf/ConsoleSessionImpl.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _QMF_CONSOLE_SESSION_IMPL_H_ -#define _QMF_CONSOLE_SESSION_IMPL_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/RefCounted.h" -#include "qmf/ConsoleSession.h" -#include "qmf/AgentImpl.h" -#include "qmf/SchemaId.h" -#include "qmf/Schema.h" -#include "qmf/ConsoleEventImpl.h" -#include "qmf/EventNotifierImpl.h" -#include "qmf/SchemaCache.h" -#include "qmf/Query.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Condition.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Address.h" -#include "qpid/management/Buffer.h" -#include "qpid/types/Variant.h" - -#include -#include -#include - -namespace qmf { - class ConsoleSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable { - public: - ~ConsoleSessionImpl(); - - // - // Methods from API handle - // - ConsoleSessionImpl(qpid::messaging::Connection& c, const std::string& o); - void setDomain(const std::string& d) { domain = d; } - void setAgentFilter(const std::string& f); - void open(); - void closeAsync(); - void close(); - bool nextEvent(ConsoleEvent& e, qpid::messaging::Duration t); - int pendingEvents() const; - - void setEventNotifier(EventNotifierImpl* notifier); - EventNotifierImpl* getEventNotifier() const; - - uint32_t getAgentCount() const; - Agent getAgent(uint32_t i) const; - Agent getConnectedBrokerAgent() const { return connectedBrokerAgent; } - Subscription subscribe(const Query&, const std::string& agentFilter, const std::string& options); - Subscription subscribe(const std::string&, const std::string& agentFilter, const std::string& options); - - protected: - mutable qpid::sys::Mutex lock; - qpid::sys::Condition cond; - qpid::messaging::Connection connection; - qpid::messaging::Session session; - qpid::messaging::Sender directSender; - qpid::messaging::Sender topicSender; - std::string domain; - uint32_t maxAgentAgeMinutes; - bool listenOnDirect; - bool strictSecurity; - uint32_t maxThreadWaitTime; - Query agentQuery; - bool opened; - std::queue eventQueue; - EventNotifierImpl* eventNotifier; - qpid::sys::Thread* thread; - bool threadCanceled; - uint64_t lastVisit; - uint64_t lastAgePass; - std::map agents; - Agent connectedBrokerAgent; - bool connectedBrokerInAgentList; - qpid::messaging::Address replyAddress; - std::string directBase; - std::string topicBase; - boost::shared_ptr schemaCache; - qpid::sys::Mutex corrlock; - uint32_t nextCorrelator; - - void enqueueEvent(const ConsoleEvent&); - void enqueueEventLH(const ConsoleEvent&); - void dispatch(qpid::messaging::Message); - void sendBrokerLocate(); - void sendAgentLocate(); - void handleAgentUpdate(const std::string&, const qpid::types::Variant::Map&, const qpid::messaging::Message&); - void handleV1SchemaResponse(qpid::management::Buffer&, uint32_t, const qpid::messaging::Message&); - void periodicProcessing(uint64_t); - void alertEventNotifierLH(bool readable); - void run(); - uint32_t correlator() { qpid::sys::Mutex::ScopedLock l(corrlock); return nextCorrelator++; } - - friend class AgentImpl; - }; - - struct ConsoleSessionImplAccess { - static ConsoleSessionImpl& get(ConsoleSession& session); - static const ConsoleSessionImpl& get(const ConsoleSession& session); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/Data.cpp b/qpid/cpp/src/qmf/Data.cpp deleted file mode 100644 index c503bab445..0000000000 --- a/qpid/cpp/src/qmf/Data.cpp +++ /dev/null @@ -1,130 +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/DataImpl.h" -#include "qmf/DataAddrImpl.h" -#include "qmf/SchemaImpl.h" -#include "qmf/SchemaIdImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/SchemaProperty.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef PI; - -Data::Data(DataImpl* impl) { PI::ctor(*this, impl); } -Data::Data(const Data& s) : qmf::Handle() { PI::copy(*this, s); } -Data::~Data() { PI::dtor(*this); } -Data& Data::operator=(const Data& s) { return PI::assign(*this, s); } - -Data::Data(const Schema& s) { PI::ctor(*this, new DataImpl(s)); } -void Data::setAddr(const DataAddr& a) { impl->setAddr(a); } -void Data::setProperty(const string& k, const qpid::types::Variant& v) { impl->setProperty(k, v); } -void Data::overwriteProperties(const qpid::types::Variant::Map& m) { impl->overwriteProperties(m); } -bool Data::hasSchema() const { return impl->hasSchema(); } -bool Data::hasAddr() const { return impl->hasAddr(); } -const SchemaId& Data::getSchemaId() const { return impl->getSchemaId(); } -const DataAddr& Data::getAddr() const { return impl->getAddr(); } -const Variant& Data::getProperty(const string& k) const { return impl->getProperty(k); } -const Variant::Map& Data::getProperties() const { return impl->getProperties(); } -bool Data::hasAgent() const { return impl->hasAgent(); } -const Agent& Data::getAgent() const { return impl->getAgent(); } - - -void DataImpl::overwriteProperties(const Variant::Map& m) { - for (Variant::Map::const_iterator iter = m.begin(); iter != m.end(); iter++) - properties[iter->first] = iter->second; -} - -const Variant& DataImpl::getProperty(const string& k) const { - Variant::Map::const_iterator iter = properties.find(k); - if (iter == properties.end()) - throw KeyNotFound(k); - return iter->second; -} - - -DataImpl::DataImpl(const qpid::types::Variant::Map& map, const Agent& a) -{ - Variant::Map::const_iterator iter; - - agent = a; - - iter = map.find("_values"); - if (iter != map.end()) - properties = iter->second.asMap(); - - iter = map.find("_object_id"); - if (iter != map.end()) - dataAddr = DataAddr(new DataAddrImpl(iter->second.asMap())); - - iter = map.find("_schema_id"); - if (iter != map.end()) - schemaId = SchemaId(new SchemaIdImpl(iter->second.asMap())); -} - - -Variant::Map DataImpl::asMap() const -{ - Variant::Map result; - - result["_values"] = properties; - - if (hasAddr()) { - const DataAddrImpl& aImpl(DataAddrImplAccess::get(getAddr())); - result["_object_id"] = aImpl.asMap(); - } - - if (hasSchema()) { - const SchemaIdImpl& sImpl(SchemaIdImplAccess::get(getSchemaId())); - result["_schema_id"] = sImpl.asMap(); - } - - return result; -} - - -void DataImpl::setProperty(const std::string& k, const qpid::types::Variant& v) -{ - if (schema.isValid()) { - // - // If we have a valid schema, make sure that the property is included in the - // schema and that the variant type is compatible with the schema type. - // - if (!SchemaImplAccess::get(schema).isValidProperty(k, v)) - throw QmfException("Property '" + k + "' either not in the schema or value is of incompatible type"); - } - properties[k] = v; -} - - -DataImpl& DataImplAccess::get(Data& item) -{ - return *item.impl; -} - - -const DataImpl& DataImplAccess::get(const Data& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/DataAddr.cpp b/qpid/cpp/src/qmf/DataAddr.cpp deleted file mode 100644 index 08b64d5b5d..0000000000 --- a/qpid/cpp/src/qmf/DataAddr.cpp +++ /dev/null @@ -1,108 +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/DataAddrImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/DataAddr.h" -#include - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef PI; - -DataAddr::DataAddr(DataAddrImpl* impl) { PI::ctor(*this, impl); } -DataAddr::DataAddr(const DataAddr& s) : qmf::Handle() { PI::copy(*this, s); } -DataAddr::~DataAddr() { PI::dtor(*this); } -DataAddr& DataAddr::operator=(const DataAddr& s) { return PI::assign(*this, s); } - -bool DataAddr::operator==(const DataAddr& o) { return *impl == *o.impl; } -bool DataAddr::operator==(const DataAddr& o) const { return *impl == *o.impl; } -bool DataAddr::operator<(const DataAddr& o) { return *impl < *o.impl; } -bool DataAddr::operator<(const DataAddr& o) const { return *impl < *o.impl; } - -DataAddr::DataAddr(const qpid::types::Variant::Map& m) { PI::ctor(*this, new DataAddrImpl(m)); } -DataAddr::DataAddr(const string& n, const string& a, uint32_t e) { PI::ctor(*this, new DataAddrImpl(n, a, e)); } -const string& DataAddr::getName() const { return impl->getName(); } -const string& DataAddr::getAgentName() const { return impl->getAgentName(); } -uint32_t DataAddr::getAgentEpoch() const { return impl->getAgentEpoch(); } -Variant::Map DataAddr::asMap() const { return impl->asMap(); } - -bool DataAddrImpl::operator==(const DataAddrImpl& other) const -{ - return - agentName == other.agentName && - name == other.name && - agentEpoch == other.agentEpoch; -} - - -bool DataAddrImpl::operator<(const DataAddrImpl& other) const -{ - if (agentName < other.agentName) return true; - if (agentName > other.agentName) return false; - if (name < other.name) return true; - if (name > other.name) return false; - return agentEpoch < other.agentEpoch; -} - - -DataAddrImpl::DataAddrImpl(const Variant::Map& map) : agentEpoch(0) -{ - Variant::Map::const_iterator iter; - - iter = map.find("_agent_name"); - if (iter != map.end()) - agentName = iter->second.asString(); - - iter = map.find("_object_name"); - if (iter != map.end()) - name = iter->second.asString(); - - iter = map.find("_agent_epoch"); - if (iter != map.end()) - agentEpoch = (uint32_t) iter->second.asUint64(); -} - - -Variant::Map DataAddrImpl::asMap() const -{ - Variant::Map result; - - result["_agent_name"] = agentName; - result["_object_name"] = name; - if (agentEpoch > 0) - result["_agent_epoch"] = agentEpoch; - return result; -} - - -DataAddrImpl& DataAddrImplAccess::get(DataAddr& item) -{ - return *item.impl; -} - - -const DataAddrImpl& DataAddrImplAccess::get(const DataAddr& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/DataAddrImpl.h b/qpid/cpp/src/qmf/DataAddrImpl.h deleted file mode 100644 index 11d512f0c4..0000000000 --- a/qpid/cpp/src/qmf/DataAddrImpl.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _QMF_DATA_ADDR_IMPL_H_ -#define _QMF_DATA_ADDR_IMPL_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/RefCounted.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/types/Variant.h" -#include "qmf/DataAddr.h" - -namespace qmf { - class DataAddrImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only methods - // - void setName(const std::string& n) { name = n; } - void setAgent(const std::string& n, uint32_t e=0) { agentName = n; agentEpoch = e; } - - // - // Methods from API handle - // - bool operator==(const DataAddrImpl&) const; - bool operator<(const DataAddrImpl&) const; - DataAddrImpl(const qpid::types::Variant::Map&); - DataAddrImpl(const std::string& _name, const std::string& _agentName, uint32_t _agentEpoch=0) : - agentName(_agentName), name(_name), agentEpoch(_agentEpoch) {} - const std::string& getName() const { return name; } - const std::string& getAgentName() const { return agentName; } - uint32_t getAgentEpoch() const { return agentEpoch; } - qpid::types::Variant::Map asMap() const; - - private: - std::string agentName; - std::string name; - uint32_t agentEpoch; - }; - - struct DataAddrImplAccess - { - static DataAddrImpl& get(DataAddr&); - static const DataAddrImpl& get(const DataAddr&); - }; - - struct DataAddrCompare { - bool operator() (const DataAddr& lhs, const DataAddr& rhs) const - { - if (lhs.getName() != rhs.getName()) - return lhs.getName() < rhs.getName(); - return lhs.getAgentName() < rhs.getAgentName(); - } - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/DataImpl.h b/qpid/cpp/src/qmf/DataImpl.h deleted file mode 100644 index 4ac3197da0..0000000000 --- a/qpid/cpp/src/qmf/DataImpl.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _QMF_DATA_IMPL_H_ -#define _QMF_DATA_IMPL_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/RefCounted.h" -#include "qmf/Data.h" -#include "qmf/SchemaId.h" -#include "qmf/Schema.h" -#include "qmf/DataAddr.h" -#include "qmf/Agent.h" -#include "qmf/AgentSubscription.h" -#include "qpid/types/Variant.h" - -namespace qmf { - class DataImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - DataImpl(const qpid::types::Variant::Map&, const Agent&); - qpid::types::Variant::Map asMap() const; - DataImpl() {} - void addSubscription(boost::shared_ptr); - void delSubscription(uint64_t); - qpid::types::Variant::Map publishSubscription(uint64_t); - const Schema& getSchema() const { return schema; } - - // - // Methods from API handle - // - DataImpl(const Schema& s) : schema(s) {} - void setAddr(const DataAddr& a) { dataAddr = a; } - void setProperty(const std::string& k, const qpid::types::Variant& v); - void overwriteProperties(const qpid::types::Variant::Map& m); - bool hasSchema() const { return schemaId.isValid() || schema.isValid(); } - bool hasAddr() const { return dataAddr.isValid(); } - const SchemaId& getSchemaId() const { if (schema.isValid()) return schema.getSchemaId(); else return schemaId; } - const DataAddr& getAddr() const { return dataAddr; } - const qpid::types::Variant& getProperty(const std::string& k) const; - const qpid::types::Variant::Map& getProperties() const { return properties; } - bool hasAgent() const { return agent.isValid(); } - const Agent& getAgent() const { return agent; } - - private: - struct Subscr { - boost::shared_ptr subscription; - qpid::types::Variant::Map deltas; - }; - std::map > subscriptions; - - SchemaId schemaId; - Schema schema; - DataAddr dataAddr; - qpid::types::Variant::Map properties; - Agent agent; - }; - - struct DataImplAccess - { - static DataImpl& get(Data&); - static const DataImpl& get(const Data&); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/EventNotifierImpl.cpp b/qpid/cpp/src/qmf/EventNotifierImpl.cpp deleted file mode 100644 index 81b6d637a3..0000000000 --- a/qpid/cpp/src/qmf/EventNotifierImpl.cpp +++ /dev/null @@ -1,60 +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/EventNotifierImpl.h" -#include "qmf/AgentSessionImpl.h" -#include "qmf/ConsoleSessionImpl.h" - -namespace qmf { - -EventNotifierImpl::EventNotifierImpl(AgentSession& agentSession) - : readable(false), agent(agentSession) -{ - AgentSessionImplAccess::get(agent).setEventNotifier(this); -} - - -EventNotifierImpl::EventNotifierImpl(ConsoleSession& consoleSession) - : readable(false), console(consoleSession) -{ - ConsoleSessionImplAccess::get(console).setEventNotifier(this); -} - - -EventNotifierImpl::~EventNotifierImpl() -{ - if (agent.isValid()) - AgentSessionImplAccess::get(agent).setEventNotifier(NULL); - if (console.isValid()) - ConsoleSessionImplAccess::get(console).setEventNotifier(NULL); -} - -void EventNotifierImpl::setReadable(bool readable) -{ - update(readable); - this->readable = readable; -} - - -bool EventNotifierImpl::isReadable() const -{ - return this->readable; -} - -} diff --git a/qpid/cpp/src/qmf/EventNotifierImpl.h b/qpid/cpp/src/qmf/EventNotifierImpl.h deleted file mode 100644 index d85f9979d2..0000000000 --- a/qpid/cpp/src/qmf/EventNotifierImpl.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __QMF_EVENT_NOTIFIER_IMPL_H -#define __QMF_EVENT_NOTIFIER_IMPL_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 "qmf/AgentSession.h" -#include "qmf/ConsoleSession.h" - -namespace qmf -{ - class EventNotifierImpl { - private: - bool readable; - AgentSession agent; - ConsoleSession console; - - public: - EventNotifierImpl(AgentSession& agentSession); - EventNotifierImpl(ConsoleSession& consoleSession); - virtual ~EventNotifierImpl(); - - void setReadable(bool readable); - bool isReadable() const; - - protected: - virtual void update(bool readable) = 0; - }; -} - -#endif - diff --git a/qpid/cpp/src/qmf/Expression.cpp b/qpid/cpp/src/qmf/Expression.cpp deleted file mode 100644 index 7d48678c15..0000000000 --- a/qpid/cpp/src/qmf/Expression.cpp +++ /dev/null @@ -1,441 +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/exceptions.h" -#include "qmf/Expression.h" -#include - -using namespace std; -using namespace qmf; -using namespace qpid::types; - -Expression::Expression(const Variant::List& expr) -{ - static int level(0); - level++; - Variant::List::const_iterator iter(expr.begin()); - string op(iter->asString()); - iter++; - - if (op == "not") logicalOp = LOGICAL_NOT; - else if (op == "and") logicalOp = LOGICAL_AND; - else if (op == "or") logicalOp = LOGICAL_OR; - else { - logicalOp = LOGICAL_ID; - if (op == "eq") boolOp = BOOL_EQ; - else if (op == "ne") boolOp = BOOL_NE; - else if (op == "lt") boolOp = BOOL_LT; - else if (op == "le") boolOp = BOOL_LE; - else if (op == "gt") boolOp = BOOL_GT; - else if (op == "ge") boolOp = BOOL_GE; - else if (op == "re_match") boolOp = BOOL_RE_MATCH; - else if (op == "exists") boolOp = BOOL_EXISTS; - else if (op == "true") boolOp = BOOL_TRUE; - else if (op == "false") boolOp = BOOL_FALSE; - else - throw QmfException("Invalid operator in predicate expression"); - } - - if (logicalOp == LOGICAL_ID) { - switch (boolOp) { - case BOOL_EQ: - case BOOL_NE: - case BOOL_LT: - case BOOL_LE: - case BOOL_GT: - case BOOL_GE: - case BOOL_RE_MATCH: - // - // Binary operator: get two operands. - // - operandCount = 2; - break; - - case BOOL_EXISTS: - // - // Unary operator: get one operand. - // - operandCount = 1; - break; - - case BOOL_TRUE: - case BOOL_FALSE: - // - // Literal operator: no operands. - // - operandCount = 0; - break; - } - - for (int idx = 0; idx < operandCount; idx++) { - if (iter == expr.end()) - throw QmfException("Too few operands for operation: " + op); - if (iter->getType() == VAR_STRING) { - quoted[idx] = false; - operands[idx] = *iter; - } else if (iter->getType() == VAR_LIST) { - const Variant::List& sublist(iter->asList()); - Variant::List::const_iterator subIter(sublist.begin()); - if (subIter != sublist.end() && subIter->asString() == "quote") { - quoted[idx] = true; - subIter++; - if (subIter != sublist.end()) { - operands[idx] = *subIter; - subIter++; - if (subIter != sublist.end()) - throw QmfException("Extra tokens at end of 'quote'"); - } - } else - throw QmfException("Expected '[quote, ]'"); - } else - throw QmfException("Expected string or list as operand for: " + op); - iter++; - } - - if (iter != expr.end()) - throw QmfException("Too many operands for operation: " + op); - - } else { - // - // This is a logical expression, collect sub-expressions - // - while (iter != expr.end()) { - if (iter->getType() != VAR_LIST) - throw QmfException("Operands of " + op + " must be lists"); - expressionList.push_back(boost::shared_ptr(new Expression(iter->asList()))); - iter++; - } - } - level--; -} - - -bool Expression::evaluate(const Variant::Map& data) const -{ - list >::const_iterator iter; - - switch (logicalOp) { - case LOGICAL_ID: - return boolEval(data); - - case LOGICAL_NOT: - for (iter = expressionList.begin(); iter != expressionList.end(); iter++) - if ((*iter)->evaluate(data)) - return false; - return true; - - case LOGICAL_AND: - for (iter = expressionList.begin(); iter != expressionList.end(); iter++) - if (!(*iter)->evaluate(data)) - return false; - return true; - - case LOGICAL_OR: - for (iter = expressionList.begin(); iter != expressionList.end(); iter++) - if ((*iter)->evaluate(data)) - return true; - return false; - } - - return false; -} - - -bool Expression::boolEval(const Variant::Map& data) const -{ - Variant val[2]; - bool exists[2]; - - for (int idx = 0; idx < operandCount; idx++) { - if (quoted[idx]) { - exists[idx] = true; - val[idx] = operands[idx]; - } else { - Variant::Map::const_iterator mIter(data.find(operands[idx].asString())); - if (mIter == data.end()) { - exists[idx] = false; - } else { - exists[idx] = true; - val[idx] = mIter->second; - } - } - } - - switch (boolOp) { - case BOOL_EQ: return (exists[0] && exists[1] && (val[0].asString() == val[1].asString())); - case BOOL_NE: return (exists[0] && exists[1] && (val[0].asString() != val[1].asString())); - case BOOL_LT: return (exists[0] && exists[1] && lessThan(val[0], val[1])); - case BOOL_LE: return (exists[0] && exists[1] && lessEqual(val[0], val[1])); - case BOOL_GT: return (exists[0] && exists[1] && greaterThan(val[0], val[1])); - case BOOL_GE: return (exists[0] && exists[1] && greaterEqual(val[0], val[1])); - case BOOL_RE_MATCH: return false; // TODO - case BOOL_EXISTS: return exists[0]; - case BOOL_TRUE: return true; - case BOOL_FALSE: return false; - } - - return false; -} - -bool Expression::lessThan(const Variant& left, const Variant& right) const -{ - switch (left.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - return left.asInt64() < right.asInt64(); - case VAR_STRING: - try { - return left.asInt64() < right.asInt64(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_FLOAT: case VAR_DOUBLE: - switch (right.getType()) { - case VAR_FLOAT: case VAR_DOUBLE: - return left.asDouble() < right.asDouble(); - case VAR_STRING: - try { - return left.asDouble() < right.asDouble(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_STRING: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - try { - return left.asInt64() < right.asInt64(); - } catch (std::exception&) {} - break; - - case VAR_FLOAT: case VAR_DOUBLE: - try { - return left.asDouble() < right.asDouble(); - } catch (std::exception&) {} - break; - - case VAR_STRING: - return left.asString() < right.asString(); - default: - break; - } - default: - break; - } - - return false; -} - - -bool Expression::lessEqual(const Variant& left, const Variant& right) const -{ - switch (left.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - return left.asInt64() <= right.asInt64(); - case VAR_STRING: - try { - return left.asInt64() <= right.asInt64(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_FLOAT: case VAR_DOUBLE: - switch (right.getType()) { - case VAR_FLOAT: case VAR_DOUBLE: - return left.asDouble() <= right.asDouble(); - case VAR_STRING: - try { - return left.asDouble() <= right.asDouble(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_STRING: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - try { - return left.asInt64() <= right.asInt64(); - } catch (std::exception&) {} - break; - - case VAR_FLOAT: case VAR_DOUBLE: - try { - return left.asDouble() <= right.asDouble(); - } catch (std::exception&) {} - break; - - case VAR_STRING: - return left.asString() <= right.asString(); - default: - break; - } - default: - break; - } - - return false; -} - - -bool Expression::greaterThan(const Variant& left, const Variant& right) const -{ - switch (left.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - return left.asInt64() > right.asInt64(); - case VAR_STRING: - try { - return left.asInt64() > right.asInt64(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_FLOAT: case VAR_DOUBLE: - switch (right.getType()) { - case VAR_FLOAT: case VAR_DOUBLE: - return left.asDouble() > right.asDouble(); - case VAR_STRING: - try { - return left.asDouble() > right.asDouble(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_STRING: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - try { - return left.asInt64() > right.asInt64(); - } catch (std::exception&) {} - break; - - case VAR_FLOAT: case VAR_DOUBLE: - try { - return left.asDouble() > right.asDouble(); - } catch (std::exception&) {} - break; - - case VAR_STRING: - return left.asString() > right.asString(); - default: - break; - } - default: - break; - } - - return false; -} - - -bool Expression::greaterEqual(const Variant& left, const Variant& right) const -{ - switch (left.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - return left.asInt64() >= right.asInt64(); - case VAR_STRING: - try { - return left.asInt64() >= right.asInt64(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_FLOAT: case VAR_DOUBLE: - switch (right.getType()) { - case VAR_FLOAT: case VAR_DOUBLE: - return left.asDouble() >= right.asDouble(); - case VAR_STRING: - try { - return left.asDouble() >= right.asDouble(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_STRING: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - try { - return left.asInt64() >= right.asInt64(); - } catch (std::exception&) {} - break; - - case VAR_FLOAT: case VAR_DOUBLE: - try { - return left.asDouble() >= right.asDouble(); - } catch (std::exception&) {} - break; - - case VAR_STRING: - return left.asString() >= right.asString(); - default: - break; - } - default: - break; - } - - return false; -} - - diff --git a/qpid/cpp/src/qmf/Expression.h b/qpid/cpp/src/qmf/Expression.h deleted file mode 100644 index 6fbfdbc4ba..0000000000 --- a/qpid/cpp/src/qmf/Expression.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _QMF_EXPRESSION_H_ -#define _QMF_EXPRESSION_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/types/Variant.h" -#include -#include -#include - -namespace qmf { - - enum LogicalOp { - LOGICAL_ID = 1, - LOGICAL_NOT = 2, - LOGICAL_AND = 3, - LOGICAL_OR = 4 - }; - - enum BooleanOp { - BOOL_EQ = 1, - BOOL_NE = 2, - BOOL_LT = 3, - BOOL_LE = 4, - BOOL_GT = 5, - BOOL_GE = 6, - BOOL_RE_MATCH = 7, - BOOL_EXISTS = 8, - BOOL_TRUE = 9, - BOOL_FALSE = 10 - }; - - class Expression { - public: - Expression(const qpid::types::Variant::List& expr); - bool evaluate(const qpid::types::Variant::Map& data) const; - private: - LogicalOp logicalOp; - BooleanOp boolOp; - int operandCount; - qpid::types::Variant operands[2]; - bool quoted[2]; - std::list > expressionList; - - bool boolEval(const qpid::types::Variant::Map& data) const; - bool lessThan(const qpid::types::Variant& left, const qpid::types::Variant& right) const; - bool lessEqual(const qpid::types::Variant& left, const qpid::types::Variant& right) const; - bool greaterThan(const qpid::types::Variant& left, const qpid::types::Variant& right) const; - bool greaterEqual(const qpid::types::Variant& left, const qpid::types::Variant& right) const; - }; - -} - -#endif - diff --git a/qpid/cpp/src/qmf/Hash.cpp b/qpid/cpp/src/qmf/Hash.cpp deleted file mode 100644 index 86738dda2f..0000000000 --- a/qpid/cpp/src/qmf/Hash.cpp +++ /dev/null @@ -1,45 +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/Hash.h" - -using namespace qmf; - -Hash::Hash() -{ - data[0] = 0x5A5A5A5A5A5A5A5ALL; - data[1] = 0x5A5A5A5A5A5A5A5ALL; -} - -void Hash::update(const char* s, uint32_t len) -{ - uint64_t* first = &data[0]; - uint64_t* second = &data[1]; - - for (uint32_t idx = 0; idx < len; idx++) { - uint64_t recycle = ((*second & 0xff00000000000000LL) >> 56); - *second = *second << 8; - *second |= ((*first & 0xFF00000000000000LL) >> 56); - *first = *first << 8; - *first = *first + (uint64_t) s[idx] + recycle; - } -} - diff --git a/qpid/cpp/src/qmf/Hash.h b/qpid/cpp/src/qmf/Hash.h deleted file mode 100644 index 4bd76832aa..0000000000 --- a/qpid/cpp/src/qmf/Hash.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef QMF_HASH_H -#define QMF_HASH_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/types/Uuid.h" -#include - -namespace qmf { - class Hash { - public: - Hash(); - qpid::types::Uuid asUuid() const { return qpid::types::Uuid((const unsigned char*) data); } - void update(const char* s, uint32_t len); - void update(uint8_t v) { update((char*) &v, sizeof(v)); } - void update(uint32_t v) { update((char*) &v, sizeof(v)); } - void update(const std::string& v) { update(const_cast(v.c_str()), v.size()); } - void update(bool v) { update(uint8_t(v ? 1 : 0)); } - - private: - uint64_t data[2]; - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/PosixEventNotifier.cpp b/qpid/cpp/src/qmf/PosixEventNotifier.cpp deleted file mode 100644 index a364cc155d..0000000000 --- a/qpid/cpp/src/qmf/PosixEventNotifier.cpp +++ /dev/null @@ -1,65 +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/posix/EventNotifier.h" -#include "qmf/PosixEventNotifierImpl.h" -#include "qmf/PrivateImplRef.h" - -using namespace qmf; -using namespace std; - -typedef qmf::PrivateImplRef PI; - -posix::EventNotifier::EventNotifier(PosixEventNotifierImpl* impl) { PI::ctor(*this, impl); } - -posix::EventNotifier::EventNotifier(AgentSession& agentSession) -{ - PI::ctor(*this, new PosixEventNotifierImpl(agentSession)); -} - - -posix::EventNotifier::EventNotifier(ConsoleSession& consoleSession) -{ - PI::ctor(*this, new PosixEventNotifierImpl(consoleSession)); -} - - -posix::EventNotifier::EventNotifier(const posix::EventNotifier& that) - : Handle() -{ - PI::copy(*this, that); -} - - -posix::EventNotifier::~EventNotifier() -{ - PI::dtor(*this); -} - -posix::EventNotifier& posix::EventNotifier::operator=(const posix::EventNotifier& that) -{ - return PI::assign(*this, that); -} - - -int posix::EventNotifier::getHandle() const -{ - return impl->getHandle(); -} - diff --git a/qpid/cpp/src/qmf/PosixEventNotifierImpl.cpp b/qpid/cpp/src/qmf/PosixEventNotifierImpl.cpp deleted file mode 100644 index 011dbcc214..0000000000 --- a/qpid/cpp/src/qmf/PosixEventNotifierImpl.cpp +++ /dev/null @@ -1,112 +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 "PosixEventNotifierImpl.h" -#include "qpid/log/Statement.h" - -#include -#include -#include - -#define BUFFER_SIZE 10 - -using namespace qmf; - -PosixEventNotifierImpl::PosixEventNotifierImpl(AgentSession& agentSession) - : EventNotifierImpl(agentSession) -{ - openHandle(); -} - - -PosixEventNotifierImpl::PosixEventNotifierImpl(ConsoleSession& consoleSession) - : EventNotifierImpl(consoleSession) -{ - openHandle(); -} - - -PosixEventNotifierImpl::~PosixEventNotifierImpl() -{ - closeHandle(); -} - - -void PosixEventNotifierImpl::update(bool readable) -{ - char buffer[BUFFER_SIZE]; - - if(readable && !this->isReadable()) { - if (::write(myHandle, "1", 1) == -1) - QPID_LOG(error, "PosixEventNotifierImpl::update write failed: " << errno); - } - else if(!readable && this->isReadable()) { - if (::read(yourHandle, buffer, BUFFER_SIZE) == -1) - QPID_LOG(error, "PosixEventNotifierImpl::update read failed: " << errno); - } -} - - -void PosixEventNotifierImpl::openHandle() -{ - int pair[2]; - - if(::pipe(pair) == -1) - throw QmfException("Unable to open event notifier handle."); - - yourHandle = pair[0]; - myHandle = pair[1]; - - int flags; - - flags = ::fcntl(yourHandle, F_GETFL); - if((::fcntl(yourHandle, F_SETFL, flags | O_NONBLOCK)) == -1) - throw QmfException("Unable to make remote handle non-blocking."); - - flags = ::fcntl(myHandle, F_GETFL); - if((::fcntl(myHandle, F_SETFL, flags | O_NONBLOCK)) == -1) - throw QmfException("Unable to make local handle non-blocking."); -} - - -void PosixEventNotifierImpl::closeHandle() -{ - if(myHandle > 0) { - ::close(myHandle); - myHandle = -1; - } - - if(yourHandle > 0) { - ::close(yourHandle); - yourHandle = -1; - } -} - - -PosixEventNotifierImpl& PosixEventNotifierImplAccess::get(posix::EventNotifier& notifier) -{ - return *notifier.impl; -} - - -const PosixEventNotifierImpl& PosixEventNotifierImplAccess::get(const posix::EventNotifier& notifier) -{ - return *notifier.impl; -} - diff --git a/qpid/cpp/src/qmf/PosixEventNotifierImpl.h b/qpid/cpp/src/qmf/PosixEventNotifierImpl.h deleted file mode 100644 index c8a7446bd5..0000000000 --- a/qpid/cpp/src/qmf/PosixEventNotifierImpl.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef __QMF_POSIX_EVENT_NOTIFIER_IMPL_H -#define __QMF_POSIX_EVENT_NOTIFIER_IMPL_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 "qmf/posix/EventNotifier.h" -#include "qmf/EventNotifierImpl.h" -#include "qpid/RefCounted.h" - -namespace qmf -{ - class AgentSession; - class ConsoleSession; - - class PosixEventNotifierImpl : public EventNotifierImpl, public virtual qpid::RefCounted - { - public: - PosixEventNotifierImpl(AgentSession& agentSession); - PosixEventNotifierImpl(ConsoleSession& consoleSession); - virtual ~PosixEventNotifierImpl(); - - int getHandle() const { return yourHandle; } - - private: - int myHandle; - int yourHandle; - - void openHandle(); - void closeHandle(); - - protected: - void update(bool readable); - }; - - struct PosixEventNotifierImplAccess - { - static PosixEventNotifierImpl& get(posix::EventNotifier& notifier); - static const PosixEventNotifierImpl& get(const posix::EventNotifier& notifier); - }; - -} - -#endif - diff --git a/qpid/cpp/src/qmf/PrivateImplRef.h b/qpid/cpp/src/qmf/PrivateImplRef.h deleted file mode 100644 index c0c07d7e1b..0000000000 --- a/qpid/cpp/src/qmf/PrivateImplRef.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef QMF_PRIVATEIMPL_H -#define QMF_PRIVATEIMPL_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 "qmf/ImportExport.h" -#include "qpid/RefCounted.h" -#include - -namespace qmf { - -/** - * Helper class to implement a class with a private, reference counted - * implementation and reference semantics. - * - * Such classes are used in the public API to hide implementation, they - * should. Example of use: - * - * === Foo.h - * - * template PrivateImplRef; - * class FooImpl; - * - * Foo : public Handle { - * public: - * Foo(FooImpl* = 0); - * Foo(const Foo&); - * ~Foo(); - * Foo& operator=(const Foo&); - * - * int fooDo(); // and other Foo functions... - * - * private: - * typedef FooImpl Impl; - * Impl* impl; - * friend class PrivateImplRef; - * - * === Foo.cpp - * - * typedef PrivateImplRef PI; - * Foo::Foo(FooImpl* p) { PI::ctor(*this, p); } - * Foo::Foo(const Foo& c) : Handle() { PI::copy(*this, c); } - * Foo::~Foo() { PI::dtor(*this); } - * Foo& Foo::operator=(const Foo& c) { return PI::assign(*this, c); } - * - * int foo::fooDo() { return impl->fooDo(); } - * - */ -template class PrivateImplRef { - public: - typedef typename T::Impl Impl; - typedef boost::intrusive_ptr intrusive_ptr; - - /** Get the implementation pointer from a handle */ - static intrusive_ptr get(const T& t) { return intrusive_ptr(t.impl); } - - /** Set the implementation pointer in a handle */ - static void set(T& t, const intrusive_ptr& p) { - if (t.impl == p) return; - if (t.impl) intrusive_ptr_release(t.impl); - t.impl = p.get(); - if (t.impl) intrusive_ptr_add_ref(t.impl); - } - - // Helper functions to implement the ctor, dtor, copy, assign - static void ctor(T& t, Impl* p) { t.impl = p; if (p) intrusive_ptr_add_ref(p); } - static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); } - static void dtor(T& t) { if(t.impl) intrusive_ptr_release(t.impl); } - static T& assign(T& t, const T& x) { set(t, get(x)); return t;} -}; - -} // namespace qmf - -#endif /*!QMF_PRIVATEIMPL_H*/ diff --git a/qpid/cpp/src/qmf/Query.cpp b/qpid/cpp/src/qmf/Query.cpp deleted file mode 100644 index ee8ca38e59..0000000000 --- a/qpid/cpp/src/qmf/Query.cpp +++ /dev/null @@ -1,153 +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/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/QueryImpl.h" -#include "qmf/DataAddrImpl.h" -#include "qmf/SchemaIdImpl.h" -#include "qpid/messaging/AddressParser.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef PI; - -Query::Query(QueryImpl* impl) { PI::ctor(*this, impl); } -Query::Query(const Query& s) : qmf::Handle() { PI::copy(*this, s); } -Query::~Query() { PI::dtor(*this); } -Query& Query::operator=(const Query& s) { return PI::assign(*this, s); } - -Query::Query(QueryTarget t, const string& pr) { PI::ctor(*this, new QueryImpl(t, pr)); } -Query::Query(QueryTarget t, const string& c, const string& p, const string& pr) { PI::ctor(*this, new QueryImpl(t, c, p, pr)); } -Query::Query(QueryTarget t, const SchemaId& s, const string& pr) { PI::ctor(*this, new QueryImpl(t, s, pr)); } -Query::Query(const DataAddr& a) { PI::ctor(*this, new QueryImpl(a)); } - -QueryTarget Query::getTarget() const { return impl->getTarget(); } -const DataAddr& Query::getDataAddr() const { return impl->getDataAddr(); } -const SchemaId& Query::getSchemaId() const { return impl->getSchemaId(); } -void Query::setPredicate(const Variant::List& pr) { impl->setPredicate(pr); } -const Variant::List& Query::getPredicate() const { return impl->getPredicate(); } -bool Query::matchesPredicate(const qpid::types::Variant::Map& map) const { return impl->matchesPredicate(map); } - - -QueryImpl::QueryImpl(const Variant::Map& map) : predicateCompiled(false) -{ - Variant::Map::const_iterator iter; - - iter = map.find("_what"); - if (iter == map.end()) - throw QmfException("Query missing _what element"); - - const string& targetString(iter->second.asString()); - if (targetString == "OBJECT") target = QUERY_OBJECT; - else if (targetString == "OBJECT_ID") target = QUERY_OBJECT_ID; - else if (targetString == "SCHEMA") target = QUERY_SCHEMA; - else if (targetString == "SCHEMA_ID") target = QUERY_SCHEMA_ID; - else - throw QmfException("Query with invalid _what value: " + targetString); - - iter = map.find("_object_id"); - if (iter != map.end()) { - auto_ptr addrImpl(new DataAddrImpl(iter->second.asMap())); - dataAddr = DataAddr(addrImpl.release()); - } - - iter = map.find("_schema_id"); - if (iter != map.end()) { - auto_ptr sidImpl(new SchemaIdImpl(iter->second.asMap())); - schemaId = SchemaId(sidImpl.release()); - } - - iter = map.find("_where"); - if (iter != map.end()) - predicate = iter->second.asList(); -} - - -Variant::Map QueryImpl::asMap() const -{ - Variant::Map map; - string targetString; - - switch (target) { - case QUERY_OBJECT : targetString = "OBJECT"; break; - case QUERY_OBJECT_ID : targetString = "OBJECT_ID"; break; - case QUERY_SCHEMA : targetString = "SCHEMA"; break; - case QUERY_SCHEMA_ID : targetString = "SCHEMA_ID"; break; - } - - map["_what"] = targetString; - - if (dataAddr.isValid()) - map["_object_id"] = DataAddrImplAccess::get(dataAddr).asMap(); - - if (schemaId.isValid()) - map["_schema_id"] = SchemaIdImplAccess::get(schemaId).asMap(); - - if (!predicate.empty()) - map["_where"] = predicate; - - return map; -} - - -bool QueryImpl::matchesPredicate(const qpid::types::Variant::Map& data) const -{ - if (predicate.empty()) - return true; - - if (!predicateCompiled) { - expression.reset(new Expression(predicate)); - predicateCompiled = true; - } - - return expression->evaluate(data); -} - - -void QueryImpl::parsePredicate(const string& pred) -{ - if (pred.empty()) - return; - - if (pred[0] == '[') { - // - // Parse this as an AddressParser list. - // - qpid::messaging::AddressParser parser(pred); - parser.parseList(predicate); - } else - throw QmfException("Invalid predicate format"); -} - - -QueryImpl& QueryImplAccess::get(Query& item) -{ - return *item.impl; -} - - -const QueryImpl& QueryImplAccess::get(const Query& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/QueryImpl.h b/qpid/cpp/src/qmf/QueryImpl.h deleted file mode 100644 index 27ec427684..0000000000 --- a/qpid/cpp/src/qmf/QueryImpl.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _QMF_QUERY_IMPL_H_ -#define _QMF_QUERY_IMPL_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/RefCounted.h" -#include "qmf/Query.h" -#include "qmf/DataAddr.h" -#include "qmf/SchemaId.h" -#include "qmf/Expression.h" -#include "qpid/types/Variant.h" -#include - -namespace qmf { - class QueryImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - QueryImpl(const qpid::types::Variant::Map&); - qpid::types::Variant::Map asMap() const; - - // - // Methods from API handle - // - QueryImpl(QueryTarget t, const std::string& pr) : target(t), predicateCompiled(false) { parsePredicate(pr); } - QueryImpl(QueryTarget t, const std::string& c, const std::string& p, const std::string& pr) : - target(t), schemaId(SCHEMA_TYPE_DATA, p, c), predicateCompiled(false) { parsePredicate(pr); } - QueryImpl(QueryTarget t, const SchemaId& s, const std::string& pr) : - target(t), schemaId(s), predicateCompiled(false) { parsePredicate(pr); } - QueryImpl(const DataAddr& a) : target(QUERY_OBJECT), dataAddr(a), predicateCompiled(false) {} - - QueryTarget getTarget() const { return target; } - const DataAddr& getDataAddr() const { return dataAddr; } - const SchemaId& getSchemaId() const { return schemaId; } - void setPredicate(const qpid::types::Variant::List& pr) { predicate = pr; } - const qpid::types::Variant::List& getPredicate() const { return predicate; } - bool matchesPredicate(const qpid::types::Variant::Map& map) const; - - private: - QueryTarget target; - SchemaId schemaId; - DataAddr dataAddr; - qpid::types::Variant::List predicate; - mutable bool predicateCompiled; - mutable boost::shared_ptr expression; - - void parsePredicate(const std::string& s); - }; - - struct QueryImplAccess - { - static QueryImpl& get(Query&); - static const QueryImpl& get(const Query&); - }; -} - -#endif - diff --git a/qpid/cpp/src/qmf/Schema.cpp b/qpid/cpp/src/qmf/Schema.cpp deleted file mode 100644 index 872aad724c..0000000000 --- a/qpid/cpp/src/qmf/Schema.cpp +++ /dev/null @@ -1,358 +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/SchemaImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaIdImpl.h" -#include "qmf/SchemaPropertyImpl.h" -#include "qmf/SchemaMethodImpl.h" -#include "qmf/Hash.h" -#include "qpid/log/Statement.h" -#include "qpid/management/Buffer.h" -#include - -using namespace std; -using qpid::types::Variant; -using namespace qmf; - -typedef PrivateImplRef PI; - -Schema::Schema(SchemaImpl* impl) { PI::ctor(*this, impl); } -Schema::Schema(const Schema& s) : qmf::Handle() { PI::copy(*this, s); } -Schema::~Schema() { PI::dtor(*this); } -Schema& Schema::operator=(const Schema& s) { return PI::assign(*this, s); } - -Schema::Schema(int t, const string& p, const string& c) { PI::ctor(*this, new SchemaImpl(t, p, c)); } -const SchemaId& Schema::getSchemaId() const { return impl->getSchemaId(); } -void Schema::finalize() { impl->finalize(); } -bool Schema::isFinalized() const { return impl->isFinalized(); } -void Schema::addProperty(const SchemaProperty& p) { impl->addProperty(p); } -void Schema::addMethod(const SchemaMethod& m) { impl->addMethod(m); } -void Schema::setDesc(const string& d) { impl->setDesc(d); } -const string& Schema::getDesc() const { return impl->getDesc(); } -void Schema::setDefaultSeverity(int s) { impl->setDefaultSeverity(s); } -int Schema::getDefaultSeverity() const { return impl->getDefaultSeverity(); } -uint32_t Schema::getPropertyCount() const { return impl->getPropertyCount(); } -SchemaProperty Schema::getProperty(uint32_t i) const { return impl->getProperty(i); } -uint32_t Schema::getMethodCount() const { return impl->getMethodCount(); } -SchemaMethod Schema::getMethod(uint32_t i) const { return impl->getMethod(i); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -SchemaImpl::SchemaImpl(const Variant::Map& map) : finalized(false) -{ - Variant::Map::const_iterator iter; - Variant::List::const_iterator lIter; - - iter = map.find("_schema_id"); - if (iter == map.end()) - throw QmfException("Schema map missing _schema_id element"); - schemaId = SchemaId(new SchemaIdImpl(iter->second.asMap())); - - iter = map.find("_desc"); - if (iter != map.end()) - description = iter->second.asString(); - - iter = map.find("_default_severity"); - if (iter != map.end()) - defaultSeverity = int(iter->second.asUint32()); - - iter = map.find("_properties"); - if (iter != map.end()) { - const Variant::List& props(iter->second.asList()); - for (lIter = props.begin(); lIter != props.end(); lIter++) - addProperty(SchemaProperty(new SchemaPropertyImpl(lIter->asMap()))); - } - - iter = map.find("_methods"); - if (iter != map.end()) { - const Variant::List& meths(iter->second.asList()); - for (lIter = meths.begin(); lIter != meths.end(); lIter++) - addMethod(SchemaMethod(new SchemaMethodImpl(lIter->asMap()))); - } - - finalized = true; -} - - -Variant::Map SchemaImpl::asMap() const -{ - Variant::Map map; - Variant::List propList; - Variant::List methList; - - checkNotFinal(); - - map["_schema_id"] = SchemaIdImplAccess::get(schemaId).asMap(); - if (!description.empty()) - map["_desc"] = description; - if (schemaId.getType() == SCHEMA_TYPE_EVENT) - map["_default_severity"] = uint32_t(defaultSeverity); - - for (list::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++) - propList.push_back(SchemaPropertyImplAccess::get(*pIter).asMap()); - - for (list::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) - methList.push_back(SchemaMethodImplAccess::get(*mIter).asMap()); - - map["_properties"] = propList; - map["_methods"] = methList; - return map; -} - - -SchemaImpl::SchemaImpl(qpid::management::Buffer& buffer) : finalized(false) -{ - int schemaType; - string packageName; - string className; - uint8_t hash[16]; - - schemaType = int(buffer.getOctet()); - buffer.getShortString(packageName); - buffer.getShortString(className); - buffer.getBin128(hash); - schemaId = SchemaId(schemaType, packageName, className); - schemaId.setHash(qpid::types::Uuid(hash)); - - if (schemaType == SCHEMA_TYPE_DATA) { - uint16_t propCount(buffer.getShort()); - uint16_t statCount(buffer.getShort()); - uint16_t methCount(buffer.getShort()); - for (uint16_t idx = 0; idx < propCount + statCount; idx++) - addProperty(new SchemaPropertyImpl(buffer)); - for (uint16_t idx = 0; idx < methCount; idx++) - addMethod(new SchemaMethodImpl(buffer)); - } - - finalized = true; -} - - -string SchemaImpl::asV1Content(uint32_t sequence) const -{ -#define RAW_BUF_SIZE 65536 - char rawBuf[RAW_BUF_SIZE]; - qpid::management::Buffer buffer(rawBuf, RAW_BUF_SIZE); - - // - // Encode the QMFv1 Header - // - buffer.putOctet('A'); - buffer.putOctet('M'); - buffer.putOctet('2'); - buffer.putOctet('s'); - buffer.putLong(sequence); - - // - // Encode the common schema information - // - buffer.putOctet(uint8_t(schemaId.getType())); - buffer.putShortString(schemaId.getPackageName()); - buffer.putShortString(schemaId.getName()); - buffer.putBin128(schemaId.getHash().data()); - - if (schemaId.getType() == SCHEMA_TYPE_DATA) { - buffer.putShort(properties.size()); - buffer.putShort(0); - buffer.putShort(methods.size()); - for (list::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++) - SchemaPropertyImplAccess::get(*pIter).encodeV1(buffer, false, false); - for (list::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) - SchemaMethodImplAccess::get(*mIter).encodeV1(buffer); - } else { - buffer.putShort(properties.size()); - for (list::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++) - SchemaPropertyImplAccess::get(*pIter).encodeV1(buffer, true, false); - } - - return string(rawBuf, buffer.getPosition()); -} - - -bool SchemaImpl::isValidProperty(const std::string& k, const Variant& v) const -{ - for (list::const_iterator iter = properties.begin(); iter != properties.end(); iter++) - if (iter->getName() == k) - return (isCompatibleType(iter->getType(), v.getType())); - return false; -} - - -bool SchemaImpl::isValidMethodInArg(const std::string& m, const std::string& k, const Variant& v) const -{ - for (list::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) { - if (mIter->getName() == m) { - uint32_t count(mIter->getArgumentCount()); - for (uint32_t i = 0; i < count; i++) { - const SchemaProperty prop(mIter->getArgument(i)); - if (prop.getName() == k) { - if (prop.getDirection() == DIR_IN || prop.getDirection() == DIR_IN_OUT) - return (isCompatibleType(prop.getType(), v.getType())); - else - return false; - } - } - } - } - return false; -} - - -bool SchemaImpl::isValidMethodOutArg(const std::string& m, const std::string& k, const Variant& v) const -{ - for (list::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) { - if (mIter->getName() == m) { - uint32_t count(mIter->getArgumentCount()); - for (uint32_t i = 0; i < count; i++) { - const SchemaProperty prop(mIter->getArgument(i)); - if (prop.getName() == k) { - if (prop.getDirection() == DIR_OUT || prop.getDirection() == DIR_IN_OUT) - return (isCompatibleType(prop.getType(), v.getType())); - else - return false; - } - } - } - } - return false; -} - - -void SchemaImpl::finalize() -{ - Hash hash; - - hash.update((uint8_t) schemaId.getType()); - hash.update(schemaId.getPackageName()); - hash.update(schemaId.getName()); - - for (list::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++) - SchemaPropertyImplAccess::get(*pIter).updateHash(hash); - for (list::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) - SchemaMethodImplAccess::get(*mIter).updateHash(hash); - - schemaId.setHash(hash.asUuid()); - QPID_LOG(debug, "Schema Finalized: " << schemaId.getPackageName() << ":" << schemaId.getName() << ":" << - schemaId.getHash()); - - finalized = true; -} - - -SchemaProperty SchemaImpl::getProperty(uint32_t i) const -{ - uint32_t count = 0; - for (list::const_iterator iter = properties.begin(); iter != properties.end(); iter++) - if (count++ == i) - return *iter; - throw IndexOutOfRange(); -} - - -SchemaMethod SchemaImpl::getMethod(uint32_t i) const -{ - uint32_t count = 0; - for (list::const_iterator iter = methods.begin(); iter != methods.end(); iter++) - if (count++ == i) - return *iter; - throw IndexOutOfRange(); -} - -void SchemaImpl::checkFinal() const -{ - if (finalized) - throw QmfException("Modification of a finalized schema is forbidden"); -} - - -void SchemaImpl::checkNotFinal() const -{ - if (!finalized) - throw QmfException("Schema is not yet finalized/registered"); -} - - -bool SchemaImpl::isCompatibleType(int qmfType, qpid::types::VariantType qpidType) const -{ - bool typeValid(false); - - switch (qpidType) { - case qpid::types::VAR_VOID: - if (qmfType == SCHEMA_DATA_VOID) - typeValid = true; - break; - case qpid::types::VAR_BOOL: - if (qmfType == SCHEMA_DATA_BOOL) - typeValid = true; - break; - case qpid::types::VAR_UINT8: - case qpid::types::VAR_UINT16: - case qpid::types::VAR_UINT32: - case qpid::types::VAR_UINT64: - case qpid::types::VAR_INT8: - case qpid::types::VAR_INT16: - case qpid::types::VAR_INT32: - case qpid::types::VAR_INT64: - if (qmfType == SCHEMA_DATA_INT) - typeValid = true; - break; - case qpid::types::VAR_FLOAT: - case qpid::types::VAR_DOUBLE: - if (qmfType == SCHEMA_DATA_FLOAT) - typeValid = true; - break; - case qpid::types::VAR_STRING: - if (qmfType == SCHEMA_DATA_STRING) - typeValid = true; - break; - case qpid::types::VAR_MAP: - if (qmfType == SCHEMA_DATA_MAP) - typeValid = true; - break; - case qpid::types::VAR_LIST: - if (qmfType == SCHEMA_DATA_LIST) - typeValid = true; - break; - case qpid::types::VAR_UUID: - if (qmfType == SCHEMA_DATA_UUID) - typeValid = true; - break; - } - - return typeValid; -} - - -SchemaImpl& SchemaImplAccess::get(Schema& item) -{ - return *item.impl; -} - - -const SchemaImpl& SchemaImplAccess::get(const Schema& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/SchemaCache.cpp b/qpid/cpp/src/qmf/SchemaCache.cpp deleted file mode 100644 index 74ca4044fd..0000000000 --- a/qpid/cpp/src/qmf/SchemaCache.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 "qmf/SchemaCache.h" -#include "qmf/exceptions.h" - -using namespace std; -using namespace qmf; - -bool SchemaCache::declareSchemaId(const SchemaId& id) -{ - qpid::sys::Mutex::ScopedLock l(lock); - SchemaMap::const_iterator iter = schemata.find(id); - if (iter == schemata.end()) { - schemata[id] = Schema(); - return false; - } - return true; -} - - -void SchemaCache::declareSchema(const Schema& schema) -{ - qpid::sys::Mutex::ScopedLock l(lock); - SchemaMap::const_iterator iter = schemata.find(schema.getSchemaId()); - if (iter == schemata.end() || !iter->second.isValid()) { - schemata[schema.getSchemaId()] = schema; - - // - // If there are any threads blocking in SchemaCache::getSchema waiting for - // this schema, unblock them all now. - // - CondMap::iterator cIter = conditions.find(schema.getSchemaId()); - if (cIter != conditions.end()) - cIter->second->notifyAll(); - } -} - - -bool SchemaCache::haveSchema(const SchemaId& id) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - SchemaMap::const_iterator iter = schemata.find(id); - return iter != schemata.end() && iter->second.isValid(); -} - - -const Schema& SchemaCache::getSchema(const SchemaId& id, qpid::messaging::Duration timeout) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - SchemaMap::const_iterator iter = schemata.find(id); - if (iter != schemata.end() && iter->second.isValid()) - return iter->second; - - // - // The desired schema is not in the cache. Assume that the caller knows this and has - // sent a schema request to the remote agent and now wishes to wait until the schema - // information arrives. - // - CondMap::iterator cIter = conditions.find(id); - if (cIter == conditions.end()) - conditions[id] = boost::shared_ptr(new qpid::sys::Condition()); - - uint64_t milliseconds = timeout.getMilliseconds(); - conditions[id]->wait(lock, qpid::sys::AbsTime(qpid::sys::now(), - qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC))); - iter = schemata.find(id); - if (iter != schemata.end() && iter->second.isValid()) - return iter->second; - - throw QmfException("Schema lookup timed out"); -} - diff --git a/qpid/cpp/src/qmf/SchemaCache.h b/qpid/cpp/src/qmf/SchemaCache.h deleted file mode 100644 index a1f104233f..0000000000 --- a/qpid/cpp/src/qmf/SchemaCache.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef QMF_SCHEMA_CACHE_H -#define QMF_SCHEMA_CACHE_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 "qmf/SchemaIdImpl.h" -#include "qmf/Schema.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Condition.h" -#include "qpid/messaging/Duration.h" -#include -#include -#include - -namespace qmf { - - class SchemaCache { - public: - SchemaCache() {} - ~SchemaCache() {} - - bool declareSchemaId(const SchemaId&); - void declareSchema(const Schema&); - bool haveSchema(const SchemaId&) const; - const Schema& getSchema(const SchemaId&, qpid::messaging::Duration) const; - - private: - mutable qpid::sys::Mutex lock; - typedef std::map SchemaMap; - typedef std::map, SchemaIdCompare> CondMap; - SchemaMap schemata; - mutable CondMap conditions; - }; - -} - -#endif - diff --git a/qpid/cpp/src/qmf/SchemaId.cpp b/qpid/cpp/src/qmf/SchemaId.cpp deleted file mode 100644 index 25fa9915ae..0000000000 --- a/qpid/cpp/src/qmf/SchemaId.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/SchemaIdImpl.h" -#include "qmf/PrivateImplRef.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef PI; - -SchemaId::SchemaId(SchemaIdImpl* impl) { PI::ctor(*this, impl); } -SchemaId::SchemaId(const SchemaId& s) : qmf::Handle() { PI::copy(*this, s); } -SchemaId::~SchemaId() { PI::dtor(*this); } -SchemaId& SchemaId::operator=(const SchemaId& s) { return PI::assign(*this, s); } - -SchemaId::SchemaId(int t, const string& p, const string& n) { PI::ctor(*this, new SchemaIdImpl(t, p, n)); } -void SchemaId::setHash(const qpid::types::Uuid& h) { impl->setHash(h); } -int SchemaId::getType() const { return impl->getType(); } -const string& SchemaId::getPackageName() const { return impl->getPackageName(); } -const string& SchemaId::getName() const { return impl->getName(); } -const qpid::types::Uuid& SchemaId::getHash() const { return impl->getHash(); } - - -SchemaIdImpl::SchemaIdImpl(const Variant::Map& map) -{ - Variant::Map::const_iterator iter; - - iter = map.find("_package_name"); - if (iter != map.end()) - package = iter->second.asString(); - - iter = map.find("_class_name"); - if (iter != map.end()) - name = iter->second.asString(); - - iter = map.find("_type"); - if (iter != map.end()) { - const string& stype = iter->second.asString(); - if (stype == "_data") - sType = SCHEMA_TYPE_DATA; - else if (stype == "_event") - sType = SCHEMA_TYPE_EVENT; - } - - iter = map.find("_hash"); - if (iter != map.end()) - hash = iter->second.asUuid(); -} - - -Variant::Map SchemaIdImpl::asMap() const -{ - Variant::Map result; - - result["_package_name"] = package; - result["_class_name"] = name; - if (sType == SCHEMA_TYPE_DATA) - result["_type"] = "_data"; - else - result["_type"] = "_event"; - if (!hash.isNull()) - result["_hash"] = hash; - return result; -} - - -SchemaIdImpl& SchemaIdImplAccess::get(SchemaId& item) -{ - return *item.impl; -} - - -const SchemaIdImpl& SchemaIdImplAccess::get(const SchemaId& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/SchemaIdImpl.h b/qpid/cpp/src/qmf/SchemaIdImpl.h deleted file mode 100644 index ae1a3d8d3b..0000000000 --- a/qpid/cpp/src/qmf/SchemaIdImpl.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef _QMF_SCHEMA_ID_IMPL_H_ -#define _QMF_SCHEMA_ID_IMPL_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/RefCounted.h" -#include "qmf/SchemaId.h" -#include "qpid/types/Variant.h" -#include "qpid/types/Uuid.h" -#include - -namespace qmf { - class SchemaIdImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - SchemaIdImpl(const qpid::types::Variant::Map&); - qpid::types::Variant::Map asMap() const; - - // - // Methods from API handle - // - SchemaIdImpl(int t, const std::string& p, const std::string& n) : sType(t), package(p), name(n) {} - void setHash(const qpid::types::Uuid& h) { hash = h; } - int getType() const { return sType; } - const std::string& getPackageName() const { return package; } - const std::string& getName() const { return name; } - const qpid::types::Uuid& getHash() const { return hash; } - - private: - int sType; - std::string package; - std::string name; - qpid::types::Uuid hash; - }; - - struct SchemaIdImplAccess - { - static SchemaIdImpl& get(SchemaId&); - static const SchemaIdImpl& get(const SchemaId&); - }; - - struct SchemaIdCompare { - bool operator() (const SchemaId& lhs, const SchemaId& rhs) const - { - if (lhs.getName() != rhs.getName()) - return lhs.getName() < rhs.getName(); - if (lhs.getPackageName() != rhs.getPackageName()) - return lhs.getPackageName() < rhs.getPackageName(); - return lhs.getHash() < rhs.getHash(); - } - }; - - struct SchemaIdCompareNoHash { - bool operator() (const SchemaId& lhs, const SchemaId& rhs) const - { - if (lhs.getName() != rhs.getName()) - return lhs.getName() < rhs.getName(); - return lhs.getPackageName() < rhs.getPackageName(); - } - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/SchemaImpl.h b/qpid/cpp/src/qmf/SchemaImpl.h deleted file mode 100644 index 1c88f87808..0000000000 --- a/qpid/cpp/src/qmf/SchemaImpl.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _QMF_SCHEMAIMPL_H_ -#define _QMF_SCHEMAIMPL_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/RefCounted.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaId.h" -#include "qmf/Schema.h" -#include "qmf/SchemaProperty.h" -#include "qmf/SchemaMethod.h" -#include - -namespace qpid { -namespace management { - class Buffer; -}} - -namespace qmf { - class SchemaImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only public methods - // - SchemaImpl(const qpid::types::Variant::Map& m); - qpid::types::Variant::Map asMap() const; - SchemaImpl(qpid::management::Buffer& v1Buffer); - std::string asV1Content(uint32_t sequence) const; - bool isValidProperty(const std::string& k, const qpid::types::Variant& v) const; - bool isValidMethodInArg(const std::string& m, const std::string& k, const qpid::types::Variant& v) const; - bool isValidMethodOutArg(const std::string& m, const std::string& k, const qpid::types::Variant& v) const; - - // - // Methods from API handle - // - SchemaImpl(int t, const std::string& p, const std::string& c) : schemaId(t, p, c), finalized(false) {} - const SchemaId& getSchemaId() const { checkNotFinal(); return schemaId; } - - void finalize(); - bool isFinalized() const { return finalized; } - void addProperty(const SchemaProperty& p) { checkFinal(); properties.push_back(p); } - void addMethod(const SchemaMethod& m) { checkFinal(); methods.push_back(m); } - - void setDesc(const std::string& d) { description = d; } - const std::string& getDesc() const { return description; } - - void setDefaultSeverity(int s) { checkFinal(); defaultSeverity = s; } - int getDefaultSeverity() const { return defaultSeverity; } - - uint32_t getPropertyCount() const { return properties.size(); } - SchemaProperty getProperty(uint32_t i) const; - - uint32_t getMethodCount() const { return methods.size(); } - SchemaMethod getMethod(uint32_t i) const; - private: - SchemaId schemaId; - int defaultSeverity; - std::string description; - bool finalized; - std::list properties; - std::list methods; - - void checkFinal() const; - void checkNotFinal() const; - bool isCompatibleType(int qmfType, qpid::types::VariantType qpidType) const; - }; - - struct SchemaImplAccess - { - static SchemaImpl& get(Schema&); - static const SchemaImpl& get(const Schema&); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/SchemaMethod.cpp b/qpid/cpp/src/qmf/SchemaMethod.cpp deleted file mode 100644 index e267878238..0000000000 --- a/qpid/cpp/src/qmf/SchemaMethod.cpp +++ /dev/null @@ -1,186 +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/SchemaMethodImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/Hash.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/management/Buffer.h" - -using namespace std; -using qpid::types::Variant; -using namespace qmf; - -typedef PrivateImplRef PI; - -SchemaMethod::SchemaMethod(SchemaMethodImpl* impl) { PI::ctor(*this, impl); } -SchemaMethod::SchemaMethod(const SchemaMethod& s) : qmf::Handle() { PI::copy(*this, s); } -SchemaMethod::~SchemaMethod() { PI::dtor(*this); } -SchemaMethod& SchemaMethod::operator=(const SchemaMethod& s) { return PI::assign(*this, s); } - -SchemaMethod::SchemaMethod(const string& n, const string& o) { PI::ctor(*this, new SchemaMethodImpl(n, o)); } -void SchemaMethod::setDesc(const string& d) { impl->setDesc(d); } -void SchemaMethod::addArgument(const SchemaProperty& p) { impl->addArgument(p); } -const string& SchemaMethod::getName() const { return impl->getName(); } -const string& SchemaMethod::getDesc() const { return impl->getDesc(); } -uint32_t SchemaMethod::getArgumentCount() const { return impl->getArgumentCount(); } -SchemaProperty SchemaMethod::getArgument(uint32_t i) const { return impl->getArgument(i); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -SchemaMethodImpl::SchemaMethodImpl(const string& n, const string& options) : name(n) -{ - if (!options.empty()) { - qpid::messaging::AddressParser parser = qpid::messaging::AddressParser(options); - Variant::Map optMap; - Variant::Map::iterator iter; - - parser.parseMap(optMap); - iter = optMap.find("desc"); - if (iter != optMap.end()) { - desc = iter->second.asString(); - optMap.erase(iter); - } - - if (!optMap.empty()) - throw QmfException("Unrecognized option: " + optMap.begin()->first); - } -} - - -SchemaMethodImpl::SchemaMethodImpl(const qpid::types::Variant::Map& map) -{ - Variant::Map::const_iterator iter; - Variant::List::const_iterator lIter; - - iter = map.find("_name"); - if (iter == map.end()) - throw QmfException("SchemaMethod without a _name element"); - name = iter->second.asString(); - - iter = map.find("_desc"); - if (iter != map.end()) - desc = iter->second.asString(); - - iter = map.find("_arguments"); - if (iter != map.end()) { - const Variant::List& argList(iter->second.asList()); - for (lIter = argList.begin(); lIter != argList.end(); lIter++) - addArgument(SchemaProperty(new SchemaPropertyImpl(lIter->asMap()))); - } -} - - -Variant::Map SchemaMethodImpl::asMap() const -{ - Variant::Map map; - Variant::List argList; - - map["_name"] = name; - - if (!desc.empty()) - map["_desc"] = desc; - - for (list::const_iterator iter = arguments.begin(); iter != arguments.end(); iter++) - argList.push_back(SchemaPropertyImplAccess::get(*iter).asMap()); - map["_arguments"] = argList; - - return map; -} - - -SchemaMethodImpl::SchemaMethodImpl(qpid::management::Buffer& buffer) -{ - Variant::Map::const_iterator iter; - Variant::Map argMap; - - buffer.getMap(argMap); - - iter = argMap.find("name"); - if (iter == argMap.end()) - throw QmfException("Received V1 Method without a name"); - name = iter->second.asString(); - - iter = argMap.find("desc"); - if (iter != argMap.end()) - desc = iter->second.asString(); - - iter = argMap.find("argCount"); - if (iter == argMap.end()) - throw QmfException("Received V1 Method without argCount"); - - int64_t count = iter->second.asInt64(); - for (int idx = 0; idx < count; idx++) { - SchemaProperty arg(new SchemaPropertyImpl(buffer)); - addArgument(arg); - } -} - - -SchemaProperty SchemaMethodImpl::getArgument(uint32_t i) const -{ - uint32_t count = 0; - for (list::const_iterator iter = arguments.begin(); iter != arguments.end(); iter++) - if (count++ == i) - return *iter; - - throw IndexOutOfRange(); -} - - -void SchemaMethodImpl::updateHash(Hash& hash) const -{ - hash.update(name); - hash.update(desc); - for (list::const_iterator iter = arguments.begin(); iter != arguments.end(); iter++) - SchemaPropertyImplAccess::get(*iter).updateHash(hash); -} - - -void SchemaMethodImpl::encodeV1(qpid::management::Buffer& buffer) const -{ - Variant::Map map; - - map["name"] = name; - map["argCount"] = (uint64_t) arguments.size(); - if (!desc.empty()) - map["desc"] = desc; - - buffer.putMap(map); - - for (list::const_iterator iter = arguments.begin(); iter != arguments.end(); iter++) - SchemaPropertyImplAccess::get(*iter).encodeV1(buffer, true, true); -} - - -SchemaMethodImpl& SchemaMethodImplAccess::get(SchemaMethod& item) -{ - return *item.impl; -} - - -const SchemaMethodImpl& SchemaMethodImplAccess::get(const SchemaMethod& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/SchemaMethodImpl.h b/qpid/cpp/src/qmf/SchemaMethodImpl.h deleted file mode 100644 index 930d48509c..0000000000 --- a/qpid/cpp/src/qmf/SchemaMethodImpl.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _QMF_SCHEMA_METHOD_IMPL_H_ -#define _QMF_SCHEMA_METHOD_IMPL_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/RefCounted.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaMethod.h" -#include "qmf/SchemaPropertyImpl.h" -#include "qpid/management/Buffer.h" -#include -#include - -namespace qpid { -namespace management { - class Buffer; -}} - -namespace qmf { - class Hash; - class SchemaMethodImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - SchemaMethodImpl(const qpid::types::Variant::Map& m); - SchemaMethodImpl(qpid::management::Buffer& v1Buffer); - qpid::types::Variant::Map asMap() const; - void updateHash(Hash&) const; - void encodeV1(qpid::management::Buffer&) const; - - // - // Methods from API handle - // - SchemaMethodImpl(const std::string& n, const std::string& options); - - void setDesc(const std::string& d) { desc = d; } - void addArgument(const SchemaProperty& p) { arguments.push_back(p); } - const std::string& getName() const { return name; } - const std::string& getDesc() const { return desc; } - uint32_t getArgumentCount() const { return arguments.size(); } - SchemaProperty getArgument(uint32_t i) const; - - private: - std::string name; - std::string desc; - std::list arguments; - }; - - struct SchemaMethodImplAccess - { - static SchemaMethodImpl& get(SchemaMethod&); - static const SchemaMethodImpl& get(const SchemaMethod&); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/SchemaProperty.cpp b/qpid/cpp/src/qmf/SchemaProperty.cpp deleted file mode 100644 index 106127261b..0000000000 --- a/qpid/cpp/src/qmf/SchemaProperty.cpp +++ /dev/null @@ -1,434 +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/SchemaPropertyImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaProperty.h" -#include "qmf/Hash.h" -#include "qpid/messaging/AddressParser.h" -#include -#include - -using namespace std; -using qpid::types::Variant; -using namespace qmf; - -typedef PrivateImplRef PI; - -SchemaProperty::SchemaProperty(SchemaPropertyImpl* impl) { PI::ctor(*this, impl); } -SchemaProperty::SchemaProperty(const SchemaProperty& s) : qmf::Handle() { PI::copy(*this, s); } -SchemaProperty::~SchemaProperty() { PI::dtor(*this); } -SchemaProperty& SchemaProperty::operator=(const SchemaProperty& s) { return PI::assign(*this, s); } - -SchemaProperty::SchemaProperty(const string& n, int t, const string& o) { PI::ctor(*this, new SchemaPropertyImpl(n, t, o)); } - -void SchemaProperty::setAccess(int a) { impl->setAccess(a); } -void SchemaProperty::setIndex(bool i) { impl->setIndex(i); } -void SchemaProperty::setOptional(bool o) { impl->setOptional(o); } -void SchemaProperty::setUnit(const string& u) { impl->setUnit(u); } -void SchemaProperty::setDesc(const string& d) { impl->setDesc(d); } -void SchemaProperty::setSubtype(const string& s) { impl->setSubtype(s); } -void SchemaProperty::setDirection(int d) { impl->setDirection(d); } - -const string& SchemaProperty::getName() const { return impl->getName(); } -int SchemaProperty::getType() const { return impl->getType(); } -int SchemaProperty::getAccess() const { return impl->getAccess(); } -bool SchemaProperty::isIndex() const { return impl->isIndex(); } -bool SchemaProperty::isOptional() const { return impl->isOptional(); } -const string& SchemaProperty::getUnit() const { return impl->getUnit(); } -const string& SchemaProperty::getDesc() const { return impl->getDesc(); } -const string& SchemaProperty::getSubtype() const { return impl->getSubtype(); } -int SchemaProperty::getDirection() const { return impl->getDirection(); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -SchemaPropertyImpl::SchemaPropertyImpl(const string& n, int t, const string options) : - name(n), dataType(t), access(ACCESS_READ_ONLY), index(false), - optional(false), direction(DIR_IN) -{ - if (!options.empty()) { - qpid::messaging::AddressParser parser = qpid::messaging::AddressParser(options); - Variant::Map optMap; - Variant::Map::iterator iter; - - parser.parseMap(optMap); - - iter = optMap.find("access"); - if (iter != optMap.end()) { - const string& v(iter->second.asString()); - if (v == "RC") access = ACCESS_READ_CREATE; - else if (v == "RO") access = ACCESS_READ_ONLY; - else if (v == "RW") access = ACCESS_READ_WRITE; - else - throw QmfException("Invalid value for 'access' option. Expected RC, RO, or RW"); - optMap.erase(iter); - } - - iter = optMap.find("index"); - if (iter != optMap.end()) { - index = iter->second.asBool(); - optMap.erase(iter); - } - - iter = optMap.find("optional"); - if (iter != optMap.end()) { - optional = iter->second.asBool(); - optMap.erase(iter); - } - - iter = optMap.find("unit"); - if (iter != optMap.end()) { - unit = iter->second.asString(); - optMap.erase(iter); - } - - iter = optMap.find("desc"); - if (iter != optMap.end()) { - desc = iter->second.asString(); - optMap.erase(iter); - } - - iter = optMap.find("subtype"); - if (iter != optMap.end()) { - subtype = iter->second.asString(); - optMap.erase(iter); - } - - iter = optMap.find("dir"); - if (iter != optMap.end()) { - const string& v(iter->second.asString()); - if (v == "IN") direction = DIR_IN; - else if (v == "OUT") direction = DIR_OUT; - else if (v == "INOUT") direction = DIR_IN_OUT; - else - throw QmfException("Invalid value for 'dir' option. Expected IN, OUT, or INOUT"); - optMap.erase(iter); - } - - if (!optMap.empty()) - throw QmfException("Unexpected option: " + optMap.begin()->first); - } -} - - -SchemaPropertyImpl::SchemaPropertyImpl(const Variant::Map& map) : - access(ACCESS_READ_ONLY), index(false), optional(false), direction(DIR_IN) -{ - Variant::Map::const_iterator iter; - - iter = map.find("_name"); - if (iter == map.end()) - throw QmfException("SchemaProperty without a _name element"); - name = iter->second.asString(); - - iter = map.find("_type"); - if (iter == map.end()) - throw QmfException("SchemaProperty without a _type element"); - const string& ts(iter->second.asString()); - if (ts == "TYPE_VOID") dataType = SCHEMA_DATA_VOID; - else if (ts == "TYPE_BOOL") dataType = SCHEMA_DATA_BOOL; - else if (ts == "TYPE_INT") dataType = SCHEMA_DATA_INT; - else if (ts == "TYPE_FLOAT") dataType = SCHEMA_DATA_FLOAT; - else if (ts == "TYPE_STRING") dataType = SCHEMA_DATA_STRING; - else if (ts == "TYPE_MAP") dataType = SCHEMA_DATA_MAP; - else if (ts == "TYPE_LIST") dataType = SCHEMA_DATA_LIST; - else if (ts == "TYPE_UUID") dataType = SCHEMA_DATA_UUID; - else - throw QmfException("SchemaProperty with an invalid type code: " + ts); - - iter = map.find("_access"); - if (iter != map.end()) { - const string& as(iter->second.asString()); - if (as == "RO") access = ACCESS_READ_ONLY; - else if (as == "RC") access = ACCESS_READ_CREATE; - else if (as == "RW") access = ACCESS_READ_WRITE; - else - throw QmfException("SchemaProperty with an invalid access code: " + as); - } - - iter = map.find("_unit"); - if (iter != map.end()) - unit = iter->second.asString(); - - iter = map.find("_dir"); - if (iter != map.end()) { - const string& ds(iter->second.asString()); - if (ds == "I") direction = DIR_IN; - else if (ds == "O") direction = DIR_OUT; - else if (ds == "IO") direction = DIR_IN_OUT; - else - throw QmfException("SchemaProperty with an invalid direction code: " + ds); - } - - iter = map.find("_desc"); - if (iter != map.end()) - desc = iter->second.asString(); - - iter = map.find("_index"); - if (iter != map.end()) - index = iter->second.asBool(); - - iter = map.find("_subtype"); - if (iter != map.end()) - subtype = iter->second.asString(); -} - - -Variant::Map SchemaPropertyImpl::asMap() const -{ - Variant::Map map; - string ts; - - map["_name"] = name; - - switch (dataType) { - case SCHEMA_DATA_VOID: ts = "TYPE_VOID"; break; - case SCHEMA_DATA_BOOL: ts = "TYPE_BOOL"; break; - case SCHEMA_DATA_INT: ts = "TYPE_INT"; break; - case SCHEMA_DATA_FLOAT: ts = "TYPE_FLOAT"; break; - case SCHEMA_DATA_STRING: ts = "TYPE_STRING"; break; - case SCHEMA_DATA_MAP: ts = "TYPE_MAP"; break; - case SCHEMA_DATA_LIST: ts = "TYPE_LIST"; break; - case SCHEMA_DATA_UUID: ts = "TYPE_UUID"; break; - } - map["_type"] = ts; - - switch (access) { - case ACCESS_READ_ONLY: ts = "RO"; break; - case ACCESS_READ_CREATE: ts = "RC"; break; - case ACCESS_READ_WRITE: ts = "RW"; break; - } - map["_access"] = ts; - - if (!unit.empty()) - map["_unit"] = unit; - - switch (direction) { - case DIR_IN: ts = "I"; break; - case DIR_OUT: ts = "O"; break; - case DIR_IN_OUT: ts = "IO"; break; - } - map["_dir"] = ts; - - if (!desc.empty()) - map["_desc"] = desc; - - if (index) - map["_index"] = true; - - if (!subtype.empty()) - map["_subtype"] = subtype; - - return map; -} - - -SchemaPropertyImpl::SchemaPropertyImpl(qpid::management::Buffer& buffer) : - access(ACCESS_READ_ONLY), index(false), optional(false), direction(DIR_IN) -{ - Variant::Map::const_iterator iter; - Variant::Map pmap; - - buffer.getMap(pmap); - iter = pmap.find("name"); - if (iter == pmap.end()) - throw QmfException("Received V1 Schema property without a name"); - name = iter->second.asString(); - - iter = pmap.find("type"); - if (iter == pmap.end()) - throw QmfException("Received V1 Schema property without a type"); - fromV1TypeCode(iter->second.asInt8()); - - iter = pmap.find("unit"); - if (iter != pmap.end()) - unit = iter->second.asString(); - - iter = pmap.find("desc"); - if (iter != pmap.end()) - desc = iter->second.asString(); - - iter = pmap.find("access"); - if (iter != pmap.end()) { - int8_t val = iter->second.asInt8(); - if (val < 1 || val > 3) - throw QmfException("Received V1 Schema property with invalid 'access' code"); - access = val; - } - - iter = pmap.find("index"); - if (iter != pmap.end()) - index = iter->second.asInt64() != 0; - - iter = pmap.find("optional"); - if (iter != pmap.end()) - optional = iter->second.asInt64() != 0; - - iter = pmap.find("dir"); - if (iter != pmap.end()) { - string dirStr(iter->second.asString()); - if (dirStr == "I") direction = DIR_IN; - else if (dirStr == "O") direction = DIR_OUT; - else if (dirStr == "IO") direction = DIR_IN_OUT; - else - throw QmfException("Received V1 Schema property with invalid 'dir' code"); - } -} - - -void SchemaPropertyImpl::updateHash(Hash& hash) const -{ - hash.update(name); - hash.update((uint8_t) dataType); - hash.update(subtype); - hash.update((uint8_t) access); - hash.update(index); - hash.update(optional); - hash.update(unit); - hash.update(desc); - hash.update((uint8_t) direction); -} - - -void SchemaPropertyImpl::encodeV1(qpid::management::Buffer& buffer, bool isArg, bool isMethodArg) const -{ - Variant::Map pmap; - - pmap["name"] = name; - pmap["type"] = v1TypeCode(); - if (!unit.empty()) - pmap["unit"] = unit; - if (!desc.empty()) - pmap["desc"] = desc; - if (!isArg) { - pmap["access"] = access; - pmap["index"] = index ? 1 : 0; - pmap["optional"] = optional ? 1 : 0; - } else { - if (isMethodArg) { - string dirStr; - switch (direction) { - case DIR_IN : dirStr = "I"; break; - case DIR_OUT : dirStr = "O"; break; - case DIR_IN_OUT : dirStr = "IO"; break; - } - pmap["dir"] = dirStr; - } - } - - buffer.putMap(pmap); -} - - -uint8_t SchemaPropertyImpl::v1TypeCode() const -{ - switch (dataType) { - case SCHEMA_DATA_VOID: return 1; - case SCHEMA_DATA_BOOL: return 11; - case SCHEMA_DATA_INT: - if (subtype == "timestamp") return 8; - if (subtype == "duration") return 9; - return 19; - case SCHEMA_DATA_FLOAT: return 13; - case SCHEMA_DATA_STRING: return 7; - case SCHEMA_DATA_LIST: return 21; - case SCHEMA_DATA_UUID: return 14; - case SCHEMA_DATA_MAP: - if (subtype == "reference") return 10; - if (subtype == "data") return 20; - return 15; - } - - return 1; -} - -void SchemaPropertyImpl::fromV1TypeCode(int8_t code) -{ - switch (code) { - case 1: // U8 - case 2: // U16 - case 3: // U32 - case 4: // U64 - dataType = SCHEMA_DATA_INT; - break; - case 6: // SSTR - case 7: // LSTR - dataType = SCHEMA_DATA_STRING; - break; - case 8: // ABSTIME - dataType = SCHEMA_DATA_INT; - subtype = "timestamp"; - break; - case 9: // DELTATIME - dataType = SCHEMA_DATA_INT; - subtype = "duration"; - break; - case 10: // REF - dataType = SCHEMA_DATA_MAP; - subtype = "reference"; - break; - case 11: // BOOL - dataType = SCHEMA_DATA_BOOL; - break; - case 12: // FLOAT - case 13: // DOUBLE - dataType = SCHEMA_DATA_FLOAT; - break; - case 14: // UUID - dataType = SCHEMA_DATA_UUID; - break; - case 15: // FTABLE - dataType = SCHEMA_DATA_MAP; - break; - case 16: // S8 - case 17: // S16 - case 18: // S32 - case 19: // S64 - dataType = SCHEMA_DATA_INT; - break; - case 20: // OBJECT - dataType = SCHEMA_DATA_MAP; - subtype = "data"; - break; - case 21: // LIST - case 22: // ARRAY - dataType = SCHEMA_DATA_LIST; - break; - default: - throw QmfException("Received V1 schema with an unknown data type"); - } -} - - -SchemaPropertyImpl& SchemaPropertyImplAccess::get(SchemaProperty& item) -{ - return *item.impl; -} - - -const SchemaPropertyImpl& SchemaPropertyImplAccess::get(const SchemaProperty& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/SchemaPropertyImpl.h b/qpid/cpp/src/qmf/SchemaPropertyImpl.h deleted file mode 100644 index cdfc29066f..0000000000 --- a/qpid/cpp/src/qmf/SchemaPropertyImpl.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _QMF_SCHEMA_PROPERTY_IMPL_H_ -#define _QMF_SCHEMA_PROPERTY_IMPL_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/RefCounted.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaProperty.h" -#include "qpid/types/Variant.h" -#include "qpid/management/Buffer.h" - -namespace qpid { -namespace management { - class Buffer; -}} - -namespace qmf { - class Hash; - class SchemaPropertyImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - SchemaPropertyImpl(const qpid::types::Variant::Map& m); - SchemaPropertyImpl(qpid::management::Buffer& v1Buffer); - qpid::types::Variant::Map asMap() const; - void updateHash(Hash&) const; - void encodeV1(qpid::management::Buffer&, bool isArg, bool isMethodArg) const; - - // - // Methods from API handle - // - SchemaPropertyImpl(const std::string& n, int t, const std::string o); - void setAccess(int a) { access = a; } - void setIndex(bool i) { index = i; } - void setOptional(bool o) { optional = o; } - void setUnit(const std::string& u) { unit = u; } - void setDesc(const std::string& d) { desc = d; } - void setSubtype(const std::string& s) { subtype = s; } - void setDirection(int d) { direction = d; } - - const std::string& getName() const { return name; } - int getType() const { return dataType; } - int 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 desc; } - const std::string& getSubtype() const { return subtype; } - int getDirection() const { return direction; } - - private: - std::string name; - int dataType; - std::string subtype; - int access; - bool index; - bool optional; - std::string unit; - std::string desc; - int direction; - - uint8_t v1TypeCode() const; - void fromV1TypeCode(int8_t); - }; - - struct SchemaPropertyImplAccess - { - static SchemaPropertyImpl& get(SchemaProperty&); - static const SchemaPropertyImpl& get(const SchemaProperty&); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/Subscription.cpp b/qpid/cpp/src/qmf/Subscription.cpp deleted file mode 100644 index 73afc8c79d..0000000000 --- a/qpid/cpp/src/qmf/Subscription.cpp +++ /dev/null @@ -1,88 +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/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/SubscriptionImpl.h" -#include "qmf/DataImpl.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef PI; - -Subscription::Subscription(SubscriptionImpl* impl) { PI::ctor(*this, impl); } -Subscription::Subscription(const Subscription& s) : qmf::Handle() { PI::copy(*this, s); } -Subscription::~Subscription() { PI::dtor(*this); } -Subscription& Subscription::operator=(const Subscription& s) { return PI::assign(*this, s); } - -void Subscription::cancel() { impl->cancel(); } -bool Subscription::isActive() const { return impl->isActive(); } -void Subscription::lock() { impl->lock(); } -void Subscription::unlock() { impl->unlock(); } -uint32_t Subscription::getDataCount() const { return impl->getDataCount(); } -Data Subscription::getData(uint32_t i) const { return impl->getData(i); } - - -void SubscriptionImpl::cancel() -{ -} - - -bool SubscriptionImpl::isActive() const -{ - return false; -} - - -void SubscriptionImpl::lock() -{ -} - - -void SubscriptionImpl::unlock() -{ -} - - -uint32_t SubscriptionImpl::getDataCount() const -{ - return 0; -} - - -Data SubscriptionImpl::getData(uint32_t) const -{ - return Data(); -} - - -SubscriptionImpl& SubscriptionImplAccess::get(Subscription& item) -{ - return *item.impl; -} - - -const SubscriptionImpl& SubscriptionImplAccess::get(const Subscription& item) -{ - return *item.impl; -} diff --git a/qpid/cpp/src/qmf/SubscriptionImpl.h b/qpid/cpp/src/qmf/SubscriptionImpl.h deleted file mode 100644 index 053e3cd00e..0000000000 --- a/qpid/cpp/src/qmf/SubscriptionImpl.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _QMF_SUBSCRIPTION_IMPL_H_ -#define _QMF_SUBSCRIPTION_IMPL_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/RefCounted.h" -#include "qmf/Subscription.h" - -namespace qmf { - class SubscriptionImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - SubscriptionImpl(int p) : placeholder(p) {} - ~SubscriptionImpl(); - - // - // Methods from API handle - // - void cancel(); - bool isActive() const; - void lock(); - void unlock(); - uint32_t getDataCount() const; - Data getData(uint32_t) const; - - private: - int placeholder; - }; - - struct SubscriptionImplAccess - { - static SubscriptionImpl& get(Subscription&); - static const SubscriptionImpl& get(const Subscription&); - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/agentCapability.h b/qpid/cpp/src/qmf/agentCapability.h deleted file mode 100644 index 6a3f6f8534..0000000000 --- a/qpid/cpp/src/qmf/agentCapability.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef QMF_AGENT_CAPABILITY_H -#define QMF_AGENT_CAPABILITY_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 qmf { - - /** - * Legacy (Qpid 0.7 C++ Agent, 0.7 Broker Agent) capabilities - */ - const uint32_t AGENT_CAPABILITY_LEGACY = 0; - - /** - * Qpid 0.8 QMFv2 capabilities - */ - const uint32_t AGENT_CAPABILITY_0_8 = 1; - const uint32_t AGENT_CAPABILITY_V2_SCHEMA = 1; - const uint32_t AGENT_CAPABILITY_AGENT_PREDICATE = 1; -} - -#endif diff --git a/qpid/cpp/src/qmf/constants.cpp b/qpid/cpp/src/qmf/constants.cpp deleted file mode 100644 index 6e2fd935a9..0000000000 --- a/qpid/cpp/src/qmf/constants.cpp +++ /dev/null @@ -1,77 +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 "constants.h" - -using namespace std; -using namespace qmf; - -/** - * Header key strings - */ -const string protocol::HEADER_KEY_APP_ID = "x-amqp-0-10.app-id"; -const string protocol::HEADER_KEY_METHOD = "method"; -const string protocol::HEADER_KEY_OPCODE = "qmf.opcode"; -const string protocol::HEADER_KEY_AGENT = "qmf.agent"; -const string protocol::HEADER_KEY_CONTENT = "qmf.content"; -const string protocol::HEADER_KEY_PARTIAL = "partial"; - -/** - * Header values per-key - */ -const string protocol::HEADER_APP_ID_QMF = "qmf2"; - -const string protocol::HEADER_METHOD_REQUEST = "request"; -const string protocol::HEADER_METHOD_RESPONSE = "response"; -const string protocol::HEADER_METHOD_INDICATION = "indication"; - -const string protocol::HEADER_OPCODE_EXCEPTION = "_exception"; -const string protocol::HEADER_OPCODE_AGENT_LOCATE_REQUEST = "_agent_locate_request"; -const string protocol::HEADER_OPCODE_AGENT_LOCATE_RESPONSE = "_agent_locate_response"; -const string protocol::HEADER_OPCODE_AGENT_HEARTBEAT_INDICATION = "_agent_heartbeat_indication"; -const string protocol::HEADER_OPCODE_QUERY_REQUEST = "_query_request"; -const string protocol::HEADER_OPCODE_QUERY_RESPONSE = "_query_response"; -const string protocol::HEADER_OPCODE_SUBSCRIBE_REQUEST = "_subscribe_request"; -const string protocol::HEADER_OPCODE_SUBSCRIBE_RESPONSE = "_subscribe_response"; -const string protocol::HEADER_OPCODE_SUBSCRIBE_CANCEL_INDICATION = "_subscribe_cancel_indication"; -const string protocol::HEADER_OPCODE_SUBSCRIBE_REFRESH_INDICATION = "_subscribe_refresh_indication"; -const string protocol::HEADER_OPCODE_DATA_INDICATION = "_data_indication"; -const string protocol::HEADER_OPCODE_METHOD_REQUEST = "_method_request"; -const string protocol::HEADER_OPCODE_METHOD_RESPONSE = "_method_response"; - -const string protocol::HEADER_CONTENT_SCHEMA_ID = "_schema_id"; -const string protocol::HEADER_CONTENT_SCHEMA_CLASS = "_schema_class"; -const string protocol::HEADER_CONTENT_OBJECT_ID = "_object_id"; -const string protocol::HEADER_CONTENT_DATA = "_data"; -const string protocol::HEADER_CONTENT_EVENT = "_event"; -const string protocol::HEADER_CONTENT_QUERY = "_query"; - -/** - * Keywords for Agent attributes - */ -const string protocol::AGENT_ATTR_VENDOR = "_vendor"; -const string protocol::AGENT_ATTR_PRODUCT = "_product"; -const string protocol::AGENT_ATTR_INSTANCE = "_instance"; -const string protocol::AGENT_ATTR_NAME = "_name"; -const string protocol::AGENT_ATTR_TIMESTAMP = "_timestamp"; -const string protocol::AGENT_ATTR_HEARTBEAT_INTERVAL = "_heartbeat_interval"; -const string protocol::AGENT_ATTR_EPOCH = "_epoch"; -const string protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP = "_schema_updated"; diff --git a/qpid/cpp/src/qmf/constants.h b/qpid/cpp/src/qmf/constants.h deleted file mode 100644 index 79beaaf1ca..0000000000 --- a/qpid/cpp/src/qmf/constants.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QMF_CONSTANTS_H -#define QMF_CONSTANTS_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 - -namespace qmf { - - struct protocol { - /** - * Header key strings - */ - static const std::string HEADER_KEY_APP_ID; - static const std::string HEADER_KEY_METHOD; - static const std::string HEADER_KEY_OPCODE; - static const std::string HEADER_KEY_AGENT; - static const std::string HEADER_KEY_CONTENT; - static const std::string HEADER_KEY_PARTIAL; - - /** - * Header values per-key - */ - static const std::string HEADER_APP_ID_QMF; - - static const std::string HEADER_METHOD_REQUEST; - static const std::string HEADER_METHOD_RESPONSE; - static const std::string HEADER_METHOD_INDICATION; - - static const std::string HEADER_OPCODE_EXCEPTION; - static const std::string HEADER_OPCODE_AGENT_LOCATE_REQUEST; - static const std::string HEADER_OPCODE_AGENT_LOCATE_RESPONSE; - static const std::string HEADER_OPCODE_AGENT_HEARTBEAT_INDICATION; - static const std::string HEADER_OPCODE_QUERY_REQUEST; - static const std::string HEADER_OPCODE_QUERY_RESPONSE; - static const std::string HEADER_OPCODE_SUBSCRIBE_REQUEST; - static const std::string HEADER_OPCODE_SUBSCRIBE_RESPONSE; - static const std::string HEADER_OPCODE_SUBSCRIBE_CANCEL_INDICATION; - static const std::string HEADER_OPCODE_SUBSCRIBE_REFRESH_INDICATION; - static const std::string HEADER_OPCODE_DATA_INDICATION; - static const std::string HEADER_OPCODE_METHOD_REQUEST; - static const std::string HEADER_OPCODE_METHOD_RESPONSE; - - static const std::string HEADER_CONTENT_SCHEMA_ID; - static const std::string HEADER_CONTENT_SCHEMA_CLASS; - static const std::string HEADER_CONTENT_OBJECT_ID; - static const std::string HEADER_CONTENT_DATA; - static const std::string HEADER_CONTENT_EVENT; - static const std::string HEADER_CONTENT_QUERY; - - /** - * Keywords for Agent attributes - */ - static const std::string AGENT_ATTR_VENDOR; - static const std::string AGENT_ATTR_PRODUCT; - static const std::string AGENT_ATTR_INSTANCE; - static const std::string AGENT_ATTR_NAME; - static const std::string AGENT_ATTR_TIMESTAMP; - static const std::string AGENT_ATTR_HEARTBEAT_INTERVAL; - static const std::string AGENT_ATTR_EPOCH; - static const std::string AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP; - }; -} - -#endif diff --git a/qpid/cpp/src/qmf/exceptions.cpp b/qpid/cpp/src/qmf/exceptions.cpp deleted file mode 100644 index be212f62f7..0000000000 --- a/qpid/cpp/src/qmf/exceptions.cpp +++ /dev/null @@ -1,37 +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/exceptions.h" - -namespace qmf { - - QmfException::QmfException(const std::string& msg) : qpid::types::Exception(msg) {} - QmfException::~QmfException() throw() {} - - KeyNotFound::KeyNotFound(const std::string& msg) : QmfException("Key Not Found: " + msg) {} - KeyNotFound::~KeyNotFound() throw() {} - - IndexOutOfRange::IndexOutOfRange() : QmfException("Index out-of-range") {} - IndexOutOfRange::~IndexOutOfRange() throw() {} - - OperationTimedOut::OperationTimedOut() : QmfException("Timeout Expired") {} - OperationTimedOut::~OperationTimedOut() throw() {} -} - diff --git a/qpid/cpp/src/qmf2.pc.in b/qpid/cpp/src/qmf2.pc.in deleted file mode 100644 index 4c7e6f9763..0000000000 --- a/qpid/cpp/src/qmf2.pc.in +++ /dev/null @@ -1,30 +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. -# - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: qmf2 -Version: @VERSION@ -Description: Qpid Management Framework -Requires: qpid -Libs: -L@libdir@ -lqmf2 @LIBS@ -Cflags: -I@includedir@ diff --git a/qpid/cpp/src/qpid.linkmap b/qpid/cpp/src/qpid.linkmap deleted file mode 100644 index 264e6bac57..0000000000 --- a/qpid/cpp/src/qpid.linkmap +++ /dev/null @@ -1,31 +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. - * - */ - -{ - global: - extern "C++" { - typeinfo*qpid::*; - vtable*qpid::*; - qpid::*; - qpid::*operator*qpid::*; - }; - local: *; -}; diff --git a/qpid/cpp/src/qpid.pc.in b/qpid/cpp/src/qpid.pc.in deleted file mode 100644 index c44a157347..0000000000 --- a/qpid/cpp/src/qpid.pc.in +++ /dev/null @@ -1,30 +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. -# - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: qpid -Version: @VERSION@ -Description: Qpid C++ client library -Requires: -Libs: -L@libdir@ -lqpidmessaging -lqpidtypes @LIBS@ -Cflags: -I@includedir@ diff --git a/qpid/cpp/src/qpid/AclHost.cpp b/qpid/cpp/src/qpid/AclHost.cpp deleted file mode 100644 index 1581d3b46a..0000000000 --- a/qpid/cpp/src/qpid/AclHost.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * Copyright (c) 2014 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/AclHost.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/StringUtils.h" -#include "qpid/log/Logger.h" -#include "qpid/sys/SocketAddress.h" - -#include -#include - -using namespace std; - -namespace qpid { - -AclHost::Invalid::Invalid(const string& s) : Exception(s) {} - -string AclHost::str() const { - if (cache.empty()) { - ostringstream os; - os << *this; - cache = os.str(); - } - return cache; -} - -std::string undecorateIPv6Name(std::string& host) { - std::string s(host); - if (host.length() >= 3 && host.find("[") == 0 && host.rfind("]") == host.length()-1) - s = host.substr(1, host.length()-2); - return s; -} - -ostream& operator<<(ostream& os, const AclHost& aclhost) { - os << aclhost.comparisonDetails(); - return os; -} - -class AclHostParser { - public: - AclHostParser(AclHost& ah, const std::string& hSpec) : - aclhost(ah), hostSpec(hSpec) {} - - bool parse() { - // Convert given host spec into vector of host names - // Blank host name means "all addresses. Create AclHost - // with no SocketAddress objects - if (hostSpec.compare("") == 0) { - aclhost.allAddresses = true; - return true; - } - std::vector hostList; - split(hostList, hostSpec, ","); - if (hostList.size() == 0 || hostList.size() > 2) { - throw AclHost::Invalid( - QPID_MSG("Invalid AclHost: hostlist must be one name or " - "two names separated with a comma : " << hostSpec)); - } - // Create pairs of SocketAddress objects representing the host range - if (hostList.size() == 1) { - hostList[0] = undecorateIPv6Name(hostList[0]); - aclhost.loSAptr = AclHost::SAptr(new sys::SocketAddress(hostList[0], "")); - aclhost.hiSAptr = AclHost::SAptr(new sys::SocketAddress(hostList[0], "")); - } else { - hostList[0] = undecorateIPv6Name(hostList[0]); - hostList[1] = undecorateIPv6Name(hostList[1]); - aclhost.loSAptr = AclHost::SAptr(new sys::SocketAddress(hostList[0], "")); - aclhost.hiSAptr = AclHost::SAptr(new sys::SocketAddress(hostList[1], "")); - } - // Make sure that this pair will work for run-time comparisons - if (!aclhost.loSAptr->isComparable(*aclhost.hiSAptr)) { - throw AclHost::Invalid( - QPID_MSG("AclHost specifies hosts that cannot be compared : " << hostSpec)); - } - - return true; - } - - AclHost& aclhost; - const std::string& hostSpec; -}; - -void AclHost::parse(const std::string& hostSpec) { - parseNoThrow(hostSpec); - if (isEmpty() && !allAddresses) - throw AclHost::Invalid(QPID_MSG("Invalid AclHost : " << hostSpec)); -} - -void AclHost::parseNoThrow(const std::string& hostSpec) { - clear(); - try { - if (!AclHostParser(*this, hostSpec).parse()) - clear(); - } catch (...) { - clear(); - } -} - -std::istream& operator>>(std::istream& is, AclHost& aclhost) { - std::string s; - is >> s; - aclhost.parse(s); - return is; -} - -/** - * Given a connecting host's numeric IP address as a string - * Return true if the host is in the range of any of our kept - * SocketAddress's binary address ranges. - */ -bool AclHost::match(const std::string& hostIp) const { - try { - sys::SocketAddress sa1(hostIp, ""); - return match(sa1); - } catch (...) { - return false; - } -} - -/** - * Given a connecting host's SocketAddress - * Return true if the host is in the range of any of our kept - * SocketAddress's binary address ranges. - */ -bool AclHost::match(const sys::SocketAddress& peer) const { - if (!loSAptr.get()) { - // No kept socket address means "all addresses" - return true; - } - bool result = peer.inRange(*loSAptr, *hiSAptr); - return result; -} - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/AclHost.h b/qpid/cpp/src/qpid/AclHost.h deleted file mode 100644 index 3c4bbe1ce3..0000000000 --- a/qpid/cpp/src/qpid/AclHost.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef QPID_ACLHOST_H -#define QPID_ACLHOST_H - -/* - * - * Copyright (c) 2014 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/SocketAddress.h" -#include "qpid/Exception.h" -#include -#include -#include -#include -#include -#include -#include "qpid/CommonImportExport.h" - -namespace qpid { - -/** An AclHost contains shared_ptrs to two SocketAddresses - * representing a low-high pair of addresses. - */ -class AclHost { - public: - typedef boost::shared_ptr SAptr; - - struct Invalid : public Exception { QPID_COMMON_EXTERN Invalid(const std::string& s); }; - - /** Convert to string form. */ - QPID_COMMON_EXTERN std::string str() const; - - /** Empty AclHost. */ - AclHost() : allAddresses(false) {} - - explicit AclHost(const std::string& hostSpec) : allAddresses(false) { parse(hostSpec); } - - QPID_COMMON_EXTERN std::string comparisonDetails() const { - if (loSAptr.get()) { - return loSAptr->comparisonDetails(*hiSAptr); - } else { - return "(all)"; - } - } - - QPID_COMMON_EXTERN bool match(const std::string& hostIp) const; - - QPID_COMMON_EXTERN bool match(const sys::SocketAddress& sa) const; - - QPID_COMMON_EXTERN void parse( const std::string& hostSpec); - QPID_COMMON_EXTERN void parseNoThrow(const std::string& hostSpec); - - QPID_COMMON_EXTERN void clear() { - cache.clear(); - loSAptr.reset(); - hiSAptr.reset(); - } - - QPID_COMMON_EXTERN bool isEmpty() const { - return !loSAptr.get() && !hiSAptr.get(); } - - QPID_COMMON_EXTERN bool isAllAddresses() const { return allAddresses; } - - private: - mutable std::string cache; // cache string form for efficiency. - - bool allAddresses; - SAptr loSAptr; - SAptr hiSAptr; - - friend class AclHostParser; -}; - -inline bool operator==(const AclHost& a, const AclHost& b) { return a.str()==b.str(); } -inline bool operator!=(const AclHost& a, const AclHost& b) { return a.str()!=b.str(); } - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& os, const AclHost& aclhost); -QPID_COMMON_EXTERN std::istream& operator>>(std::istream& is, AclHost& aclhost); - -} // namespace qpid - -#endif /*!QPID_ACLHOST_H*/ diff --git a/qpid/cpp/src/qpid/Address.cpp b/qpid/cpp/src/qpid/Address.cpp deleted file mode 100644 index 01770524c8..0000000000 --- a/qpid/cpp/src/qpid/Address.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * 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/client/ConnectionSettings.h" - -#include - -using namespace std; - -namespace qpid { - -const string Address::TCP("tcp"); - -ostream& operator<<(ostream& os, const Address& a) { - // If the host is an IPv6 literal we need to print "[]" around it - // (we detect IPv6 literals because they contain ":" which is otherwise illegal) - if (a.host.find(':') != string::npos) { - return os << a.protocol << ":[" << a.host << "]:" << a.port; - } else { - return os << a.protocol << ":" << a.host << ":" << a.port; - } -} - -bool operator==(const Address& x, const Address& y) { - return y.protocol==x.protocol && y.host==x.host && y.port == x.port; -} -bool operator!=(const Address& x, const Address& y) { return !(x == y); } -} // namespace qpid diff --git a/qpid/cpp/src/qpid/Address.h b/qpid/cpp/src/qpid/Address.h deleted file mode 100755 index fe43f3847d..0000000000 --- a/qpid/cpp/src/qpid/Address.h +++ /dev/null @@ -1,56 +0,0 @@ -#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 -#include - -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/BufferRef.h b/qpid/cpp/src/qpid/BufferRef.h deleted file mode 100644 index bfe1f9ebaa..0000000000 --- a/qpid/cpp/src/qpid/BufferRef.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QPID_BUFFERREF_H -#define QPID_BUFFERREF_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/RefCounted.h" -#include - -namespace qpid { - -/** Template for mutable or const buffer references */ -template class BufferRefT { - public: - BufferRefT() : begin_(0), end_(0) {} - - BufferRefT(boost::intrusive_ptr c, T* begin, T* end) : - counter(c), begin_(begin), end_(end) {} - - template BufferRefT(const BufferRefT& other) : - counter(other.counter), begin_(other.begin_), end_(other.end_) {} - - T* begin() const { return begin_; } - T* end() const { return end_; } - - /** Return a sub-buffer of the current buffer */ - BufferRefT sub_buffer(T* begin, T* end) { - assert(begin_ <= begin && begin <= end_); - assert(begin_ <= end && end <= end_); - assert(begin <= end); - return BufferRefT(counter, begin, end); - } - - private: - boost::intrusive_ptr counter; - T* begin_; - T* end_; -}; - -/** - * Reference to a mutable ref-counted buffer. - */ -typedef BufferRefT BufferRef; - -/** - * Reference to a const ref-counted buffer. - */ -typedef BufferRefT ConstBufferRef; - -} // namespace qpid - -#endif /*!QPID_BUFFERREF_H*/ diff --git a/qpid/cpp/src/qpid/CommonImportExport.h b/qpid/cpp/src/qpid/CommonImportExport.h deleted file mode 100644 index dd2b900b73..0000000000 --- a/qpid/cpp/src/qpid/CommonImportExport.h +++ /dev/null @@ -1,35 +0,0 @@ -#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/DataDir.cpp b/qpid/cpp/src/qpid/DataDir.cpp deleted file mode 100644 index 546df3dabd..0000000000 --- a/qpid/cpp/src/qpid/DataDir.cpp +++ /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. - * - */ - -#include "qpid/Exception.h" -#include "qpid/DataDir.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/FileSysDir.h" -#include "qpid/sys/LockFile.h" - -namespace qpid { - -DataDir::DataDir (const std::string& path) : - enabled (!path.empty ()), - dirPath (path) -{ - if (enabled) - { - sys::FileSysDir dir(dirPath); - if (!dir.exists()) - dir.mkdir(); - std::string lockFileName(path); - lockFileName += "/lock"; - lockFile = std::auto_ptr(new sys::LockFile(lockFileName, true)); - } -} - -DataDir::~DataDir () {} - -} // namespace qpid - diff --git a/qpid/cpp/src/qpid/DataDir.h b/qpid/cpp/src/qpid/DataDir.h deleted file mode 100644 index ec73d28796..0000000000 --- a/qpid/cpp/src/qpid/DataDir.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_DATADIR_H -#define QPID_DATADIR_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 -#include -#include "qpid/CommonImportExport.h" - -namespace qpid { - - namespace sys { - class LockFile; - } - -/** - * DataDir class. - */ -class DataDir -{ - const bool enabled; - const std::string dirPath; - std::auto_ptr lockFile; - - public: - - QPID_COMMON_EXTERN DataDir (const std::string& path); - QPID_COMMON_EXTERN ~DataDir (); - - bool isEnabled() const { return enabled; } - const std::string& getPath() const { return dirPath; } -}; - -} // namespace qpid - -#endif /*!QPID_DATADIR_H*/ diff --git a/qpid/cpp/src/qpid/DisableExceptionLogging.h b/qpid/cpp/src/qpid/DisableExceptionLogging.h deleted file mode 100644 index 04a9240513..0000000000 --- a/qpid/cpp/src/qpid/DisableExceptionLogging.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef QPID_DISABLEEXCEPTIONLOGGING_H -#define QPID_DISABLEEXCEPTIONLOGGING_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" - -namespace qpid { - -/** - * Temporarily disable logging in qpid::Exception constructor. - * Used by log::Logger to avoid logging exceptions during Logger construction. - */ -struct DisableExceptionLogging -{ - QPID_COMMON_EXTERN DisableExceptionLogging(); - QPID_COMMON_EXTERN ~DisableExceptionLogging(); -}; -} // namespace qpid - -#endif /*!QPID_DISABLEEXCEPTIONLOGGING_H*/ diff --git a/qpid/cpp/src/qpid/Exception.cpp b/qpid/cpp/src/qpid/Exception.cpp deleted file mode 100644 index 999c2aeb52..0000000000 --- a/qpid/cpp/src/qpid/Exception.cpp +++ /dev/null @@ -1,71 +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/log/Statement.h" -#include "qpid/Exception.h" -#include "qpid/DisableExceptionLogging.h" -#include -#include -#include - -namespace qpid { - -// Note on static initialization order: if an exception is constructed -// in a static constructor before disableExceptionLogging has been -// initialized, the worst that can happen is we lose an exception log -// message. Since we shouldn't be throwing a lot of exceptions during -// static construction this seems safe. -static bool disableExceptionLogging = false; - -DisableExceptionLogging::DisableExceptionLogging() { disableExceptionLogging = true; } -DisableExceptionLogging::~DisableExceptionLogging() { disableExceptionLogging = false; } - -Exception::Exception(const std::string& msg) throw() : message(msg) { - if (disableExceptionLogging) return; - QPID_LOG_IF(debug, !msg.empty(), "Exception constructed: " << message); -} - -Exception::~Exception() throw() {} - -std::string Exception::getPrefix() const { return std::string(); } - -std::string Exception::getMessage() const { return message; } - -namespace { const std::string COLON(": "); } - -const char* Exception::what() const throw() { - // Construct the what string the first time it is needed. - if (whatStr.empty()) { - if (message.compare(0, getPrefix().size(), getPrefix()) == 0 || // Already has prefix - getPrefix().empty()) // No prefix - whatStr = message; - else - whatStr = getPrefix() + COLON + message; - } - return whatStr.c_str(); -} - -ClosedException::ClosedException(const std::string& msg) - : Exception(msg) {} - -std::string ClosedException::getPrefix() const { return "Closed"; } - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/Exception.h b/qpid/cpp/src/qpid/Exception.h deleted file mode 100644 index 6df012ba28..0000000000 --- a/qpid/cpp/src/qpid/Exception.h +++ /dev/null @@ -1,95 +0,0 @@ -#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 -#include - -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) {} -}; - -struct ProtocolVersionError : public TransportFailure { - ProtocolVersionError(const std::string& msg=std::string()) : TransportFailure(msg) {} -}; - -} // namespace qpid - -#endif /*!_Exception_*/ diff --git a/qpid/cpp/src/qpid/InlineAllocator.h b/qpid/cpp/src/qpid/InlineAllocator.h deleted file mode 100644 index 28ea73ec12..0000000000 --- a/qpid/cpp/src/qpid/InlineAllocator.h +++ /dev/null @@ -1,101 +0,0 @@ -#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 -#include -#include -#include - -namespace qpid { - -template -struct InlineRebind; - - -/** - * An allocator that has inline storage for up to Max objects - * of type BaseAllocator::value_type. - */ -template -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, std::allocator::const_pointer = 0) { - if (n <= Max && !allocated) { - allocated=true; - return reinterpret_cast(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 - struct rebind { - typedef typename InlineRebind::other other; - }; - - private: - // POD object with alignment and size to hold Max value_types. - static const size_t ALIGNMENT=boost::alignment_of::value; - typedef typename boost::type_with_alignment::type Aligner; - union Store { - Aligner aligner_; - char sizer_[sizeof(value_type)*Max]; - } store; - value_type* address() { return reinterpret_cast(&store); } - bool allocated; -}; - - -// Rebind: if RequestedType == InlineType, use the InlineAllocator, -// otherwise, use the BaseAllocator without any inlining. - -template -struct InlineRebind { - typedef typename BaseAllocator::template rebind::other other; -}; - -template -struct InlineRebind { - typedef typename qpid::InlineAllocator other; -}; - -} // namespace qpid - -#endif /*!QPID_INLINEALLOCATOR_H*/ diff --git a/qpid/cpp/src/qpid/InlineVector.h b/qpid/cpp/src/qpid/InlineVector.h deleted file mode 100644 index c55db295f3..0000000000 --- a/qpid/cpp/src/qpid/InlineVector.h +++ /dev/null @@ -1,68 +0,0 @@ -#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 - -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 InlineVector : public std::vector > -{ - typedef std::vector > 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/Modules.cpp b/qpid/cpp/src/qpid/Modules.cpp deleted file mode 100644 index 049ededaa7..0000000000 --- a/qpid/cpp/src/qpid/Modules.cpp +++ /dev/null @@ -1,94 +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 "config.h" -#include "qpid/Modules.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Shlib.h" -#include "qpid/sys/FileSysDir.h" - -namespace { - -// CMake sets QPID_MODULE_SUFFIX; Autoconf doesn't, so assume Linux .so -#ifndef QPID_MODULE_SUFFIX -#define QPID_MODULE_SUFFIX ".so" -#endif - -inline std::string& suffix() { - static std::string s(QPID_MODULE_SUFFIX); - return s; -} - -bool isShlibName(const std::string& name) { - return name.substr(name.size()-suffix().size()) == suffix(); -} - -} - -namespace qpid { - -ModuleOptions::ModuleOptions(const std::string& defaultModuleDir) - : qpid::Options("Module options"), loadDir(defaultModuleDir), noLoad(false) -{ - addOptions() - ("module-dir", optValue(loadDir, "DIR"), "Load all shareable modules in this directory") - ("load-module", optValue(load, "FILE"), "Specifies additional module(s) to be loaded") - ("no-module-dir", optValue(noLoad), "Don't load modules from module directory"); -} - -void tryShlib(const std::string& libname) { - sys::Shlib shlib( isShlibName(libname) ? libname : (libname + suffix())); -} - -namespace { - -void tryOnlyShlib(const std::string& libname) throw() { - try { - if (isShlibName(libname)) sys::Shlib shlib( libname ); - } - catch (const std::exception& /*e*/) { - } -} - -} - -void loadModuleDir (std::string dirname, bool isDefault) -{ - - sys::FileSysDir dirPath (dirname); - - bool exists; - try - { - exists = dirPath.exists(); - } catch (Exception& e) { - throw Exception ("Invalid value for module-dir: " + e.getMessage()); - } - if (!exists) { - if (isDefault) return; - throw Exception ("Directory not found: " + dirname); - } - - dirPath.forEachFile(&tryOnlyShlib); -} - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/Modules.h b/qpid/cpp/src/qpid/Modules.h deleted file mode 100644 index 9fb91d60eb..0000000000 --- a/qpid/cpp/src/qpid/Modules.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef QPID_MODULES_H -#define QPID_MODULES_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/Options.h" -#include -#include -#include "qpid/CommonImportExport.h" - -namespace qpid { - -struct ModuleOptions : public qpid::Options { - std::string loadDir; - std::vector load; - bool noLoad; - QPID_COMMON_EXTERN ModuleOptions(const std::string& defaultModuleDir); -}; - -QPID_COMMON_EXTERN void tryShlib(const std::string& libname); -QPID_COMMON_EXTERN void loadModuleDir (std::string dirname, bool isDefault); - -} // namespace qpid - -#endif /*!QPID_MODULES_H*/ diff --git a/qpid/cpp/src/qpid/Msg.h b/qpid/cpp/src/qpid/Msg.h deleted file mode 100644 index 5f0b11bc60..0000000000 --- a/qpid/cpp/src/qpid/Msg.h +++ /dev/null @@ -1,79 +0,0 @@ -#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 -#include -#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 Msg& operator<<(const T& t) { os < NullSaslClient::getSecurityLayer(uint16_t) -{ - return std::auto_ptr(); -} -} // namespace qpid diff --git a/qpid/cpp/src/qpid/NullSaslClient.h b/qpid/cpp/src/qpid/NullSaslClient.h deleted file mode 100644 index 26882c6c20..0000000000 --- a/qpid/cpp/src/qpid/NullSaslClient.h +++ /dev/null @@ -1,45 +0,0 @@ -#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: - NullSaslClient(const std::string& username, const std::string& password); - 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 getSecurityLayer(uint16_t maxFrameSize); - private: - const std::string username; - const std::string password; - std::string mechanism; -}; -} // namespace qpid - -#endif /*!QPID_NULLSASLCLIENT_H*/ diff --git a/qpid/cpp/src/qpid/NullSaslServer.cpp b/qpid/cpp/src/qpid/NullSaslServer.cpp deleted file mode 100644 index 9d560c8e68..0000000000 --- a/qpid/cpp/src/qpid/NullSaslServer.cpp +++ /dev/null @@ -1,85 +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 "NullSaslServer.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SecurityLayer.h" -#include -#include - -namespace qpid { -NullSaslServer::NullSaslServer(const std::string& r) : realm(r) {} -NullSaslServer::Status NullSaslServer::start(const std::string& mechanism, const std::string* response, std::string& /*challenge*/) -{ - if (mechanism == "PLAIN") { - if (response) { - std::string uid; - std::string::size_type i = response->find((char)0); - if (i == 0 && response->size() > 1) { - //no authorization id; use authentication id - i = response->find((char)0, 1); - if (i != std::string::npos) uid = response->substr(1, i-1); - } else if (i != std::string::npos) { - //authorization id is first null delimited field - uid = response->substr(0, i); - } else { - QPID_LOG(error, "Invalid PLAIN request, null delimiter not found in response data"); - return FAIL; - } - if (!uid.empty()) { - //append realm if it has not already been added - i = uid.find(realm); - if (i == std::string::npos || realm.size() + i < uid.size()) { - uid = boost::str(boost::format("%1%@%2%") % uid % realm); - } - userid = uid; - } - return OK; - } else { - QPID_LOG(error, "Invalid PLAIN request, expected response containing user credentials"); - return FAIL; - } - } else if (mechanism == "ANONYMOUS") { - userid = "anonymous"; - return OK; - } else { - return FAIL; - } -} - -NullSaslServer::Status NullSaslServer::step(const std::string* /*response*/, std::string& /*challenge*/) -{ - return FAIL; -} -std::string NullSaslServer::getMechanisms() -{ - return std::string("ANONYMOUS PLAIN"); -} -std::string NullSaslServer::getUserid() -{ - return userid; -} - -std::auto_ptr NullSaslServer::getSecurityLayer(size_t) -{ - return std::auto_ptr(); -} - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/NullSaslServer.h b/qpid/cpp/src/qpid/NullSaslServer.h deleted file mode 100644 index 22a1b293a3..0000000000 --- a/qpid/cpp/src/qpid/NullSaslServer.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_NULLSASLSERVER_H -#define QPID_NULLSASLSERVER_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/SaslServer.h" - -namespace qpid { - -/** - * Dummy implementation of the SASL server role. This will advertise - * ANONYMOUS and PLAIN, and parse the reponse data for those - * accordingly, but will make no attempt to actually authenticate - * users. - */ -class NullSaslServer : public SaslServer -{ - public: - 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(); - std::string getUserid(); - std::auto_ptr getSecurityLayer(size_t); - private: - std::string realm; - std::string userid; -}; -} // namespace qpid - -#endif /*!QPID_NULLSASLSERVER_H*/ diff --git a/qpid/cpp/src/qpid/Options.cpp b/qpid/cpp/src/qpid/Options.cpp deleted file mode 100644 index 0021afc574..0000000000 --- a/qpid/cpp/src/qpid/Options.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* - * - * 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 "config.h" -#include "qpid/Options.h" -#include "qpid/OptionsTemplates.h" -#include "qpid/Exception.h" -#include "qpid/log/Logger.h" -#include "qpid/sys/Time.h" - -#include - -#include -#include -#include - -namespace qpid { - -using namespace std; - - -namespace { - -struct EnvOptMapper { - static bool matchChar(char env, char opt) { - return (env==toupper(opt)) || (strchr("-.", opt) && env=='_'); - } - - static bool matchStr(const string& env, boost::shared_ptr desc) { - return desc->long_name().size() == env.size() && - std::equal(env.begin(), env.end(), desc->long_name().begin(), &matchChar); - } - - static bool matchCase(const string& env, boost::shared_ptr desc) { - return env == desc->long_name(); - } - - EnvOptMapper(const Options& o) : opts(o) {} - - string operator()(const string& envVar) { - static const std::string prefix("QPID_"); - if (envVar.substr(0, prefix.size()) == prefix) { - string env = envVar.substr(prefix.size()); - typedef const std::vector< boost::shared_ptr > OptDescs; - OptDescs::const_iterator i = - find_if(opts.options().begin(), opts.options().end(), boost::bind(matchStr, env, _1)); - if (i != opts.options().end()) - return (*i)->long_name(); - } - return string(); - } - - - bool - isComment ( string const & str ) - { - size_t i = str.find_first_not_of ( " \t" ); - - if ( i == string::npos ) - return true; - - return str[i] == '#'; - } - - - void badArg ( string& line ) { - ostringstream msg; - msg << "Bad argument: |" << line << "|\n"; - throw Exception(msg.str()); - } - - - string configFileLine (string& line, bool allowUnknowns=true) { - - if ( isComment ( line ) ) { - return string(); - } - - size_t pos = line.find ('='); - if (pos == string::npos) { - if ( allowUnknowns ) { - return string(); - } - else { - badArg ( line ); - } - } - string key = line.substr (0, pos); -#if (BOOST_VERSION >= 103300) - typedef const std::vector< boost::shared_ptr > OptDescs; - OptDescs::const_iterator i = - find_if(opts.options().begin(), opts.options().end(), boost::bind(matchCase, key, _1)); - if (i != opts.options().end()) - return string (line) + "\n"; - else { - if ( allowUnknowns ) { - return string(); - } - else { - badArg ( line ); - } - } -#else - // Use 'count' to see if this option exists. Using 'find' will - // SEGV or hang if the option has not been defined yet. - if ( opts.count(key.c_str()) > 0 ) - return string ( line ) + "\n"; - else { - if ( allowUnknowns ) { - return string ( ); - } - else { - badArg ( line ); - } - } -#endif - // Control will not arrive here, but the compiler things it could. - // Calls to badArg(), that I used above, throw. - return string(); - } - - const Options& opts; -}; - -} - -template QPID_COMMON_EXTERN po::value_semantic* create_value(bool& val, const std::string& arg); -template QPID_COMMON_EXTERN po::value_semantic* create_value(int16_t& val, const std::string& arg); -template QPID_COMMON_EXTERN po::value_semantic* create_value(int32_t& val, const std::string& arg); -template QPID_COMMON_EXTERN po::value_semantic* create_value(int64_t& val, const std::string& arg); -template QPID_COMMON_EXTERN po::value_semantic* create_value(uint16_t& val, const std::string& arg); -template QPID_COMMON_EXTERN po::value_semantic* create_value(uint32_t& val, const std::string& arg); -template QPID_COMMON_EXTERN po::value_semantic* create_value(uint64_t& val, const std::string& arg); -#ifdef QPID_SIZE_T_DISTINCT -template QPID_COMMON_EXTERN po::value_semantic* create_value(size_t& val, const std::string& arg); -#endif -template QPID_COMMON_EXTERN po::value_semantic* create_value(double& val, const std::string& arg); - -template QPID_COMMON_EXTERN po::value_semantic* create_value(string& val, const std::string& arg); -template QPID_COMMON_EXTERN po::value_semantic* create_value(vector& val, const std::string& arg); -template QPID_COMMON_EXTERN po::value_semantic* create_value(vector& val, const std::string& arg); - -template QPID_COMMON_EXTERN po::value_semantic* create_value(sys::Duration& val, const std::string& arg); - - -po::value_semantic* optValue(bool& value) { -#if (BOOST_VERSION >= 103500) - return create_value(value, "", true); -#else - return po::bool_switch(&value); -#endif -} - -po::value_semantic* pure_switch(bool& value) { - return po::bool_switch(&value); -} - -std::string prettyArg(const std::string& name, const std::string& value) { - return value.empty() ? name+" " : name+" ("+value+") "; -} - -Options::Options(const string& name) : - poOptions(new po::options_description(name)) -{ -} - -void Options::parse(int argc, char const* const* argv, const std::string& configFile, bool allowUnknown) -{ - string defaultConfigFile = configFile; // May be changed by env/cmdline - string parsing; - try { - po::variables_map vm; - parsing="command line options"; - if (argc > 0 && argv != 0) { - if (allowUnknown) { - // This hideous workaround is required because boost 1.33 has a bug - // that causes 'allow_unregistered' to not work. - po::command_line_parser clp = po::command_line_parser(argc, const_cast(argv)). - options(*poOptions).allow_unregistered(); - po::parsed_options opts = clp.run(); - po::parsed_options filtopts = clp.run(); - filtopts.options.clear (); - for (std::vector< po::basic_option >::iterator i = opts.options.begin(); - i != opts.options.end(); i++) - if (!i->unregistered) - filtopts.options.push_back (*i); - po::store(filtopts, vm); - - } - else - po::store(po::parse_command_line(argc, const_cast(argv), *poOptions), vm); - } - parsing="environment variables"; - po::store(po::parse_environment(*poOptions, EnvOptMapper(*this)), vm); - po::notify(vm); // configFile may be updated from arg/env options. - if (!configFile.empty()) { - parsing="configuration file "+configFile; - ifstream conf(configFile.c_str()); - conf.peek(); - if (conf.good()) { - // Remove this hack when we get a stable version of boost that - // can allow unregistered options in config files. - EnvOptMapper mapper(*this); - stringstream filtered; - - while (!conf.eof()) { - string line; - getline (conf, line); - filtered << mapper.configFileLine (line, allowUnknown); - } - - po::store(po::parse_config_file(filtered, *poOptions), vm); - // End of hack - } - else { - // log the inability to read the configuration file - QPID_LOG(debug, "Config file not read: " << configFile); - // No error if default configfile is missing/unreadable - // but complain for non-default config file. - if (configFile != defaultConfigFile) - throw Exception("cannot read configuration file " - +configFile); - } - } - po::notify(vm); - } - catch (const std::exception& e) { - ostringstream msg; - msg << "Error in " << parsing << ": " << e.what() << endl; -#if (BOOST_VERSION >= 103300) - if (find_nothrow("help", false)) - msg << "Use --help to see valid options" << endl; -#endif - throw Exception(msg.str()); - } -} - -options_description_easy_init::options_description_easy_init(po::options_description* o) : - owner(o) -{} - -options_description_easy_init Options::addOptions() -{ - return options_description_easy_init(poOptions.get()); -} - -void Options::add(Options& o) -{ - poOptions->add(*o.poOptions); -} - -const std::vector< boost::shared_ptr >& Options::options() const -{ - return poOptions->options(); -} - -bool Options::find_nothrow(const std::string& s, bool b) -{ - return poOptions->find_nothrow(s, b); -} - -bool Options::findArg(int argc, char const* const* argv, const std::string& theArg) -{ - const string parsing("command line options"); - bool result(false); - try { - if (argc > 0 && argv != 0) { - po::command_line_parser clp = po::command_line_parser(argc, const_cast(argv)). - options(*poOptions).allow_unregistered(); - po::parsed_options opts = clp.run(); - - for (std::vector< po::basic_option >::iterator - i = opts.options.begin(); i != opts.options.end(); i++) { - if (theArg.compare(i->string_key) == 0) { - result = true; - break; - } - } - } - return result; - } - catch (const std::exception& e) { - ostringstream msg; - msg << "Error in " << parsing << ": " << e.what() << endl; - throw Exception(msg.str()); - } -} - -void Options::print(ostream& os) -{ - poOptions->print(os); -} - -std::ostream& operator<<(std::ostream& os, const Options& options) -{ - return os << *(options.poOptions); -} - -options_description_easy_init& -options_description_easy_init::operator()(const char* name, - const po::value_semantic* s, - const char* description) -{ - owner->add(boost::shared_ptr(new po::option_description(name, s, description))); - return *this; -} - - -CommonOptions::CommonOptions(const string& name, const string& configfile, const string& clientfile) -: Options(name), config(configfile), clientConfig(clientfile) -{ - addOptions() - ("help,h", optValue(help), "Displays the help message") - ("version,v", optValue(version), "Displays version information") - ("config", optValue(config, "FILE"), "Reads configuration from FILE") - ("client-config", optValue(clientConfig, "FILE"), "Reads client configuration from FILE (for cluster interconnect)"); -} - -} // namespace qpid - diff --git a/qpid/cpp/src/qpid/Options.h b/qpid/cpp/src/qpid/Options.h deleted file mode 100644 index ed4221fc90..0000000000 --- a/qpid/cpp/src/qpid/Options.h +++ /dev/null @@ -1,203 +0,0 @@ -#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 -#include - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -#include -#include -#include -#include -#include -#include - -#include "qpid/CommonImportExport.h" - -namespace boost { -namespace program_options { -class value_semantic; -class option_description; -class options_description; -}} - -namespace qpid { -namespace po=boost::program_options; - - - -///@internal -QPID_COMMON_EXTERN std::string prettyArg(const std::string&, const std::string&); - -///@internal -template -po::value_semantic* create_value(T& val, const std::string& arg); - -/** Create an option value. - * name, value appear after the option name in help like this: - * (=) - * T must support operator <<. - *@see Options for example of use. - */ -template -po::value_semantic* optValue(T& value, const char* name) { - std::string valstr(boost::lexical_cast(value)); - return create_value(value, prettyArg(name, valstr)); -} - -/** Create a vector value. Multiple occurences of the option are - * accumulated into the vector - */ -template -po::value_semantic* optValue(std::vector& value, const char* name) { - std::ostringstream os; - std::copy(value.begin(), value.end(), std::ostream_iterator(os, " ")); - std::string val=os.str(); - if (!val.empty()) - val.erase(val.end()-1); // Remove trailing " " - return create_value(value, prettyArg(name, val)); -} - -/** Create a boolean switch value. Presence of the option sets the value. */ -QPID_COMMON_EXTERN po::value_semantic* optValue(bool& value); -QPID_COMMON_EXTERN po::value_semantic* pure_switch(bool& 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 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 - */ - - -class options_description_easy_init { -public: - QPID_COMMON_EXTERN options_description_easy_init(po::options_description* o); - - QPID_COMMON_EXTERN options_description_easy_init& - operator()(const char* name, - const po::value_semantic* s, - const char* description); - -private: - po::options_description* owner; -}; - - -struct Options { - friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& os, const Options&); - - struct Exception : public qpid::Exception { - Exception(const std::string& msg) : qpid::Exception(msg) {} - }; - - QPID_COMMON_EXTERN explicit 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); - - QPID_COMMON_EXTERN options_description_easy_init addOptions(); - QPID_COMMON_EXTERN void add(Options&); - QPID_COMMON_EXTERN const std::vector< boost::shared_ptr >& options() const; - QPID_COMMON_EXTERN bool find_nothrow(const std::string&, bool); - QPID_COMMON_EXTERN void print(std::ostream& os); - -private: - boost::shared_ptr poOptions; -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& os, const 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/OptionsTemplates.h b/qpid/cpp/src/qpid/OptionsTemplates.h deleted file mode 100644 index 5e7f7b5e1d..0000000000 --- a/qpid/cpp/src/qpid/OptionsTemplates.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * 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 - -#include - -#include "qpid/CommonImportExport.h" - -namespace qpid { - -namespace po=boost::program_options; - -template -class OptValue : public po::typed_value { -public: - OptValue(T& val, const std::string& arg) : - po::typed_value(&val), - argName(arg) - {} - std::string name() const { return argName; } - -private: - std::string argName; -}; - -template -po::value_semantic* create_value(T& val, const std::string& arg) { - return new OptValue(val, arg); -} - -template -po::value_semantic* create_value(T& val, const std::string& arg, const T& implicit_val) { - return (new OptValue(val, arg))->implicit_value(implicit_val); -} - -} diff --git a/qpid/cpp/src/qpid/Plugin.cpp b/qpid/cpp/src/qpid/Plugin.cpp deleted file mode 100644 index 196b5c2333..0000000000 --- a/qpid/cpp/src/qpid/Plugin.cpp +++ /dev/null @@ -1,94 +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/Plugin.h" -#include "qpid/Options.h" -#include -#include - -namespace qpid { - -namespace { - -Plugin::Plugins& thePlugins() { - // This is a single threaded singleton implementation so - // it is important to be sure that the first use of this - // singleton is when the program is still single threaded - static Plugin::Plugins plugins; - return plugins; -} - -void invoke(boost::function f) { f(); } - -} // namespace - -Plugin::Target::~Target() { finalize(); } - -void Plugin::Target::finalize() { - std::for_each(finalizers.begin(), finalizers.end(), invoke); - finalizers.clear(); -} - -void Plugin::Target::addFinalizer(const boost::function& f) { - finalizers.push_back(f); -} - -namespace { -bool initBefore(const Plugin* a, const Plugin* b) { - return a->initOrder() < b->initOrder(); -} -} - -Plugin::Plugin() { - // Register myself. - thePlugins().push_back(this); - std::sort(thePlugins().begin(), thePlugins().end(), &initBefore); -} - -Plugin::~Plugin() {} - -Options* Plugin::getOptions() { return 0; } - -const Plugin::Plugins& Plugin::getPlugins() { return thePlugins(); } - -namespace { -template void each_plugin(const F& f) { - std::for_each(Plugin::getPlugins().begin(), Plugin::getPlugins().end(), f); -} -} - -void Plugin::addOptions(Options& opts) { - for (Plugins::const_iterator i = getPlugins().begin(); i != getPlugins().end(); ++i) { - if ((*i)->getOptions()) - opts.add(*(*i)->getOptions()); - } -} - -int Plugin::initOrder() const { return DEFAULT_INIT_ORDER; } - -void Plugin::earlyInitAll(Target& t) { - each_plugin(boost::bind(&Plugin::earlyInitialize, _1, boost::ref(t))); -} - -void Plugin::initializeAll(Target& t) { - each_plugin(boost::bind(&Plugin::initialize, _1, boost::ref(t))); -} - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/Plugin.h b/qpid/cpp/src/qpid/Plugin.h deleted file mode 100644 index 4e057872b9..0000000000 --- a/qpid/cpp/src/qpid/Plugin.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef QPID_PLUGIN_H -#define QPID_PLUGIN_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 -#include -#include -#include "qpid/CommonImportExport.h" - -/**@file Generic plug-in framework. */ - -namespace qpid { -struct Options; - -/** - * Plug-in base class. - */ -class Plugin : private boost::noncopyable { - public: - typedef std::vector Plugins; - /** Default value returned by initOrder() */ - static const int DEFAULT_INIT_ORDER=1000; - - /** - * Base interface for targets that can receive plug-ins. - * Also allows plug-ins to attach a a function to be called - * when the target is 'finalized'. - */ - class Target : private boost::noncopyable - { - public: - /** Calls finalize() if not already called. */ - QPID_COMMON_EXTERN virtual ~Target(); - - /** Run all the finalizers */ - QPID_COMMON_EXTERN void finalize(); - - /** Add a function to run when finalize() is called */ - QPID_COMMON_EXTERN void addFinalizer(const boost::function&); - - private: - std::vector > finalizers; - }; - - /** - * Constructor registers the plug-in to appear in getPlugins(). - * - * A concrete Plugin is instantiated as a global or static - * member variable in a library so it is registered during - * initialization when the library is loaded. - */ - QPID_COMMON_EXTERN Plugin(); - - QPID_COMMON_EXTERN virtual ~Plugin(); - - /** - * Configuration options for the plugin. - * Then will be updated during option parsing by the host program. - * - * @return An options group or 0 for no options. Default returns 0. - * Plugin retains ownership of return value. - */ - QPID_COMMON_EXTERN virtual Options* getOptions(); - - /** - * Initialize Plugin functionality on a Target, called before - * initializing the target. - * - * Plugins should ignore targets they don't recognize. - * - * Called before the target itself is initialized. - */ - virtual void earlyInitialize(Target&) = 0; - - /** - * Initialize Plugin functionality on a Target. Called after - * initializing the target. - * - * Plugins should ignore targets they don't recognize. - * - * Called after the target is fully initialized. - */ - virtual void initialize(Target&) = 0; - - /** - * Initialization order. If a plugin does not override this, it - * returns DEFAULT_INIT_ORDER. Plugins that need to be initialized - * earlier/later than normal can override initOrder to return - * a lower/higher value than DEFAULT_INIT_ORDER. - */ - QPID_COMMON_EXTERN virtual int initOrder() const; - - /** List of registered Plugin objects. - * Caller must not delete plugin pointers. - */ - QPID_COMMON_EXTERN static const Plugins& getPlugins(); - - /** Call earlyInitialize() on all registered plugins */ - QPID_COMMON_EXTERN static void earlyInitAll(Target&); - - /** Call initialize() on all registered plugins */ - QPID_COMMON_EXTERN static void initializeAll(Target&); - - /** For each registered plugin, add plugin.getOptions() to opts. */ - QPID_COMMON_EXTERN static void addOptions(Options& opts); -}; - -} // namespace qpid - -#endif /*!QPID_PLUGIN_H*/ diff --git a/qpid/cpp/src/qpid/RangeSet.h b/qpid/cpp/src/qpid/RangeSet.h deleted file mode 100644 index 20ee722fcb..0000000000 --- a/qpid/cpp/src/qpid/RangeSet.h +++ /dev/null @@ -1,330 +0,0 @@ -#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 -#include -#include - -#include -#include -#include - -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 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& 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 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 RangeSet - : private boost::additive1, - boost::additive2, Range, - boost::additive2, T> > > -{ - typedef InlineVector, 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; - friend class boost::iterator_core_access; - }; - - typedef iterator const_iterator; - - RangeSet() {} - explicit RangeSet(const Range& r) { *this += r; } - RangeSet(const T& a, const T& b) { *this += Range(a,b); } - - bool contiguous() const { return ranges.size() <= 1; } - - bool contains(const T& t) const; - bool contains(const Range&) const; - - /**@pre contiguous() */ - Range toRange() const; - - bool operator==(const RangeSet&) const; - - void addRange (const Range&); - void addSet (const RangeSet&); - - RangeSet& operator+=(const T& t) { return *this += Range(t); } - RangeSet& operator+=(const Range& r) { addRange(r); return *this; } - RangeSet& operator+=(const RangeSet& s) { addSet(s); return *this; } - - void removeRange (const Range&); - void removeSet (const RangeSet&); - - RangeSet& operator-=(const T& t) { return *this -= Range(t); } - RangeSet& operator-=(const Range& r) { removeRange(r); return *this; } - RangeSet& operator-=(const RangeSet& 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 rangeContaining(const T&) const; - - template void serialize(S& s) { s.split(*this); s(ranges.begin(), ranges.end()); } - template void encode(S& s) const { s(uint16_t(ranges.size()*sizeof(Range))); } - template void decode(S& s) { uint16_t sz; s(sz); ranges.resize(sz/sizeof(Range)); } - - private: - static size_t accumulateSize(size_t s, const Range& r) { return s+r.size(); } - Ranges ranges; - - template friend std::ostream& operator<<(std::ostream& o, const RangeSet& r); - - friend class iterator; -}; - -template -std::ostream& operator<<(std::ostream& o, const Range& r) { - return o << "[" << r.begin() << "," << r.end() << ")"; -} - -template -std::ostream& operator<<(std::ostream& o, const RangeSet& rs) { - std::ostream_iterator > i(o, " "); - o << "{ "; - std::copy(rs.ranges.begin(), rs.ranges.end(), i); - return o << "}"; -} - -template -bool RangeSet::contains(const T& t) const { - typename Ranges::const_iterator i = - std::lower_bound(ranges.begin(), ranges.end(), Range(t)); - return i != ranges.end() && i->contains(t); -} - -template -bool RangeSet::contains(const Range& r) const { - typename Ranges::const_iterator i = - std::lower_bound(ranges.begin(), ranges.end(), r); - return i != ranges.end() && i->contains(r); -} - -template void RangeSet::addRange(const Range& 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 void RangeSet::addSet(const RangeSet& s) { - typedef RangeSet& (RangeSet::*RangeSetRangeOp)(const Range&); - std::for_each(s.ranges.begin(), s.ranges.end(), - boost::bind((RangeSetRangeOp)&RangeSet::operator+=, this, _1)); -} - -template void RangeSet::removeRange(const Range& 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 i1(i->begin(), r.begin()); - Range 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 void RangeSet::removeSet(const RangeSet& r) { - std::for_each( - r.ranges.begin(), r.ranges.end(), - boost::bind(&RangeSet::removeRange, this, _1)); -} - -template Range RangeSet::toRange() const { - assert(contiguous()); - return empty() ? Range() : ranges.front(); -} - -template void RangeSet::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 bool RangeSet::operator==(const RangeSet& r) const { - return ranges.size() == r.ranges.size() && std::equal(ranges.begin(), ranges.end(), r.ranges.begin()); -} - -template typename RangeSet::iterator RangeSet::begin() const { - return empty() ? end() : iterator(ranges, ranges.begin(), front()); -} - -template typename RangeSet::iterator RangeSet::end() const { - return iterator(); -} - -template bool RangeSet::iterator::equal(const iterator& i) const { - return ranges==i.ranges && (ranges==0 || value==i.value); -} - -template Range RangeSet::rangeContaining(const T& t) const { - typename Ranges::const_iterator i = - std::lower_bound(ranges.begin(), ranges.end(), Range(t)); - return (i != ranges.end() && i->contains(t)) ? *i : Range(t,t); -} - -template uint32_t RangeSet::span() const { - if (ranges.empty()) return 0; - return ranges.back().last() - ranges.front().first(); -} - -template size_t RangeSet::size() const { - return std::accumulate(rangesBegin(), rangesEnd(), 0, &RangeSet::accumulateSize); -} - -} // namespace qpid - - -#endif /*!QPID_RANGESET_H*/ diff --git a/qpid/cpp/src/qpid/RefCounted.h b/qpid/cpp/src/qpid/RefCounted.h deleted file mode 100644 index c2ec367658..0000000000 --- a/qpid/cpp/src/qpid/RefCounted.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_REFCOUNTED_H -#define QPID_REFCOUNTED_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 -#include - -namespace qpid { - -/** - * Reference-counted base class. - * Note: this class isn't copyable - you must copy the intrusive_ptr that points - * to the class that has mixed this in not the class itself (as that would sidestep - * the reference counting) - */ -class RefCounted : private boost::noncopyable { - mutable boost::detail::atomic_count count; - -public: - RefCounted() : count(0) {} - void addRef() const { ++count; } - void release() const { if (--count==0) released(); } - long refCount() { return count; } - -protected: - virtual ~RefCounted() {}; - // Allow subclasses to over-ride behavior when refcount reaches 0. - virtual void released() const { delete this; } -}; - - -// intrusive_ptr support. -inline void intrusive_ptr_add_ref(const RefCounted* p) { p->addRef(); } -inline void intrusive_ptr_release(const RefCounted* p) { p->release(); } - -} // namespace qpid - - -#endif /*!QPID_REFCOUNTED_H*/ diff --git a/qpid/cpp/src/qpid/RefCountedBuffer.cpp b/qpid/cpp/src/qpid/RefCountedBuffer.cpp deleted file mode 100644 index a82e1a02ab..0000000000 --- a/qpid/cpp/src/qpid/RefCountedBuffer.cpp +++ /dev/null @@ -1,46 +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/RefCountedBuffer.h" -#include -#include - -namespace qpid { - -void RefCountedBuffer::released() const { - this->~RefCountedBuffer(); - ::free (reinterpret_cast(const_cast(this))); -} - -BufferRef RefCountedBuffer::create(size_t n) { - void* store=::malloc (n + sizeof(RefCountedBuffer)); - if (NULL == store) - throw std::bad_alloc(); - new(store) RefCountedBuffer; - char* start = reinterpret_cast(store) + sizeof(RefCountedBuffer); - return BufferRef( - boost::intrusive_ptr(reinterpret_cast(store)), - start, start+n); -} - -} // namespace qpid - - diff --git a/qpid/cpp/src/qpid/RefCountedBuffer.h b/qpid/cpp/src/qpid/RefCountedBuffer.h deleted file mode 100644 index f0ea86130b..0000000000 --- a/qpid/cpp/src/qpid/RefCountedBuffer.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef QPID_REFCOUNTEDBUFFER_H -#define QPID_REFCOUNTEDBUFFER_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 -#include - -namespace qpid { - -/** - * Reference-counted byte buffer. No alignment guarantees. - */ -class RefCountedBuffer : public RefCounted { - public: - /** Create a reference counted buffer of size n */ - static BufferRef create(size_t n); - - protected: - void released() const; -}; - -} // namespace qpid - -#endif /*!QPID_REFCOUNTEDBUFFER_H*/ diff --git a/qpid/cpp/src/qpid/Sasl.h b/qpid/cpp/src/qpid/Sasl.h deleted file mode 100644 index 1164fb5ec3..0000000000 --- a/qpid/cpp/src/qpid/Sasl.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_SASL_H -#define QPID_SASL_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 -#include -#include "qpid/CommonImportExport.h" -#include "qpid/sys/IntegerTypes.h" - -namespace qpid { - -namespace sys { -class SecurityLayer; -struct SecuritySettings; -} - -/** - * Interface to support for the SASL client role. This class is implemented by platform-specific - * SASL providers. - */ -class Sasl -{ - public: - /** - * Start SASL negotiation with the broker. - * - * @param mechanisms Comma-separated list of the SASL mechanism the - * client supports. - * @param externalSecuritySettings security related details from the underlying transport - */ - virtual bool start(const std::string& mechanisms, std::string& response, - const qpid::sys::SecuritySettings* externalSecuritySettings = 0) = 0; - virtual std::string step(const std::string& challenge) = 0; - virtual std::string getMechanism() = 0; - virtual std::string getUserId() = 0; - virtual std::auto_ptr getSecurityLayer(uint16_t maxFrameSize) = 0; - QPID_COMMON_EXTERN virtual ~Sasl() {} -}; -} // namespace qpid - -#endif /*!QPID_SASL_H*/ diff --git a/qpid/cpp/src/qpid/SaslFactory.cpp b/qpid/cpp/src/qpid/SaslFactory.cpp deleted file mode 100644 index 7bfc510936..0000000000 --- a/qpid/cpp/src/qpid/SaslFactory.cpp +++ /dev/null @@ -1,646 +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/SaslFactory.h" -#include "qpid/SaslServer.h" -#include "qpid/NullSaslClient.h" -#include "qpid/NullSaslServer.h" -#include -#include - -#include "config.h" - -#ifndef HAVE_SASL - -namespace qpid { - -//Null implementation - - -SaslFactory::SaslFactory() {} - -SaslFactory::~SaslFactory() {} - -SaslFactory& SaslFactory::getInstance() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!instance.get()) { - instance = std::auto_ptr(new SaslFactory()); - } - return *instance; -} - -std::auto_ptr SaslFactory::create(const std::string& username, const std::string& password, const std::string&, const std::string&, int, int, bool) -{ - std::auto_ptr client(new NullSaslClient(username, password)); - return client; -} - -std::auto_ptr SaslFactory::createServer(const std::string& realm, const std::string& /*service*/, bool /*encryptionRequired*/, const qpid::sys::SecuritySettings&) -{ - std::auto_ptr server(new NullSaslServer(realm)); - return server; -} - -qpid::sys::Mutex SaslFactory::lock; -std::auto_ptr SaslFactory::instance; - -} // namespace qpid - -#else - -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/cyrus/CyrusSecurityLayer.h" -#include "qpid/log/Statement.h" -#include -#include - -namespace qpid { - -using qpid::sys::SecurityLayer; -using qpid::sys::SecuritySettings; -using qpid::sys::cyrus::CyrusSecurityLayer; -using qpid::framing::InternalErrorException; - -const size_t MAX_LOGIN_LENGTH = 50; - -struct CyrusSaslSettings -{ - CyrusSaslSettings ( ) : - username ( std::string(0) ), - password ( std::string(0) ), - service ( std::string(0) ), - host ( std::string(0) ), - minSsf ( 0 ), - maxSsf ( 0 ) - { - } - - CyrusSaslSettings ( const std::string & user, const std::string & password, const std::string & service, const std::string & host, int minSsf, int maxSsf ) : - username(user), - password(password), - service(service), - host(host), - minSsf(minSsf), - maxSsf(maxSsf) - { - } - - std::string username, - password, - service, - host; - - int minSsf, - maxSsf; -}; - - -class CyrusSasl : public Sasl -{ - public: - CyrusSasl(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction); - ~CyrusSasl(); - bool start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings); - std::string step(const std::string& challenge); - std::string getMechanism(); - std::string getUserId(); - std::auto_ptr getSecurityLayer(uint16_t maxFrameSize); - private: - sasl_conn_t* conn; - sasl_callback_t callbacks[5];//realm, user, authname, password, end-of-list - CyrusSaslSettings settings; - std::string input; - std::string mechanism; - char login[MAX_LOGIN_LENGTH]; - - /* In some contexts, like running in the broker or as a daemon, console - * interaction is impossible. In those cases, we will treat the attempt - * to interact as an error. */ - bool allowInteraction; - void interact(sasl_interact_t* client_interact); -}; - -//sasl callback functions -int getUserFromSettings(void *context, int id, const char **result, unsigned *len); -int getPasswordFromSettings(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret); -typedef int CallbackProc(); - -qpid::sys::Mutex SaslFactory::lock; -std::auto_ptr SaslFactory::instance; - -class CyrusSaslServer : public SaslServer -{ - public: - CyrusSaslServer(const std::string& realm, const std::string& service, bool encryptionRequired, const qpid::sys::SecuritySettings& external); - ~CyrusSaslServer(); - 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(); - std::string getUserid(); - std::auto_ptr getSecurityLayer(size_t); - private: - std::string realm; - std::string service; - std::string userid; - sasl_conn_t *sasl_conn; -}; - -SaslFactory::SaslFactory() -{ - sasl_callback_t* callbacks = 0; - int result = sasl_client_init(callbacks); - if (result != SASL_OK) { - throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errstring(result, 0, 0))); - } -} - -SaslFactory::~SaslFactory() -{ - sasl_done(); -} - -SaslFactory& SaslFactory::getInstance() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!instance.get()) { - instance = std::auto_ptr(new SaslFactory()); - } - return *instance; -} - -std::auto_ptr SaslFactory::create(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction) -{ - std::auto_ptr sasl(new CyrusSasl(username, password, serviceName, hostName, minSsf, maxSsf, allowInteraction)); - return sasl; -} - -std::auto_ptr SaslFactory::createServer(const std::string& realm, const std::string& service, bool encryptionRequired, const qpid::sys::SecuritySettings& external) -{ - std::auto_ptr server(new CyrusSaslServer(realm, service, encryptionRequired, external)); - return server; -} - -CyrusSasl::CyrusSasl(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction) - : conn(0), settings(username, password, serviceName, hostName, minSsf, maxSsf), allowInteraction(allowInteraction) -{ - size_t i = 0; - - callbacks[i].id = SASL_CB_GETREALM; - callbacks[i].proc = 0; - callbacks[i++].context = 0; - - if (!settings.username.empty()) { - callbacks[i].id = SASL_CB_AUTHNAME; - callbacks[i].proc = (CallbackProc*) &getUserFromSettings; - callbacks[i++].context = &settings; - - callbacks[i].id = SASL_CB_PASS; - if (settings.password.empty()) { - callbacks[i].proc = 0; - callbacks[i++].context = 0; - } else { - callbacks[i].proc = (CallbackProc*) &getPasswordFromSettings; - callbacks[i++].context = &settings; - } - } - - - callbacks[i].id = SASL_CB_LIST_END; - callbacks[i].proc = 0; - callbacks[i++].context = 0; -} - -CyrusSasl::~CyrusSasl() -{ - if (conn) { - sasl_dispose(&conn); - } -} - -namespace { - const std::string SSL("ssl"); -} - -bool CyrusSasl::start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings) -{ - QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << ")"); - int result = sasl_client_new(settings.service.c_str(), - settings.host.c_str(), - 0, 0, /* Local and remote IP address strings */ - callbacks, - 0, /* security flags */ - &conn); - - if (result != SASL_OK) throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn))); - - sasl_security_properties_t secprops; - - if (externalSettings) { - sasl_ssf_t external_ssf = (sasl_ssf_t) externalSettings->ssf; - if (external_ssf) { - int result = sasl_setprop(conn, SASL_SSF_EXTERNAL, &external_ssf); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result)); - } - QPID_LOG(debug, "external SSF detected and set to " << external_ssf); - } - if (externalSettings->authid.size()) { - const char* external_authid = externalSettings->authid.c_str(); - result = sasl_setprop(conn, SASL_AUTH_EXTERNAL, external_authid); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external auth: " << result)); - } - QPID_LOG(debug, "external auth detected and set to " << external_authid); - } - } - - secprops.min_ssf = settings.minSsf; - secprops.max_ssf = settings.maxSsf; - secprops.maxbufsize = 65535; - - QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << ", max_ssf: " << secprops.max_ssf); - - secprops.property_names = 0; - secprops.property_values = 0; - secprops.security_flags = 0;//TODO: provide means for application to configure these - - result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(conn))); - } - - sasl_interact_t* client_interact = 0; - const char *out = 0; - unsigned outlen = 0; - const char *chosenMechanism = 0; - - do { - result = sasl_client_start(conn, - mechanisms.c_str(), - &client_interact, - &out, - &outlen, - &chosenMechanism); - - if (result == SASL_INTERACT) { - interact(client_interact); - } - } while (result == SASL_INTERACT); - - if (result == SASL_NOMECH) { - if (mechanisms.size()) { - throw qpid::Exception(std::string("Can't authenticate using ") + mechanisms); - } else { - throw qpid::Exception("No mutually acceptable authentication mechanism"); - } - } else if (result != SASL_CONTINUE && result != SASL_OK) { - throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn))); - } - - mechanism = std::string(chosenMechanism); - QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << "): selected " - << mechanism << " response: '" << std::string(out, outlen) << "'"); - if (out) { - response = std::string(out, outlen); - return true; - } else { - return false; - } -} - -std::string CyrusSasl::step(const std::string& challenge) -{ - sasl_interact_t* client_interact = 0; - const char *out = 0; - unsigned outlen = 0; - int result = 0; - do { - result = sasl_client_step(conn, /* our context */ - challenge.data(), /* the data from the server */ - challenge.size(), /* it's length */ - &client_interact, /* this should be - unallocated and NULL */ - &out, /* filled in on success */ - &outlen); /* filled in on success */ - - if (result == SASL_INTERACT) { - interact(client_interact); - } - } while (result == SASL_INTERACT); - - std::string response; - if (result == SASL_CONTINUE || result == SASL_OK) response = std::string(out, outlen); - else if (result != SASL_OK) { - throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn))); - } - QPID_LOG(debug, "CyrusSasl::step(" << challenge << "): " << response); - return response; -} - -std::string CyrusSasl::getMechanism() -{ - return mechanism; -} - -std::string CyrusSasl::getUserId() -{ - int propResult; - const void* operName; - - propResult = sasl_getprop(conn, SASL_USERNAME, &operName); - if (propResult == SASL_OK) - return std::string((const char*) operName); - - return std::string(); -} - -void CyrusSasl::interact(sasl_interact_t* client_interact) -{ - - /* - In some context console interaction cannot be allowed, such - as when this code run as part of a broker, or as a some other - daemon. In those cases we will treat the attempt to - */ - if ( ! allowInteraction ) { - throw InternalErrorException("interaction disallowed"); - } - - if (client_interact->id == SASL_CB_PASS) { - char* password = getpass(client_interact->prompt); - input = std::string(password); - client_interact->result = input.data(); - client_interact->len = input.size(); - } else { - std::cout << client_interact->prompt; - if (client_interact->defresult) std::cout << " (" << client_interact->defresult << ")"; - std::cout << ": "; - if (std::cin >> input) { - client_interact->result = input.data(); - client_interact->len = input.size(); - } - } - -} - -std::auto_ptr CyrusSasl::getSecurityLayer(uint16_t maxFrameSize) -{ - const void* value(0); - int result = sasl_getprop(conn, SASL_SSF, &value); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(conn))); - } - uint ssf = *(reinterpret_cast(value)); - std::auto_ptr securityLayer; - if (ssf) { - QPID_LOG(info, "Installing security layer, SSF: "<< ssf); - securityLayer = std::auto_ptr(new CyrusSecurityLayer(conn, maxFrameSize, ssf)); - } - return securityLayer; -} - -CyrusSaslServer::CyrusSaslServer(const std::string& r, const std::string& s, bool encryptionRequired, const qpid::sys::SecuritySettings& external) : realm(r), service(s), sasl_conn(0) -{ - int code = sasl_server_new(service.c_str(), /* Service name */ - NULL, /* Server FQDN, gethostname() */ - realm.c_str(), /* Authentication realm */ - NULL, /* Local IP, needed for some mechanism */ - NULL, /* Remote IP, needed for some mechanism */ - NULL, /* Callbacks */ - 0, /* Connection flags */ - &sasl_conn); - - if (SASL_OK != code) { - QPID_LOG(error, "SASL: Connection creation failed: [" << code << "] " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw qpid::framing::ConnectionForcedException("Unable to perform authentication"); - } - - sasl_security_properties_t secprops; - - //TODO: should the actual SSF values be configurable here? - secprops.min_ssf = encryptionRequired ? 10: 0; - secprops.max_ssf = 256; - - // If the transport provides encryption, notify the SASL library of - // the key length and set the ssf range to prevent double encryption. - QPID_LOG(debug, "External ssf=" << external.ssf << " and auth=" << external.authid); - sasl_ssf_t external_ssf = (sasl_ssf_t) external.ssf; - if (external_ssf) { - int result = sasl_setprop(sasl_conn, SASL_SSF_EXTERNAL, &external_ssf); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result)); - } - - secprops.max_ssf = secprops.min_ssf = 0; - } - - QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << - ", max_ssf: " << secprops.max_ssf << - ", external_ssf: " << external_ssf ); - - if (!external.authid.empty()) { - const char* external_authid = external.authid.c_str(); - int result = sasl_setprop(sasl_conn, SASL_AUTH_EXTERNAL, external_authid); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external auth: " << result)); - } - - QPID_LOG(debug, "external auth detected and set to " << external_authid); - } - secprops.maxbufsize = 65535; - secprops.property_names = 0; - secprops.property_values = 0; - secprops.security_flags = 0; /* or SASL_SEC_NOANONYMOUS etc as appropriate */ - /* - * The nodict flag restricts SASL authentication mechanisms - * to those that are not susceptible to dictionary attacks. - * They are: - * SRP - * PASSDSS-3DES-1 - * EXTERNAL - */ - if (external.nodict) secprops.security_flags |= SASL_SEC_NODICTIONARY; - int result = sasl_setprop(sasl_conn, SASL_SEC_PROPS, &secprops); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << result)); - } -} - -CyrusSaslServer::~CyrusSaslServer() -{ - if (sasl_conn) { - sasl_dispose(&sasl_conn); - sasl_conn = 0; - } -} - -CyrusSaslServer::Status CyrusSaslServer::start(const std::string& mechanism, const std::string* response, std::string& chllng) -{ - const char *challenge; - unsigned int challenge_len; - - // This should be at same debug level as mech list in getMechanisms(). - QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism); - int code = sasl_server_start(sasl_conn, - mechanism.c_str(), - (response ? response->c_str() : 0), (response ? response->size() : 0), - &challenge, &challenge_len); - switch (code) { - case SASL_OK: - return SaslServer::OK; - case SASL_CONTINUE: - chllng = std::string(challenge, challenge_len); - return SaslServer::CHALLENGE; - case SASL_NOMECH: - QPID_LOG(info, "Unsupported mechanism: " << mechanism); - default: - return SaslServer::FAIL; - } -} - -CyrusSaslServer::Status CyrusSaslServer::step(const std::string* response, std::string& chllng) -{ - const char *challenge; - unsigned int challenge_len; - - int code = sasl_server_step(sasl_conn, - (response ? response->c_str() : 0), (response ? response->size() : 0), - &challenge, &challenge_len); - - switch (code) { - case SASL_OK: - return SaslServer::OK; - case SASL_CONTINUE: - chllng = std::string(challenge, challenge_len); - return SaslServer::CHALLENGE; - default: - return SaslServer::FAIL; - } - -} -std::string CyrusSaslServer::getMechanisms() -{ - const char *separator = " "; - const char *list; - unsigned int list_len; - int count; - - int code = sasl_listmech(sasl_conn, NULL, - "", separator, "", - &list, &list_len, - &count); - - if (SASL_OK != code) { - QPID_LOG(info, "SASL: Mechanism listing failed: " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw qpid::framing::ConnectionForcedException("Mechanism listing failed"); - } else { - std::string mechanisms(list, list_len); - QPID_LOG(info, "SASL: Mechanism list: " << mechanisms); - return mechanisms; - } -} -std::string CyrusSaslServer::getUserid() -{ - const void* ptr; - int code = sasl_getprop(sasl_conn, SASL_USERNAME, &ptr); - if (SASL_OK == code) { - userid = static_cast(ptr); - } else { - QPID_LOG(warning, "Failed to retrieve sasl username"); - } - return userid; -} - -std::auto_ptr CyrusSaslServer::getSecurityLayer(size_t maxFrameSize) -{ - const void* value(0); - int result = sasl_getprop(sasl_conn, SASL_SSF, &value); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(sasl_conn))); - } - uint ssf = *(reinterpret_cast(value)); - std::auto_ptr securityLayer; - if (ssf) { - securityLayer = std::auto_ptr(new CyrusSecurityLayer(sasl_conn, maxFrameSize, ssf)); - } - return securityLayer; -} - -int getUserFromSettings(void* context, int /*id*/, const char** result, unsigned* /*len*/) -{ - if (context) { - *result = ((CyrusSaslSettings*) context)->username.c_str(); - QPID_LOG(debug, "getUserFromSettings(): " << (*result)); - return SASL_OK; - } else { - return SASL_FAIL; - } -} - -namespace { -// Global map of secrets allocated for SASL connections via callback -// to getPasswordFromSettings. Ensures secrets are freed. -class SecretsMap { - typedef std::map Map; - Map map; - sys::Mutex lock; - public: - void keep(sasl_conn_t* conn, void* secret) { - sys::Mutex::ScopedLock l(lock); - Map::iterator i = map.find(conn); - if (i != map.end()) free(i->second); - map[conn] = secret; - } - - ~SecretsMap() { - for (Map::iterator i = map.begin(); i != map.end(); ++i) - free(i->second); - } -}; -SecretsMap getPasswordFromSettingsSecrets; -} - -int getPasswordFromSettings(sasl_conn_t* conn, void* context, int /*id*/, sasl_secret_t** psecret) -{ - if (context) { - size_t length = ((CyrusSaslSettings*) context)->password.size(); - sasl_secret_t* secret = (sasl_secret_t*) malloc(sizeof(sasl_secret_t) + length); - getPasswordFromSettingsSecrets.keep(conn, secret); - secret->len = length; - memcpy(secret->data, ((CyrusSaslSettings*) context)->password.data(), length); - *psecret = secret; - return SASL_OK; - } else { - return SASL_FAIL; - } -} -} // namespace qpid - -#endif diff --git a/qpid/cpp/src/qpid/SaslFactory.h b/qpid/cpp/src/qpid/SaslFactory.h deleted file mode 100644 index 39a9d74fd0..0000000000 --- a/qpid/cpp/src/qpid/SaslFactory.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef QPID_SASLFACTORY_H -#define QPID_SASLFACTORY_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/Sasl.h" -#include "qpid/sys/Mutex.h" -#include - -namespace qpid { -class SaslServer; -/** - * Factory for instances of the Sasl interface through which Sasl - * support is provided to a ConnectionHandler. - */ -class SaslFactory -{ - public: - QPID_COMMON_EXTERN std::auto_ptr create(const std::string & userName, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction=true ); - QPID_COMMON_EXTERN std::auto_ptr createServer(const std::string& realm, const std::string& service, bool encryptionRequired, const qpid::sys::SecuritySettings&); - QPID_COMMON_EXTERN static SaslFactory& getInstance(); - QPID_COMMON_EXTERN ~SaslFactory(); - private: - SaslFactory(); - static qpid::sys::Mutex lock; - static std::auto_ptr instance; -}; -} // namespace qpid - -#endif /*!QPID_SASLFACTORY_H*/ diff --git a/qpid/cpp/src/qpid/SaslServer.h b/qpid/cpp/src/qpid/SaslServer.h deleted file mode 100644 index 88909c69a9..0000000000 --- a/qpid/cpp/src/qpid/SaslServer.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef QPID_SASLSERVER_H -#define QPID_SASLSERVER_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 -#include - -namespace qpid { -namespace sys { -class SecurityLayer; -} -/** - * - */ -class SaslServer -{ - public: - typedef enum {OK, FAIL, CHALLENGE} Status; - 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; - virtual std::string getUserid() = 0; - virtual std::auto_ptr getSecurityLayer(size_t) = 0; - private: -}; -} // namespace qpid - -#endif /*!QPID_SASLSERVER_H*/ diff --git a/qpid/cpp/src/qpid/Serializer.h b/qpid/cpp/src/qpid/Serializer.h deleted file mode 100644 index a8ded9f5e0..0000000000 --- a/qpid/cpp/src/qpid/Serializer.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef QPID_SERIALIZER_H -#define QPID_SERIALIZER_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 -#include -#include "qpid/Exception.h" // FIXME aconway 2008-04-03: proper exception class. - -namespace qpid { - -/** - * Overload for types that do not provide a serialize() member. - * It should retrun a wrapper holding a reference to t that implements - * serialize() - */ -template T& serializable(T& t) { return t; } - -/** Serialize std::pair */ -template struct SerializablePair { - std::pair& value; - SerializablePair(std::pair& x) : value(x) {} - template void serialize(S& s) { s(value.first)(value.second); } -}; - -template -SerializablePair serializable(std::pair& p) { - return SerializablePair(p); -} - -/** - * Base class for all serializers. - * Derived serializers inherit from either Encoder or Decoder. - * Serializers can be used as functors or static_visitors. - */ -template class Serializer { - public: - /** Temporarily set a lower relative limit on the serializer */ - class ScopedLimit { - public: - ScopedLimit(Serializer& s, size_t l) - : serializer(s), save(serializer.setLimit(l)) {} - - ~ScopedLimit() { serializer.setAbsLimit(save); } - - private: - Serializer& serializer; - size_t save; - }; - - static size_t maxLimit() { return std::numeric_limits::max(); } - - Serializer() : bytes(0), limit(maxLimit()) {} - - typedef Derived& result_type; // unary functor requirement. - - /** Wrapper functor to pass serializer functors by reference. */ - template struct Ref { - typedef typename S::result_type result_type; - S& s; - Ref(S& ss) : s(ss) {} - template result_type operator()(T& x) { return s(x); } - template result_type operator()(const T& x) { return s(x); } - }; - - /** Reference wrapper to pass serializers by reference, - * e.g. to std:: functions that take functors. - */ - template static Ref ref(S& s) { return Ref(s); } - - /** Generic rule to serialize an iterator range */ - template Derived& operator()(Iter begin, Iter end) { - std::for_each(begin, end, ref(this->self())); - return self(); - } - - /** Set limit relative to current position. - * @return old absolute limit. - */ - size_t setLimit(size_t n) { - size_t l=limit; - limit = bytes+n; - return l; - } - - /** Get the max number of bytes that can be processed under the - * current limit. - */ - size_t bytesRemaining() const { - return limit - bytes; - } - /** Set absolute limit. */ - void setAbsLimit(size_t n) { - limit = n; - if (bytes > limit) - throw Exception("Framing error: data overrun"); // FIXME aconway 2008-04-03: proper exception. - } - - protected: - Derived& self() { return *static_cast(this); } - void addBytes(size_t n) { - size_t newBytes=bytes+n; - if (newBytes > limit) - throw Exception("Framing error: data overrun"); // FIXME aconway 2008-04-03: proper exception. - bytes = newBytes; - } - - private: - void checkLimit() { - } - - size_t bytes; // how many bytes serialized. - size_t limit; // bytes may not exceed this limit. -}; - -/** - * Base class for encoders, provides generic encode functions. - * - * A derived encoder must provide operator(const T&) to encode all - * primitive types T. - */ -template class EncoderBase : public Serializer { - public: - using Serializer::operator(); - using Serializer::self; - - /** Default op() for non-primitive types. */ - template Derived& operator()(const T& t) { - serializable(const_cast(t)).serialize(self()); return self(); - } - - /** Split serialize() into encode()/decode() */ - template Derived& split(const T& t) { - t.encode(self()); return self(); - } -}; - -/** - * Base class for decoders, provides generic decode functions. - * - * A derived encoder must provide operator(T&) to encode all - * primitive types T. - */ -template class DecoderBase : public Serializer { - public: - using Serializer::operator(); - using Serializer::self; - - /** Default op() for non-primitive types. */ - template Derived& operator()(T& t) { - - serializable(t).serialize(self()); return self(); - } - - /** Split serialize() into encode()/decode() */ - template Derived& split(T& t) { - t.decode(self()); return self(); - } -}; - -/** Serialize a type by converting it to/from another type. - * To serialize type Foo by converting to/from type Bar create - * a serializable() overload like this: - * - * SerializeAs serializable(Foo& t) { return SerializeAs(t); } - */ -template -struct SerializeAs { - Type& value; - SerializeAs(Type & t) : value(t) {} - template void serialize(S& s) { s.split(*this); } - template void encode(S& s) const { s(AsType(value)); } - template void decode(S& s) { AsType x; s(x); value=Type(x); } -}; - -} // namespace qpid - -#endif /*!QPID_SERIALIZER_H*/ diff --git a/qpid/cpp/src/qpid/SessionId.cpp b/qpid/cpp/src/qpid/SessionId.cpp deleted file mode 100644 index c7e83f83d7..0000000000 --- a/qpid/cpp/src/qpid/SessionId.cpp +++ /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. - * - */ - -#include "qpid/SessionId.h" -#include - -namespace qpid { - -SessionId::SessionId(const std::string& u, const std::string& n) : userId(u), name(n) {} - -bool SessionId::operator<(const SessionId& id) const { - return userId < id.userId || (userId == id.userId && name < id.name); -} - -bool SessionId::operator==(const SessionId& id) const { - return id.name == name && id.userId == userId; -} - -std::ostream& operator<<(std::ostream& o, const SessionId& id) { - return o << id.getUserId() << "." << id.getName(); -} - -std::string SessionId::str() const { - std::ostringstream o; - o << *this; - return o.str(); -} - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/SessionId.h b/qpid/cpp/src/qpid/SessionId.h deleted file mode 100644 index d950ad9d1a..0000000000 --- a/qpid/cpp/src/qpid/SessionId.h +++ /dev/null @@ -1,60 +0,0 @@ -#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 -#include -#include - -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 : private boost::totally_ordered1 { - 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/SessionState.cpp b/qpid/cpp/src/qpid/SessionState.cpp deleted file mode 100644 index e5019604d2..0000000000 --- a/qpid/cpp/src/qpid/SessionState.cpp +++ /dev/null @@ -1,287 +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/SessionState.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" -#include -#include - -namespace qpid { -using framing::AMQFrame; -using framing::NotImplementedException; -using framing::InvalidArgumentException; -using framing::IllegalStateException; -using framing::ResourceLimitExceededException; -using framing::InternalErrorException; -using framing::FramingErrorException; - -namespace { -bool isControl(const AMQFrame& f) { - return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_CONTROL; -} -bool isCommand(const AMQFrame& f) { - return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_COMMAND; -} -} // namespace - -SessionPoint::SessionPoint(SequenceNumber c, uint64_t o) : command(c), offset(o) {} - -// TODO aconway 2008-05-22: Do complete frame sequence validity check here, -// currently duplicated betwen broker and client session impl. -// -void SessionPoint::advance(const AMQFrame& f) { - if (isControl(f)) return; // Ignore controls. - if (f.isFirstSegment() && f.isFirstFrame()) { - if (offset != 0) - throw FramingErrorException(QPID_MSG("Unexpected command start frame.")); - if (!isCommand(f)) - throw FramingErrorException( - QPID_MSG("Command start frame has invalid type" << f.getBody()->type())); - if (f.isLastSegment() && f.isLastFrame()) - ++command; // Single-frame command. - else - offset += f.encodedSize(); - } - else { // continuation frame for partial command - if (offset == 0) - throw FramingErrorException(QPID_MSG("Unexpected command continuation frame.")); - if (f.isLastSegment() && f.isLastFrame()) { - ++command; - offset = 0; - } - else { - // TODO aconway 2008-04-24: if we go to support for partial - // command replay, then it may be better to record the unframed - // data size in a command point rather than the framed size so - // that the relationship of fragment offsets to the replay - // list can be computed more easily. - // - offset += f.encodedSize(); - } - } -} - -bool SessionPoint::operator<(const SessionPoint& x) const { - return command < x.command || (command == x.command && offset < x.offset); -} - -bool SessionPoint::operator==(const SessionPoint& x) const { - return command == x.command && offset == x.offset; -} - - -SessionState::SendState::SendState() : unflushedSize(), replaySize(), bytesSinceKnownCompleted() {} - -SessionState::ReceiveState::ReceiveState() : bytesSinceKnownCompleted() {} - -uint32_t SessionState::getTimeout() const { return timeout; } -void SessionState::setTimeout(uint32_t seconds) { timeout = seconds; } - -SessionPoint SessionState::senderGetCommandPoint() { return sender.sendPoint; } -SequenceSet SessionState::senderGetIncomplete() const { return sender.incomplete; } -SessionPoint SessionState::senderGetReplayPoint() const { return sender.replayPoint; } - -SessionState::ReplayRange SessionState::senderExpected(const SessionPoint& expect) { - if (expect < sender.replayPoint || sender.sendPoint < expect) - throw InvalidArgumentException(QPID_MSG(getId() << ": expected command-point out of range.")); - QPID_LOG(debug, getId() << ": sender expected point moved to " << expect); - ReplayList::iterator i = sender.replayList.begin(); - SessionPoint p = sender.replayPoint; - while (i != sender.replayList.end() && p.command < expect.command) - p.advance(*i++); - assert(p.command == expect.command); - return boost::make_iterator_range(i, sender.replayList.end()); -} - -void SessionState::senderRecord(const AMQFrame& f) { - if (isControl(f)) return; // Ignore control frames. - QPID_LOG(trace, getId() << ": sent cmd " << sender.sendPoint.command << ": " << *f.getBody()); - - stateful = true; - if (timeout) sender.replayList.push_back(f); - sender.unflushedSize += f.encodedSize(); - sender.bytesSinceKnownCompleted += f.encodedSize(); - sender.replaySize += f.encodedSize(); - sender.incomplete += sender.sendPoint.command; - sender.sendPoint.advance(f); - if (config.replayHardLimit && config.replayHardLimit < sender.replaySize) - throw ResourceLimitExceededException("Replay buffer exceeeded hard limit"); -} - -static const uint32_t SPONTANEOUS_REQUEST_INTERVAL = 65536; - -bool SessionState::senderNeedFlush() const { - return (sender.sendPoint.command % SPONTANEOUS_REQUEST_INTERVAL == 0) || - (config.replayFlushLimit && sender.unflushedSize >= config.replayFlushLimit); -} - -void SessionState::senderRecordFlush() { - sender.flushPoint = sender.sendPoint; - sender.unflushedSize = 0; -} - -bool SessionState::senderNeedKnownCompleted() const { - return config.replayFlushLimit && sender.bytesSinceKnownCompleted >= config.replayFlushLimit; -} - -void SessionState::senderRecordKnownCompleted() { - sender.bytesSinceKnownCompleted = 0; -} - -void SessionState::senderConfirmed(const SessionPoint& confirmed) { - if (confirmed > sender.sendPoint) - throw InvalidArgumentException(QPID_MSG(getId() << ": confirmed < " << confirmed << " but only sent < " << sender.sendPoint)); - QPID_LOG(debug, getId() << ": sender confirmed point moved to " << confirmed); - ReplayList::iterator i = sender.replayList.begin(); - while (i != sender.replayList.end() && sender.replayPoint.command < confirmed.command) { - sender.replayPoint.advance(*i); - assert(sender.replayPoint <= sender.sendPoint); - sender.replaySize -= i->encodedSize(); - if (sender.replayPoint > sender.flushPoint) - sender.unflushedSize -= i->encodedSize(); - ++i; - } - if (sender.replayPoint > sender.flushPoint) - sender.flushPoint = sender.replayPoint; - sender.replayList.erase(sender.replayList.begin(), i); - assert(sender.replayPoint.offset == 0); -} - -void SessionState::senderCompleted(const SequenceSet& commands) { - if (commands.empty()) return; - QPID_LOG(debug, getId() << ": sender marked completed: " << commands); - sender.incomplete -= commands; - // Completion implies confirmation but we don't handle out-of-order - // confirmation, so confirm up to the end of the first contiguous range of commands. - senderConfirmed(SessionPoint(commands.rangesBegin()->end())); -} - -void SessionState::receiverSetCommandPoint(const SessionPoint& point) { - if (hasState() && point > receiver.received) - throw InvalidArgumentException(QPID_MSG(getId() << ": Command-point out of range.")); - QPID_LOG(debug, getId() << ": receiver command-point set to: " << point); - receiver.expected = point; - if (receiver.expected > receiver.received) - receiver.received = receiver.expected; -} - -bool SessionState::receiverRecord(const AMQFrame& f) { - if (receiverTrackingDisabled) return true; //Very nasty hack for push bridges - if (isControl(f)) return true; // Ignore control frames. - stateful = true; - receiver.expected.advance(f); - receiver.bytesSinceKnownCompleted += f.encodedSize(); - bool firstTime = receiver.expected > receiver.received; - if (firstTime) { - receiver.received = receiver.expected; - receiver.incomplete += receiverGetCurrent(); - } - QPID_LOG(trace, getId() << ": recv cmd " << receiverGetCurrent() << ": " << *f.getBody()); - if (!firstTime) QPID_LOG(trace, "Ignoring duplicate frame."); - return firstTime; -} - -void SessionState::receiverCompleted(SequenceNumber command, bool cumulative) { - if (receiverTrackingDisabled) return; //Very nasty hack for push bridges - assert(receiver.incomplete.contains(command)); // Internal error to complete command twice. - SequenceNumber first =cumulative ? receiver.incomplete.front() : command; - SequenceNumber last = command; - receiver.unknownCompleted.add(first, last); - receiver.incomplete.remove(first, last); - QPID_LOG(debug, getId() << ": receiver marked completed: " << command - << " incomplete: " << receiver.incomplete - << " unknown-completed: " << receiver.unknownCompleted); -} - -void SessionState::receiverKnownCompleted(const SequenceSet& commands) { - if (!commands.empty() && commands.back() > receiver.received.command) - throw InvalidArgumentException(QPID_MSG(getId() << ": Known-completed has invalid commands.")); - receiver.bytesSinceKnownCompleted=0; - receiver.unknownCompleted -= commands; - QPID_LOG(debug, getId() << ": receiver known completed: " << commands << " unknown: " << receiver.unknownCompleted); -} - -bool SessionState::receiverNeedKnownCompleted() const { - return (receiver.expected.command % SPONTANEOUS_REQUEST_INTERVAL == 0) || - (config.replayFlushLimit && receiver.bytesSinceKnownCompleted >= config.replayFlushLimit); -} - -const SessionPoint& SessionState::receiverGetExpected() const { return receiver.expected; } -const SessionPoint& SessionState::receiverGetReceived() const { return receiver.received; } -const SequenceSet& SessionState::receiverGetUnknownComplete() const { return receiver.unknownCompleted; } -const SequenceSet& SessionState::receiverGetIncomplete() const { return receiver.incomplete; } - -SequenceNumber SessionState::receiverGetCurrent() const { - SequenceNumber current = receiver.expected.command; - if (receiver.expected.offset == 0) - --current; - return current; -} - -SessionState::Configuration::Configuration(size_t flush, size_t hard) : - replayFlushLimit(flush), replayHardLimit(hard) {} - -SessionState::SessionState(const SessionId& i, const Configuration& c) - : id(i), timeout(0), config(c), stateful(false), receiverTrackingDisabled(false) -{ - QPID_LOG(debug, "SessionState::SessionState " << id << ": " << this); -} - -bool SessionState::hasState() const { return stateful; } - -SessionState::~SessionState() {} - -std::ostream& operator<<(std::ostream& o, const SessionPoint& p) { - return o << "(" << p.command.getValue() << "+" << p.offset << ")"; -} - -void SessionState::setState( - const SequenceNumber& replayStart, - const SequenceNumber& sendCommandPoint, - const SequenceSet& sentIncomplete, - const SequenceNumber& expected, - const SequenceNumber& received, - const SequenceSet& unknownCompleted, - const SequenceSet& receivedIncomplete -) -{ - sender.replayPoint = replayStart; - sender.flushPoint = sendCommandPoint; - sender.sendPoint = sendCommandPoint; - sender.unflushedSize = 0; - sender.replaySize = 0; // Replay list will be updated separately. - sender.incomplete = sentIncomplete; - sender.bytesSinceKnownCompleted = 0; - - receiver.expected = expected; - receiver.received = received; - receiver.unknownCompleted = unknownCompleted; - receiver.incomplete = receivedIncomplete; - receiver.bytesSinceKnownCompleted = 0; -} - -void SessionState::disableReceiverTracking() { receiverTrackingDisabled = true; } -void SessionState::enableReceiverTracking() { receiverTrackingDisabled = false; } - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/SessionState.h b/qpid/cpp/src/qpid/SessionState.h deleted file mode 100644 index 02853b1143..0000000000 --- a/qpid/cpp/src/qpid/SessionState.h +++ /dev/null @@ -1,235 +0,0 @@ -#ifndef QPID_SESSIONSTATE_H -#define QPID_SESSIONSTATE_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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -using framing::SequenceNumber; -using framing::SequenceSet; - -/** A point in the session. Points to command id + offset */ -struct SessionPoint : boost::totally_ordered1 { - QPID_COMMON_EXTERN SessionPoint(SequenceNumber command = 0, uint64_t offset = 0); - - SequenceNumber command; - uint64_t offset; - - /** Advance past frame f */ - QPID_COMMON_EXTERN void advance(const framing::AMQFrame& f); - - QPID_COMMON_EXTERN bool operator<(const SessionPoint&) const; - QPID_COMMON_EXTERN bool operator==(const SessionPoint&) const; -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const SessionPoint&); - -/** - * Support for session idempotence barrier and resume as defined in - * AMQP 0-10. - * - * We only issue/use contiguous confirmations, out-of-order confirmation - * is ignored. Out of order completion is fully supported. - * - * Raises NotImplemented if the command point is set greater than the - * max currently received command data, either explicitly via - * session.command-point or implicitly via session.gap. - * - * Partial replay is not supported, replay always begins on a command - * boundary, and we never confirm partial commands. - * - * The SessionPoint data structure does store offsets so this class - * could be extended to support partial replay without - * source-incompatbile API changes. - */ -class SessionState { - typedef std::vector ReplayList; - - public: - - typedef boost::iterator_range ReplayRange; - - struct Configuration { - QPID_COMMON_EXTERN Configuration(size_t flush=1024*1024, size_t hard=0); - size_t replayFlushLimit; // Flush when the replay list >= N bytes. 0 disables. - size_t replayHardLimit; // Kill session if replay list > N bytes. 0 disables. - }; - - QPID_COMMON_EXTERN SessionState(const SessionId& =SessionId(), const Configuration& =Configuration()); - - QPID_COMMON_EXTERN virtual ~SessionState(); - - bool hasState() const; - - const SessionId& getId() const { return id; } - - QPID_COMMON_EXTERN virtual uint32_t getTimeout() const; - QPID_COMMON_EXTERN virtual void setTimeout(uint32_t seconds); - - bool operator==(const SessionId& other) const { return id == other; } - bool operator==(const SessionState& other) const { return id == other.id; } - - // ==== Functions for sender state. - - /** Record frame f for replay. Should not be called during replay. */ - QPID_COMMON_EXTERN virtual void senderRecord(const framing::AMQFrame& f); - - /** @return true if we should send flush for confirmed and completed commands. */ - QPID_COMMON_EXTERN virtual bool senderNeedFlush() const; - - /** Called when flush for confirmed and completed commands is sent to peer. */ - QPID_COMMON_EXTERN virtual void senderRecordFlush(); - - /** True if we should reply to the next incoming completed command */ - QPID_COMMON_EXTERN virtual bool senderNeedKnownCompleted() const; - - /** Called when knownCompleted is sent to peer. */ - QPID_COMMON_EXTERN virtual void senderRecordKnownCompleted(); - - /** Called when the peer confirms up to comfirmed. */ - QPID_COMMON_EXTERN virtual void senderConfirmed(const SessionPoint& confirmed); - - /** Called when the peer indicates commands completed */ - QPID_COMMON_EXTERN virtual void senderCompleted(const SequenceSet& commands); - - /** Point from which the next new (not replayed) data will be sent. */ - QPID_COMMON_EXTERN virtual SessionPoint senderGetCommandPoint(); - - /** Set of outstanding incomplete commands */ - QPID_COMMON_EXTERN virtual SequenceSet senderGetIncomplete() const; - - /** Point from which we can replay. */ - QPID_COMMON_EXTERN virtual SessionPoint senderGetReplayPoint() const; - - /** Peer expecting commands from this point. - *@return Range of frames to be replayed. - */ - QPID_COMMON_EXTERN virtual ReplayRange senderExpected(const SessionPoint& expected); - - // ==== Functions for receiver state - - /** Set the command point. */ - QPID_COMMON_EXTERN virtual void receiverSetCommandPoint(const SessionPoint& point); - - /** Returns true if frame should be be processed, false if it is a duplicate. */ - QPID_COMMON_EXTERN virtual bool receiverRecord(const framing::AMQFrame& f); - - /** Command completed locally */ - QPID_COMMON_EXTERN virtual void receiverCompleted(SequenceNumber command, bool cumulative=false); - - /** Peer has indicated commands are known completed */ - QPID_COMMON_EXTERN virtual void receiverKnownCompleted(const SequenceSet& commands); - - /** True if the next completed control should set the timely-reply argument - * to request a knonw-completed response. - */ - QPID_COMMON_EXTERN virtual bool receiverNeedKnownCompleted() const; - - /** Get the incoming command point */ - QPID_COMMON_EXTERN virtual const SessionPoint& receiverGetExpected() const; - - /** Get the received high-water-mark, may be > getExpected() during replay */ - QPID_COMMON_EXTERN virtual const SessionPoint& receiverGetReceived() const; - - /** Completed received commands that the peer may not know about. */ - QPID_COMMON_EXTERN virtual const SequenceSet& receiverGetUnknownComplete() const; - - /** Incomplete received commands. */ - QPID_COMMON_EXTERN virtual const SequenceSet& receiverGetIncomplete() const; - - /** ID of the command currently being handled. */ - QPID_COMMON_EXTERN virtual SequenceNumber receiverGetCurrent() const; - - /** Set the state variables, used to create a session that will resume - * from some previously established point. - */ - QPID_COMMON_EXTERN virtual void setState( - const SequenceNumber& replayStart, - const SequenceNumber& sendCommandPoint, - const SequenceSet& sentIncomplete, - const SequenceNumber& expected, - const SequenceNumber& received, - const SequenceSet& unknownCompleted, - const SequenceSet& receivedIncomplete - ); - - /** - * So called 'push' bridges work by faking a subscribe request - * (and the accompanying flows etc) to the local broker to initiate - * the outflow of messages for the bridge. - * - * As the peer doesn't send these it cannot include them in its - * session state. To keep the session state on either side of the - * bridge in sync, this hack allows the tracking of state for - * received messages to be disabled for the faked commands and - * subsequently re-enabled. - */ - QPID_COMMON_EXTERN void disableReceiverTracking(); - QPID_COMMON_EXTERN void enableReceiverTracking(); - - private: - - struct SendState { - SendState(); - // invariant: replayPoint <= flushPoint <= sendPoint - SessionPoint replayPoint; // Can replay from this point - SessionPoint flushPoint; // Point of last flush - SessionPoint sendPoint; // Send from this point - ReplayList replayList; // Starts from replayPoint. - size_t unflushedSize; // Un-flushed bytes in replay list. - size_t replaySize; // Total bytes in replay list. - SequenceSet incomplete; // Commands sent and not yet completed. - size_t bytesSinceKnownCompleted; // Bytes sent since we last issued a knownCompleted. - } sender; - - struct ReceiveState { - ReceiveState(); - SessionPoint expected; // Expected from here - SessionPoint received; // Received to here. Invariant: expected <= received. - SequenceSet unknownCompleted; // Received & completed, may not not known-complete by peer. - SequenceSet incomplete; // Incomplete received commands. - size_t bytesSinceKnownCompleted; // Bytes sent since we last issued a knownCompleted. - } receiver; - - SessionId id; - uint32_t timeout; - Configuration config; - bool stateful; - bool receiverTrackingDisabled;//very nasty hack for 'push' bridges -}; - -inline bool operator==(const SessionId& id, const SessionState& s) { return s == id; } - -} // namespace qpid - - -#endif /*!QPID_SESSIONSTATE_H*/ diff --git a/qpid/cpp/src/qpid/SharedObject.h b/qpid/cpp/src/qpid/SharedObject.h deleted file mode 100644 index 852a036ab9..0000000000 --- a/qpid/cpp/src/qpid/SharedObject.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _SharedObject_ -#define _SharedObject_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 -#include - -namespace qpid { - /** - * Template to enforce shared object conventions. - * Shared object classes should inherit : public qpid::SharedObject - * That ensures Foo: - * - has typedef boost::shared_ptr shared_ptr - * - has virtual destructor - * - is boost::noncopyable (no default copy or assign) - * - has a protected default constructor. - * - * Shared objects should not have public constructors. - * Make constructors protected and provide public statc create() - * functions that return a shared_ptr. - */ - template - class SharedObject : private boost::noncopyable - { - public: - typedef boost::shared_ptr shared_ptr; - - virtual ~SharedObject() {}; - - protected: - SharedObject() {} - }; -} - -#endif /*!_SharedObject_*/ diff --git a/qpid/cpp/src/qpid/StringUtils.cpp b/qpid/cpp/src/qpid/StringUtils.cpp deleted file mode 100644 index c436441c56..0000000000 --- a/qpid/cpp/src/qpid/StringUtils.cpp +++ /dev/null @@ -1,50 +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/StringUtils.h" - -namespace qpid { - -using std::string; -using std::vector; - -void split(vector& out, const string& in, const string& delims) -{ - string::size_type start = in.find_first_not_of(delims); - if (start == string::npos) return; - - string::size_type end = in.find_first_of(delims, start); - while (end != string::npos) { - out.push_back(in.substr(start, end - start)); - start = in.find_first_not_of(delims, end); - if (start == string::npos) return; - end = in.find_first_of(delims, start); - } - out.push_back(in.substr(start)); -} - -vector split(const string& in, const string& delims) -{ - vector out; - split(out, in, delims); - return out; -} - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/StringUtils.h b/qpid/cpp/src/qpid/StringUtils.h deleted file mode 100644 index 4130fae017..0000000000 --- a/qpid/cpp/src/qpid/StringUtils.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_STRINGUTILS_H -#define QPID_STRINGUTILS_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 -#include - -namespace qpid { - -/** - * Split 'in' into words using delimiters in 'delims' and put - * resulting strings into 'out' vector. - */ -QPID_COMMON_EXTERN void split(std::vector& out, const std::string& in, const std::string& delims); -/** - * Split 'in' into words using delimiters in 'delims' and return the - * resulting strings in a vector. - */ -QPID_COMMON_EXTERN std::vector split(const std::string& in, const std::string& delims); - -} // namespace qpid - -#endif /*!QPID_STRINGUTILS_H*/ diff --git a/qpid/cpp/src/qpid/Url.cpp b/qpid/cpp/src/qpid/Url.cpp deleted file mode 100644 index 1780a07f92..0000000000 --- a/qpid/cpp/src/qpid/Url.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - * - * 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/Url.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/StrError.h" -#include "qpid/client/Connector.h" -#include "qpid/sys/Mutex.h" -#include - -#include -#include -#include - -#include - -using namespace std; -using boost::lexical_cast; - -namespace qpid { - -class ProtocolTags { - public: - bool find(const string& tag) { - sys::Mutex::ScopedLock l(lock); - return std::find(tags.begin(), tags.end(), tag) != tags.end(); - } - - void add(const string& tag) { - sys::Mutex::ScopedLock l(lock); - if (std::find(tags.begin(), tags.end(), tag) == tags.end()) - tags.push_back(tag); - } - - static ProtocolTags& instance() { - /** First call must be made while program is still single threaded. - * This will be the case since tags are registered in static initializers. - */ - static ProtocolTags tags; - return tags; - } - - private: - sys::Mutex lock; - vector tags; -}; - -Url::Invalid::Invalid(const string& s) : Exception(s) {} - -string Url::str() const { - if (cache.empty() && !this->empty()) { - ostringstream os; - os << *this; - cache = os.str(); - } - return cache; -} - -ostream& operator<<(ostream& os, const Url& url) { - os << "amqp:"; - if (!url.getUser().empty()) os << url.getUser(); - if (!url.getPass().empty()) os << "/" << url.getPass(); - if (!(url.getUser().empty() && url.getPass().empty())) os << "@"; - Url::const_iterator i = url.begin(); - if (i!=url.end()) { - os << *i++; - while (i != url.end()) - os << "," << *i++; - } - return os; -} - -static const std::string TCP = "tcp"; - -/** Simple recursive-descent parser for this grammar: -url = ["amqp:"][ user ["/" password] "@" ] protocol_addr *("," protocol_addr) -protocol_addr = tcp_addr / rmda_addr / ssl_addr / .. others plug-in -tcp_addr = ["tcp:"] host [":" port] -rdma_addr = "rdma:" host [":" port] -ssl_addr = "ssl:" host [":" port] -*/ -class UrlParser { - public: - UrlParser(Url& u, const char* s, const std::string& defaultProtocol_=Address::TCP) : url(u), text(s), end(s+strlen(s)), i(s), - defaultProtocol(defaultProtocol_) {} - bool parse() { - literal("amqp:"); // Optional - userPass(); // Optional - return list(&UrlParser::protocolAddr, &UrlParser::comma) && i == end; - } - - private: - typedef bool (UrlParser::*Rule)(); - - bool userPass() { - const char* at = std::find(i, end, '@'); - if (at == end) return false; - const char* slash = std::find(i, at, '/'); - const char* colon = std::find(i, at, ':'); - const char* sep = std::min(slash, colon); - url.setUser(string(i, sep)); - const char* pass = (sep == at) ? sep : sep+1; - url.setPass(string(pass, at)); - i = at+1; - return true; - } - - bool comma() { return literal(","); } - - bool protocolAddr() { - Address addr(defaultProtocol, "", Address::AMQP_PORT); // Set up defaults - protocolTag(addr.protocol); // Optional - bool ok = (host(addr.host) && - (literal(":") ? port(addr.port) : true)); - if (ok) url.push_back(addr); - return ok; - } - - bool protocolTag(string& result) { - const char* j = std::find(i,end,':'); - if (j != end) { - string tag(i,j); - if (ProtocolTags::instance().find(tag)) { - i = j+1; - result = tag; - return true; - } - } - return false; - } - - // A liberal interpretation of http://www.ietf.org/rfc/rfc3986.txt. - // Works for DNS names and and ipv4 and ipv6 literals - // - bool host(string& h) { - if (ip6literal(h)) return true; - - const char* start=i; - while (unreserved() || pctEncoded()) - ; - if (start == i) return false;//host is required - else h.assign(start, i); - return true; - } - - // This is a bit too liberal for IPv6 literal addresses, but probably good enough - bool ip6literal(string& h) { - if (literal("[")) { - const char* start = i; - while (hexDigit() || literal(":") || literal(".")) - ; - const char* end = i; - if ( end-start < 2 ) return false; // Smallest valid address is "::" - if (literal("]")) { - h.assign(start, end); - return true; - } - } - return false; - } - - bool unreserved() { return (::isalnum(*i) || ::strchr("-._~", *i)) && advance(); } - - bool pctEncoded() { return literal("%") && hexDigit() && hexDigit(); } - - bool hexDigit() { return i < end && ::strchr("01234567890abcdefABCDEF", *i) && advance(); } - - bool port(uint16_t& p) { return decimalInt(p); } - - template bool decimalInt(IntType& n) { - const char* start = i; - while (decDigit()) - ; - try { - n = lexical_cast(string(start, i)); - return true; - } catch(...) { return false; } - } - - bool decDigit() { return i < end && ::isdigit(*i) && advance(); } - - bool literal(const char* s) { - int n = ::strlen(s); - if (n <= end-i && equal(s, s+n, i)) return advance(n); - return false; - }; - - bool noop() { return true; } - - /** List of item, separated by separator, with min & max bounds. */ - bool list(Rule item, Rule separator, size_t min=0, size_t max=UNLIMITED) { - assert(max > 0); - assert(max >= min); - if (!(this->*item)()) return min == 0; // Empty list. - size_t n = 1; - while (n < max && i < end) { - if (!(this->*separator)()) break; - if (i == end || !(this->*item)()) return false; // Separator with no item. - ++n; - } - return n >= min; - } - - /** List of items with no separator */ - bool list(Rule item, size_t min=0, size_t max=UNLIMITED) { return list(item, &UrlParser::noop, min, max); } - - bool advance(size_t n=1) { - if (i+n > end) return false; - i += n; - return true; - } - - static const size_t UNLIMITED = size_t(~1); - static const std::string LOCALHOST; - - Url& url; - const char* text; - const char* end; - const char* i; - const std::string defaultProtocol; -}; - -const string UrlParser::LOCALHOST("127.0.0.1"); - -void Url::parse(const char* url) { - parse(url, Address::TCP); -} -void Url::parse(const char* url, const std::string& defaultProtocol) { - parseNoThrow(url, defaultProtocol); - if (empty()) - throw Url::Invalid(QPID_MSG("Invalid URL: " << url)); -} - -void Url::parseNoThrow(const char* url) { - parseNoThrow(url, Address::TCP); -} - -void Url::parseNoThrow(const char* url, const std::string& defaultProtocol) { - clear(); - cache.clear(); - if (!UrlParser(*this, url, defaultProtocol).parse()) - clear(); -} - -void Url::throwIfEmpty() const { - if (empty()) - throw Url::Invalid("URL contains no addresses"); -} - -std::string Url::getUser() const { return user; } -std::string Url::getPass() const { return pass; } -void Url::setUser(const std::string& s) { user = s; } -void Url::setPass(const std::string& s) { pass = s; } - -std::istream& operator>>(std::istream& is, Url& url) { - std::string s; - is >> s; - url.parse(s); - return is; -} - -void Url::addProtocol(const std::string& tag) { ProtocolTags::instance().add(tag); } - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/Url.h b/qpid/cpp/src/qpid/Url.h deleted file mode 100644 index f9ed87c24b..0000000000 --- a/qpid/cpp/src/qpid/Url.h +++ /dev/null @@ -1,96 +0,0 @@ -#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 -#include -#include -#include -#include "qpid/CommonImportExport.h" - -namespace qpid { - -/** An AMQP URL contains a list of addresses */ -struct Url : public std::vector
{ - - 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/UrlArray.cpp b/qpid/cpp/src/qpid/UrlArray.cpp deleted file mode 100644 index 9ebacbd945..0000000000 --- a/qpid/cpp/src/qpid/UrlArray.cpp +++ /dev/null @@ -1,43 +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 "UrlArray.h" - -#include - -namespace qpid { - -std::vector urlArrayToVector(const framing::Array& array) { - std::vector urls; - for (framing::Array::ValueVector::const_iterator i = array.begin(); - i != array.end(); - ++i ) - urls.push_back(Url((*i)->get())); - return urls; -} - -framing::Array vectorToUrlArray(const std::vector& urls) { - framing::Array array(0x95); - for (std::vector::const_iterator i = urls.begin(); i != urls.end(); ++i) - array.add(boost::shared_ptr(new framing::Str16Value(i->str()))); - return array; -} - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/UrlArray.h b/qpid/cpp/src/qpid/UrlArray.h deleted file mode 100644 index f0065f0f0c..0000000000 --- a/qpid/cpp/src/qpid/UrlArray.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef QPID_URLARRAY_H -#define QPID_URLARRAY_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/Array.h" -#include "qpid/Url.h" -#include - -namespace qpid { - -/** @file Functions to encode/decode an array of URLs. */ -QPID_COMMON_EXTERN std::vector urlArrayToVector(const framing::Array& array); -QPID_COMMON_EXTERN framing::Array vectorToUrlArray(const std::vector& urls); -} // namespace qpid - -#endif /* !QPID_URLARRAY_H */ diff --git a/qpid/cpp/src/qpid/Version.h b/qpid/cpp/src/qpid/Version.h deleted file mode 100755 index 6a06566907..0000000000 --- a/qpid/cpp/src/qpid/Version.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef QPID_VERSION_H -#define QPID_VERSION_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 - -#include "config.h" - -namespace qpid { - const std::string product = PACKAGE_NAME; - const std::string version = PACKAGE_VERSION; -# if HAVE_SASL - const std::string saslName = BROKER_SASL_NAME; -# else - const std::string saslName = "qpidd-no-sasl"; -# endif -} - -#endif /*!QPID_VERSION_H*/ diff --git a/qpid/cpp/src/qpid/acl/Acl.cpp b/qpid/cpp/src/qpid/acl/Acl.cpp deleted file mode 100644 index bd9482ef41..0000000000 --- a/qpid/cpp/src/qpid/acl/Acl.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* - * - * 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/acl/Acl.h" -#include "qpid/acl/AclConnectionCounter.h" -#include "qpid/acl/AclResourceCounter.h" -#include "qpid/acl/AclData.h" -#include "qpid/acl/AclValidator.h" -#include "qpid/sys/Mutex.h" - -#include "qpid/broker/Broker.h" -#include "qpid/broker/Connection.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/log/Logger.h" -#include "qpid/types/Variant.h" -#include "qmf/org/apache/qpid/acl/ArgsAclLookup.h" -#include "qmf/org/apache/qpid/acl/ArgsAclLookupPublish.h" -#include "qmf/org/apache/qpid/acl/Package.h" -#include "qmf/org/apache/qpid/acl/EventAllow.h" -#include "qmf/org/apache/qpid/acl/EventConnectionDeny.h" -#include "qmf/org/apache/qpid/acl/EventQueueQuotaDeny.h" -#include "qmf/org/apache/qpid/acl/EventDeny.h" -#include "qmf/org/apache/qpid/acl/EventFileLoaded.h" -#include "qmf/org/apache/qpid/acl/EventFileLoadFailed.h" - -#include - -#include - -using namespace std; -using namespace qpid::acl; -using qpid::broker::Broker; -using namespace qpid::sys; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::acl; - -Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(false), - connectionCounter(new ConnectionCounter(*this, aclValues.aclMaxConnectPerUser, aclValues.aclMaxConnectPerIp, aclValues.aclMaxConnectTotal)), - resourceCounter(new ResourceCounter(*this, aclValues.aclMaxQueuesPerUser)),userRules(false) -{ - - if (aclValues.aclMaxConnectPerUser > AclData::getConnectMaxSpec()) - throw Exception("--connection-limit-per-user switch cannot be larger than " + AclData::getMaxConnectSpecStr()); - if (aclValues.aclMaxConnectPerIp > AclData::getConnectMaxSpec()) - throw Exception("--connection-limit-per-ip switch cannot be larger than " + AclData::getMaxConnectSpecStr()); - if (aclValues.aclMaxConnectTotal > AclData::getConnectMaxSpec()) - throw Exception("--max-connections switch cannot be larger than " + AclData::getMaxConnectSpecStr()); - if (aclValues.aclMaxQueuesPerUser > AclData::getConnectMaxSpec()) - throw Exception("--max-queues-per-user switch cannot be larger than " + AclData::getMaxQueueSpecStr()); - - agent = broker->getManagementAgent(); - - if (agent != 0) { - _qmf::Package packageInit(agent); - mgmtObject = _qmf::Acl::shared_ptr(new _qmf::Acl (agent, this, broker)); - agent->addObject (mgmtObject); - mgmtObject->set_maxConnections(aclValues.aclMaxConnectTotal); - mgmtObject->set_maxConnectionsPerIp(aclValues.aclMaxConnectPerIp); - mgmtObject->set_maxConnectionsPerUser(aclValues.aclMaxConnectPerUser); - mgmtObject->set_maxQueuesPerUser(aclValues.aclMaxQueuesPerUser); - } - - if (!aclValues.aclFile.empty()) { - std::string errorString; - if (!readAclFile(errorString)){ - if (mgmtObject!=0) mgmtObject->set_enforcingAcl(0); - throw Exception("Could not read ACL file " + errorString); - } - } else { - loadEmptyAclRuleset(); - QPID_LOG(debug, "ACL loaded empty rule set"); - } - broker->getConnectionObservers().add(connectionCounter); - QPID_LOG(info, "ACL Plugin loaded"); - if (mgmtObject!=0) mgmtObject->set_enforcingAcl(1); -} - - -void Acl::reportConnectLimit(const std::string user, const std::string addr) -{ - if (mgmtObject!=0) - mgmtObject->inc_connectionDenyCount(); - - if (agent != 0) { - agent->raiseEvent(_qmf::EventConnectionDeny(user, addr)); - } -} - - -void Acl::reportQueueLimit(const std::string user, const std::string queueName) -{ - if (mgmtObject!=0) - mgmtObject->inc_queueQuotaDenyCount(); - - if (agent != 0) { - agent->raiseEvent(_qmf::EventQueueQuotaDeny(user, queueName)); - } -} - - -bool Acl::authorise( - const std::string& id, - const Action& action, - const ObjectType& objType, - const std::string& name, - std::map* params) -{ - boost::shared_ptr dataLocal; - { - Mutex::ScopedLock locker(dataLock); - dataLocal = data; //rcu copy - } - - // add real ACL check here... - AclResult aclreslt = dataLocal->lookup(id,action,objType,name,params); - - - return result(aclreslt, id, action, objType, name); -} - -bool Acl::authorise( - const std::string& id, - const Action& action, - const ObjectType& objType, - const std::string& ExchangeName, - const std::string& RoutingKey) -{ - boost::shared_ptr dataLocal; - { - Mutex::ScopedLock locker(dataLock); - dataLocal = data; //rcu copy - } - - // only use dataLocal here... - AclResult aclreslt = dataLocal->lookup(id,action,objType,ExchangeName,RoutingKey); - - return result(aclreslt, id, action, objType, ExchangeName); -} - - -bool Acl::approveConnection(const qpid::broker::Connection& conn) -{ - const std::string& userName(conn.getUserId()); - uint16_t connectionLimit(0); - - boost::shared_ptr dataLocal; - { - Mutex::ScopedLock locker(dataLock); - dataLocal = data; //rcu copy - } - - (void) dataLocal->getConnQuotaForUser(userName, &connectionLimit); - - return connectionCounter->approveConnection( - conn, - userName, - dataLocal->enforcingConnectionQuotas(), - connectionLimit, - dataLocal); -} - -bool Acl::approveCreateQueue(const std::string& userId, const std::string& queueName) -{ -// return resourceCounter->approveCreateQueue(userId, queueName); - uint16_t queueLimit(0); - - boost::shared_ptr dataLocal; - { - Mutex::ScopedLock locker(dataLock); - dataLocal = data; //rcu copy - } - - (void) dataLocal->getQueueQuotaForUser(userId, &queueLimit); - - return resourceCounter->approveCreateQueue(userId, queueName, dataLocal->enforcingQueueQuotas(), queueLimit); -} - - -void Acl::recordDestroyQueue(const std::string& queueName) -{ - resourceCounter->recordDestroyQueue(queueName); -} - - -bool Acl::result( - const AclResult& aclreslt, - const std::string& id, - const Action& action, - const ObjectType& objType, - const std::string& name) -{ - bool result(false); - - switch (aclreslt) - { - case ALLOWLOG: - QPID_LOG(info, "ACL Allow id:" << id - << " action:" << AclHelper::getActionStr(action) - << " ObjectType:" << AclHelper::getObjectTypeStr(objType) - << " Name:" << name ); - if (agent != 0) { - agent->raiseEvent(_qmf::EventAllow(id, AclHelper::getActionStr(action), - AclHelper::getObjectTypeStr(objType), - name, types::Variant::Map())); - } - // FALLTHROUGH - case ALLOW: - result = true; - break; - - case DENYLOG: - QPID_LOG(info, "ACL Deny id:" << id - << " action:" << AclHelper::getActionStr(action) - << " ObjectType:" << AclHelper::getObjectTypeStr(objType) - << " Name:" << name); - if (agent != 0) { - agent->raiseEvent(_qmf::EventDeny(id, AclHelper::getActionStr(action), - AclHelper::getObjectTypeStr(objType), - name, types::Variant::Map())); - } - // FALLTHROUGH - case DENY: - if (mgmtObject!=0) - mgmtObject->inc_aclDenyCount(); - result = false; - break; - - default: - assert (false); - } - - return result; -} - -bool Acl::readAclFile(std::string& errorText) -{ - // only set transferAcl = true if a rule implies the use of ACL on transfer, else keep false for performance reasons. - return readAclFile(aclValues.aclFile, errorText); -} - -bool Acl::readAclFile(std::string& aclFile, std::string& errorText) { - boost::shared_ptr d(new AclData); - AclReader ar(aclValues.aclMaxConnectPerUser, aclValues.aclMaxQueuesPerUser); - if (ar.read(aclFile, d)){ - if (agent != 0) { - agent->raiseEvent(_qmf::EventFileLoadFailed("", ar.getError())); - } - errorText = ar.getError(); - QPID_LOG(error,ar.getError()); - return false; - } - - AclValidator validator; - validator.validate(d); - - { - Mutex::ScopedLock locker(dataLock); - data = d; - } - transferAcl = data->transferAcl; // any transfer ACL - userRules = true; // rules in force came from an ACL file - - if (data->transferAcl){ - QPID_LOG(debug,"ACL: Transfer ACL is Enabled!"); - } - - if (data->enforcingConnectionQuotas()){ - QPID_LOG(debug, "ACL: Connection quotas are Enabled."); - } - - if (data->enforcingQueueQuotas()){ - QPID_LOG(debug, "ACL: Queue quotas are Enabled."); - } - - QPID_LOG(debug, "ACL: Default connection mode : " - << AclHelper::getAclResultStr(d->connectionMode())); - - data->aclSource = aclFile; - if (mgmtObject!=0){ - mgmtObject->set_transferAcl(transferAcl?1:0); - mgmtObject->set_policyFile(aclFile); - mgmtObject->set_lastAclLoad(Duration::FromEpoch()); - if (agent != 0) { - agent->raiseEvent(_qmf::EventFileLoaded("")); - } - } - return true; -} - -// -// loadEmptyAclRuleset() -// -// No ACL file is specified but ACL should run. -// Create a ruleset as if only "ACL ALLOW ALL ALL" was in a file -// -void Acl::loadEmptyAclRuleset() { - boost::shared_ptr d(new AclData); - d->decisionMode = ALLOW; - d->aclSource = ""; - d->connectionDecisionMode = ALLOW; - { - Mutex::ScopedLock locker(dataLock); - data = d; - } - if (mgmtObject!=0){ - mgmtObject->set_transferAcl(transferAcl?1:0); - mgmtObject->set_policyFile(""); - mgmtObject->set_lastAclLoad(Duration::FromEpoch()); - if (agent != 0) { - agent->raiseEvent(_qmf::EventFileLoaded("")); - } - } -} - -// -// management lookup function performs general query on acl engine -// -Manageable::status_t Acl::lookup(qpid::management::Args& args, std::string& text) -{ - _qmf::ArgsAclLookup& ioArgs = (_qmf::ArgsAclLookup&) args; - Manageable::status_t result(STATUS_USER); - - try { - ObjectType objType = AclHelper::getObjectType(ioArgs.i_object); - Action action = AclHelper::getAction( ioArgs.i_action); - std::map propertyMap; - for (::qpid::types::Variant::Map::const_iterator - iMapIter = ioArgs.i_propertyMap.begin(); - iMapIter != ioArgs.i_propertyMap.end(); - iMapIter++) - { - Property property = AclHelper::getProperty(iMapIter->first); - propertyMap.insert(make_pair(property, iMapIter->second)); - } - - boost::shared_ptr dataLocal; - { - Mutex::ScopedLock locker(dataLock); - dataLocal = data; //rcu copy - } - AclResult aclResult; - // CREATE CONNECTION does not use lookup() - if (action == ACT_CREATE && objType == OBJ_CONNECTION) { - std::string host = propertyMap[acl::PROP_HOST]; - std::string logString; - aclResult = dataLocal->isAllowedConnection( - ioArgs.i_userId, - host, - logString); - } else { - aclResult = dataLocal->lookup( - ioArgs.i_userId, - action, - objType, - ioArgs.i_objectName, - &propertyMap); - } - ioArgs.o_result = AclHelper::getAclResultStr(aclResult); - result = STATUS_OK; - - } catch (const std::exception& e) { - std::ostringstream oss; - oss << "AclLookup invalid name : " << e.what(); - ioArgs.o_result = oss.str(); - text = oss.str(); - } - - return result; -} - - -// -// management lookupPublish function performs fastpath -// PUBLISH EXCHANGE query on acl engine -// -Manageable::status_t Acl::lookupPublish(qpid::management::Args& args, std::string& /*text*/) -{ - _qmf::ArgsAclLookupPublish& ioArgs = (_qmf::ArgsAclLookupPublish&) args; - boost::shared_ptr dataLocal; - { - Mutex::ScopedLock locker(dataLock); - dataLocal = data; //rcu copy - } - AclResult aclResult = dataLocal->lookup( - ioArgs.i_userId, - ACT_PUBLISH, - OBJ_EXCHANGE, - ioArgs.i_exchangeName, - ioArgs.i_routingKey); - - ioArgs.o_result = AclHelper::getAclResultStr(aclResult); - - return STATUS_OK; -} - - -Acl::~Acl(){ - broker->getConnectionObservers().remove(connectionCounter); -} - -ManagementObject::shared_ptr Acl::GetManagementObject(void) const -{ - return mgmtObject; -} - -Manageable::status_t Acl::ManagementMethod (uint32_t methodId, Args& args, string& text) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - QPID_LOG (debug, "ACL: Queue::ManagementMethod [id=" << methodId << "]"); - - switch (methodId) - { - case _qmf::Acl::METHOD_RELOADACLFILE : - readAclFile(text); - if (text.empty()) - status = Manageable::STATUS_OK; - else - status = Manageable::STATUS_USER; - break; - - case _qmf::Acl::METHOD_LOOKUP : - status = lookup(args, text); - break; - - case _qmf::Acl::METHOD_LOOKUPPUBLISH : - status = lookupPublish(args, text); - break; - } - - return status; -} diff --git a/qpid/cpp/src/qpid/acl/Acl.h b/qpid/cpp/src/qpid/acl/Acl.h deleted file mode 100644 index df2fb66c82..0000000000 --- a/qpid/cpp/src/qpid/acl/Acl.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef QPID_ACL_ACL_H -#define QPID_ACL_ACL_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/acl/AclReader.h" -#include "qpid/AclHost.h" -#include "qpid/RefCounted.h" -#include "qpid/broker/AclModule.h" -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/acl/Acl.h" -#include "qpid/sys/Mutex.h" - -#include -#include -#include - - -namespace qpid { -namespace broker { -class Broker; -class Connection; -} - -namespace acl { -class ConnectionCounter; -class ResourceCounter; - -struct AclValues { - std::string aclFile; - uint16_t aclMaxConnectPerUser; - uint16_t aclMaxConnectPerIp; - uint16_t aclMaxConnectTotal; - uint16_t aclMaxQueuesPerUser; -}; - - -class Acl : public broker::AclModule, public RefCounted, public management::Manageable -{ - -private: - acl::AclValues aclValues; - broker::Broker* broker; - bool transferAcl; - boost::shared_ptr data; - qmf::org::apache::qpid::acl::Acl::shared_ptr mgmtObject; - qpid::management::ManagementAgent* agent; - mutable qpid::sys::Mutex dataLock; - boost::shared_ptr connectionCounter; - boost::shared_ptr resourceCounter; - bool userRules; - -public: - Acl (AclValues& av, broker::Broker& b); - - /** reportConnectLimit - * issue management counts and alerts for denied connections - */ - void reportConnectLimit(const std::string user, const std::string addr); - void reportQueueLimit(const std::string user, const std::string queueName); - - inline virtual bool doTransferAcl() { - return transferAcl; - }; - - inline virtual uint16_t getMaxConnectTotal() { - return aclValues.aclMaxConnectTotal; - }; - - inline virtual bool userAclRules() { - return userRules; - }; - -// create specilied authorise methods for cases that need faster matching as needed. - virtual bool authorise( - const std::string& id, - const Action& action, - const ObjectType& objType, - const std::string& name, - std::map* params=0); - - virtual bool authorise( - const std::string& id, - const Action& action, - const ObjectType& objType, - const std::string& ExchangeName, - const std::string& RoutingKey); - - // Resource quota tracking - virtual bool approveConnection(const broker::Connection& connection); - virtual bool approveCreateQueue(const std::string& userId, const std::string& queueName); - virtual void recordDestroyQueue(const std::string& queueName); - - virtual ~Acl(); -private: - bool result( - const AclResult& aclreslt, - const std::string& id, - const Action& action, - const ObjectType& objType, - const std::string& name); - bool readAclFile(std::string& errorText); - bool readAclFile(std::string& aclFile, std::string& errorText); - void loadEmptyAclRuleset(); - Manageable::status_t lookup (management::Args& args, std::string& text); - Manageable::status_t lookupPublish(management::Args& args, std::string& text); - virtual qpid::management::ManagementObject::shared_ptr GetManagementObject(void) const; - virtual management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args, std::string& text); - -}; - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACL_H diff --git a/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp b/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp deleted file mode 100644 index ca3da50088..0000000000 --- a/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp +++ /dev/null @@ -1,320 +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 "AclConnectionCounter.h" -#include "Acl.h" -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/SocketAddress.h" -#include -#include - -using namespace qpid::sys; - -namespace qpid { -namespace acl { - -// -// This module instantiates a broker::ConnectionObserver and limits client -// connections by counting connections per user name, per client IP address -// and per total connection count. -// - - -// -// -// -ConnectionCounter::ConnectionCounter(Acl& a, uint16_t nl, uint16_t hl, uint16_t tl) : - acl(a), nameLimit(nl), hostLimit(hl), totalLimit(tl), totalCurrentConnections(0) {} - -ConnectionCounter::~ConnectionCounter() {} - - -// -// limitApproveLH -// -// Connection creation approver. Return true only if user is under limit. -// Called with lock held. -// -bool ConnectionCounter::limitApproveLH( - connectCountsMap_t& theMap, - const std::string& theName, - uint16_t theLimit, - bool emitLog) { - - bool result(true); - if (theLimit > 0) { - uint16_t count; - connectCountsMap_t::iterator eRef = theMap.find(theName); - if (eRef != theMap.end()) { - count = (uint16_t)(*eRef).second; - result = count <= theLimit; - } else { - // Not found - count = 0; - } - if (emitLog) { - QPID_LOG(trace, "ACL ConnectionApprover IP=" << theName - << " limit=" << theLimit - << " curValue=" << count - << " result=" << (result ? "allow" : "deny")); - } - } - return result; -} - - -// -// countConnectionLH -// -// Increment the name's count in map and return an optional comparison -// against a connection limit. -// Called with dataLock already taken. -// -bool ConnectionCounter::countConnectionLH( - connectCountsMap_t& theMap, - const std::string& theName, - uint16_t theLimit, - bool emitLog, - bool enforceLimit) { - - bool result(true); - uint16_t count(0); - connectCountsMap_t::iterator eRef = theMap.find(theName); - if (eRef != theMap.end()) { - count = (uint16_t)(*eRef).second + 1; - (*eRef).second = count; - } else { - theMap[theName] = count = 1; - } - if (enforceLimit) { - result = count <= theLimit; - } - if (emitLog) { - QPID_LOG(trace, "ACL ConnectionApprover user=" << theName - << " limit=" << theLimit - << " curValue=" << count - << " result=" << (result ? "allow" : "deny")); - } - return result; -} - - -// -// releaseLH -// -// Decrement the name's count in map. -// called with dataLock already taken -// -void ConnectionCounter::releaseLH( - connectCountsMap_t& theMap, const std::string& theName) { - - connectCountsMap_t::iterator eRef = theMap.find(theName); - if (eRef != theMap.end()) { - uint16_t count = (uint16_t) (*eRef).second; - assert (count > 0); - if (1 == count) { - theMap.erase (eRef); - } else { - (*eRef).second = count - 1; - } - } else { - // User had no connections. - // Connections denied by ACL never get users added - //QPID_LOG(notice, "ACL ConnectionCounter Connection for '" << theName - // << "' not found in connection count pool"); - } -} - - -// -// connection - called during Connection's constructor -// -void ConnectionCounter::connection(broker::Connection& connection) { - QPID_LOG(trace, "ACL ConnectionCounter new connection: " << connection.getMgmtId()); - - const std::string& hostName(getClientHost(connection.getMgmtId())); - - Mutex::ScopedLock locker(dataLock); - - // Total connections goes up - totalCurrentConnections += 1; - - // Record the fact that this connection exists - connectProgressMap[connection.getMgmtId()] = C_CREATED; - - // Count the connection from this host. - (void) countConnectionLH(connectByHostMap, hostName, hostLimit, false, false); -} - - -// -// closed - called during Connection's destructor -// -void ConnectionCounter::closed(broker::Connection& connection) { - QPID_LOG(trace, "ACL ConnectionCounter closed: " << connection.getMgmtId() - << ", userId:" << connection.getUserId()); - - Mutex::ScopedLock locker(dataLock); - - connectCountsMap_t::iterator eRef = connectProgressMap.find(connection.getMgmtId()); - if (eRef != connectProgressMap.end()) { - if ((*eRef).second == C_OPENED){ - // Normal case: connection was created and opened. - // Decrement user in-use counts - releaseLH(connectByNameMap, - connection.getUserId()); - } else { - // Connection was created but not opened. - // Don't decrement user count. - } - - // Decrement host in-use count. - releaseLH(connectByHostMap, - getClientHost(connection.getMgmtId())); - - // destroy connection progress indicator - connectProgressMap.erase(eRef); - - } else { - // connection not found in progress map - QPID_LOG(notice, "ACL ConnectionCounter closed info for '" << connection.getMgmtId() - << "' not found in connection state pool"); - } - - // total connections - totalCurrentConnections -= 1; -} - - -// -// approveConnection -// check total connections, connections from IP, connections by user and -// disallow if over any limit -// -bool ConnectionCounter::approveConnection( - const broker::Connection& connection, - const std::string& userName, - bool enforcingConnectionQuotas, - uint16_t connectionUserQuota, - boost::shared_ptr localdata) -{ - const std::string& hostName(getClientHost(connection.getMgmtId())); - - Mutex::ScopedLock locker(dataLock); - - // Bump state from CREATED to OPENED - (void) countConnectionLH(connectProgressMap, connection.getMgmtId(), - C_OPENED, false, false); - - // Run global black/white list check - sys::SocketAddress sa(hostName, ""); - bool okByHostList(true); - std::string hostLimitText; - if (sa.isIp()) { - AclResult result = localdata->isAllowedConnection(userName, hostName, hostLimitText); - okByHostList = AclHelper::resultAllows(result); - if (okByHostList) { - QPID_LOG(trace, "ACL: ConnectionApprover host list " << hostLimitText); - } - } - - // Approve total connections - bool okTotal = true; - if (totalLimit > 0) { - okTotal = totalCurrentConnections <= totalLimit; - QPID_LOG(trace, "ACL ConnectionApprover totalLimit=" << totalLimit - << " curValue=" << totalCurrentConnections - << " result=" << (okTotal ? "allow" : "deny")); - } - - // Approve by IP host connections - bool okByIP = limitApproveLH(connectByHostMap, hostName, hostLimit, true); - - // Count and Approve the connection by the user - bool okByUser = countConnectionLH(connectByNameMap, userName, - connectionUserQuota, true, - enforcingConnectionQuotas); - - // Emit separate log for each disapproval - if (!okByHostList) { - QPID_LOG(error, "ACL: ConnectionApprover host list " << hostLimitText - << " Connection refused."); - } - if (!okTotal) { - QPID_LOG(error, "Client max total connection count limit of " << totalLimit - << " exceeded by '" - << connection.getMgmtId() << "', user: '" - << userName << "'. Connection refused"); - } - if (!okByIP) { - QPID_LOG(error, "Client max per-host connection count limit of " - << hostLimit << " exceeded by '" - << connection.getMgmtId() << "', user: '" - << userName << "'. Connection refused."); - } - if (!okByUser) { - QPID_LOG(error, "Client max per-user connection count limit of " - << connectionUserQuota << " exceeded by '" - << connection.getMgmtId() << "', user: '" - << userName << "'. Connection refused."); - } - - // Count/Event once for each disapproval - bool result = okByHostList && okTotal && okByIP && okByUser; - if (!result) { - acl.reportConnectLimit(userName, hostName); - } - - return result; -} - -// -// getClientIp - given a connection's mgmtId return the client host part. -// -// TODO: Ideally this would be a method of the connection itself. -// TODO: Verify it works with rdma connection names. -// -std::string ConnectionCounter::getClientHost(const std::string mgmtId) -{ - size_t hyphen = mgmtId.find('-'); - if (std::string::npos != hyphen) { - size_t colon = mgmtId.find_last_of(':'); - if (std::string::npos != colon) { - // trailing colon found - std::string tmp = mgmtId.substr(hyphen+1, colon - hyphen - 1); - // undecorate ipv6 - if (tmp.length() >= 3 && tmp.find("[") == 0 && tmp.rfind("]") == tmp.length()-1) - tmp = tmp.substr(1, tmp.length()-2); - return tmp; - - } else { - // colon not found - use everything after hyphen - return mgmtId.substr(hyphen+1); - } - } - - // no hyphen found - use whole string - return mgmtId; -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/acl/AclConnectionCounter.h b/qpid/cpp/src/qpid/acl/AclConnectionCounter.h deleted file mode 100644 index 3683b573ff..0000000000 --- a/qpid/cpp/src/qpid/acl/AclConnectionCounter.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef QPID_ACL_CONNECTIONCOUNTER_H -#define QPID_ACL_CONNECTIONCOUNTER_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/ConnectionObserver.h" -#include "qpid/sys/Mutex.h" -#include "qpid/acl/AclData.h" - -#include - -namespace qpid { - -namespace broker { -class Connection; -} - -namespace acl { -class Acl; - - /** - * Terminate client connections when a user tries to create 'too many'. - * Terminate hostIp connections when an IP host tries to create 'too many'. - */ -class ConnectionCounter : public broker::ConnectionObserver -{ -private: - typedef std::map connectCountsMap_t; - enum CONNECTION_PROGRESS { C_CREATED=1, C_OPENED=2 }; - - Acl& acl; - uint16_t nameLimit; - uint16_t hostLimit; - uint16_t totalLimit; - uint16_t totalCurrentConnections; - qpid::sys::Mutex dataLock; - - /** Records per-connection state */ - connectCountsMap_t connectProgressMap; - - /** Records per-username counts */ - connectCountsMap_t connectByNameMap; - - /** Records per-host counts */ - connectCountsMap_t connectByHostMap; - - /** Given a connection's management ID, return the client host name */ - std::string getClientHost(const std::string mgmtId); - - /** Return approval for proposed connection */ - bool limitApproveLH(connectCountsMap_t& theMap, - const std::string& theName, - uint16_t theLimit, - bool emitLog); - - /** Record a connection. - * @return indication if user/host is over its limit */ - bool countConnectionLH(connectCountsMap_t& theMap, - const std::string& theName, - uint16_t theLimit, - bool emitLog, - bool enforceLimit); - - /** Release a connection */ - void releaseLH(connectCountsMap_t& theMap, - const std::string& theName); - -public: - ConnectionCounter(Acl& acl, uint16_t nl, uint16_t hl, uint16_t tl); - ~ConnectionCounter(); - - // ConnectionObserver interface - void connection(broker::Connection& connection); - void closed(broker::Connection& connection); - - // Connection counting - bool approveConnection(const broker::Connection& conn, - const std::string& userName, - bool enforcingConnectionQuotas, - uint16_t connectionLimit, - boost::shared_ptr localdata - ); -}; - -}} // namespace qpid::ha - -#endif /*!QPID_ACL_CONNECTIONCOUNTER_H*/ diff --git a/qpid/cpp/src/qpid/acl/AclData.cpp b/qpid/cpp/src/qpid/acl/AclData.cpp deleted file mode 100644 index a629e44d60..0000000000 --- a/qpid/cpp/src/qpid/acl/AclData.cpp +++ /dev/null @@ -1,890 +0,0 @@ -/* - * - * 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/acl/AclData.h" -#include "qpid/acl/AclValidator.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/IntegerTypes.h" -#include -#include -#include -#include - -namespace qpid { -namespace acl { - -// -// Instantiate the keyword strings -// -const std::string AclData::ACL_KEYWORD_USER_SUBST = "${user}"; -const std::string AclData::ACL_KEYWORD_DOMAIN_SUBST = "${domain}"; -const std::string AclData::ACL_KEYWORD_USERDOMAIN_SUBST = "${userdomain}"; -const std::string AclData::ACL_KEYWORD_ALL = "all"; -const std::string AclData::ACL_KEYWORD_ACL = "acl"; -const std::string AclData::ACL_KEYWORD_GROUP = "group"; -const std::string AclData::ACL_KEYWORD_QUOTA = "quota"; -const std::string AclData::ACL_KEYWORD_QUOTA_CONNECTIONS = "connections"; -const std::string AclData::ACL_KEYWORD_QUOTA_QUEUES = "queues"; -const char AclData::ACL_SYMBOL_WILDCARD = '*'; -const std::string AclData::ACL_KEYWORD_WILDCARD = "*"; -const char AclData::ACL_SYMBOL_LINE_CONTINUATION = '\\'; -const std::string AclData::ACL_KEYWORD_DEFAULT_EXCHANGE = "amq.default"; - -// -// constructor -// -AclData::AclData(): - decisionMode(qpid::acl::DENY), - transferAcl(false), - aclSource("UNKNOWN"), - connectionDecisionMode(qpid::acl::ALLOW), - connQuotaRuleSettings(new quotaRuleSet), - queueQuotaRuleSettings(new quotaRuleSet), - connBWHostsGlobalRules(new bwHostRuleSet), - connBWHostsUserRules(new bwHostUserRuleMap) -{ - for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++) { - actionList[cnt]=0; - } -} - - -// -// clear -// -void AclData::clear () -{ - for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++) { - if (actionList[cnt]) { - for (unsigned int cnt1=0; cnt1< qpid::acl::OBJECTSIZE; cnt1++) { - delete actionList[cnt][cnt1]; - } - } - delete[] actionList[cnt]; - } - transferAcl = false; - connectionDecisionMode = qpid::acl::ALLOW; - connQuotaRuleSettings->clear(); - queueQuotaRuleSettings->clear(); - connBWHostsGlobalRules->clear(); - connBWHostsUserRules->clear(); -} - -void AclData::printDecisionRules(int userFieldWidth) { - AclValidator validator; - QPID_LOG(trace, "ACL: Decision rule cross reference"); - for (int act=0; actbegin(); - aoitr != actionList[act][obj]->end(); - aoitr++) { - std::string user = (*aoitr).first; - ruleSetItr rsitr = (*aoitr).second.end(); - for (size_t rCnt=0; rCnt < (*aoitr).second.size(); rCnt++) { - rsitr--; - std::vector candidates; - validator.findPossibleLookupMatch( - action, object, rsitr->props, candidates); - std::stringstream ss; - std::string sep(""); - for (std::vector::const_iterator - itr = candidates.begin(); itr != candidates.end(); itr++) { - ss << sep << *itr; - sep = ","; - } - QPID_LOG(trace, "ACL: User: " - << std::setfill(' ') << std::setw(userFieldWidth +1) << std::left - << user << " " - << std::setfill(' ') << std::setw(acl::ACTION_STR_WIDTH +1) << std::left - << AclHelper::getActionStr(action) - << std::setfill(' ') << std::setw(acl::OBJECTTYPE_STR_WIDTH) << std::left - << AclHelper::getObjectTypeStr(object) - << " Rule: " - << rsitr->toString() << " may match Lookups : (" - << ss.str() << ")"); - } - } - } else { - // no rules for action/object - } - } - } -} - -// -// matchProp -// -// Compare a rule's property name with a lookup name, -// The rule's name may contain a trailing '*' to specify a wildcard match. -// -bool AclData::matchProp(const std::string& ruleStr, - const std::string& lookupStr) -{ - // allow wildcard on the end of rule strings... - if (ruleStr.data()[ruleStr.size()-1]==ACL_SYMBOL_WILDCARD) { - return ruleStr.compare(0, - ruleStr.size()-1, - lookupStr, - 0, - ruleStr.size()-1 ) == 0; - } else { - return ruleStr.compare(lookupStr) == 0; - } -} - - -// -// lookupMatchRule -// -// Check a single rule and if it's a match return the decision -// -bool AclData::lookupMatchRule( - const ruleSetItr& rsItr, - const std::string& id, - const std::string& name, - const std::map* params, - AclResult& aclresult) -{ - QPID_LOG(debug, "ACL: checking rule " << rsItr->toString()); - - bool match = true; - bool limitChecked = true; - - // Iterate this rule's properties. A 'match' is true when - // all of the rule's properties are found to be satisfied - // in the lookup param list. The lookup may specify things - // (they usually do) that are not in the rule properties but - // these things don't interfere with the rule match. - - for (specPropertyMapItr rulePropMapItr = rsItr->props.begin(); - (rulePropMapItr != rsItr->props.end()) && match; - rulePropMapItr++) { - // The rule property map's NAME property is given in - // the calling args and not in the param map. - if (rulePropMapItr->first == acl::SPECPROP_NAME) - { - // substitute user name into object name - bool result; - if (rsItr->ruleHasUserSub[PROP_NAME]) { - std::string sName(rulePropMapItr->second); - substituteUserId(sName, id); - result = matchProp(sName, name); - } else { - result = matchProp(rulePropMapItr->second, name); - } - - if (result) { - QPID_LOG(debug, "ACL: lookup name '" << name - << "' matched with rule name '" - << rulePropMapItr->second << "'"); - } else { - match = false; - QPID_LOG(debug, "ACL: lookup name '" << name - << "' didn't match with rule name '" - << rulePropMapItr->second << "'"); - } - } else { - if (params) { - // The rule's property map non-NAME properties - // found in the lookup's params list. - // In some cases the param's index is not the same - // as rule's index. - propertyMapItr lookupParamItr; - switch (rulePropMapItr->first) { - case acl::SPECPROP_MAXPAGESLOWERLIMIT: - case acl::SPECPROP_MAXPAGESUPPERLIMIT: - lookupParamItr = params->find(PROP_MAXPAGES); - break; - - case acl::SPECPROP_MAXPAGEFACTORLOWERLIMIT: - case acl::SPECPROP_MAXPAGEFACTORUPPERLIMIT: - lookupParamItr = params->find(PROP_MAXPAGEFACTOR); - break; - - case acl::SPECPROP_MAXQUEUECOUNTUPPERLIMIT: - case acl::SPECPROP_MAXQUEUECOUNTLOWERLIMIT: - lookupParamItr = params->find(PROP_MAXQUEUECOUNT); - break; - - case acl::SPECPROP_MAXQUEUESIZEUPPERLIMIT: - case acl::SPECPROP_MAXQUEUESIZELOWERLIMIT: - lookupParamItr = params->find(PROP_MAXQUEUESIZE); - break; - - case acl::SPECPROP_MAXFILECOUNTUPPERLIMIT: - case acl::SPECPROP_MAXFILECOUNTLOWERLIMIT: - lookupParamItr = params->find(PROP_MAXFILECOUNT); - break; - - case acl::SPECPROP_MAXFILESIZEUPPERLIMIT: - case acl::SPECPROP_MAXFILESIZELOWERLIMIT: - lookupParamItr = params->find(PROP_MAXFILESIZE); - break; - - default: - lookupParamItr = params->find((Property)rulePropMapItr->first); - break; - }; - - if (lookupParamItr == params->end()) { - // Now the rule has a specified property - // that does not exist in the caller's - // lookup params list. - // This rule does not match. - match = false; - QPID_LOG(debug, "ACL: lookup parameter map doesn't contain the rule property '" - << AclHelper::getPropertyStr(rulePropMapItr->first) << "'"); - } else { - // Now account for the business of rules - // whose property indexes are mismatched. - switch (rulePropMapItr->first) { - case acl::SPECPROP_MAXQUEUECOUNTUPPERLIMIT: - case acl::SPECPROP_MAXQUEUESIZEUPPERLIMIT: - case acl::SPECPROP_MAXFILECOUNTUPPERLIMIT: - case acl::SPECPROP_MAXFILESIZEUPPERLIMIT: - case acl::SPECPROP_MAXPAGESUPPERLIMIT: - case acl::SPECPROP_MAXPAGEFACTORUPPERLIMIT: - limitChecked &= - compareInt( - rulePropMapItr->first, - boost::lexical_cast(rulePropMapItr->second), - boost::lexical_cast(lookupParamItr->second), - true); - break; - - case acl::SPECPROP_MAXQUEUECOUNTLOWERLIMIT: - case acl::SPECPROP_MAXQUEUESIZELOWERLIMIT: - case acl::SPECPROP_MAXFILECOUNTLOWERLIMIT: - case acl::SPECPROP_MAXFILESIZELOWERLIMIT: - case acl::SPECPROP_MAXPAGESLOWERLIMIT: - case acl::SPECPROP_MAXPAGEFACTORLOWERLIMIT: - limitChecked &= - compareInt( - rulePropMapItr->first, - boost::lexical_cast(rulePropMapItr->second), - boost::lexical_cast(lookupParamItr->second), - false); - break; - - default: - bool result; - if ((SPECPROP_ALTERNATE == rulePropMapItr->first && rsItr->ruleHasUserSub[PROP_ALTERNATE]) || - (SPECPROP_QUEUENAME == rulePropMapItr->first && rsItr->ruleHasUserSub[PROP_QUEUENAME])) { - // These properties are allowed to have username substitution - std::string sName(rulePropMapItr->second); - substituteUserId(sName, id); - result = matchProp(sName, lookupParamItr->second); - } else if (SPECPROP_ROUTINGKEY == rulePropMapItr->first) { - // Routing key is allowed to have username substitution - // and it gets topic exchange matching - if (rsItr->ruleHasUserSub[PROP_ROUTINGKEY]) { - std::string sKey(lookupParamItr->second); - substituteKeywords(sKey, id); - result = rsItr->matchRoutingKey(sKey); - } else { - result = rsItr->matchRoutingKey(lookupParamItr->second); - } - } else { - // Rules without substitution - result = matchProp(rulePropMapItr->second, lookupParamItr->second); - } - - if (result) { - QPID_LOG(debug, "ACL: the pair(" - << AclHelper::getPropertyStr(lookupParamItr->first) - << "," << lookupParamItr->second - << ") given in lookup matched the pair(" - << AclHelper::getPropertyStr(rulePropMapItr->first) << "," - << rulePropMapItr->second - << ") given in the rule"); - } else { - match = false; - QPID_LOG(debug, "ACL: the pair(" - << AclHelper::getPropertyStr(lookupParamItr->first) - << "," << lookupParamItr->second - << ") given in lookup doesn't match the pair(" - << AclHelper::getPropertyStr(rulePropMapItr->first) - << "," << rulePropMapItr->second - << ") given in the rule"); - } - break; - }; - } - } else { - // params don't exist. - } - } - } - if (match) { - aclresult = rsItr->ruleMode; - if (!limitChecked) { - // Now a lookup matched all rule properties but one - // of the numeric limit checks has failed. - // Demote allow rules to corresponding deny rules. - switch (aclresult) { - case acl::ALLOW: - aclresult = acl::DENY; - break; - case acl::ALLOWLOG: - aclresult = acl::DENYLOG; - break; - default: - break; - }; - } - QPID_LOG(debug,"ACL: Successful match, the decision is:" - << AclHelper::getAclResultStr(aclresult)); - } else { - // This rule did not match the requested lookup and - // does not contribute to an ACL decision. - } - return match; -} - -// -// lookup - general ACL lookup -// -// The ACL main business logic function of matching rules and declaring -// an allow or deny result. -// -AclResult AclData::lookup( - const std::string& id, - const Action& action, - const ObjectType& objType, - const std::string& name, - std::map* params) -{ - QPID_LOG(debug, "ACL: Lookup for id:" << id - << " action:" << AclHelper::getActionStr((Action) action) - << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) - << " name:" << name - << " with params " << AclHelper::propertyMapToString(params)); - - // A typical log looks like: - // ACL: Lookup for id:bob@QPID action:create objectType:queue name:q2 - // with params { durable=false passive=false autodelete=false - // exclusive=false alternate= policytype= maxqueuesize=0 - // maxqueuecount=0 } - - // Default result is blanket decision mode for the entire ACL list. - AclResult aclresult = decisionMode; - - // Test for lists of rules at the intersection of the Action & Object - if (actionList[action] && actionList[action][objType]) { - // Find the list of rules for this actorId - AclData::actObjItr itrRule = actionList[action][objType]->find(id); - - // If individual actorId not found then find a rule set for '*'. - if (itrRule == actionList[action][objType]->end()) { - itrRule = actionList[action][objType]->find(ACL_KEYWORD_WILDCARD); - } - if (itrRule != actionList[action][objType]->end()) { - // A list of rules exists for this actor/action/object tuple. - // Iterate the rule set to search for a matching rule. - ruleSetItr rsItr = itrRule->second.end(); - for (int cnt = itrRule->second.size(); cnt != 0; cnt--) { - rsItr--; - if (lookupMatchRule(rsItr, id, name, params, aclresult)) { - return aclresult; - } - } - } else { - // The Action-Object list has entries but not for this actorId - // nor for *. - } - } else { - // The Action-Object list has no entries. - } - - QPID_LOG(debug,"ACL: No successful match, defaulting to the decision mode " - << AclHelper::getAclResultStr(aclresult)); - return aclresult; -} - - -// -// lookupMatchPublishExchangeRule -// -// check a single publish exchange rule -// -bool AclData::lookupMatchPublishExchangeRule( - const ruleSetItr& rsItr, - const std::string& id, - const std::string& name, - const std::string& routingKey, - AclResult& aclresult) -{ - QPID_LOG(debug, "ACL: checking rule " << rsItr->toString()); - - // Search on exchange name and routing key only if specfied in rule. - bool match =true; - if (rsItr->pubExchNameInRule) { - // substitute user name into object name - bool result; - - if (rsItr->ruleHasUserSub[PROP_NAME]) { - std::string sName(rsItr->pubExchName); - substituteUserId(sName, id); - result = matchProp(sName, name); - } - else if (rsItr->pubExchNameMatchesBlank) { - result = name.empty(); - } else { - result = matchProp(rsItr->pubExchName, name); - } - - if (result) { - QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup exchange name '" - << name << "' matched with rule name '" - << rsItr->pubExchName << "'"); - } else { - match= false; - QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup exchange name '" - << name << "' did not match with rule name '" - << rsItr->pubExchName << "'"); - } - } - - if (match && rsItr->pubRoutingKeyInRule) { - if ((routingKey.find(ACL_KEYWORD_USER_SUBST, 0) != std::string::npos) || - (routingKey.find(ACL_KEYWORD_DOMAIN_SUBST, 0) != std::string::npos) || - (routingKey.find(ACL_KEYWORD_USERDOMAIN_SUBST, 0) != std::string::npos)) { - // The user is not allowed to present a routing key with the substitution key in it - QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << - " User-specified routing key has substitution wildcard:" << routingKey - << ". Rule match prohibited."); - match = false; - } else { - bool result; - if (rsItr->ruleHasUserSub[PROP_ROUTINGKEY]) { - std::string sKey(routingKey); - substituteKeywords(sKey, id); - result = rsItr->matchRoutingKey(sKey); - } else { - result = rsItr->matchRoutingKey(routingKey); - } - - if (result) { - QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '" - << routingKey << "' matched with rule routing key '" - << rsItr->pubRoutingKey << "'"); - } else { - QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '" - << routingKey << "' did not match with rule routing key '" - << rsItr->pubRoutingKey << "'"); - match = false; - } - } - } - - if (match) { - aclresult = rsItr->ruleMode; - QPID_LOG(debug,"ACL: Rule: " << rsItr->rawRuleNum << " Successful match, the decision is:" - << AclHelper::getAclResultStr(aclresult)); - } - return match; -} - -// -// lookup - special PUBLISH EXCHANGE lookup -// -// The ACL main business logic function of matching rules and declaring -// an allow or deny result. This lookup is the fastpath per-message -// lookup to verify if a user is allowed to publish to an exchange with -// a given key. -// -AclResult AclData::lookup( - const std::string& id, - const Action& action, - const ObjectType& objType, - const std::string& /*Exchange*/ name, - const std::string& routingKey) -{ - - QPID_LOG(debug, "ACL: Lookup for id:" << id - << " action:" << AclHelper::getActionStr((Action) action) - << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) - << " exchange name:" << name - << " with routing key " << routingKey); - - AclResult aclresult = decisionMode; - - if (actionList[action] && actionList[action][objType]){ - AclData::actObjItr itrRule = actionList[action][objType]->find(id); - - if (itrRule == actionList[action][objType]->end()) { - itrRule = actionList[action][objType]->find(ACL_KEYWORD_WILDCARD); - } - if (itrRule != actionList[action][objType]->end() ) { - // Found a rule list for this user-action-object set. - // Search the rule list for a matching rule. - ruleSetItr rsItr = itrRule->second.end(); - for (int cnt = itrRule->second.size(); cnt != 0; cnt--) { - rsItr--; - - if (lookupMatchPublishExchangeRule(rsItr, id, name, routingKey, aclresult)) { - return aclresult; - } - } - } - } - QPID_LOG(debug,"ACL: No successful match, defaulting to the decision mode " - << AclHelper::getAclResultStr(aclresult)); - return aclresult; - -} - - - -// -// -// -void AclData::setConnQuotaRuleSettings ( - boost::shared_ptr quotaPtr) -{ - connQuotaRuleSettings = quotaPtr; -} - - -// -// getConnQuotaForUser -// -// Return the true or false value of connQuotaRulesExist, -// indicating whether any kind of lookup was done or not. -// -// When lookups are performed return the result value of -// 1. The user's setting else -// 2. The 'all' user setting else -// 3. Zero -// When lookups are not performed then return a result value of Zero. -// -bool AclData::getConnQuotaForUser(const std::string& theUserName, - uint16_t* theResult) const { - if (this->enforcingConnectionQuotas()) { - // look for this user explicitly - quotaRuleSetItr nameItr = (*connQuotaRuleSettings).find(theUserName); - if (nameItr != (*connQuotaRuleSettings).end()) { - QPID_LOG(trace, "ACL: Connection quota for user " << theUserName - << " explicitly set to : " << (*nameItr).second); - *theResult = (*nameItr).second; - } else { - // Look for the 'all' user - nameItr = (*connQuotaRuleSettings).find(ACL_KEYWORD_ALL); - if (nameItr != (*connQuotaRuleSettings).end()) { - QPID_LOG(trace, "ACL: Connection quota for user " << theUserName - << " chosen through value for 'all' : " << (*nameItr).second); - *theResult = (*nameItr).second; - } else { - // Neither userName nor "all" found. - QPID_LOG(trace, "ACL: Connection quota for user " << theUserName - << " absent in quota settings. Return value : 0"); - *theResult = 0; - } - } - } else { - // Rules do not exist - QPID_LOG(trace, "ACL: Connection quota for user " << theUserName - << " unavailable; quota settings are not specified. Return value : 0"); - *theResult = 0; - } - return this->enforcingConnectionQuotas(); -} - -// -// -// -void AclData::setQueueQuotaRuleSettings ( - boost::shared_ptr quotaPtr) -{ - queueQuotaRuleSettings = quotaPtr; -} - - -// -// getQueueQuotaForUser -// -// Return the true or false value of queueQuotaRulesExist, -// indicating whether any kind of lookup was done or not. -// -// When lookups are performed return the result value of -// 1. The user's setting else -// 2. The 'all' user setting else -// 3. Zero -// When lookups are not performed then return a result value of Zero. -// -bool AclData::getQueueQuotaForUser(const std::string& theUserName, - uint16_t* theResult) const { - if (this->enforcingQueueQuotas()) { - // look for this user explicitly - quotaRuleSetItr nameItr = (*queueQuotaRuleSettings).find(theUserName); - if (nameItr != (*queueQuotaRuleSettings).end()) { - QPID_LOG(trace, "ACL: Queue quota for user " << theUserName - << " explicitly set to : " << (*nameItr).second); - *theResult = (*nameItr).second; - } else { - // Look for the 'all' user - nameItr = (*queueQuotaRuleSettings).find(ACL_KEYWORD_ALL); - if (nameItr != (*queueQuotaRuleSettings).end()) { - QPID_LOG(trace, "ACL: Queue quota for user " << theUserName - << " chosen through value for 'all' : " << (*nameItr).second); - *theResult = (*nameItr).second; - } else { - // Neither userName nor "all" found. - QPID_LOG(trace, "ACL: Queue quota for user " << theUserName - << " absent in quota settings. Return value : 0"); - *theResult = 0; - } - } - } else { - // Rules do not exist - QPID_LOG(trace, "ACL: Queue quota for user " << theUserName - << " unavailable; quota settings are not specified. Return value : 0"); - *theResult = 0; - } - return this->enforcingQueueQuotas(); -} - -void AclData::setConnGlobalRules (boost::shared_ptr cgr) { - connBWHostsGlobalRules = cgr; -} - -void AclData::setConnUserRules (boost::shared_ptr hurm) { - connBWHostsUserRules = hurm; -} - -AclResult AclData::isAllowedConnection(const std::string& userName, - const std::string& hostName, - std::string& logText) { - bool decisionMade(false); - AclResult result(ALLOW); - for (bwHostRuleSetItr it=connBWHostsGlobalRules->begin(); - it!=connBWHostsGlobalRules->end(); it++) { - if (it->getAclHost().match(hostName)) { - // This host matches a global spec and controls the - // allow/deny decision for this connection. - result = it->getAclResult(); - logText = QPID_MSG("global rule " << it->toString() - << (AclHelper::resultAllows(result) ? " allows" : " denies") - << " connection for host " << hostName << ", user " - << userName); - decisionMade = true; - break; - } else { - // This rule in the global spec doesn't match and - // does not control the allow/deny decision. - } - } - - // Run user black/white list check - if (!decisionMade) { - bwHostUserRuleMapItr itrRule = connBWHostsUserRules->find(userName); - if (itrRule != connBWHostsUserRules->end()) { - for (bwHostRuleSetItr it=(*itrRule).second.begin(); - it!=(*itrRule).second.end(); it++) { - if (it->getAclHost().match(hostName)) { - // This host matches a user spec and controls the - // allow/deny decision for this connection. - result = it->getAclResult(); - logText = QPID_MSG("global rule " << it->toString() - << (AclHelper::resultAllows(result) ? " allows" : " denies") - << " connection for host " << hostName << ", user " - << userName); - decisionMade = true; - break; - } else { - // This rule in the user's spec doesn't match and - // does not control the allow/deny decision. - } - } - } - } - - // Apply global connection mode - if (!decisionMade) { - result = connectionDecisionMode; - logText = QPID_MSG("default connection policy " - << (AclHelper::resultAllows(result) ? "allows" : "denies") - << " connection for host " << hostName << ", user " - << userName); - } - return result; -} - -// -// -// -AclData::~AclData() -{ - clear(); -} - - -// -// Limit check an int limit -// -bool AclData::compareInt(const qpid::acl::SpecProperty theProperty, - const std::string theAclValue, - const std::string theLookupValue, - bool theMaxFlag) -{ - uint64_t aclRuleValue (0); - uint64_t lookupValue (0); - - QPID_LOG(debug, "ACL: " - << (theMaxFlag ? "Upper" : "Lower") << "-limit comparison for property " - << AclHelper::getPropertyStr(theProperty) - << ". Success if lookup(" << theLookupValue - << ") " - << (theMaxFlag ? "<=" : ">=") << " rule(" << theAclValue << ")"); - - try { - aclRuleValue = boost::lexical_cast(theAclValue); - } - catch(const boost::bad_lexical_cast&) { - assert (false); - return false; - } - - if (aclRuleValue == 0) { - QPID_LOG(debug, "ACL: Comparison is always true when ACL rule value is zero"); - return true; - } - - try { - lookupValue = boost::lexical_cast(theLookupValue); - } - catch(const boost::bad_lexical_cast&) { - QPID_LOG(error,"ACL: Illegal value given in lookup for property '" - << AclHelper::getPropertyStr(theProperty) - << "' : " << theLookupValue); - return false; - } - - bool result = - (theMaxFlag ? lookupValue > aclRuleValue : lookupValue < aclRuleValue); - if ( result ) { - QPID_LOG(debug, "ACL: Limit exceeded for property '" - << AclHelper::getPropertyStr(theProperty) << "'"); - return false; - } - - return true; -} - -const std::string DOMAIN_SEPARATOR("@"); -const std::string PERIOD("."); -const std::string UNDERSCORE("_"); -// -// substituteString -// Given a name string from an Acl rule, substitute the replacement into it -// wherever the placeholder directs. -// -void AclData::substituteString(std::string& targetString, - const std::string& placeholder, - const std::string& replacement) -{ - assert (!placeholder.empty()); - if (placeholder.empty()) { - return; - } - size_t start_pos(0); - while((start_pos = targetString.find(placeholder, start_pos)) != std::string::npos) { - targetString.replace(start_pos, placeholder.length(), replacement); - start_pos += replacement.length(); - } -} - - -// -// normalizeUserId -// Given a name string return it in a form usable as topic keys: -// change "@" and "." to "_". -// -std::string AclData::normalizeUserId(const std::string& userId) -{ - std::string normalId(userId); - substituteString(normalId, DOMAIN_SEPARATOR, UNDERSCORE); - substituteString(normalId, PERIOD, UNDERSCORE); - return normalId; -} - - -// -// substituteUserId -// Given an Acl rule and an authenticated userId -// do the keyword substitutions on the rule. -// -void AclData::substituteUserId(std::string& ruleString, - const std::string& userId) -{ - size_t locDomSeparator(0); - std::string user(""); - std::string domain(""); - std::string userdomain = normalizeUserId(userId); - - locDomSeparator = userId.find(DOMAIN_SEPARATOR); - if (std::string::npos == locDomSeparator) { - // "@" not found. There's just a user name - user = normalizeUserId(userId); - } else { - // "@" found, split the names. Domain may be blank. - user = normalizeUserId(userId.substr(0,locDomSeparator)); - domain = normalizeUserId(userId.substr(locDomSeparator+1)); - } - - substituteString(ruleString, ACL_KEYWORD_USER_SUBST, user); - substituteString(ruleString, ACL_KEYWORD_DOMAIN_SUBST, domain); - substituteString(ruleString, ACL_KEYWORD_USERDOMAIN_SUBST, userdomain); -} - - -// -// substituteKeywords -// Given an Acl rule and an authenticated userId -// do reverse keyword substitutions on the rule. -// That is, replace the normalized name in the rule string with -// the keyword that represents it. This stragegy is used for -// topic key lookups where the keyword string proper is in the -// topic key search tree. -// -void AclData::substituteKeywords(std::string& ruleString, - const std::string& userId) -{ - size_t locDomSeparator(0); - std::string user(""); - std::string domain(""); - std::string userdomain = normalizeUserId(userId); - - locDomSeparator = userId.find(DOMAIN_SEPARATOR); - if (std::string::npos == locDomSeparator) { - // "@" not found. There's just a user name - user = normalizeUserId(userId); - } else { - // "@" found, split the names - user = normalizeUserId(userId.substr(0,locDomSeparator)); - domain = normalizeUserId(userId.substr(locDomSeparator+1)); - } - std::string oRule(ruleString); - substituteString(ruleString, userdomain, ACL_KEYWORD_USERDOMAIN_SUBST); - substituteString(ruleString, user, ACL_KEYWORD_USER_SUBST); - substituteString(ruleString, domain, ACL_KEYWORD_DOMAIN_SUBST); -} -}} diff --git a/qpid/cpp/src/qpid/acl/AclData.h b/qpid/cpp/src/qpid/acl/AclData.h deleted file mode 100644 index 105a5d9c67..0000000000 --- a/qpid/cpp/src/qpid/acl/AclData.h +++ /dev/null @@ -1,323 +0,0 @@ -#ifndef QPID_ACL_ACLDATA_H -#define QPID_ACL_ACLDATA_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/broker/AclModule.h" -#include "qpid/AclHost.h" -#include "AclTopicMatch.h" -#include "qpid/log/Statement.h" -#include "boost/shared_ptr.hpp" -#include -#include - -namespace qpid { -namespace acl { - -/** A rule for tracking black/white host connection settings. - * When a connection is attempted, the remote host is verified - * against lists of these rules. When the remote host is in - * the range specified by this aclHost then the AclResult is - * applied as allow/deny. - */ -class AclBWHostRule { -public: - AclBWHostRule(AclResult r, std::string h) : - aclResult(r), aclHost(h) {} - - std::string toString () const { - std::ostringstream ruleStr; - ruleStr << "[ruleMode = " << AclHelper::getAclResultStr(aclResult) - << " {" << aclHost.str() << "}"; - return ruleStr.str(); - } - const AclHost& getAclHost() const { return aclHost; } - const AclResult& getAclResult() const { return aclResult; } - -private: - AclResult aclResult; - AclHost aclHost; -}; - - -class AclData { - - -public: - - typedef std::map propertyMap; - typedef propertyMap::const_iterator propertyMapItr; - - typedef std::map specPropertyMap; - typedef specPropertyMap::const_iterator specPropertyMapItr; - - // - // Rule - // - // Created by AclReader and stored in a ruleSet vector for subsequent - // run-time lookup matching and allow/deny decisions. - // RuleSet vectors are indexed by Action-Object-actorId so these - // attributes are not part of a rule. - // A single ACL file entry may create many rule entries in - // many ruleset vectors. - // - struct Rule { - typedef broker::TopicExchange::TopicExchangeTester topicTester; - - int rawRuleNum; // rule number in ACL file - qpid::acl::AclResult ruleMode; // combined allow/deny log/nolog - specPropertyMap props; // properties to be matched - // pubXxx for publish exchange fastpath - bool pubRoutingKeyInRule; - std::string pubRoutingKey; - boost::shared_ptr pTTest; - bool pubExchNameInRule; - bool pubExchNameMatchesBlank; - std::string pubExchName; - std::vector ruleHasUserSub; - std::string lookupSource; - std::string lookupHelp; - - Rule (int ruleNum, qpid::acl::AclResult res, specPropertyMap& p) : - rawRuleNum(ruleNum), - ruleMode(res), - props(p), - pubRoutingKeyInRule(false), - pubRoutingKey(), - pTTest(boost::shared_ptr(new topicTester())), - pubExchNameInRule(false), - pubExchNameMatchesBlank(false), - pubExchName(), - ruleHasUserSub(PROPERTYSIZE, false) - {} - - // Variation of Rule for tracking PropertyDefs - // for AclValidation. - Rule (int ruleNum, qpid::acl::AclResult res, specPropertyMap& p, - const std::string& ls, const std::string& lh - ) : - rawRuleNum(ruleNum), - ruleMode(res), - props(p), - pubRoutingKeyInRule(false), - pubRoutingKey(), - pubExchNameInRule(false), - pubExchNameMatchesBlank(false), - pubExchName(), - ruleHasUserSub(PROPERTYSIZE, false), - lookupSource(ls), - lookupHelp(lh) - {} - - - std::string toString () const { - std::ostringstream ruleStr; - ruleStr << "[rule " << rawRuleNum - << " ruleMode = " << AclHelper::getAclResultStr(ruleMode) - << " props{"; - for (specPropertyMapItr pMItr = props.begin(); - pMItr != props.end(); - pMItr++) { - ruleStr << " " - << AclHelper::getPropertyStr((SpecProperty) pMItr-> first) - << "=" << pMItr->second; - } - ruleStr << " }]"; - return ruleStr.str(); - } - - void addTopicTest(const std::string& pattern) { - pTTest->addBindingKey(broker::TopicExchange::normalize(pattern)); - } - - // Topic Exchange tester - // return true if any bindings match 'pattern' - bool matchRoutingKey(const std::string& pattern) const - { - topicTester::BindingVec bv; - return pTTest->findMatches(pattern, bv); - } - }; - - typedef std::vector ruleSet; - typedef ruleSet::const_iterator ruleSetItr; - typedef std::map actionObject; // user - typedef actionObject::iterator actObjItr; - typedef actionObject* aclAction; - typedef std::map quotaRuleSet; // - typedef quotaRuleSet::const_iterator quotaRuleSetItr; - typedef std::vector bwHostRuleSet; // allow/deny hosts-vector - typedef bwHostRuleSet::const_iterator bwHostRuleSetItr; - typedef std::map bwHostUserRuleMap; // - typedef bwHostUserRuleMap::const_iterator bwHostUserRuleMapItr; - - // Action*[] -> Object*[] -> map > - aclAction* actionList[qpid::acl::ACTIONSIZE]; - qpid::acl::AclResult decisionMode; // allow/deny[-log] if no matching rule found - bool transferAcl; - std::string aclSource; - qpid::acl::AclResult connectionDecisionMode; - - AclResult lookup( - const std::string& id, // actor id - const Action& action, - const ObjectType& objType, - const std::string& name, // object name - std::map* params=0); - - AclResult lookup( - const std::string& id, // actor id - const Action& action, - const ObjectType& objType, - const std::string& ExchangeName, - const std::string& RoutingKey); - - boost::shared_ptr getGlobalConnectionRules() { - return connBWHostsGlobalRules; - } - - boost::shared_ptr getUserConnectionRules() { - return connBWHostsUserRules; - } - - bool matchProp(const std::string & src, const std::string& src1); - void clear (); - void printDecisionRules(int userFieldWidth); - - static const std::string ACL_KEYWORD_USER_SUBST; - static const std::string ACL_KEYWORD_DOMAIN_SUBST; - static const std::string ACL_KEYWORD_USERDOMAIN_SUBST; - static const std::string ACL_KEYWORD_ALL; - static const std::string ACL_KEYWORD_ACL; - static const std::string ACL_KEYWORD_GROUP; - static const std::string ACL_KEYWORD_QUOTA; - static const std::string ACL_KEYWORD_QUOTA_CONNECTIONS; - static const std::string ACL_KEYWORD_QUOTA_QUEUES; - static const char ACL_SYMBOL_WILDCARD; - static const std::string ACL_KEYWORD_WILDCARD; - static const char ACL_SYMBOL_LINE_CONTINUATION; - static const std::string ACL_KEYWORD_DEFAULT_EXCHANGE; - - void substituteString(std::string& targetString, - const std::string& placeholder, - const std::string& replacement); - std::string normalizeUserId(const std::string& userId); - void substituteUserId(std::string& ruleString, - const std::string& userId); - void substituteKeywords(std::string& ruleString, - const std::string& userId); - - // Per user connection quotas extracted from acl rule file - // Set by reader - void setConnQuotaRuleSettings (boost::shared_ptr); - // Get by connection approvers - bool enforcingConnectionQuotas() const { return connQuotaRuleSettings->size() > 0; } - bool getConnQuotaForUser(const std::string&, uint16_t*) const; - - // Per user queue quotas extracted from acl rule file - // Set by reader - void setQueueQuotaRuleSettings (boost::shared_ptr); - // Get by queue approvers - bool enforcingQueueQuotas() const { return queueQuotaRuleSettings->size() > 0; } - bool getQueueQuotaForUser(const std::string&, uint16_t*) const; - - // Global connection Black/White list rules - void setConnGlobalRules (boost::shared_ptr); - - // Per-user connection Black/White list rules map - void setConnUserRules (boost::shared_ptr); - - /** getConnectMaxSpec - * Connection quotas are held in uint16_t variables. - * This function specifies the largest value that a user is allowed - * to declare for a connection quota. The upper limit serves two - * purposes: 1. It leaves room for magic numbers that may be declared - * by keyword names in Acl files and not have those numbers conflict - * with innocent user declared values, and 2. It makes the unsigned - * math very close to _MAX work reliably with no risk of accidental - * wrapping back to zero. - */ - static uint16_t getConnectMaxSpec() { - return 65530; - } - static std::string getMaxConnectSpecStr() { - return "65530"; - } - - static uint16_t getQueueMaxSpec() { - return 65530; - } - static std::string getMaxQueueSpecStr() { - return "65530"; - } - - /** - * isAllowedConnection - * Return true if this user is allowed to connect to this host. - * Return log text describing both success and failure. - */ - AclResult isAllowedConnection(const std::string& userName, - const std::string& hostName, - std::string& logText); - - AclResult connectionMode() const { - return connectionDecisionMode; - } - - AclData(); - virtual ~AclData(); - -private: - - inline bool lookupMatchRule( - const ruleSetItr& rsItr, - const std::string& id, - const std::string& name, - const std::map* params, - AclResult& aclresult); - - inline bool lookupMatchPublishExchangeRule( - const ruleSetItr& rsItr, - const std::string& id, - const std::string& name, - const std::string& routingKey, - AclResult& aclresult); - - bool compareInt(const qpid::acl::SpecProperty theProperty, - const std::string theAclValue, - const std::string theLookupValue, - bool theMaxFlag); - - // Per-user connection quota - boost::shared_ptr connQuotaRuleSettings; - - // Per-user queue quota - boost::shared_ptr queueQuotaRuleSettings; - - // Global host connection black/white rule set - boost::shared_ptr connBWHostsGlobalRules; - - // Per-user host connection black/white rule set map - boost::shared_ptr connBWHostsUserRules; -}; - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACLDATA_H diff --git a/qpid/cpp/src/qpid/acl/AclLexer.cpp b/qpid/cpp/src/qpid/acl/AclLexer.cpp deleted file mode 100644 index 4006e5271f..0000000000 --- a/qpid/cpp/src/qpid/acl/AclLexer.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * Copyright (c) 2014 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/acl/AclLexer.h" -#include "qpid/RefCounted.h" -#include "qpid/Exception.h" -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace acl { - -// ObjectType -const std::string objectNames[OBJECTSIZE] = { - "broker", "connection", "exchange", "link", "method", "query", "queue" }; - -ObjectType AclHelper::getObjectType(const std::string& str) { - for (int i=0; i< OBJECTSIZE; ++i) { - if (str.compare(objectNames[i]) == 0) - return ObjectType(i); - } - throw qpid::Exception("Acl illegal object name: " + str); -} - -const std::string& AclHelper::getObjectTypeStr(const ObjectType o) { - return objectNames[o]; -} - -// Action -const std::string actionNames[ACTIONSIZE] = { - "access", "bind", "consume", "create", "delete", - "move", "publish", "purge", "redirect", "reroute", - "unbind", "update" }; - -Action AclHelper::getAction(const std::string& str) { - for (int i=0; i< ACTIONSIZE; ++i) { - if (str.compare(actionNames[i]) == 0) - return Action(i); - } - throw qpid::Exception("Acl illegal action name: " + str); -} - -const std::string& AclHelper::getActionStr(const Action a) { - return actionNames[a]; -} - -// Property -// These are shared between broker and acl using code enums. -const std::string propertyNames[PROPERTYSIZE] = { - "name", "durable", "owner", "routingkey", "autodelete", "exclusive", "type", - "alternate", "queuename", "exchangename", "schemapackage", - "schemaclass", "policytype", "paging", "host", - - "maxpages", "maxpagefactor", - "maxqueuesize", "maxqueuecount", "maxfilesize", "maxfilecount"}; - -Property AclHelper::getProperty(const std::string& str) { - for (int i=0; i< PROPERTYSIZE; ++i) { - if (str.compare(propertyNames[i]) == 0) - return Property(i); - } - throw qpid::Exception("Acl illegal property name: " + str); -} - -const std::string& AclHelper::getPropertyStr(const Property p) { - return propertyNames[p]; -} - -// SpecProperty -// These are shared between user acl files and acl using text. -const std::string specPropertyNames[SPECPROPSIZE] = { - "name", "durable", "owner", "routingkey", "autodelete", "exclusive", "type", - "alternate", "queuename", "exchangename", "schemapackage", - "schemaclass", "policytype", "paging", "host", - - "queuemaxsizelowerlimit", "queuemaxsizeupperlimit", - "queuemaxcountlowerlimit", "queuemaxcountupperlimit", - "filemaxsizelowerlimit", "filemaxsizeupperlimit", - "filemaxcountlowerlimit", "filemaxcountupperlimit", - "pageslowerlimit", "pagesupperlimit", - "pagefactorlowerlimit", "pagefactorupperlimit" }; - -SpecProperty AclHelper::getSpecProperty(const std::string& str) { - for (int i=0; i< SPECPROPSIZE; ++i) { - if (str.compare(specPropertyNames[i]) == 0) - return SpecProperty(i); - } - // Allow old names in ACL file as aliases for newly-named properties - if (str.compare("maxqueuesize") == 0) - return SPECPROP_MAXQUEUESIZEUPPERLIMIT; - if (str.compare("maxqueuecount") == 0) - return SPECPROP_MAXQUEUECOUNTUPPERLIMIT; - throw qpid::Exception("Acl illegal spec property name: " + str); -} - -const std::string& AclHelper::getPropertyStr(const SpecProperty p) { - return specPropertyNames[p]; -} - -// AclResult -const std::string resultNames[RESULTSIZE] = { - "allow", "allow-log", "deny", "deny-log" }; - -AclResult AclHelper::getAclResult(const std::string& str) { - for (int i=0; i< RESULTSIZE; ++i) { - if (str.compare(resultNames[i]) == 0) - return AclResult(i); - } - throw qpid::Exception("Acl illegal result name: " + str); -} - -const std::string& AclHelper::getAclResultStr(const AclResult r) { - return resultNames[r]; -} - -bool AclHelper::resultAllows(const AclResult r) { - bool answer = r == ALLOW || r == ALLOWLOG; - return answer; -} - -}} // namespace qpid::acl diff --git a/qpid/cpp/src/qpid/acl/AclLexer.h b/qpid/cpp/src/qpid/acl/AclLexer.h deleted file mode 100644 index d3df411afd..0000000000 --- a/qpid/cpp/src/qpid/acl/AclLexer.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef QPID_ACL_ACLLEXER_H -#define QPID_ACL_ACLLEXER_H - -/* - * - * Copyright (c) 2014 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/Exception.h" -#include "qpid/broker/BrokerImportExport.h" -#include -#include -#include -#include -#include -#include - -namespace qpid { - -namespace acl { - - // Interface enumerations. - // These enumerations define enum lists and implied text strings - // to match. They are used in two areas: - // 1. In the ACL specifications in the ACL file, file parsing, and - // internal rule storage. - // 2. In the authorize interface in the rest of the broker where - // code requests the ACL module to authorize an action. - - // ObjectType shared between ACL spec and ACL authorise interface - enum ObjectType { - OBJ_BROKER, - OBJ_CONNECTION, - OBJ_EXCHANGE, - OBJ_LINK, - OBJ_METHOD, - OBJ_QUERY, - OBJ_QUEUE, - OBJECTSIZE }; // OBJECTSIZE must be last in list - - const int OBJECTTYPE_STR_WIDTH = 10; - - // Action shared between ACL spec and ACL authorise interface - enum Action { - ACT_ACCESS, - ACT_BIND, - ACT_CONSUME, - ACT_CREATE, - ACT_DELETE, - ACT_MOVE, - ACT_PUBLISH, - ACT_PURGE, - ACT_REDIRECT, - ACT_REROUTE, - ACT_UNBIND, - ACT_UPDATE, - ACTIONSIZE }; // ACTIONSIZE must be last in list - - const int ACTION_STR_WIDTH = 8; - - // Property used in ACL authorize interface - enum Property { - PROP_NAME, - PROP_DURABLE, - PROP_OWNER, - PROP_ROUTINGKEY, - PROP_AUTODELETE, - PROP_EXCLUSIVE, - PROP_TYPE, - PROP_ALTERNATE, - PROP_QUEUENAME, - PROP_EXCHANGENAME, - PROP_SCHEMAPACKAGE, - PROP_SCHEMACLASS, - PROP_POLICYTYPE, - PROP_PAGING, - PROP_HOST, - PROP_MAXPAGES, - PROP_MAXPAGEFACTOR, - PROP_MAXQUEUESIZE, - PROP_MAXQUEUECOUNT, - PROP_MAXFILESIZE, - PROP_MAXFILECOUNT, - PROPERTYSIZE // PROPERTYSIZE must be last in list - }; - - // Property used in ACL spec file - // Note for properties common to file processing/rule storage and to - // broker rule lookups the identical enum values are used. - enum SpecProperty { - SPECPROP_NAME = PROP_NAME, - SPECPROP_DURABLE = PROP_DURABLE, - SPECPROP_OWNER = PROP_OWNER, - SPECPROP_ROUTINGKEY = PROP_ROUTINGKEY, - SPECPROP_AUTODELETE = PROP_AUTODELETE, - SPECPROP_EXCLUSIVE = PROP_EXCLUSIVE, - SPECPROP_TYPE = PROP_TYPE, - SPECPROP_ALTERNATE = PROP_ALTERNATE, - SPECPROP_QUEUENAME = PROP_QUEUENAME, - SPECPROP_EXCHANGENAME = PROP_EXCHANGENAME, - SPECPROP_SCHEMAPACKAGE = PROP_SCHEMAPACKAGE, - SPECPROP_SCHEMACLASS = PROP_SCHEMACLASS, - SPECPROP_POLICYTYPE = PROP_POLICYTYPE, - SPECPROP_PAGING = PROP_PAGING, - SPECPROP_HOST = PROP_HOST, - - SPECPROP_MAXQUEUESIZELOWERLIMIT, - SPECPROP_MAXQUEUESIZEUPPERLIMIT, - SPECPROP_MAXQUEUECOUNTLOWERLIMIT, - SPECPROP_MAXQUEUECOUNTUPPERLIMIT, - SPECPROP_MAXFILESIZELOWERLIMIT, - SPECPROP_MAXFILESIZEUPPERLIMIT, - SPECPROP_MAXFILECOUNTLOWERLIMIT, - SPECPROP_MAXFILECOUNTUPPERLIMIT, - SPECPROP_MAXPAGESLOWERLIMIT, - SPECPROP_MAXPAGESUPPERLIMIT, - SPECPROP_MAXPAGEFACTORLOWERLIMIT, - SPECPROP_MAXPAGEFACTORUPPERLIMIT, - SPECPROPSIZE // SPECPROPSIZE must be last - }; - -// AclResult shared between ACL spec and ACL authorise interface - enum AclResult { - ALLOW, - ALLOWLOG, - DENY, - DENYLOG, - RESULTSIZE - }; - - - QPID_BROKER_CLASS_EXTERN class AclHelper { - private: - AclHelper(){} - public: - static QPID_BROKER_EXTERN ObjectType getObjectType(const std::string& str); - static QPID_BROKER_EXTERN const std::string& getObjectTypeStr(const ObjectType o); - static QPID_BROKER_EXTERN Action getAction(const std::string& str); - static QPID_BROKER_EXTERN const std::string& getActionStr(const Action a); - static QPID_BROKER_EXTERN Property getProperty(const std::string& str); - static QPID_BROKER_EXTERN const std::string& getPropertyStr(const Property p); - static QPID_BROKER_EXTERN SpecProperty getSpecProperty(const std::string& str); - static QPID_BROKER_EXTERN const std::string& getPropertyStr(const SpecProperty p); - static QPID_BROKER_EXTERN AclResult getAclResult(const std::string& str); - static QPID_BROKER_EXTERN const std::string& getAclResultStr(const AclResult r); - static QPID_BROKER_EXTERN bool resultAllows(const AclResult r); - - typedef std::set propSet; - typedef boost::shared_ptr propSetPtr; - typedef std::pair actionPair; - typedef std::map actionMap; - typedef boost::shared_ptr actionMapPtr; - typedef std::pair objectPair; - typedef std::map propMap; - typedef propMap::const_iterator propMapItr; - typedef std::map specPropMap; - typedef specPropMap::const_iterator specPropMapItr; - - // - // properyMapToString - // - template - static std::string propertyMapToString( - const std::map* params) - { - std::ostringstream ss; - ss << "{"; - if (params) - { - for (typename std::map::const_iterator - pMItr = params->begin(); pMItr != params->end(); pMItr++) - { - ss << " " << getPropertyStr((T) pMItr-> first) - << "=" << pMItr->second; - } - } - ss << " }"; - return ss.str(); - } - - }; - - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACLLEXER_H diff --git a/qpid/cpp/src/qpid/acl/AclPlugin.cpp b/qpid/cpp/src/qpid/acl/AclPlugin.cpp deleted file mode 100644 index 77580ba531..0000000000 --- a/qpid/cpp/src/qpid/acl/AclPlugin.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * 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 -#include "qpid/acl/Acl.h" -#include "qpid/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/sys/Path.h" -#include "qpid/log/Statement.h" - -#include -#include - -namespace qpid { -namespace acl { - -using namespace std; - -/** Note separating options from values to work around boost version differences. - * Old boost takes a reference to options objects, but new boost makes a copy. - * New boost allows a shared_ptr but that's not compatible with old boost. - */ -struct AclOptions : public Options { - AclValues& values; - - AclOptions(AclValues& v) : Options("ACL Options"), values(v) { - values.aclMaxConnectTotal = 500; - addOptions() - ("acl-file", optValue(values.aclFile, "FILE"), "The policy file to load from, loaded from data dir") - ("connection-limit-per-user", optValue(values.aclMaxConnectPerUser, "N"), "The maximum number of connections allowed per user. 0 implies no limit.") - ("max-connections" , optValue(values.aclMaxConnectTotal, "N"), "The maximum combined number of connections allowed. 0 implies no limit.") - ("connection-limit-per-ip" , optValue(values.aclMaxConnectPerIp, "N"), "The maximum number of connections allowed per host IP address. 0 implies no limit.") - ("max-queues-per-user", optValue(values.aclMaxQueuesPerUser, "N"), "The maximum number of queues allowed per user. 0 implies no limit.") - ; - } -}; - -struct AclPlugin : public Plugin { - - AclValues values; - AclOptions options; - boost::intrusive_ptr acl; - - AclPlugin() : options(values) {} - - Options* getOptions() { return &options; } - - void init(broker::Broker& b) { - if (acl) throw Exception("ACL plugin cannot be initialized twice in one process."); - - if (!values.aclFile.empty()){ - sys::Path aclFile(values.aclFile); - sys::Path dataDir(b.getDataDir().getPath()); - if (!aclFile.isAbsolute() && !dataDir.empty()) - values.aclFile = (dataDir + aclFile).str(); - } - acl = new Acl(values, b); - b.setAcl(acl.get()); - b.addFinalizer(boost::bind(&AclPlugin::shutdown, this)); - } - - template bool init(Plugin::Target& target) { - T* t = dynamic_cast(&target); - if (t) init(*t); - return t; - } - - void earlyInitialize(Plugin::Target&) {} - - void initialize(Plugin::Target& target) { - init(target); - } - - void shutdown() { acl = 0; } -}; - -static AclPlugin instance; // Static initialization. - -// For test purposes. -boost::intrusive_ptr getGlobalAcl() { return instance.acl; } - -}} // namespace qpid::acl diff --git a/qpid/cpp/src/qpid/acl/AclReader.cpp b/qpid/cpp/src/qpid/acl/AclReader.cpp deleted file mode 100644 index 6f595ebf58..0000000000 --- a/qpid/cpp/src/qpid/acl/AclReader.cpp +++ /dev/null @@ -1,827 +0,0 @@ -/* - * - * 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/acl/AclReader.h" -#include "qpid/acl/AclData.h" - -#include -#include -#include -#include -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" -#include -#include - -#include // degug -#include // debug - -#define ACL_FORMAT_ERR_LOG_PREFIX "ACL format error: " << fileName << ":" << lineNumber << ": " - -namespace qpid { -namespace acl { - - AclReader::aclRule::aclRule(const AclResult r, const std::string n, const groupMap& groups) : res(r), actionAll(true), action(ACT_ACCESS), objStatus(NONE), object(OBJ_BROKER) { - processName(n, groups); - } - AclReader::aclRule::aclRule(const AclResult r, const std::string n, const groupMap& groups, const Action a) : res(r), actionAll(false), action(a), objStatus(NONE) { - processName(n, groups); - } - - void AclReader::aclRule::setObjectType(const ObjectType o) { - objStatus = VALUE; - object = o; - } - - void AclReader::aclRule::setObjectTypeAll() { - objStatus = ALL; - } - - bool AclReader::aclRule::addProperty(const SpecProperty p, const std::string v) { - return props.insert(propNvPair(p, v)).second; - } - - // Debug aid - std::string AclReader::aclRule::toString() { - std::ostringstream oss; - oss << AclHelper::getAclResultStr(res) << " ["; - for (nsCitr itr = names.begin(); itr != names.end(); itr++) { - if (itr != names.begin()) oss << ", "; - oss << *itr; - } - oss << "]"; - if (actionAll) { - oss << " *"; - } else { - oss << " " << AclHelper::getActionStr(action); - } - if (objStatus == ALL) { - oss << " *"; - } else if (objStatus == VALUE) { - oss << " " << AclHelper::getObjectTypeStr(object); - } - for (pmCitr i=props.begin(); i!=props.end(); i++) { - oss << " " << AclHelper::getPropertyStr(i->first) << "=" << i->second; - } - return oss.str(); - } - - void AclReader::loadDecisionData(boost::shared_ptr d) { - d->clear(); - QPID_LOG(debug, "ACL: Load Rules"); - bool foundmode = false; - bool foundConnectionMode = false; - - rlCitr i = rules.end(); - for (int cnt = rules.size(); cnt; cnt--) { - i--; - QPID_LOG(debug, "ACL: Processing " << std::setfill(' ') << std::setw(2) - << cnt << " " << (*i)->toString()); - - if (!(*i)->actionAll && (*i)->objStatus == aclRule::VALUE && - !validator.validateAllowedProperties( - (*i)->action, (*i)->object, (*i)->props, false)) { - // specific object/action has bad property - // this rule gets ignored - continue; - } else { - // action=all or object=none/all means the rule gets propagated - // possibly to many places. - // Invalid rule combinations are not propagated. - } - - if (!foundmode && (*i)->actionAll && (*i)->names.size() == 1 - && (*((*i)->names.begin())).compare(AclData::ACL_KEYWORD_WILDCARD) == 0) { - d->decisionMode = (*i)->res; - QPID_LOG(debug, "ACL: FoundMode " - << AclHelper::getAclResultStr(d->decisionMode)); - foundmode = true; - } else if ((*i)->action == acl::ACT_CREATE && (*i)->object == acl::OBJ_CONNECTION) { - // Intercept CREATE CONNECTION rules process them into separate lists to - // be consumed in the connection approval code path. - propMap::const_iterator pName = (*i)->props.find(SPECPROP_NAME); - if (pName != (*i)->props.end()) { - throw Exception(QPID_MSG("ACL: CREATE CONNECTION rule " << cnt << " must not have a 'name' property")); - } - propMap::const_iterator pHost = (*i)->props.find(SPECPROP_HOST); - if (pHost == (*i)->props.end()) { - throw Exception(QPID_MSG("ACL: CREATE CONNECTION rule " << cnt << " has no 'host' property")); - } - // create the connection rule - bool allUsers = (*(*i)->names.begin()).compare(AclData::ACL_KEYWORD_WILDCARD) == 0; - bool allHosts = pHost->second.compare(AclData::ACL_KEYWORD_ALL) == 0; - AclBWHostRule bwRule((*i)->res, (allHosts ? "" : pHost->second)); - - // apply the rule globally or to user list - if (allUsers) { - if (allHosts) { - // allow one specification of allUsers,allHosts - if (foundConnectionMode) { - throw Exception(QPID_MSG("ACL: only one CREATE CONNECTION rule for user=all and host=all allowed")); - } - foundConnectionMode = true; - d->connectionDecisionMode = (*i)->res; - QPID_LOG(trace, "ACL: Found connection mode: " << AclHelper::getAclResultStr( (*i)->res )); - } else { - // Rules for allUsers but not allHosts go into the global list - globalHostRules->insert( globalHostRules->begin(), bwRule ); - } - } else { - // other rules go into binned rule sets for each user - for (nsCitr itr = (*i)->names.begin(); - itr != (*i)->names.end(); - itr++) { - (*userHostRules)[(*itr)].insert( (*userHostRules)[(*itr)].begin(), bwRule); - } - } - } else { - AclData::Rule rule(cnt, (*i)->res, (*i)->props); - // Record which properties have the user substitution string - for (pmCitr pItr=rule.props.begin(); pItr!=rule.props.end(); pItr++) { - if ((pItr->second.find(AclData::ACL_KEYWORD_USER_SUBST, 0) != std::string::npos) || - (pItr->second.find(AclData::ACL_KEYWORD_DOMAIN_SUBST, 0) != std::string::npos) || - (pItr->second.find(AclData::ACL_KEYWORD_USERDOMAIN_SUBST, 0) != std::string::npos)) { - rule.ruleHasUserSub[pItr->first] = true; - } - } - - // Find possible routingkey property and cache its pattern - for (pmCitr pItr=rule.props.begin(); pItr!=rule.props.end(); pItr++) { - if (acl::SPECPROP_ROUTINGKEY == pItr->first) - { - rule.pubRoutingKeyInRule = true; - rule.pubRoutingKey = (std::string)pItr->second; - rule.addTopicTest(rule.pubRoutingKey); - } - } - - // Action -> Object -> map set > - std::ostringstream actionstr; - for (int acnt = ((*i)->actionAll ? 0 : (*i)->action); - acnt < acl::ACTIONSIZE; - (*i)->actionAll ? acnt++ : acnt = acl::ACTIONSIZE) { - - if (acnt == acl::ACT_PUBLISH) - { - d->transferAcl = true; // we have transfer ACL - // For Publish the only object should be Exchange - // and the only property should be routingkey. - // Go through the rule properties and find the name and the key. - // If found then place them specially for the lookup engine. - for (pmCitr pItr=(*i)->props.begin(); pItr!=(*i)->props.end(); pItr++) { - if (acl::SPECPROP_NAME == pItr->first) - { - rule.pubExchNameInRule = true; - rule.pubExchName = pItr->second; - rule.pubExchNameMatchesBlank = rule.pubExchName.compare(AclData::ACL_KEYWORD_DEFAULT_EXCHANGE) == 0; - } - } - } - actionstr << AclHelper::getActionStr((Action) acnt) << ","; - - //find the Action, create if not exist - if (d->actionList[acnt] == NULL) { - d->actionList[acnt] = - new AclData::aclAction[qpid::acl::OBJECTSIZE]; - for (int j = 0; j < qpid::acl::OBJECTSIZE; j++) - d->actionList[acnt][j] = NULL; - } - - for (int ocnt = ((*i)->objStatus != aclRule::VALUE ? 0 - : (*i)->object); - ocnt < acl::OBJECTSIZE; - (*i)->objStatus != aclRule::VALUE ? ocnt++ : ocnt = acl::OBJECTSIZE) { - - //find the Object, create if not exist - if (d->actionList[acnt][ocnt] == NULL) - d->actionList[acnt][ocnt] = - new AclData::actionObject; - - // add users and Rule to object set - bool allNames = false; - // check to see if names.begin is '*' - if ((*(*i)->names.begin()).compare(AclData::ACL_KEYWORD_WILDCARD) == 0) - allNames = true; - - for (nsCitr itr = (allNames ? names.begin() : (*i)->names.begin()); - itr != (allNames ? names.end() : (*i)->names.end()); - itr++) { - if (validator.validateAllowedProperties(acl::Action(acnt), - acl::ObjectType(ocnt), - (*i)->props, - false)) { - AclData::actObjItr itrRule = - d->actionList[acnt][ocnt]->find(*itr); - - if (itrRule == d->actionList[acnt][ocnt]->end()) { - AclData::ruleSet rSet; - rSet.push_back(rule); - d->actionList[acnt][ocnt]->insert - (make_pair(std::string(*itr), rSet)); - } else { - itrRule->second.push_back(rule); - } - } else { - // Skip propagating this rule as it will never match. - } - } - } - } - - std::ostringstream objstr; - for (int ocnt = ((*i)->objStatus != aclRule::VALUE ? 0 : (*i)->object); - ocnt < acl::OBJECTSIZE; - (*i)->objStatus != aclRule::VALUE ? ocnt++ : ocnt = acl::OBJECTSIZE) { - objstr << AclHelper::getObjectTypeStr((ObjectType) ocnt) << ","; - } - - bool allNames = ((*(*i)->names.begin()).compare(AclData::ACL_KEYWORD_WILDCARD) == 0); - std::ostringstream userstr; - for (nsCitr itr = (allNames ? names.begin() : (*i)->names.begin()); - itr != (allNames ? names.end() : (*i)->names.end()); - itr++) { - userstr << *itr << ","; - } - - QPID_LOG(debug, "ACL: Adding actions {" << - actionstr.str().substr(0,actionstr.str().length()-1) - << "} to objects {" << - objstr.str().substr(0,objstr.str().length()-1) - << "} with props " << - AclHelper::propertyMapToString(&rule.props) - << " for users {" << - userstr.str().substr(0,userstr.str().length()-1) - << "}"); - } - } - - // connection quota - d->setConnQuotaRuleSettings(connQuota); - // queue quota - d->setQueueQuotaRuleSettings(queueQuota); - // global B/W connection rules - d->setConnGlobalRules(globalHostRules); - // user B/W connection rules - d->setConnUserRules(userHostRules); - } - - - void AclReader::aclRule::processName(const std::string& name, const groupMap& groups) { - if (name.compare(AclData::ACL_KEYWORD_ALL) == 0) { - names.insert(AclData::ACL_KEYWORD_WILDCARD); - } else { - gmCitr itr = groups.find(name); - if (itr == groups.end()) { - names.insert(name); - } else { - names.insert(itr->second->begin(), itr->second->end()); - } - } - } - - AclReader::AclReader(uint16_t theCliMaxConnPerUser, uint16_t theCliMaxQueuesPerUser) : - lineNumber(0), contFlag(false), - cliMaxConnPerUser (theCliMaxConnPerUser), - connQuotaRulesExist(false), - connQuota(new AclData::quotaRuleSet), - cliMaxQueuesPerUser (theCliMaxQueuesPerUser), - queueQuotaRulesExist(false), - queueQuota(new AclData::quotaRuleSet), - globalHostRules(new AclData::bwHostRuleSet), - userHostRules(new AclData::bwHostUserRuleMap) { - names.insert(AclData::ACL_KEYWORD_WILDCARD); - } - - AclReader::~AclReader() {} - - std::string AclReader::getError() { - return errorStream.str(); - } - - int AclReader::read(const std::string& fn, boost::shared_ptr d) { - fileName = fn; - lineNumber = 0; - char buff[1024]; - std::ifstream ifs(fn.c_str(), std::ios_base::in); - if (!ifs.good()) { - errorStream << "Unable to open ACL file \"" << fn << "\": eof=" << (ifs.eof()?"T":"F") << "; fail=" << (ifs.fail()?"T":"F") << "; bad=" << (ifs.bad()?"T":"F"); - return -1; - } - // Propagate nonzero per-user max connection setting from CLI - if (cliMaxConnPerUser > 0) { - connQuotaRulesExist = true; - (*connQuota)[AclData::ACL_KEYWORD_ALL] = cliMaxConnPerUser; - } - // Propagate nonzero per-user max queue setting from CLI - if (cliMaxQueuesPerUser > 0) { - queueQuotaRulesExist = true; - (*queueQuota)[AclData::ACL_KEYWORD_ALL] = cliMaxQueuesPerUser; - } - // Loop to process the Acl file - try { - bool err = false; - while (ifs.good()) { - ifs.getline(buff, 1024); - lineNumber++; - if (std::strlen(buff) > 0 && buff[0] != '#') // Ignore blank lines and comments - err |= !processLine(buff); - } - if (!ifs.eof()) - { - errorStream << "Unable to read ACL file \"" << fn << "\": eof=" << (ifs.eof()?"T":"F") << "; fail=" << (ifs.fail()?"T":"F") << "; bad=" << (ifs.bad()?"T":"F"); - ifs.close(); - return -2; - } - ifs.close(); - if (err) return -3; - QPID_LOG(notice, "ACL: Read file \"" << fn << "\""); - } catch (const std::exception& e) { - errorStream << "Unable to read ACL file \"" << fn << "\": " << e.what(); - ifs.close(); - return -4; - } catch (...) { - errorStream << "Unable to read ACL file \"" << fn << "\": Unknown exception"; - ifs.close(); - return -5; - } - printNames(); - printRules(); - printQuotas(AclData::ACL_KEYWORD_QUOTA_CONNECTIONS, connQuota); - printQuotas(AclData::ACL_KEYWORD_QUOTA_QUEUES, queueQuota); - try { - loadDecisionData(d); - } catch (const std::exception& e) { - errorStream << "Error loading decision data : " << e.what(); - return -6; - } - printGlobalConnectRules(); - printUserConnectRules(); - validator.tracePropertyDefs(); - d->printDecisionRules( printNamesFieldWidth() ); - - return 0; - } - - bool AclReader::processLine(char* line) { - bool ret = false; - std::vector toks; - - // Check for continuation - char* contCharPtr = std::strrchr(line, AclData::ACL_SYMBOL_LINE_CONTINUATION); - bool cont = contCharPtr != 0; - if (cont) *contCharPtr = 0; - - int numToks = tokenize(line, toks); - - if (cont && numToks == 0){ - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line \"" << lineNumber << "\" contains an illegal extension."; - return false; - } - - if (numToks && (toks[0].compare(AclData::ACL_KEYWORD_GROUP) == 0 || contFlag)) { - ret = processGroupLine(toks, cont); - } else if (numToks && toks[0].compare(AclData::ACL_KEYWORD_ACL) == 0) { - ret = processAclLine(toks); - } else if (numToks && toks[0].compare(AclData::ACL_KEYWORD_QUOTA) == 0) { - ret = processQuotaLine(toks); - } else { - // Check for whitespace only line, ignore these - bool ws = true; - for (unsigned i=0; i& toks) { - const char* tokChars = " \t\n\f\v\r"; - int cnt = 0; - char* cp = std::strtok(line, tokChars); - while (cp != 0) { - toks.push_back(std::string(cp)); - cnt++; - cp = std::strtok(0, tokChars); - } - return cnt; - } - - - // Process 'quota' rule lines - // Return true if the line is successfully processed without errors - bool AclReader::processQuotaLine(tokList& toks) { - const unsigned toksSize = toks.size(); - const unsigned minimumSize = 3; - if (toksSize < minimumSize) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Insufficient tokens for quota definition."; - return false; - } - - if (toks[1].compare(AclData::ACL_KEYWORD_QUOTA_CONNECTIONS) == 0) { - if (processQuotaLine(toks, AclData::ACL_KEYWORD_QUOTA_CONNECTIONS, AclData::getConnectMaxSpec(), connQuota)) { - // We have processed a connection quota rule - connQuotaRulesExist = true; - return true; - } - } else if (toks[1].compare(AclData::ACL_KEYWORD_QUOTA_QUEUES) == 0) { - if (processQuotaLine(toks, AclData::ACL_KEYWORD_QUOTA_QUEUES, AclData::getConnectMaxSpec(), queueQuota)) { - // We have processed a queue quota rule - queueQuotaRulesExist = true; - return true; - } - } else { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Quota type \"" << toks[1] << "\" unrecognized."; - return false; - } - return false; - } - - - // Process quota rule lines - // Return true if the line is successfully processed without errors - bool AclReader::processQuotaLine(tokList& toks, const std::string theNoun, uint16_t maxSpec, aclQuotaRuleSet theRules) { - const unsigned toksSize = toks.size(); - - uint16_t nEntities(0); - try { - nEntities = boost::lexical_cast(toks[2]); - } catch(const boost::bad_lexical_cast&) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", " << theNoun << " quota value \"" << toks[2] - << "\" cannot be converted to a 16-bit unsigned integer."; - return false; - } - - // limit check the setting - if (nEntities > maxSpec) - { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", " << theNoun << " quota value \"" << toks[2] - << "\" exceeds maximum configuration setting of " - << maxSpec; - return false; - } - - // Apply the ount to all names in rule - for (unsigned idx = 3; idx < toksSize; idx++) { - if (groups.find(toks[idx]) == groups.end()) { - // This is the name of an individual, not a group - (*theRules)[toks[idx]] = nEntities; - } else { - if (!processQuotaGroup(toks[idx], nEntities, theRules)) - return false; - } - } - - return true; - } - - - // Process quota group expansion - // Return true if the quota is applied to all members of the group - bool AclReader::processQuotaGroup(const std::string& theGroup, uint16_t theQuota, aclQuotaRuleSet theRules) { - gmCitr citr = groups.find(theGroup); - - if (citr == groups.end()) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Failed to expand group \"" << theGroup << "\"."; - return false; - } - - for (nsCitr gni=citr->second->begin(); gni!=citr->second->end(); gni++) { - if (groups.find(*gni) == groups.end()) { - (*theRules)[*gni] = theQuota; - } else { - if (!processQuotaGroup(*gni, theQuota, theRules)) - return false; - } - } - return true; - } - - - void AclReader::printQuotas(const std::string theNoun, aclQuotaRuleSet theRules) const { - QPID_LOG(debug, "ACL: " << theNoun << " quota: " << (*theRules).size() << " rules found:"); - int cnt = 1; - for (AclData::quotaRuleSetItr itr=(*theRules).begin(); - itr != (*theRules).end(); - ++itr,++cnt) { - QPID_LOG(debug, "ACL: quota " << cnt << " : " << (*itr).second - << " " << theNoun << " for " << (*itr).first) - } - } - - - // Return true if the line is successfully processed without errors - // If cont is true, then groupName must be set to the continuation group name - bool AclReader::processGroupLine(tokList& toks, const bool cont) { - const unsigned toksSize = toks.size(); - - if (contFlag) { - gmCitr citr = groups.find(groupName); - for (unsigned i = 0; i < toksSize; i++) { - if (isValidGroupName(toks[i])) { - if (toks[i] == groupName) { - QPID_LOG(debug, "ACL: Line: " << lineNumber - << ", Ignoring recursive sub-group \"" << toks[i] << "\"."); - continue; - } else if (groups.find(toks[i]) == groups.end()) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Sub-group \"" << toks[i] << "\" not defined yet."; - return false; - } - } else if (!isValidUserName(toks[i])) return false; - addName(toks[i], citr->second); - } - } else { - const unsigned minimumSize = (cont ? 2 : 3); - if (toksSize < minimumSize) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Insufficient tokens for group definition."; - return false; - } - if (!isValidGroupName(toks[1])) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Group name \"" << toks[1] << "\" contains illegal characters."; - return false; - } - gmCitr citr = addGroup(toks[1]); - if (citr == groups.end()) return false; - for (unsigned i = 2; i < toksSize; i++) { - if (isValidGroupName(toks[i])) { - if (toks[i] == groupName) { - QPID_LOG(debug, "ACL: Line: " << lineNumber - << ", Ignoring recursive sub-group \"" << toks[i] << "\"."); - continue; - } else if (groups.find(toks[i]) == groups.end()) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Sub-group \"" << toks[i] << "\" not defined yet."; - return false; - } - } else if (!isValidUserName(toks[i])) return false; - addName(toks[i], citr->second); - } - } - return true; - } - - // Return true if sucessfully added group - AclReader::gmCitr AclReader::addGroup(const std::string& newGroupName) { - gmCitr citr = groups.find(newGroupName); - if (citr != groups.end()) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Duplicate group name \"" << newGroupName << "\"."; - return groups.end(); - } - groupPair p(newGroupName, nameSetPtr(new nameSet)); - gmRes res = groups.insert(p); - assert(res.second); - groupName = newGroupName; - return res.first; - } - - void AclReader::addName(const std::string& name, nameSetPtr groupNameSet) { - gmCitr citr = groups.find(name); - if (citr != groups.end()) { - // This is a previously defined group: add all the names in that group to this group - groupNameSet->insert(citr->second->begin(), citr->second->end()); - } else { - // Not a known group name - groupNameSet->insert(name); - addName(name); - } - } - - void AclReader::addName(const std::string& name) { - names.insert(name); - } - - /** - * Emit debug logs exposing the name lists - */ - void AclReader::printNames() const { - QPID_LOG(debug, "ACL: Group list: " << groups.size() << " groups found:" ); - std::string tmp("ACL: "); - for (gmCitr i=groups.begin(); i!= groups.end(); i++) { - tmp += " \""; - tmp += i->first; - tmp += "\":"; - for (nsCitr j=i->second->begin(); j!=i->second->end(); j++) { - tmp += " "; - tmp += *j; - } - QPID_LOG(debug, tmp); - tmp = "ACL: "; - } - QPID_LOG(debug, "ACL: name list: " << names.size() << " names found:" ); - tmp = "ACL: "; - for (nsCitr k=names.begin(); k!=names.end(); k++) { - tmp += " "; - tmp += *k; - } - QPID_LOG(debug, tmp); - } - - /** - * compute the width of longest user name - */ - int AclReader::printNamesFieldWidth() const { - std::string::size_type max = 0; - for (nsCitr k=names.begin(); k!=names.end(); k++) { - max = std::max(max, (*k).length()); - } - return max; - } - - bool AclReader::processAclLine(tokList& toks) { - const unsigned toksSize = toks.size(); - if (toksSize < 4) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Insufficient tokens for acl definition."; - return false; - } - - AclResult res; - try { - res = AclHelper::getAclResult(toks[1]); - } catch (...) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Unknown ACL permission \"" << toks[1] << "\"."; - return false; - } - - bool actionAllFlag = toks[3].compare(AclData::ACL_KEYWORD_ALL) == 0; - bool userAllFlag = toks[2].compare(AclData::ACL_KEYWORD_ALL) == 0; - Action action; - if (actionAllFlag) { - - if (userAllFlag && toksSize > 4) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Tokens found after action \"all\"."; - return false; - } - action = ACT_CONSUME; // dummy; compiler must initialize action for this code path - } else { - try { - action = AclHelper::getAction(toks[3]); - } catch (...) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Unknown action \"" << toks[3] << "\"."; - return false; - } - } - - // Create rule obj; then add object (if any) and properties (if any) - aclRulePtr rule; - if (actionAllFlag) { - rule.reset(new aclRule(res, toks[2], groups)); - } else { - rule.reset(new aclRule(res, toks[2], groups, action)); - } - - if (toksSize >= 5) { // object name-value pair - if (toks[4].compare(AclData::ACL_KEYWORD_ALL) == 0) { - rule->setObjectTypeAll(); - } else { - try { - rule->setObjectType(AclHelper::getObjectType(toks[4])); - } catch (...) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Unknown object \"" << toks[4] << "\"."; - return false; - } - } - } - - if (toksSize >= 6) { // property name-value pair(s) - for (unsigned i=5; iaddProperty(prop, propNvp.second); - } - } - // Check if name (toks[2]) is group; if not, add as name of individual - if (toks[2].compare(AclData::ACL_KEYWORD_ALL) != 0) { - if (groups.find(toks[2]) == groups.end()) { - addName(toks[2]); - } - } - - rules.push_back(rule); - - return true; - } - - // Debug aid - void AclReader::printRules() const { - QPID_LOG(debug, "ACL: Rule list: " << rules.size() << " ACL rules found:"); - int cnt = 1; - for (rlCitr i=rules.begin(); itoString()); - if (!(*i)->actionAll && (*i)->objStatus == aclRule::VALUE) { - (void)validator.validateAllowedProperties((*i)->action, (*i)->object, (*i)->props, true); - } - } - } - - void AclReader::printConnectionRules(const std::string name, const AclData::bwHostRuleSet& rules) const { - QPID_LOG(debug, "ACL: " << name << " Connection Rule list : " << rules.size() << " rules found :"); - int cnt = 1; - for (AclData::bwHostRuleSetItr i=rules.begin(); itoString()); - } - } - - void AclReader::printGlobalConnectRules() const { - printConnectionRules("global", *globalHostRules); - } - - void AclReader::printUserConnectRules() const { - QPID_LOG(debug, "ACL: User Connection Rule lists : " << userHostRules->size() << " user lists found :"); - int cnt = 1; - for (AclData::bwHostUserRuleMapItr i=userHostRules->begin(); i!=userHostRules->end(); i++,cnt++) { - printConnectionRules(std::string((*i).first), (*i).second); - } - } - - // Static function - // Return true if the name is well-formed (ie contains legal characters) - bool AclReader::isValidGroupName(const std::string& name) { - for (unsigned i=0; i -#include -#include -#include -#include -#include -#include -#include "qpid/acl/AclData.h" -#include "qpid/acl/Acl.h" -#include "qpid/broker/AclModule.h" -#include "qpid/acl/AclValidator.h" - -namespace qpid { -namespace acl { - -class AclReader { - typedef std::set nameSet; - typedef nameSet::const_iterator nsCitr; - typedef boost::shared_ptr nameSetPtr; - - typedef std::pair groupPair; - typedef std::map groupMap; - typedef groupMap::const_iterator gmCitr; - typedef std::pair gmRes; - - typedef std::pair propNvPair; - typedef std::map propMap; - typedef propMap::const_iterator pmCitr; - - // - // aclRule - // - // A temporary rule created during ACL file processing. - // - class aclRule { - public: - enum objectStatus {NONE, VALUE, ALL}; - - AclResult res; - nameSet names; - bool actionAll; // True if action is set to keyword "all" - Action action; // Ignored if action is set to keyword "all" - objectStatus objStatus; - ObjectType object; // Ignored for all status values except VALUE - propMap props; - public: - aclRule(const AclResult r, const std::string n, const groupMap& groups); // action = "all" - aclRule(const AclResult r, const std::string n, const groupMap& groups, const Action a); - void setObjectType(const ObjectType o); - void setObjectTypeAll(); - bool addProperty(const SpecProperty p, const std::string v); - std::string toString(); // debug aid - private: - void processName(const std::string& name, const groupMap& groups); - }; - typedef boost::shared_ptr aclQuotaRuleSet; - typedef boost::shared_ptr aclRulePtr; - typedef std::vector ruleList; - typedef ruleList::const_iterator rlCitr; - - typedef std::vector tokList; - typedef tokList::const_iterator tlCitr; - - typedef std::set keywordSet; - typedef keywordSet::const_iterator ksCitr; - typedef std::pair nvPair; // Name-Value pair - - typedef boost::shared_ptr > aclGlobalHostRuleSet; - typedef boost::shared_ptr > > aclUserHostRuleSet; - - std::string fileName; - int lineNumber; - bool contFlag; - std::string groupName; - nameSet names; - groupMap groups; - ruleList rules; - AclValidator validator; - std::ostringstream errorStream; - - public: - AclReader(uint16_t cliMaxConnPerUser, uint16_t cliMaxQueuesPerUser); - virtual ~AclReader(); - int read(const std::string& fn, boost::shared_ptr d); // return=0 for success - std::string getError(); - - private: - bool processLine(char* line); - void loadDecisionData(boost::shared_ptr d); - int tokenize(char* line, tokList& toks); - - bool processGroupLine(tokList& toks, const bool cont); - gmCitr addGroup(const std::string& groupName); - void addName(const std::string& name, nameSetPtr groupNameSet); - void addName(const std::string& name); - void printNames() const; // debug aid - int printNamesFieldWidth() const; - - bool processAclLine(tokList& toks); - void printRules() const; // debug aid - void printConnectionRules(const std::string name, const AclData::bwHostRuleSet& rules) const; - void printGlobalConnectRules() const; - void printUserConnectRules() const; - bool isValidUserName(const std::string& name); - - bool processQuotaLine(tokList& toks); - bool processQuotaLine(tokList& toks, const std::string theNoun, uint16_t maxSpec, aclQuotaRuleSet theRules); - bool processQuotaGroup(const std::string&, uint16_t, aclQuotaRuleSet theRules); - void printQuotas(const std::string theNoun, aclQuotaRuleSet theRules) const; - - static bool isValidGroupName(const std::string& name); - static nvPair splitNameValuePair(const std::string& nvpString); - - const uint16_t cliMaxConnPerUser; - bool connQuotaRulesExist; - aclQuotaRuleSet connQuota; - - const uint16_t cliMaxQueuesPerUser; - bool queueQuotaRulesExist; - aclQuotaRuleSet queueQuota; - - aclGlobalHostRuleSet globalHostRules; - aclUserHostRuleSet userHostRules; -}; - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACLREADER_H diff --git a/qpid/cpp/src/qpid/acl/AclResourceCounter.cpp b/qpid/cpp/src/qpid/acl/AclResourceCounter.cpp deleted file mode 100644 index 2527af6375..0000000000 --- a/qpid/cpp/src/qpid/acl/AclResourceCounter.cpp +++ /dev/null @@ -1,174 +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 "AclResourceCounter.h" -#include "Acl.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Mutex.h" -#include -#include - -using namespace qpid::sys; - -namespace qpid { -namespace acl { - -// -// This module approves various resource creation requests: -// Queues -// - - -// -// -// -ResourceCounter::ResourceCounter(Acl& a, uint16_t ql) : - acl(a), queueLimit(ql) {} - -ResourceCounter::~ResourceCounter() {} - - -// -// limitApproveLH -// -// Resource creation approver. -// If user is under limit increment count and return true. -// Called with lock held. -// -bool ResourceCounter::limitApproveLH( - countsMap_t& theMap, - const std::string& theName, - uint16_t theLimit, - bool emitLog, - bool enforceLimit) { - - bool result(true); - uint16_t count; - countsMap_t::iterator eRef = theMap.find(theName); - if (eRef != theMap.end()) { - count = (uint16_t)(*eRef).second; - result = (enforceLimit ? count < theLimit : true); - if (result) { - count += 1; - (*eRef).second = count; - } - } else { - // user not found in map - if (enforceLimit) { - if (theLimit > 0) { - theMap[theName] = count = 1; - } else { - count = 0; - result = false; - } - } - else { - // not enforcing the limit - theMap[theName] = count = 1; - } - } - if (emitLog) { - QPID_LOG(trace, "ACL QueueApprover user=" << theName - << " limit=" << theLimit - << " curValue=" << count - << " result=" << (result ? "allow" : "deny")); - } - return result; -} - - -// -// releaseLH -// -// Decrement the name's count in map. -// called with dataLock already taken -// -void ResourceCounter::releaseLH(countsMap_t& theMap, const std::string& theName) { - - countsMap_t::iterator eRef = theMap.find(theName); - if (eRef != theMap.end()) { - uint16_t count = (uint16_t) (*eRef).second; - assert (count > 0); - if (1 == count) { - theMap.erase (eRef); - } else { - (*eRef).second = count - 1; - } - } else { - // User had no connections. - QPID_LOG(notice, "ACL resource counter: Queue owner for queue '" << theName - << "' not found in resource count pool"); - } -} - - -// -// approveCreateQueue -// Count an attempted queue creation by this user. -// Disapprove if over limit. -// -bool ResourceCounter::approveCreateQueue(const std::string& userId, - const std::string& queueName, - bool enforcingQueueQuotas, - uint16_t queueUserQuota ) -{ - Mutex::ScopedLock locker(dataLock); - - bool okByQ = limitApproveLH(queuePerUserMap, userId, queueUserQuota, true, enforcingQueueQuotas); - - if (okByQ) { - // Queue is owned by this userId - queueOwnerMap[queueName] = userId; - - QPID_LOG(trace, "ACL create queue approved for user '" << userId - << "' queue '" << queueName << "'"); - } else { - - QPID_LOG(error, "Client max queue count limit of " << queueUserQuota - << " exceeded by '" << userId << "' creating queue '" - << queueName << "'. Queue creation denied."); - - acl.reportQueueLimit(userId, queueName); - } - return okByQ; -} - - -// -// recordDestroyQueue -// Return a destroyed queue to a user's quota -// -void ResourceCounter::recordDestroyQueue(const std::string& queueName) -{ - Mutex::ScopedLock locker(dataLock); - - queueOwnerMap_t::iterator eRef = queueOwnerMap.find(queueName); - if (eRef != queueOwnerMap.end()) { - releaseLH(queuePerUserMap, (*eRef).second); - - queueOwnerMap.erase(eRef); - } else { - QPID_LOG(notice, "ACL resource counter: Queue '" << queueName - << "' not found in queue owner map"); - } -} - -}} // namespace qpid::acl diff --git a/qpid/cpp/src/qpid/acl/AclResourceCounter.h b/qpid/cpp/src/qpid/acl/AclResourceCounter.h deleted file mode 100644 index 8809f73b18..0000000000 --- a/qpid/cpp/src/qpid/acl/AclResourceCounter.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_ACL_RESOURCECOUNTER_H -#define QPID_ACL_RESOURCECOUNTER_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 - -namespace qpid { - -namespace acl { -class Acl; - - /** - * Approve or disapprove resource creation requests - */ -class ResourceCounter -{ -private: - typedef std::map countsMap_t; - typedef std::map queueOwnerMap_t; - - Acl& acl; - uint16_t queueLimit; - qpid::sys::Mutex dataLock; - - /** Records queueName-queueUserId */ - queueOwnerMap_t queueOwnerMap; - - /** Records queue-by-owner counts */ - countsMap_t queuePerUserMap; - - /** Return approval for proposed resource creation */ - bool limitApproveLH(countsMap_t& theMap, - const std::string& theName, - uint16_t theLimit, - bool emitLog, - bool enforceLimit); - - /** Release a connection */ - void releaseLH(countsMap_t& theMap, - const std::string& theName); - -public: - ResourceCounter(Acl& acl, uint16_t ql); - ~ResourceCounter(); - - // Queue counting - bool approveCreateQueue(const std::string& userId, - const std::string& queueName, - bool enforcingQueueQuotas, - uint16_t queueUserQuota ); - void recordDestroyQueue(const std::string& queueName); -}; - -}} // namespace qpid::acl - -#endif /*!QPID_ACL_RESOURCECOUNTER_H*/ diff --git a/qpid/cpp/src/qpid/acl/AclTopicMatch.h b/qpid/cpp/src/qpid/acl/AclTopicMatch.h deleted file mode 100644 index 654d1d63d4..0000000000 --- a/qpid/cpp/src/qpid/acl/AclTopicMatch.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef QPID_ACL_TOPIC_MATCH_H -#define QPID_ACL_TOPIC_MATCH_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/broker/TopicKeyNode.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/log/Statement.h" -#include "boost/shared_ptr.hpp" -#include -#include - -namespace qpid { -namespace broker { - -// Class for executing topic exchange routing key matching rules in -// Acl code. Allows or denies users publishing to an exchange. -class TopicExchange::TopicExchangeTester { - -class boundNode; - -public: - typedef std::vector BindingVec; - typedef TopicKeyNode TestBindingNode; - -private: - // Target class to be bound into topic key tree - class boundNode { - public: - BindingVec bindingVector; - }; - - // Acl binding trees contain only one node each. - // When the iterator sees it then the node matches the caller's spec. - class TestFinder : public TestBindingNode::TreeIterator { - public: - TestFinder(BindingVec& m) : bv(m), found(false) {}; - ~TestFinder() {}; - bool visit(TestBindingNode& /*node*/) { - assert(!found); - found = true; - return true; - } - BindingVec& bv; - bool found; - }; - -public: - TopicExchangeTester() {}; - ~TopicExchangeTester() {}; - bool addBindingKey(const std::string& bKey) { - std::string routingPattern = normalize(bKey); - boundNode *mbn = bindingTree.add(routingPattern); - if (mbn) { - // push a dummy binding to mark this node as "non-leaf" - mbn->bindingVector.push_back(true); - return true; - } - return false; - } - - bool findMatches(const std::string& rKey, BindingVec& matches) { - TestFinder testFinder(matches); - bindingTree.iterateMatch( rKey, testFinder ); - return testFinder.found; - } - -private: - TestBindingNode bindingTree; -}; -}} // namespace qpid::broker - -#endif // QPID_ACL_TOPIC_MATCH_H diff --git a/qpid/cpp/src/qpid/acl/AclValidator.cpp b/qpid/cpp/src/qpid/acl/AclValidator.cpp deleted file mode 100644 index f905b4aca5..0000000000 --- a/qpid/cpp/src/qpid/acl/AclValidator.cpp +++ /dev/null @@ -1,536 +0,0 @@ -/* - * - * 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/acl/AclValidator.h" -#include "qpid/acl/AclData.h" -#include "qpid/acl/AclLexer.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/StringUtils.h" -#include -#include -#include -#include -#include - -namespace qpid { -namespace acl { - - AclValidator::IntPropertyType::IntPropertyType(int64_t i,int64_t j) : min(i), max(j){ - } - - bool AclValidator::IntPropertyType::validate(const std::string& val) { - int64_t v; - try - { - v = boost::lexical_cast(val); - }catch(const boost::bad_lexical_cast&){ - return 0; - } - - if (v < min || v >= max){ - return 0; - }else{ - return 1; - } - } - - std::string AclValidator::IntPropertyType::allowedValues() { - return "values should be between " + - boost::lexical_cast(min) + " and " + - boost::lexical_cast(max); - } - - AclValidator::EnumPropertyType::EnumPropertyType(std::vector& allowed): values(allowed){ - } - - bool AclValidator::EnumPropertyType::validate(const std::string& val) { - for (std::vector::iterator itr = values.begin(); itr != values.end(); ++itr ){ - if (val.compare(*itr) == 0){ - return 1; - } - } - - return 0; - } - - std::string AclValidator::EnumPropertyType::allowedValues() { - std::ostringstream oss; - oss << "possible values are one of { "; - for (std::vector::iterator itr = values.begin(); itr != values.end(); itr++ ){ - oss << "'" << *itr << "' "; - } - oss << "}"; - return oss.str(); - } - - AclValidator::AclValidator() : propertyIndex(1) { - validators.insert(Validator(acl::SPECPROP_MAXQUEUESIZELOWERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXQUEUESIZEUPPERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXQUEUECOUNTLOWERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXQUEUECOUNTUPPERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXFILESIZELOWERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXFILESIZEUPPERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXFILECOUNTLOWERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXFILECOUNTUPPERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXPAGESLOWERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXPAGESUPPERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXPAGEFACTORLOWERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - validators.insert(Validator(acl::SPECPROP_MAXPAGEFACTORUPPERLIMIT, - boost::shared_ptr( - new IntPropertyType(0,std::numeric_limits::max())))); - - std::string policyTypes[] = {"ring", "self-destruct", "reject"}; - std::vector v(policyTypes, policyTypes + sizeof(policyTypes) / sizeof(std::string)); - validators.insert(Validator(acl::SPECPROP_POLICYTYPE, - boost::shared_ptr( - new EnumPropertyType(v)))); - - // Insert allowed action/object/property sets (generated manually 20140712) -#define RP registerProperties - RP( "Broker::getTimestampConfig", - "User querying message timestamp setting ", - ACT_ACCESS, OBJ_BROKER); - RP( "ExchangeHandlerImpl::query", - "AMQP 0-10 protocol received 'query' ", - ACT_ACCESS, OBJ_EXCHANGE, "name"); - RP( "ExchangeHandlerImpl::bound", - "AMQP 0-10 query binding ", - ACT_ACCESS, OBJ_EXCHANGE, "name queuename routingkey"); - RP( "ExchangeHandlerImpl::declare", - "AMQP 0-10 exchange declare ", - ACT_ACCESS, OBJ_EXCHANGE, "name type alternate durable autodelete"); - RP( "Authorise::access", - "AMQP 1.0 exchange access ", - ACT_ACCESS, OBJ_EXCHANGE, "name type durable"); - RP( "Authorise::access", - "AMQP 1.0 node resolution ", - ACT_ACCESS, OBJ_EXCHANGE, "name"); - RP( "ManagementAgent::handleMethodRequest", - "Management method request ", - ACT_ACCESS, OBJ_METHOD, "name schemapackage schemaclass"); - RP( "ManagementAgent::authorizeAgentMessage", - "Management agent method request ", - ACT_ACCESS, OBJ_METHOD, "name schemapackage schemaclass"); - RP( "ManagementAgent::handleGetQuery", - "Management agent query ", - ACT_ACCESS, OBJ_QUERY, "name schemaclass"); - RP( "Broker::queryQueue", - "QMF 'query queue' method ", - ACT_ACCESS, OBJ_QUEUE, "name"); - RP( "QueueHandlerImpl::query", - "AMQP 0-10 query ", - ACT_ACCESS, OBJ_QUEUE, "name"); - RP( "QueueHandlerImpl::declare", - "AMQP 0-10 queue declare ", - ACT_ACCESS, OBJ_QUEUE, "name alternate durable exclusive autodelete policytype maxqueuecount maxqueuesize"); - RP( "Authorise::access", - "AMQP 1.0 queue access ", - ACT_ACCESS, OBJ_QUEUE, "name alternate durable exclusive autodelete policytype maxqueuecount maxqueuesize"); - RP( "Authorise::access", - "AMQP 1.0 node resolution ", - ACT_ACCESS, OBJ_QUEUE, "name"); - RP( "Broker::bind", - "AMQP 0-10 or QMF bind request ", - ACT_BIND, OBJ_EXCHANGE, "name queuename routingkey"); - RP( "Authorise::outgoing", - "AMQP 1.0 new outgoing link from exchange", - ACT_BIND, OBJ_EXCHANGE, "name queuename routingkey"); - RP( "MessageHandlerImpl::subscribe", - "AMQP 0-10 subscribe request ", - ACT_CONSUME, OBJ_QUEUE, "name"); - RP( "Authorise::outgoing", - "AMQP 1.0 new outgoing link from queue ", - ACT_CONSUME, OBJ_QUEUE, "name"); - RP( "ConnectionHandler", - "TCP/IP connection creation ", - ACT_CREATE, OBJ_CONNECTION, "host"); - RP( "Broker::createExchange", - "Create exchange ", - ACT_CREATE, OBJ_EXCHANGE, "name type alternate durable autodelete"); - RP( "ConnectionHandler::Handler::open", - "Interbroker link creation ", - ACT_CREATE, OBJ_LINK); - RP( "Authorise::interlink", - "Interbroker link creation ", - ACT_CREATE, OBJ_LINK); - RP( "Broker::createQueue", - "Create queue ", - ACT_CREATE, OBJ_QUEUE, "name alternate durable exclusive autodelete policytype paging maxpages maxpagefactor maxqueuecount maxqueuesize maxfilecount maxfilesize"); - RP( "Broker::deleteExchange", - "Delete exchange ", - ACT_DELETE, OBJ_EXCHANGE, "name type alternate durable"); - RP( "Broker::deleteQueue", - "Delete queue ", - ACT_DELETE, OBJ_QUEUE, "name alternate durable exclusive autodelete policytype"); - RP( "Broker::queueMoveMessages", - "Management 'move queue' request ", - ACT_MOVE, OBJ_QUEUE, "name queuename"); - RP( "SemanticState::route", - "AMQP 0-10 received message processing ", - ACT_PUBLISH, OBJ_EXCHANGE, "name routingkey"); - RP( "Authorise::incoming", - "AMQP 1.0 establish sender link to queue ", - ACT_PUBLISH, OBJ_EXCHANGE, "routingkey"); - RP( "Authorise::route", - "AMQP 1.0 received message processing ", - ACT_PUBLISH, OBJ_EXCHANGE, "name routingkey"); - RP( "Queue::ManagementMethod", - "Management 'purge queue' request ", - ACT_PURGE, OBJ_QUEUE, "name"); - RP( "QueueHandlerImpl::purge", - "Management 'purge queue' request ", - ACT_PURGE, OBJ_QUEUE, "name"); - RP( "Broker::queueRedirect", - "Management 'redirect queue' request ", - ACT_REDIRECT,OBJ_QUEUE, "name queuename"); - RP( "Queue::ManagementMethod", - "Management 'reroute queue' request ", - ACT_REROUTE, OBJ_QUEUE, "name exchangename"); - RP( "Broker::unbind", - "Management 'unbind exchange' request ", - ACT_UNBIND, OBJ_EXCHANGE, "name queuename routingkey"); - RP( "Broker::setTimestampConfig", - "User modifying message timestamp setting", - ACT_UPDATE, OBJ_BROKER); - } - - AclValidator::~AclValidator(){ - } - - /* Iterate through the data model and validate the parameters. */ - void AclValidator::validate(boost::shared_ptr d) { - - for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++){ - - if (d->actionList[cnt]){ - - for (unsigned int cnt1=0; cnt1< qpid::acl::OBJECTSIZE; cnt1++){ - - if (d->actionList[cnt][cnt1]){ - - std::for_each(d->actionList[cnt][cnt1]->begin(), - d->actionList[cnt][cnt1]->end(), - boost::bind(&AclValidator::validateRuleSet, this, _1)); - } - } - } - } - } - - void AclValidator::validateRuleSet(std::pair& rules){ - std::for_each(rules.second.begin(), - rules.second.end(), - boost::bind(&AclValidator::validateRule, this, _1)); - } - - void AclValidator::validateRule(qpid::acl::AclData::Rule& rule){ - std::for_each(rule.props.begin(), - rule.props.end(), - boost::bind(&AclValidator::validateProperty, this, _1)); - } - - void AclValidator::validateProperty(std::pair& prop){ - ValidatorItr itr = validators.find(prop.first); - if (itr != validators.end()){ - QPID_LOG(debug,"ACL: Found validator for property '" << acl::AclHelper::getPropertyStr(itr->first) - << "'. " << itr->second->allowedValues()); - - if (!itr->second->validate(prop.second)){ - QPID_LOG(debug, "ACL: Property failed validation. '" << prop.second << "' is not a valid value for '" - << AclHelper::getPropertyStr(prop.first) << "'"); - - throw Exception( prop.second + " is not a valid value for '" + - AclHelper::getPropertyStr(prop.first) + "', " + - itr->second->allowedValues()); - } - } - } - - /** - * validateAllowedProperties - * verify that at least one lookup definition can satisfy this - * action/object/props tuple. - * Return false and conditionally emit a warning log entry if the - * incoming definition can not be matched. - */ - bool AclValidator::validateAllowedProperties(qpid::acl::Action action, - qpid::acl::ObjectType object, - const AclData::specPropertyMap& props, - bool emitLog) const { - // No rules defined means no match - if (!allowedSpecProperties[action][object].get()) { - if (emitLog) { - QPID_LOG(warning, "ACL rule ignored: Broker never checks for rules with action: '" - << AclHelper::getActionStr(action) << "' and object: '" - << AclHelper::getObjectTypeStr(object) << "'"); - } - return false; - } - // two empty property sets is a match - if (allowedSpecProperties[action][object]->size() == 0) { - if ((props.size() == 0) || - (props.size() == 1 && props.find(acl::SPECPROP_NAME) != props.end())) { - return true; - } - } - // Scan vector of rules looking for one that matches all properties - bool validRuleFound = false; - for (std::vector::const_iterator - ruleItr = allowedSpecProperties[action][object]->begin(); - ruleItr != allowedSpecProperties[action][object]->end() && !validRuleFound; - ruleItr++) { - // Scan one rule - validRuleFound = true; - for(AclData::specPropertyMapItr itr = props.begin(); - itr != props.end(); - itr++) { - if ((*itr).first != acl::SPECPROP_NAME && - ruleItr->props.find((*itr).first) == - ruleItr->props.end()) { - // Test property not found in this rule - validRuleFound = false; - break; - } - } - } - if (!validRuleFound) { - if (emitLog) { - QPID_LOG(warning, "ACL rule ignored: Broker checks for rules with action: '" - << AclHelper::getActionStr(action) << "' and object: '" - << AclHelper::getObjectTypeStr(object) - << "' but will never match with property set: " - << AclHelper::propertyMapToString(&props)); - } - return false; - } - return true; - } - - /** - * Return a list of indexes of definitions that this lookup might match - */ - void AclValidator::findPossibleLookupMatch(qpid::acl::Action action, - qpid::acl::ObjectType object, - const AclData::specPropertyMap& props, - std::vector& result) const { - if (!allowedSpecProperties[action][object].get()) { - return; - } else { - // Scan vector of rules returning the indexes of all that match - bool validRuleFound; - for (std::vector::const_iterator - ruleItr = allowedSpecProperties[action][object]->begin(); - ruleItr != allowedSpecProperties[action][object]->end(); - ruleItr++) { - // Scan one rule - validRuleFound = true; - for(AclData::specPropertyMapItr - itr = props.begin(); itr != props.end(); itr++) { - if ((*itr).first != acl::SPECPROP_NAME && - ruleItr->props.find((*itr).first) == - ruleItr->props.end()) { - // Test property not found in this rule - validRuleFound = false; - break; - } - } - if (validRuleFound) { - result.push_back(ruleItr->rawRuleNum); - } - } - } - return; - } - - /** - * Emit trace log of original property definitions - */ - void AclValidator::tracePropertyDefs() { - QPID_LOG(trace, "ACL: Definitions of action, object, (allowed properties) lookups"); - for (int iA=0; iA::const_iterator - ruleItr = allowedSpecProperties[iA][iO]->begin(); - ruleItr != allowedSpecProperties[iA][iO]->end(); - ruleItr++) { - std::string pstr; - for (AclData::specPropertyMapItr pMItr = ruleItr->props.begin(); - pMItr != ruleItr->props.end(); - pMItr++) { - pstr += AclHelper::getPropertyStr((SpecProperty) pMItr-> first); - pstr += ","; - } - QPID_LOG(trace, "ACL: Lookup " - << std::setfill(' ') << std::setw(2) - << ruleItr->rawRuleNum << ": " - << ruleItr->lookupHelp << " " - << std::setfill(' ') << std::setw(acl::ACTION_STR_WIDTH +1) << std::left - << AclHelper::getActionStr(acl::Action(iA)) - << std::setfill(' ') << std::setw(acl::OBJECTTYPE_STR_WIDTH) << std::left - << AclHelper::getObjectTypeStr(acl::ObjectType(iO)) - << " (" << pstr.substr(0, pstr.length()-1) << ")"); - } - } - } - } - } - - /** - * Construct a record of all the calls that the broker will - * make to acl::authorize and the properties for each call. - * From that create the list of all the spec properties that - * users are then allowed to specify in acl rule files. - */ - void AclValidator::registerProperties( - const std::string& source, - const std::string& description, - Action action, - ObjectType object, - const std::string& properties) { - if (!allowedProperties[action][object].get()) { - boost::shared_ptr > t1(new std::set()); - allowedProperties[action][object] = t1; - boost::shared_ptr > t2(new std::vector()); - allowedSpecProperties[action][object] = t2; - } - std::vector props = split(properties, " "); - AclData::specPropertyMap spm; - for (size_t i=0; iinsert(prop); - // Given that the broker will be calling with this property, - // determine what user rule settings are allowed. - switch (prop) { - // Cases where broker and Acl file share property name and meaning - case PROP_NAME: - spm[SPECPROP_NAME]=""; - break; - case PROP_DURABLE: - spm[SPECPROP_DURABLE]=""; - break; - case PROP_OWNER: - spm[SPECPROP_OWNER]=""; - break; - case PROP_ROUTINGKEY: - spm[SPECPROP_ROUTINGKEY]=""; - break; - case PROP_AUTODELETE: - spm[SPECPROP_AUTODELETE]=""; - break; - case PROP_EXCLUSIVE: - spm[SPECPROP_EXCLUSIVE]=""; - break; - case PROP_TYPE: - spm[SPECPROP_TYPE]=""; - break; - case PROP_ALTERNATE: - spm[SPECPROP_ALTERNATE]=""; - break; - case PROP_QUEUENAME: - spm[SPECPROP_QUEUENAME]=""; - break; - case PROP_EXCHANGENAME: - spm[SPECPROP_EXCHANGENAME]=""; - break; - case PROP_SCHEMAPACKAGE: - spm[SPECPROP_SCHEMAPACKAGE]=""; - break; - case PROP_SCHEMACLASS: - spm[SPECPROP_SCHEMACLASS]=""; - break; - case PROP_POLICYTYPE: - spm[SPECPROP_POLICYTYPE]=""; - break; - case PROP_PAGING: - spm[SPECPROP_PAGING]=""; - break; - case PROP_HOST: - spm[SPECPROP_HOST]=""; - break; - // Cases where broker supplies a property but Acl has upper/lower limit for it - case PROP_MAXPAGES: - spm[SPECPROP_MAXPAGESLOWERLIMIT]=""; - spm[SPECPROP_MAXPAGESUPPERLIMIT]=""; - break; - case PROP_MAXPAGEFACTOR: - spm[SPECPROP_MAXPAGEFACTORLOWERLIMIT]=""; - spm[SPECPROP_MAXPAGEFACTORUPPERLIMIT]=""; - break; - case PROP_MAXQUEUESIZE: - spm[SPECPROP_MAXQUEUESIZELOWERLIMIT]=""; - spm[SPECPROP_MAXQUEUESIZEUPPERLIMIT]=""; - break; - case PROP_MAXQUEUECOUNT: - spm[SPECPROP_MAXQUEUECOUNTLOWERLIMIT]=""; - spm[SPECPROP_MAXQUEUECOUNTUPPERLIMIT]=""; - break; - case PROP_MAXFILESIZE: - spm[SPECPROP_MAXFILESIZELOWERLIMIT]=""; - spm[SPECPROP_MAXFILESIZEUPPERLIMIT]=""; - break; - case PROP_MAXFILECOUNT: - spm[SPECPROP_MAXFILECOUNTLOWERLIMIT]=""; - spm[SPECPROP_MAXFILECOUNTUPPERLIMIT]=""; - break; - default: - throw Exception( "acl::RegisterProperties no case for property: " + - AclHelper::getPropertyStr(prop) ); - } - } - AclData::Rule someProps(propertyIndex, acl::ALLOW, spm, source, description); - propertyIndex++; - allowedSpecProperties[action][object]->push_back(someProps); - } - -}} diff --git a/qpid/cpp/src/qpid/acl/AclValidator.h b/qpid/cpp/src/qpid/acl/AclValidator.h deleted file mode 100644 index 8f555797c2..0000000000 --- a/qpid/cpp/src/qpid/acl/AclValidator.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef QPID_ACL_ACLVALIDATOR_H -#define QPID_ACL_ACLVALIDATOR_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/broker/AclModule.h" -#include "qpid/acl/AclData.h" -#include "qpid/sys/IntegerTypes.h" -#include -#include -#include -#include - -namespace qpid { -namespace acl { - -class AclValidator { - - /* Base Property */ - class PropertyType{ - - public: - virtual ~PropertyType(){}; - virtual bool validate(const std::string& val)=0; - virtual std::string allowedValues()=0; - }; - - class IntPropertyType : public PropertyType{ - int64_t min; - int64_t max; - - public: - IntPropertyType(int64_t min,int64_t max); - virtual ~IntPropertyType (){}; - virtual bool validate(const std::string& val); - virtual std::string allowedValues(); - }; - - class EnumPropertyType : public PropertyType{ - std::vector values; - - public: - EnumPropertyType(std::vector& allowed); - virtual ~EnumPropertyType (){}; - virtual bool validate(const std::string& val); - virtual std::string allowedValues(); - }; - - typedef std::pair > Validator; - typedef std::map > ValidatorMap; - typedef ValidatorMap::iterator ValidatorItr; - typedef boost::shared_ptr > AllowedProperties [ACTIONSIZE][OBJECTSIZE]; - typedef boost::shared_ptr > AllowedSpecProperties[ACTIONSIZE][OBJECTSIZE]; - - ValidatorMap validators; - AllowedProperties allowedProperties; - AllowedSpecProperties allowedSpecProperties; - -public: - - void validateRuleSet(std::pair& rules); - void validateRule(qpid::acl::AclData::Rule& rule); - void validateProperty(std::pair& prop); - void validate(boost::shared_ptr d); - bool validateAllowedProperties(qpid::acl::Action action, - qpid::acl::ObjectType object, - const AclData::specPropertyMap& props, - bool emitLog) const; - void findPossibleLookupMatch(qpid::acl::Action action, - qpid::acl::ObjectType object, - const AclData::specPropertyMap& props, - std::vector& result) const; - void tracePropertyDefs(); - - AclValidator(); - ~AclValidator(); - -private: - void registerProperties(const std::string& source, - const std::string& description, - Action action, - ObjectType object, - const std::string& properties = ""); - int propertyIndex; -}; - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACLVALIDATOR_H diff --git a/qpid/cpp/src/qpid/acl/management-schema.xml b/qpid/cpp/src/qpid/acl/management-schema.xml deleted file mode 100644 index 2ac20bb324..0000000000 --- a/qpid/cpp/src/qpid/acl/management-schema.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qpid/cpp/src/qpid/amqp/CharSequence.cpp b/qpid/cpp/src/qpid/amqp/CharSequence.cpp deleted file mode 100644 index ad5b0ec84c..0000000000 --- a/qpid/cpp/src/qpid/amqp/CharSequence.cpp +++ /dev/null @@ -1,65 +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 "CharSequence.h" - -namespace qpid { -namespace amqp { - -void CharSequence::init() -{ - data = 0; - size = 0; -} - -CharSequence::operator bool() const -{ - return data && size; -} -std::string CharSequence::str() const -{ - return (data && size) ? std::string(data, size) : std::string(); -} - -CharSequence CharSequence::create() -{ - CharSequence c = {0, 0}; - return c; -} - -CharSequence CharSequence::create(const std::string& str) -{ - CharSequence c = {str.data(), str.size()}; - return c; -} - -CharSequence CharSequence::create(const char* data, size_t size) -{ - CharSequence c = {data, size}; - return c; -} - -CharSequence CharSequence::create(const unsigned char* data, size_t size) -{ - CharSequence c = {reinterpret_cast(data), size}; - return c; -} - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/CharSequence.h b/qpid/cpp/src/qpid/amqp/CharSequence.h deleted file mode 100644 index 752097c913..0000000000 --- a/qpid/cpp/src/qpid/amqp/CharSequence.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_AMQP_CHARSEQUENCE_H -#define QPID_AMQP_CHARSEQUENCE_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 -#include -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace amqp { - -/** - * Simple record of a particular sequence of chars/bytes. The memroy - * referenced is assumed to be owned by some other entity, this is - * merely a pointer into a (segment of) it. - */ -struct CharSequence -{ - const char* data; - size_t size; - - QPID_COMMON_EXTERN operator bool() const; - QPID_COMMON_EXTERN std::string str() const; - QPID_COMMON_EXTERN void init(); - - QPID_COMMON_EXTERN static CharSequence create(); - QPID_COMMON_EXTERN static CharSequence create(const std::string& str); - QPID_COMMON_EXTERN static CharSequence create(const char* data, size_t size); - QPID_COMMON_EXTERN static CharSequence create(const unsigned char* data, size_t size); -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_CHARSEQUENCE_H*/ diff --git a/qpid/cpp/src/qpid/amqp/Codec.h b/qpid/cpp/src/qpid/amqp/Codec.h deleted file mode 100644 index c91cd0a96b..0000000000 --- a/qpid/cpp/src/qpid/amqp/Codec.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QPID_AMQP_CODEC_H -#define QPID_AMQP_CODEC_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 amqp { - -/** - * - */ -class Codec -{ - public: - - - - private: - - struct Constructor - { - uint8_t code; - Descriptor descriptor; - bool isDescribed; - }; - - Constructor readConstructor(Decoder decoder, Reader reader) - { - Constructor result; - result.code = decoder.readCode(); - if (code == DESCRIPTOR) { - result.isDescribed = true; - result.descriptor = decoder.readDescriptor(); - result.code = decoder.readCode(); - } else { - result.isDescribed = false; - } - return result; - } -}; - -Codec::Descriptor Codec::Decoder::readDescriptor() -{ - uint8_t code = decoder.readCode(); - switch(code) { - case SYMBOL8: - return Descriptor(readSequence8()); - case SYMBOL32: - return Descriptor(readSequence32()); - case ULONG: - return Descriptor(readULong()); - case ULONG_SMALL: - return Descriptor((uint64_t) readUByte()); - case ULONG_ZERO: - return Descriptor((uint64_t) 0); - default: - throw qpid::Exception("Expected descriptor of type ulong or symbol; found " << code); - } -} - -Codec::Descriptor::Descriptor(uint64_t id) : value.id(id), type(NUMERIC) {} -Codec::Descriptor::Descriptor(const CharSequence& symbol) : value.symbol(symbol), type(SYMBOLIC) {} -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_CODEC_H*/ diff --git a/qpid/cpp/src/qpid/amqp/Constructor.h b/qpid/cpp/src/qpid/amqp/Constructor.h deleted file mode 100644 index 444e455670..0000000000 --- a/qpid/cpp/src/qpid/amqp/Constructor.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_AMQP_CONSTRUCTOR_H -#define QPID_AMQP_CONSTRUCTOR_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/amqp/Descriptor.h" -namespace qpid { -namespace amqp { - -/** - * Representation of an AMQP 1.0 type 'constructor' (i.e. a type code - * with an optional descriptor) - */ -struct Constructor -{ - uint8_t code; - Descriptor descriptor; - bool isDescribed; - - Constructor(uint8_t c) : code(c), descriptor(0), isDescribed(false) {} -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_CONSTRUCTOR_H*/ diff --git a/qpid/cpp/src/qpid/amqp/DataBuilder.cpp b/qpid/cpp/src/qpid/amqp/DataBuilder.cpp deleted file mode 100644 index aeb9b9c612..0000000000 --- a/qpid/cpp/src/qpid/amqp/DataBuilder.cpp +++ /dev/null @@ -1,196 +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 "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: - if (nested.size() > 1 || nested.top()->asMap().size() > 0) { - QPID_LOG(error, QPID_MSG("Expecting map key; got " << n << " " << *(nested.top()))); - } - 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 deleted file mode 100644 index 51ee3da5f8..0000000000 --- a/qpid/cpp/src/qpid/amqp/DataBuilder.h +++ /dev/null @@ -1,79 +0,0 @@ -#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 - -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 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 deleted file mode 100644 index 53cd367c25..0000000000 --- a/qpid/cpp/src/qpid/amqp/Decoder.cpp +++ /dev/null @@ -1,448 +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/amqp/Decoder.h" -#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" -#include "qpid/types/Variant.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" - -namespace qpid { -namespace amqp { - -using namespace qpid::amqp::typecodes; - -Decoder::Decoder(const char* d, size_t s) : start(d), size(s), position(0), current(0) {} - -void Decoder::readMap(qpid::types::Variant::Map& map) -{ - MapBuilder builder; - read(builder); - map = builder.getMap(); -} - -qpid::types::Variant::Map Decoder::readMap() -{ - qpid::types::Variant::Map map; - readMap(map); - return map; -} - -void Decoder::read(Reader& reader) -{ - while (available() && reader.proceed()) { - readOne(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); -} - -void Decoder::readValue(Reader& reader, uint8_t code, const Descriptor* descriptor) -{ - switch(code) { - case NULL_VALUE: - reader.onNull(descriptor); - break; - case BOOLEAN: - reader.onBoolean(readBoolean(), descriptor); - break; - case BOOLEAN_TRUE: - reader.onBoolean(true, descriptor); - break; - case BOOLEAN_FALSE: - reader.onBoolean(false, descriptor); - break; - case UBYTE: - reader.onUByte(readUByte(), descriptor); - break; - case USHORT: - reader.onUShort(readUShort(), descriptor); - break; - case UINT: - reader.onUInt(readUInt(), descriptor); - break; - case UINT_SMALL: - reader.onUInt(readUByte(), descriptor); - break; - case UINT_ZERO: - reader.onUInt(0, descriptor); - break; - case ULONG: - reader.onULong(readULong(), descriptor); - break; - case ULONG_SMALL: - reader.onULong(readUByte(), descriptor); - break; - case ULONG_ZERO: - reader.onULong(0, descriptor); - break; - case BYTE: - reader.onByte(readByte(), descriptor); - break; - case SHORT: - reader.onShort(readShort(), descriptor); - break; - case INT: - reader.onInt(readInt(), descriptor); - break; - case INT_SMALL: - reader.onInt(readByte(), descriptor); - break; - case LONG: - reader.onLong(readLong(), descriptor); - break; - case LONG_SMALL: - reader.onLong(readByte(), descriptor); - break; - case FLOAT: - reader.onFloat(readFloat(), descriptor); - break; - case DOUBLE: - reader.onDouble(readDouble(), descriptor); - break; - case UUID: - reader.onUuid(readRawUuid(), descriptor); - break; - case TIMESTAMP: - reader.onTimestamp(readLong(), descriptor); - break; - - case BINARY8: - reader.onBinary(readSequence8(), descriptor); - break; - case BINARY32: - reader.onBinary(readSequence32(), descriptor); - break; - case STRING8: - reader.onString(readSequence8(), descriptor); - break; - case STRING32: - reader.onString(readSequence32(), descriptor); - break; - case SYMBOL8: - reader.onSymbol(readSequence8(), descriptor); - break; - case SYMBOL32: - reader.onSymbol(readSequence32(), descriptor); - break; - - case LIST0: - reader.onStartList(0, CharSequence::create(), getCurrent(0), descriptor); - reader.onEndList(0, descriptor); - break; - case LIST8: - readList8(reader, descriptor); - break; - case LIST32: - readList32(reader, descriptor); - break; - case MAP8: - readMap8(reader, descriptor); - break; - case MAP32: - readMap32(reader, descriptor); - break; - case ARRAY8: - readArray8(reader, descriptor); - break; - case ARRAY32: - readArray32(reader, descriptor); - break; - default: - break; - } -} - -void Decoder::readList8(Reader& reader, const Descriptor* descriptor) -{ - uint8_t size = readUByte(); - uint8_t count = readUByte(); - readList(reader, size-sizeof(size), count, descriptor); -} - -void Decoder::readList32(Reader& reader, const Descriptor* descriptor) -{ - uint32_t size = readUInt(); - uint32_t count = readUInt(); - readList(reader, size-sizeof(size), count, descriptor); -} - -void Decoder::readMap8(Reader& reader, const Descriptor* descriptor) -{ - uint8_t size = readUByte(); - uint8_t count = readUByte(); - readMap(reader, size-sizeof(size), count, descriptor); -} - -void Decoder::readMap32(Reader& reader, const Descriptor* descriptor) -{ - uint32_t size = readUInt(); - uint32_t count = readUInt(); - readMap(reader, size-sizeof(size), count, descriptor); -} - -void Decoder::readArray8(Reader& reader, const Descriptor* descriptor) -{ - uint8_t size = readUByte(); - uint8_t count = readUByte(); - readArray(reader, size-sizeof(size), count, descriptor); -} - -void Decoder::readArray32(Reader& reader, const Descriptor* descriptor) -{ - uint32_t size = readUInt(); - uint32_t count = readUInt(); - readArray(reader, size-sizeof(size), count, descriptor); -} - -void Decoder::readList(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor) -{ - if (reader.onStartList(count, CharSequence::create(data(), size), getCurrent(size), descriptor)) { - for (uint32_t i = 0; i < count; ++i) { - readOne(reader); - } - reader.onEndList(count, descriptor); - } else { - //skip - advance(size); - } -} -void Decoder::readMap(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor) -{ - if (reader.onStartMap(count, CharSequence::create(data(), size), getCurrent(size), descriptor)) { - for (uint32_t i = 0; i < count; ++i) { - readOne(reader); - } - reader.onEndMap(count, descriptor); - } else { - //skip - advance(size); - } -} - -void Decoder::readArray(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor) -{ - size_t temp = position; - Constructor constructor = readConstructor(); - CharSequence raw = CharSequence::create(data(), size-(position-temp)); - if (reader.onStartArray(count, raw, constructor, descriptor)) { - for (uint32_t i = 0; i < count; ++i) { - readValue(reader, constructor.code, constructor.isDescribed ? &constructor.descriptor : 0); - } - reader.onEndArray(count, descriptor); - } else { - //skip - advance(raw.size); - } -} - - -Constructor Decoder::readConstructor() -{ - Constructor result(readCode()); - if (result.code == DESCRIPTOR) { - result.isDescribed = true; - result.descriptor = readDescriptor(); - result.code = readCode(); - for (Descriptor* d = &result.descriptor; result.code == DESCRIPTOR; result.code = readCode()) { - d = d->nest(readDescriptor()); - } - } else { - result.isDescribed = false; - } - return result; -} - -Descriptor Decoder::readDescriptor() -{ - uint8_t code = readCode(); - switch(code) { - case SYMBOL8: - return Descriptor(readSequence8()); - case SYMBOL32: - return Descriptor(readSequence32()); - case ULONG: - return Descriptor(readULong()); - case ULONG_SMALL: - return Descriptor((uint64_t) readUByte()); - case ULONG_ZERO: - return Descriptor((uint64_t) 0); - default: - throw qpid::Exception(QPID_MSG("Expected descriptor of type ulong or symbol; found " << (int)code)); - } -} - -void Decoder::advance(size_t n) -{ - if (n > available()) throw qpid::Exception(QPID_MSG("Out of Bounds: requested advance of " << n << " at " << position << " but only " << available() << " available")); - position += n; -} - -const char* Decoder::data() -{ - return start + position; -} - -size_t Decoder::available() -{ - return size - position; -} - -uint8_t Decoder::readCode() -{ - return readUByte(); -} - -bool Decoder::readBoolean() -{ - return readUByte(); -} - -uint8_t Decoder::readUByte() -{ - return static_cast(start[position++]); -} - -uint16_t Decoder::readUShort() -{ - uint16_t hi = (unsigned char) start[position++]; - hi = hi << 8; - hi |= (unsigned char) start[position++]; - return hi; -} - -uint32_t Decoder::readUInt() -{ - uint32_t a = (unsigned char) start[position++]; - uint32_t b = (unsigned char) start[position++]; - uint32_t c = (unsigned char) start[position++]; - uint32_t d = (unsigned char) start[position++]; - a = a << 24; - a |= b << 16; - a |= c << 8; - a |= d; - return a; -} - -uint64_t Decoder::readULong() -{ - uint64_t hi =readUInt(); - uint64_t lo = readUInt(); - hi = hi << 32; - return hi | lo; -} - -int8_t Decoder::readByte() -{ - return (int8_t) readUByte(); -} - -int16_t Decoder::readShort() -{ - return (int16_t) readUShort(); -} - -int32_t Decoder::readInt() -{ - return (int32_t) readUInt(); -} - -int64_t Decoder::readLong() -{ - return (int64_t) readULong(); -} - -float Decoder::readFloat() -{ - union { - uint32_t i; - float f; - } val; - val.i = readUInt(); - return val.f; -} - -double Decoder::readDouble() -{ - union { - uint64_t i; - double f; - } val; - val.i = readULong(); - return val.f; -} - -CharSequence Decoder::readSequence8() -{ - CharSequence s; - s.size = readUByte(); - s.data = start + position; - advance(s.size); - return s; -} - -CharSequence Decoder::readSequence32() -{ - CharSequence s; - s.size = readUInt(); - s.data = start + position; - advance(s.size); - return s; -} - -qpid::types::Uuid Decoder::readUuid() -{ - qpid::types::Uuid uuid(start + position); - advance(16); - return uuid; -} - -CharSequence Decoder::readRawUuid() -{ - CharSequence s; - s.data = start + position; - s.size = 16; - advance(s.size); - return s; -} - -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 deleted file mode 100644 index a78518be2b..0000000000 --- a/qpid/cpp/src/qpid/amqp/Decoder.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef QPID_AMQP_DECODER_H -#define QPID_AMQP_DECODER_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/CommonImportExport.h" -#include -#include -#include - -namespace qpid { -namespace types { -class Uuid; -class Variant; -} -namespace amqp { -struct CharSequence; -struct Constructor; -struct Descriptor; -class Reader; - -/** - * Class to assist in decoding an AMQP encoded data-stream. - */ -class Decoder -{ - public: - QPID_COMMON_EXTERN Decoder(const char*, size_t); - - QPID_COMMON_EXTERN size_t available(); - QPID_COMMON_EXTERN uint8_t readCode(); - - QPID_COMMON_EXTERN bool readBoolean(); - QPID_COMMON_EXTERN uint8_t readUByte(); - QPID_COMMON_EXTERN uint16_t readUShort(); - QPID_COMMON_EXTERN uint32_t readUInt(); - QPID_COMMON_EXTERN uint64_t readULong(); - QPID_COMMON_EXTERN int8_t readByte(); - QPID_COMMON_EXTERN int16_t readShort(); - QPID_COMMON_EXTERN int32_t readInt(); - QPID_COMMON_EXTERN int64_t readLong(); - QPID_COMMON_EXTERN float readFloat(); - QPID_COMMON_EXTERN double readDouble(); - QPID_COMMON_EXTERN qpid::types::Uuid readUuid(); - QPID_COMMON_EXTERN CharSequence readSequence8(); - QPID_COMMON_EXTERN CharSequence readSequence32(); - QPID_COMMON_EXTERN Descriptor readDescriptor(); - QPID_COMMON_EXTERN void read(Reader& reader); - - QPID_COMMON_EXTERN void readMap(std::map&); - QPID_COMMON_EXTERN std::map readMap(); - QPID_COMMON_EXTERN void advance(size_t); - QPID_COMMON_EXTERN size_t getPosition() const; - QPID_COMMON_EXTERN void resetSize(size_t size); - QPID_COMMON_EXTERN size_t getSize() const; - - private: - 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); - void readList(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor); - void readMap(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor); - void readArray(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor); - void readList8(Reader& reader, const Descriptor* descriptor); - void readList32(Reader& reader, const Descriptor* descriptor); - void readMap8(Reader& reader, const Descriptor* descriptor); - void readMap32(Reader& reader, const Descriptor* descriptor); - void readArray8(Reader& reader, const Descriptor* descriptor); - void readArray32(Reader& reader, const Descriptor* descriptor); - CharSequence readRawUuid(); - Constructor readConstructor(); - const char* data(); - CharSequence getCurrent(size_t remaining) const; -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_DECODER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/Descriptor.cpp b/qpid/cpp/src/qpid/amqp/Descriptor.cpp deleted file mode 100644 index 43d388ee76..0000000000 --- a/qpid/cpp/src/qpid/amqp/Descriptor.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "Descriptor.h" -#include "descriptors.h" -#include -#include - -namespace qpid { -namespace amqp { - -Descriptor::Descriptor(uint64_t code) : type(NUMERIC) { value.code = code; } - -Descriptor::Descriptor(const CharSequence& symbol) : type(SYMBOLIC) { value.symbol = symbol; } - -bool Descriptor::match(const std::string& symbol, uint64_t code) const -{ - switch (type) { - case SYMBOLIC: - return symbol.compare(0, symbol.size(), value.symbol.data, value.symbol.size) == 0; - case NUMERIC: - return code == value.code; - } - return false; -} - -size_t Descriptor::getSize() const -{ - size_t size = 1/*descriptor indicator*/ + 1/*type code*/; - switch (type) { - case Descriptor::NUMERIC: - if (value.code > 0) size += value.code < 256 ? 1/*encode as byte*/ : 8/*encode as long*/; - //else value will be indicated through ULONG_ZERO typecode - break; - case Descriptor::SYMBOLIC: - size += value.symbol.size < 256? 1/*size field is a byte*/ : 4/*size field is an int*/; - size += value.symbol.size; - break; - } - return size; -} - -Descriptor* Descriptor::nest(const Descriptor& d) -{ - nested = boost::shared_ptr(new Descriptor(0)); - *nested = d; - return nested.get(); -} - -namespace { - -class DescriptorMap { - typedef std::map SymbolMap; - typedef std::map CodeMap; - - SymbolMap symbols; - CodeMap codes; - - public: - DescriptorMap() { - symbols[message::HEADER_CODE] = message::HEADER_SYMBOL; - symbols[message::DELIVERY_ANNOTATIONS_CODE] = message::DELIVERY_ANNOTATIONS_SYMBOL; - symbols[message::MESSAGE_ANNOTATIONS_CODE] = message::MESSAGE_ANNOTATIONS_SYMBOL; - symbols[message::PROPERTIES_CODE] = message::PROPERTIES_SYMBOL; - symbols[message::APPLICATION_PROPERTIES_CODE] = message::APPLICATION_PROPERTIES_SYMBOL; - symbols[message::DATA_CODE] = message::DATA_SYMBOL; - symbols[message::AMQP_SEQUENCE_CODE] = message::AMQP_SEQUENCE_SYMBOL; - symbols[message::AMQP_VALUE_CODE] = message::AMQP_VALUE_SYMBOL; - symbols[message::FOOTER_CODE] = message::FOOTER_SYMBOL; - symbols[message::ACCEPTED_CODE] = message::ACCEPTED_SYMBOL; - symbols[sasl::SASL_MECHANISMS_CODE] = sasl::SASL_MECHANISMS_SYMBOL; - symbols[sasl::SASL_INIT_CODE] = sasl::SASL_INIT_SYMBOL; - symbols[sasl::SASL_CHALLENGE_CODE] = sasl::SASL_CHALLENGE_SYMBOL; - symbols[sasl::SASL_RESPONSE_CODE] = sasl::SASL_RESPONSE_SYMBOL; - symbols[sasl::SASL_OUTCOME_CODE] = sasl::SASL_OUTCOME_SYMBOL; - symbols[filters::LEGACY_DIRECT_FILTER_CODE] = filters::LEGACY_DIRECT_FILTER_SYMBOL; - symbols[filters::LEGACY_TOPIC_FILTER_CODE] = filters::LEGACY_TOPIC_FILTER_SYMBOL; - symbols[filters::LEGACY_HEADERS_FILTER_CODE] = filters::LEGACY_HEADERS_FILTER_SYMBOL; - symbols[filters::SELECTOR_FILTER_CODE] = filters::SELECTOR_FILTER_SYMBOL; - symbols[filters::XQUERY_FILTER_CODE] = filters::XQUERY_FILTER_SYMBOL; - symbols[lifetime_policy::DELETE_ON_CLOSE_CODE] = lifetime_policy::DELETE_ON_CLOSE_SYMBOL; - symbols[lifetime_policy::DELETE_ON_NO_LINKS_CODE] = lifetime_policy::DELETE_ON_NO_LINKS_SYMBOL; - symbols[lifetime_policy::DELETE_ON_NO_MESSAGES_CODE] = lifetime_policy::DELETE_ON_NO_MESSAGES_SYMBOL; - symbols[lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_CODE] = lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_SYMBOL; - symbols[transaction::DECLARE_CODE] = transaction::DECLARE_SYMBOL; - symbols[transaction::DISCHARGE_CODE] = transaction::DISCHARGE_SYMBOL; - symbols[transaction::DECLARED_CODE] = transaction::DECLARED_SYMBOL; - symbols[transaction::TRANSACTIONAL_STATE_CODE] = transaction::TRANSACTIONAL_STATE_SYMBOL; - symbols[0] = "unknown-descriptor"; - - for (SymbolMap::const_iterator i = symbols.begin(); i != symbols.end(); ++i) - codes[i->second] = i->first; - } - - std::string operator[](uint64_t code) const { - SymbolMap::const_iterator i = symbols.find(code); - return (i == symbols.end()) ? "unknown-descriptor" : i->second; - } - - uint64_t operator[](const std::string& symbol) const { - CodeMap::const_iterator i = codes.find(symbol); - return (i == codes.end()) ? 0 : i->second; - } -}; - -DescriptorMap DESCRIPTOR_MAP; -} - -std::string Descriptor::symbol() const { - switch (type) { - case Descriptor::NUMERIC: return DESCRIPTOR_MAP[value.code]; - case Descriptor::SYMBOLIC: return value.symbol.str(); - } - assert(0); - return std::string(); -} - -uint64_t Descriptor::code() const { - switch (type) { - case Descriptor::NUMERIC: return value.code; - case Descriptor::SYMBOLIC: return DESCRIPTOR_MAP[value.symbol.str()]; - } - assert(0); - return 0; -} - -std::ostream& operator<<(std::ostream& os, const Descriptor& d) { - return os << d.symbol() << "(" << "0x" << std::hex << d.code() << ")"; -} - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/Descriptor.h b/qpid/cpp/src/qpid/amqp/Descriptor.h deleted file mode 100644 index 3726114769..0000000000 --- a/qpid/cpp/src/qpid/amqp/Descriptor.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_AMQP_DESCRIPTOR_H -#define QPID_AMQP_DESCRIPTOR_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/amqp/CharSequence.h" -#include "qpid/sys/IntegerTypes.h" -#include -#include - -namespace qpid { -namespace amqp { - -/** - * Representation of an AMQP 1.0 type descriptor. - */ -struct Descriptor -{ - union { - CharSequence symbol; - uint64_t code; - } value; - enum { - NUMERIC, - SYMBOLIC - } type; - boost::shared_ptr nested; - - 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; - QPID_COMMON_EXTERN Descriptor* nest(const Descriptor& d); - QPID_COMMON_EXTERN std::string symbol() const; - QPID_COMMON_EXTERN uint64_t code() const; -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& os, const Descriptor& d); - -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_DESCRIPTOR_H*/ diff --git a/qpid/cpp/src/qpid/amqp/Encoder.cpp b/qpid/cpp/src/qpid/amqp/Encoder.cpp deleted file mode 100644 index 86b59fb1a2..0000000000 --- a/qpid/cpp/src/qpid/amqp/Encoder.cpp +++ /dev/null @@ -1,523 +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/amqp/Encoder.h" -#include "qpid/amqp/CharSequence.h" -#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 -#include - -using namespace qpid::types::encodings; -using qpid::types::Variant; - -namespace qpid { -namespace amqp { - -Encoder::Overflow::Overflow() : Exception("Buffer overflow in encoder!") {} - -Encoder::Encoder(char* d, size_t s) : data(d), size(s), position(0), grow(false) {} - -Encoder::Encoder() : data(0), size(0), position(0), grow(true) {} - -namespace { -template size_t encode(char* data, T i); -template <> size_t encode(char* data, uint8_t i) -{ - *data = i; - return 1; -} -template <> size_t encode(char* data, uint16_t i) -{ - uint16_t b = i; - size_t position(0); - data[position++] = (uint8_t) (0xFF & (b >> 8)); - data[position++] = (uint8_t) (0xFF & b); - return position; -} -template <> size_t encode(char* data, uint32_t i) -{ - uint32_t b = i; - size_t position(0); - data[position++] = (uint8_t) (0xFF & (b >> 24)); - data[position++] = (uint8_t) (0xFF & (b >> 16)); - data[position++] = (uint8_t) (0xFF & (b >> 8)); - data[position++] = (uint8_t) (0xFF & b); - return position; -} -template <> size_t encode(char* data, uint64_t i) -{ - uint32_t hi = i >> 32; - uint32_t lo = i; - size_t r(0); - r += encode(data, hi); - r += encode(data + r, lo); - return r; -} -template struct Backfill -{ - T size; - T count; - char* location; -}; - -template void end(T count, void* token, char* current) -{ - Backfill b; - b.location = (char*) token; - b.size = (T) (current - b.location) - sizeof(b.size); - b.count = count; - b.location += encode(b.location, b.size); - encode(b.location, b.count); -} -} -char* Encoder::skip(size_t n) -{ - char* current = data + position; - check(n); - position += n; - return current; -} - -void Encoder::write(bool b) -{ - check(sizeof(b)); - position += encode(data+position, b ? 1u : 0u); -} -void Encoder::write(uint8_t i) -{ - check(sizeof(i)); - position += encode(data+position, i); -} -void Encoder::write(uint16_t i) -{ - check(sizeof(i)); - position += encode(data+position, i); -} -void Encoder::write(uint32_t i) -{ - check(sizeof(i)); - position += encode(data+position, i); -} -void Encoder::write(uint64_t i) -{ - check(sizeof(i)); - position += encode(data+position, i); -} -void Encoder::write(int8_t i) -{ - check(sizeof(i)); - position += encode(data+position, (uint8_t) i); -} -void Encoder::write(int16_t i) -{ - check(sizeof(i)); - position += encode(data+position, (uint16_t) i); -} -void Encoder::write(int32_t i) -{ - check(sizeof(i)); - position += encode(data+position, (uint32_t) i); -} -void Encoder::write(int64_t i) -{ - check(sizeof(i)); - position += encode(data+position, (uint64_t) i); -} -void Encoder::write(float f) -{ - check(sizeof(f)); - union { - uint32_t i; - float f; - } val; - - val.f = f; - write(val.i); -} -void Encoder::write(double d) -{ - check(sizeof(d)); - union { - uint64_t i; - double d; - } val; - - val.d = d; - write(val.i); -} -void Encoder::write(const qpid::types::Uuid& uuid) -{ - writeBytes((const char*) uuid.data(), uuid.size()); -} - -void Encoder::writeBytes(const char* bytes, size_t count) -{ - check(count); - ::memcpy(data + position, bytes, count); - position += count; -} - -void Encoder::writeCode(uint8_t code) -{ - write(code); -} - -void Encoder::writeNull(const Descriptor* d) -{ - if (d) writeDescriptor(*d); - writeCode(typecodes::NULL_VALUE); -} -void Encoder::writeBoolean(bool b, const Descriptor* d) -{ - if (d) writeDescriptor(*d); - writeCode(b ? typecodes::BOOLEAN_TRUE : typecodes::BOOLEAN_FALSE); -} -void Encoder::writeUByte(uint8_t i, const Descriptor* d) -{ - write(i, typecodes::UBYTE, d); -} - -void Encoder::writeUShort(uint16_t i, const Descriptor* d) -{ - write(i, typecodes::USHORT, d); -} - -void Encoder::writeUInt(uint32_t i, const Descriptor* d) -{ - if (i == 0) { - if (d) writeDescriptor(*d); - writeCode(typecodes::UINT_ZERO); - } else { - if (i < 256) { - write((uint8_t) i, typecodes::UINT_SMALL, d); - } else { - write(i, typecodes::UINT, d); - } - } -} - -void Encoder::writeULong(uint64_t i, const Descriptor* d) -{ - if (i == 0) { - if (d) writeDescriptor(*d); - writeCode(typecodes::ULONG_ZERO); - } else { - if (i < 256) { - write((uint8_t) i, typecodes::ULONG_SMALL, d); - } else { - write(i, typecodes::ULONG, d); - } - } -} - -void Encoder::writeByte(int8_t i, const Descriptor* d) -{ - write((uint8_t) i, typecodes::LONG, d); -} - -void Encoder::writeShort(int16_t i, const Descriptor* d) -{ - write((uint16_t) i, typecodes::SHORT, d); -} - -void Encoder::writeInt(int32_t i, const Descriptor* d) -{ - write((uint32_t) i, typecodes::INT, d); -} - -void Encoder::writeLong(int64_t i, const Descriptor* d) -{ - write((uint64_t) i, typecodes::LONG, d); -} - -void Encoder::writeTimestamp(int64_t t, const Descriptor* d) -{ - write((uint64_t) t, typecodes::TIMESTAMP, d); -} - - -void Encoder::writeFloat(float f, const Descriptor* d) -{ - write(f, typecodes::FLOAT, d); -} - -void Encoder::writeDouble(double f, const Descriptor* d) -{ - write(f, typecodes::DOUBLE, d); -} - -void Encoder::writeUuid(const qpid::types::Uuid& uuid, const Descriptor* d) -{ - write(uuid, typecodes::UUID, d); -} - -void Encoder::write(const CharSequence& v, std::pair codes, const Descriptor* d) -{ - if (d) writeDescriptor(*d); - if (v.size < 256) { - writeCode(codes.first); - write((uint8_t) v.size); - } else { - writeCode(codes.second); - write((uint32_t) v.size); - } - writeBytes(v.data, v.size); -} - -void Encoder::write(const std::string& v, std::pair codes, const Descriptor* d) -{ - if (d) writeDescriptor(*d); - if (v.size() < 256) { - writeCode(codes.first); - write((uint8_t) v.size()); - } else { - writeCode(codes.second); - write((uint32_t) v.size()); - } - writeBytes(v.data(), v.size()); -} - -void Encoder::writeSymbol(const CharSequence& v, const Descriptor* d) -{ - write(v, typecodes::SYMBOL, d); -} - -void Encoder::writeSymbol(const std::string& v, const Descriptor* d) -{ - write(v, typecodes::SYMBOL, d); -} - -void Encoder::writeString(const CharSequence& v, const Descriptor* d) -{ - write(v, typecodes::STRING, d); -} - -void Encoder::writeString(const std::string& v, const Descriptor* d) -{ - write(v, typecodes::STRING, d); -} - -void Encoder::writeBinary(const CharSequence& v, const Descriptor* d) -{ - write(v, typecodes::BINARY, d); -} - -void Encoder::writeBinary(const std::string& v, const Descriptor* d) -{ - write(v, typecodes::BINARY, d); -} - -void* Encoder::startList8(const Descriptor* d) -{ - return start(typecodes::LIST8, d); -} - -void* Encoder::startList32(const Descriptor* d) -{ - return start(typecodes::LIST32, d); -} - -void Encoder::endList8(uint8_t count, void* token) -{ - end(count, token, data+position); -} - -void Encoder::endList32(uint32_t count, void* token) -{ - end(count, token, data+position); -} - -void* Encoder::startMap8(const Descriptor* d) -{ - return start(typecodes::MAP8, d); -} - -void* Encoder::startMap32(const Descriptor* d) -{ - return start(typecodes::MAP32, d); -} - -void Encoder::endMap8(uint8_t count, void* token) -{ - end(count, token, data+position); -} - -void Encoder::endMap32(uint32_t count, void* token) -{ - end(count, token, data+position); -} - -void* Encoder::startArray8(const Constructor& c, const Descriptor* d) -{ - return startArray(typecodes::ARRAY8, d, c); -} - -void* Encoder::startArray32(const Constructor& c, const Descriptor* d) -{ - return startArray(typecodes::ARRAY32, d, c); -} - -void Encoder::endArray8(size_t count, void* token) -{ - end(count, token, data+position); -} - -void Encoder::endArray32(size_t count, void* token) -{ - end(count, token, data+position); -} - -void Encoder::writeMap(const std::map& 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& 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) -{ - if (d) { - writeDescriptor(*d); // Write this descriptor before any in the value. - d = 0; - } - // Write any descriptors attached to the value. - const Variant::List& descriptors = value.getDescriptors(); - for (Variant::List::const_iterator i = descriptors.begin(); i != descriptors.end(); ++i) { - if (i->getType() == types::VAR_STRING) - writeDescriptor(Descriptor(CharSequence::create(i->asString()))); - else - writeDescriptor(Descriptor(i->asUint64())); - } - 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) -{ - writeCode(typecodes::DESCRIPTOR); - switch (d.type) { - case Descriptor::NUMERIC: - writeULong(d.value.code, 0); - break; - case Descriptor::SYMBOLIC: - writeSymbol(d.value.symbol, 0); - break; - } -} - -void Encoder::check(size_t s) -{ - if (position + s > size) { - if (grow) { - buffer.resize(buffer.size() + s); - data = const_cast(buffer.data()); - size = buffer.size(); - } - else { - QPID_LOG(notice, "Buffer overflow for write of size " << s - << " to buffer of size " << size << " at position " << position); - assert(false); - throw Overflow(); - } - } -} - -size_t Encoder::getPosition() { return position; } -size_t Encoder::getSize() const { return size; } -char* Encoder::getData() { return data + position; } -std::string Encoder::getBuffer() { return buffer; } -void Encoder::resetPosition(size_t p) { assert(p <= size); position = p; } - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/Encoder.h b/qpid/cpp/src/qpid/amqp/Encoder.h deleted file mode 100644 index 8729f29b94..0000000000 --- a/qpid/cpp/src/qpid/amqp/Encoder.h +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef QPID_AMQP_ENCODER_H -#define QPID_AMQP_ENCODER_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/amqp/Constructor.h" -#include "qpid/Exception.h" -#include -#include -#include -#include - -namespace qpid { -namespace types { -class Uuid; -class Variant; -} -namespace amqp { -struct CharSequence; -struct Descriptor; - -/** - * Class to help create AMQP encoded data. - */ -class Encoder -{ - public: - struct Overflow : public Exception { Overflow(); }; - - /** Create an encoder that writes into the buffer at data up to size bytes. - * Write operations throw Overflow if encoding exceeds size bytes. - */ - QPID_COMMON_EXTERN Encoder(char* data, size_t size); - - /** Create an encoder that manages its own buffer. Buffer grows to accomodate - * all encoded data. Call getBuffer() to get the buffer. - */ - QPID_COMMON_EXTERN Encoder(); - - void writeCode(uint8_t); - - void write(bool); - void write(uint8_t); - void write(uint16_t); - void write(uint32_t); - void write(uint64_t); - void write(int8_t); - void write(int16_t); - void write(int32_t); - void write(int64_t); - void write(float); - void write(double); - void write(const qpid::types::Uuid&); - - void writeNull(const Descriptor* d=0); - void writeBoolean(bool, const Descriptor* d=0); - void writeUByte(uint8_t, const Descriptor* d=0); - void writeUShort(uint16_t, const Descriptor* d=0); - void writeUInt(uint32_t, const Descriptor* d=0); - void writeULong(uint64_t, const Descriptor* d=0); - void writeByte(int8_t, const Descriptor* d=0); - void writeShort(int16_t, const Descriptor* d=0); - void writeInt(int32_t, const Descriptor* d=0); - void writeLong(int64_t, const Descriptor* d=0); - void writeFloat(float, const Descriptor* d=0); - void writeDouble(double, const Descriptor* d=0); - void writeUuid(const qpid::types::Uuid&, const Descriptor* d=0); - void writeTimestamp(int64_t, const Descriptor* d=0); - - void writeSymbol(const CharSequence&, const Descriptor* d=0); - void writeSymbol(const std::string&, const Descriptor* d=0); - 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); - QPID_COMMON_EXTERN void writeBinary(const std::string&, const Descriptor* d=0); - - void* startList8(const Descriptor* d=0); - void* startList32(const Descriptor* d=0); - void endList8(uint8_t count, void*); - void endList32(uint32_t count, void*); - - void* startMap8(const Descriptor* d=0); - void* startMap32(const Descriptor* d=0); - void endMap8(uint8_t count, void*); - void endMap32(uint32_t count, void*); - - void* startArray8(const Constructor&, const Descriptor* d=0); - void* startArray32(const Constructor&, const Descriptor* d=0); - 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& value, const Descriptor* d=0, bool large=true); - QPID_COMMON_EXTERN void writeList(const std::list& value, const Descriptor* d=0, bool large=true); - - void writeDescriptor(const Descriptor&); - QPID_COMMON_EXTERN size_t getPosition(); - void resetPosition(size_t p); - char* skip(size_t); - void writeBytes(const char* bytes, size_t count); - virtual ~Encoder() {} - - /** Return the total size of the buffer. */ - size_t getSize() const; - - /** Return the growable buffer. */ - std::string getBuffer(); - - /** Return the unused portion of the buffer. */ - char* getData(); - - private: - char* data; - size_t size; - size_t position; - bool grow; - std::string buffer; - - void write(const CharSequence& v, std::pair codes, const Descriptor* d); - void write(const std::string& v, std::pair codes, const Descriptor* d); - void check(size_t); - - template void write(T value, uint8_t code, const Descriptor* d) - { - if (d) writeDescriptor(*d); - writeCode(code); - write(value); - } - - template void write(T value, std::pair codes, const Descriptor* d) - { - if (value < 256) { - write((uint8_t) value, codes.first, d); - } else { - write(value, codes.second, d); - } - } - - template void* start(uint8_t code, const Descriptor* d) - { - if (d) writeDescriptor(*d); - writeCode(code); - //skip size and count, will backfill on end - return skip(sizeof(T)/*size*/ + sizeof(T)/*count*/); - } - - template void* startArray(uint8_t code, const Descriptor* d, const Constructor& c) - { - void* token = start(code, d); - if (c.isDescribed) { - writeDescriptor(c.descriptor); - } - check(1); - writeCode(c.code); - return token; - } - -}; - -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_ENCODER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/ListBuilder.cpp b/qpid/cpp/src/qpid/amqp/ListBuilder.cpp deleted file mode 100644 index f2ca8e8805..0000000000 --- a/qpid/cpp/src/qpid/amqp/ListBuilder.cpp +++ /dev/null @@ -1,33 +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 "ListBuilder.h" - -namespace qpid { -namespace amqp { - -ListBuilder::ListBuilder() : DataBuilder(qpid::types::Variant::List()) {} - -qpid::types::Variant::List& ListBuilder::getList() -{ - return getValue().asList(); -} - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/ListBuilder.h b/qpid/cpp/src/qpid/amqp/ListBuilder.h deleted file mode 100644 index 825f384f56..0000000000 --- a/qpid/cpp/src/qpid/amqp/ListBuilder.h +++ /dev/null @@ -1,41 +0,0 @@ -#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 deleted file mode 100644 index fafe2a1f9c..0000000000 --- a/qpid/cpp/src/qpid/amqp/ListReader.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef QPID_AMQP_LISTREADER_H -#define QPID_AMQP_LISTREADER_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" - -namespace qpid { -namespace amqp { - -/** - * Utility to assist in reading AMQP encoded lists - */ -class ListReader : public Reader -{ - public: - ListReader() : index(0), level(0) {} - virtual ~ListReader() {} - virtual void onNull(const Descriptor* descriptor) { getReader().onNull(descriptor); } - virtual void onBoolean(bool v, const Descriptor* descriptor) { getReader().onBoolean(v, descriptor); } - virtual void onUByte(uint8_t v, const Descriptor* descriptor) { getReader().onUByte(v, descriptor); } - virtual void onUShort(uint16_t v, const Descriptor* descriptor) { getReader().onUShort(v, descriptor); } - virtual void onUInt(uint32_t v, const Descriptor* descriptor) { getReader().onUInt(v, descriptor); } - virtual void onULong(uint64_t v, const Descriptor* descriptor) { getReader().onULong(v, descriptor); } - virtual void onByte(int8_t v, const Descriptor* descriptor) { getReader().onByte(v, descriptor); } - virtual void onShort(int16_t v, const Descriptor* descriptor) { getReader().onShort(v, descriptor); } - virtual void onInt(int32_t v, const Descriptor* descriptor) { getReader().onInt(v, descriptor); } - virtual void onLong(int64_t v, const Descriptor* descriptor) { getReader().onLong(v, descriptor); } - virtual void onFloat(float v, const Descriptor* descriptor) { getReader().onFloat(v, descriptor); } - virtual void onDouble(double v, const Descriptor* descriptor) { getReader().onDouble(v, descriptor); } - virtual void onUuid(const CharSequence& v, const Descriptor* descriptor) { getReader().onUuid(v, descriptor); } - virtual void onTimestamp(int64_t v, const Descriptor* descriptor) { getReader().onTimestamp(v, descriptor); } - - virtual void onBinary(const CharSequence& v, const Descriptor* descriptor) { getReader().onBinary(v, descriptor); } - 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& elements, const CharSequence& all, const Descriptor* descriptor) - { - ++level; - getReader().onStartList(count, elements, all, descriptor); - return false; - } - virtual void onEndList(uint32_t count, const Descriptor* descriptor) - { - --level; - getReader().onEndList(count, descriptor); - } - virtual bool onStartMap(uint32_t count, const CharSequence& elements, const CharSequence& all, const Descriptor* descriptor) - { - ++level; - getReader().onStartMap(count, elements, all, descriptor); - return false; - } - virtual void onEndMap(uint32_t count, const Descriptor* descriptor) - { - --level; - getReader().onEndList(count, descriptor); - } - virtual bool onStartArray(uint32_t count, const CharSequence& v, const Constructor& c, const Descriptor* descriptor) - { - ++level; - getReader().onStartArray(count, v, c, descriptor); - return false; - } - virtual void onEndArray(uint32_t count, const Descriptor* descriptor) - { - --level; - getReader().onEndList(count, descriptor); - } - private: - size_t index; - size_t level; - Reader& getReader() - { - Reader& r = getReader(index); - if (level == 0) ++index; - return r; - } - protected: - virtual Reader& getReader(size_t i) = 0; -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_LISTREADER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/LoggingReader.h b/qpid/cpp/src/qpid/amqp/LoggingReader.h deleted file mode 100644 index ed5cab1cbd..0000000000 --- a/qpid/cpp/src/qpid/amqp/LoggingReader.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_AMQP_LOGGINGREADER_H -#define QPID_AMQP_LOGGINGREADER_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/log/Statement.h" - -namespace qpid { -namespace amqp { - -class LoggingReader : public Reader -{ - public: - virtual ~LoggingReader() {} - virtual void onNull(const Descriptor*) { if (!ignoreNull()) QPID_LOG(warning, prefix() << "null" << suffix()); } - virtual void onBoolean(bool, const Descriptor*) { QPID_LOG(warning, prefix() << "boolean" << suffix()); } - virtual void onUByte(uint8_t, const Descriptor*) { QPID_LOG(warning, prefix() << "ubyte" << suffix()); } - virtual void onUShort(uint16_t, const Descriptor*) { QPID_LOG(warning, prefix() << "ushort" << suffix()); } - virtual void onUInt(uint32_t, const Descriptor*) { QPID_LOG(warning, prefix() << "uint" << suffix()); } - virtual void onULong(uint64_t, const Descriptor*) { QPID_LOG(warning, prefix() << "ulong" << suffix()); } - virtual void onByte(int8_t, const Descriptor*) { QPID_LOG(warning, prefix() << "byte" << suffix()); } - virtual void onShort(int16_t, const Descriptor*) { QPID_LOG(warning, prefix() << "short" << suffix()); } - virtual void onInt(int32_t, const Descriptor*) { QPID_LOG(warning, prefix() << "int" << suffix()); } - virtual void onLong(int64_t, const Descriptor*) { QPID_LOG(warning, prefix() << "long" << suffix()); } - virtual void onFloat(float, const Descriptor*) { QPID_LOG(warning, prefix() << "float" << suffix()); } - virtual void onDouble(double, const Descriptor*) { QPID_LOG(warning, prefix() << "double" << suffix()); } - virtual void onUuid(const CharSequence&, const Descriptor*) { QPID_LOG(warning, prefix() << "uuid" << suffix()); } - virtual void onTimestamp(int64_t, const Descriptor*) { QPID_LOG(warning, prefix() << "timestamp" << suffix()); } - - virtual void onBinary(const CharSequence&, const Descriptor*) { QPID_LOG(warning, prefix() << "binary" << suffix()); } - virtual void onString(const CharSequence&, const Descriptor*) { QPID_LOG(warning, prefix() << "string" << suffix()); } - virtual void onSymbol(const CharSequence&, const Descriptor*) { QPID_LOG(warning, prefix() << "symbol" << suffix()); } - - virtual bool onStartList(uint32_t, const CharSequence&, const Descriptor*) { QPID_LOG(warning, prefix() << "list" << suffix()); return recursive; } - virtual bool onStartMap(uint32_t, const CharSequence&, const Descriptor*) { QPID_LOG(warning, prefix() << "map" << suffix()); return recursive; } - virtual bool onStartArray(uint32_t, const CharSequence&, const Constructor&, const Descriptor*) { QPID_LOG(warning, prefix() << "array" << suffix()); return recursive; } - protected: - virtual bool recursive() { return true; } - virtual bool ignoreNull() { return true; } - virtual std::string prefix() = 0; - virtual std::string suffix() = 0; -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_LOGGINGREADER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/MapBuilder.cpp b/qpid/cpp/src/qpid/amqp/MapBuilder.cpp deleted file mode 100644 index ce8eea038e..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapBuilder.cpp +++ /dev/null @@ -1,30 +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 "MapBuilder.h" - -namespace qpid { -namespace amqp { -MapBuilder::MapBuilder() : DataBuilder(qpid::types::Variant::Map()) {} -qpid::types::Variant::Map MapBuilder::getMap() -{ - return getValue().asMap(); -} -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/MapBuilder.h b/qpid/cpp/src/qpid/amqp/MapBuilder.h deleted file mode 100644 index fd94ae04af..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapBuilder.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef QPID_AMQP_MAPBUILDER_H -#define QPID_AMQP_MAPBUILDER_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::Map from a data stream - */ -class MapBuilder : public DataBuilder -{ - public: - QPID_COMMON_EXTERN MapBuilder(); - QPID_COMMON_EXTERN qpid::types::Variant::Map getMap(); -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_MAPBUILDER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/MapEncoder.cpp b/qpid/cpp/src/qpid/amqp/MapEncoder.cpp deleted file mode 100644 index cf8ef4ecb5..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapEncoder.cpp +++ /dev/null @@ -1,142 +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 "MapEncoder.h" -#include "CharSequence.h" -#include "qpid/amqp/typecodes.h" -#include - -namespace qpid { -namespace amqp { - -MapEncoder::MapEncoder(char* data, size_t size) : Encoder(data, size) {} - -void MapEncoder::handleVoid(const CharSequence& key) -{ - writeString(key); - writeNull(); -} - -void MapEncoder::handleBool(const CharSequence& key, bool value) -{ - writeString(key); - writeBoolean(value); -} - -void MapEncoder::handleUint8(const CharSequence& key, uint8_t value) -{ - writeString(key); - writeUByte(value); -} - -void MapEncoder::handleUint16(const CharSequence& key, uint16_t value) -{ - writeString(key); - writeUShort(value); -} - -void MapEncoder::handleUint32(const CharSequence& key, uint32_t value) -{ - writeString(key); - writeUInt(value); -} - -void MapEncoder::handleUint64(const CharSequence& key, uint64_t value) -{ - writeString(key); - writeULong(value); -} - -void MapEncoder::handleInt8(const CharSequence& key, int8_t value) -{ - writeString(key); - writeByte(value); -} - -void MapEncoder::handleInt16(const CharSequence& key, int16_t value) -{ - writeString(key); - writeShort(value); -} - -void MapEncoder::handleInt32(const CharSequence& key, int32_t value) -{ - writeString(key); - writeInt(value); -} - -void MapEncoder::handleInt64(const CharSequence& key, int64_t value) -{ - writeString(key); - writeLong(value); -} - -void MapEncoder::handleFloat(const CharSequence& key, float value) -{ - writeString(key); - writeFloat(value); -} - -void MapEncoder::handleDouble(const CharSequence& key, double value) -{ - writeString(key); - writeDouble(value); -} - -namespace { -const std::string BINARY("binary"); -} - -void MapEncoder::handleString(const CharSequence& key, const CharSequence& value, const CharSequence& encoding) -{ - writeString(key); - if (encoding.size == BINARY.size() && ::strncmp(encoding.data, BINARY.data(), encoding.size)) { - writeBinary(value); - } else { - writeString(value); - } -} - -void MapEncoder::writeMetaData(size_t size, size_t count, const Descriptor* d) -{ - if (count > 255 || size > 255) { - writeMap32MetaData((uint32_t) size, (uint32_t) count, d); - } else { - writeMap8MetaData((uint8_t) size, (uint8_t) count, d); - } -} - -void MapEncoder::writeMap8MetaData(uint8_t size, uint8_t count, const Descriptor* d) -{ - if (d) writeDescriptor(*d); - writeCode(typecodes::MAP8); - write((uint8_t) (size+1)/*size includes count field*/); - write(count); -} - -void MapEncoder::writeMap32MetaData(uint32_t size, uint32_t count, const Descriptor* d) -{ - if (d) writeDescriptor(*d); - writeCode(typecodes::MAP32); - write((uint32_t) (size+4)/*size includes count field*/); - write(count); -} - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/MapEncoder.h b/qpid/cpp/src/qpid/amqp/MapEncoder.h deleted file mode 100644 index 1481f9125a..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapEncoder.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef QPID_AMQP_MAPENCODER_H -#define QPID_AMQP_MAPENCODER_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 "MapHandler.h" -#include "Encoder.h" - -namespace qpid { -namespace amqp { -struct Descriptor; - -/** - * Encode map like data - */ -class MapEncoder : public MapHandler, private Encoder -{ - public: - MapEncoder(char* data, size_t size); - void handleVoid(const CharSequence& key); - void handleBool(const CharSequence& key, bool value); - void handleUint8(const CharSequence& key, uint8_t value); - void handleUint16(const CharSequence& key, uint16_t value); - void handleUint32(const CharSequence& key, uint32_t value); - void handleUint64(const CharSequence& key, uint64_t value); - void handleInt8(const CharSequence& key, int8_t value); - void handleInt16(const CharSequence& key, int16_t value); - void handleInt32(const CharSequence& key, int32_t value); - void handleInt64(const CharSequence& key, int64_t value); - void handleFloat(const CharSequence& key, float value); - void handleDouble(const CharSequence& key, double value); - void handleString(const CharSequence& key, const CharSequence& value, const CharSequence& encoding); - void writeMetaData(size_t size, size_t count, const Descriptor* descriptor=0); - void writeMap8MetaData(uint8_t size, uint8_t count, const Descriptor* d=0); - void writeMap32MetaData(uint32_t size, uint32_t count, const Descriptor* d=0); - private: -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_MAPENCODER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/MapHandler.h b/qpid/cpp/src/qpid/amqp/MapHandler.h deleted file mode 100644 index 14994ccac7..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapHandler.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef QPID_AMQP_MAPHANDLER_H -#define QPID_AMQP_MAPHANDLER_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 amqp { -struct CharSequence; -/** - * Interface for processing entries in some map-like object - */ -class MapHandler -{ - public: - virtual ~MapHandler() {} - virtual void handleVoid(const CharSequence& key) = 0; - virtual void handleBool(const CharSequence& key, bool value) = 0; - virtual void handleUint8(const CharSequence& key, uint8_t value) = 0; - virtual void handleUint16(const CharSequence& key, uint16_t value) = 0; - virtual void handleUint32(const CharSequence& key, uint32_t value) = 0; - virtual void handleUint64(const CharSequence& key, uint64_t value) = 0; - virtual void handleInt8(const CharSequence& key, int8_t value) = 0; - virtual void handleInt16(const CharSequence& key, int16_t value) = 0; - virtual void handleInt32(const CharSequence& key, int32_t value) = 0; - virtual void handleInt64(const CharSequence& key, int64_t value) = 0; - virtual void handleFloat(const CharSequence& key, float value) = 0; - virtual void handleDouble(const CharSequence& key, double value) = 0; - virtual void handleString(const CharSequence& key, const CharSequence& value, const CharSequence& encoding) = 0; - private: -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_MAPHANDLER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/MapReader.cpp b/qpid/cpp/src/qpid/amqp/MapReader.cpp deleted file mode 100644 index b6c31849f0..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapReader.cpp +++ /dev/null @@ -1,309 +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/amqp/MapReader.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace amqp { - -void MapReader::onNull(const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onNullValue(key, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} -void MapReader::onBoolean(bool v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onBooleanValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onUByte(uint8_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onUByteValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onUShort(uint16_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onUShortValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onUInt(uint32_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onUIntValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onULong(uint64_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onULongValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onByte(int8_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onByteValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onShort(int16_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onShortValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onInt(int32_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onIntValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onLong(int64_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onLongValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onFloat(float v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onFloatValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onDouble(double v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onDoubleValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onUuid(const CharSequence& v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onUuidValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onTimestamp(int64_t v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onTimestampValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onBinary(const CharSequence& v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onBinaryValue(key, v, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onString(const CharSequence& v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onStringValue(key, v, d); - clearKey(); - } else { - if (keyType & STRING_KEY) { - key = v; - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key, got string " << v.str())); - } - } -} - -void MapReader::onSymbol(const CharSequence& v, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onSymbolValue(key, v, d); - clearKey(); - } else { - if (keyType & SYMBOL_KEY) { - key = v; - } else { - throw qpid::Exception(QPID_MSG("Expecting string as key, got symbol " << v.str())); - } - } -} - -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) { - bool step = onStartListValue(key, count, d); - clearKey(); - return step; - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } - return true; -} - -bool MapReader::onStartMap(uint32_t count, const CharSequence&, const CharSequence&, const Descriptor* d) -{ - if (level++) { - if (key) { - bool step = onStartMapValue(key, count, d); - clearKey(); - return step; - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } - } - return true; -} - -bool MapReader::onStartArray(uint32_t count, const CharSequence&, const Constructor& c, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - bool step = onStartArrayValue(key, count, c, d); - clearKey(); - return step; - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } - return true; -} - -void MapReader::onEndList(uint32_t count, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onEndListValue(key, count, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -void MapReader::onEndMap(uint32_t count, const Descriptor* d) -{ - if (--level) { - onEndMapValue(key, count, d); - clearKey(); - } -} - -void MapReader::onEndArray(uint32_t count, const Descriptor* d) -{ - if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum")); - if (key) { - onEndArrayValue(key, count, d); - clearKey(); - } else { - throw qpid::Exception(QPID_MSG("Expecting symbol as key")); - } -} - -MapReader::MapReader() : level(0), keyType(SYMBOL_KEY) -{ - clearKey(); -} - -void MapReader::setAllowedKeyType(int t) -{ - keyType = t; -} - -void MapReader::clearKey() -{ - key.data = 0; key.size = 0; -} - -const int MapReader::SYMBOL_KEY(1); -const int MapReader::STRING_KEY(2); -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/MapReader.h b/qpid/cpp/src/qpid/amqp/MapReader.h deleted file mode 100644 index 875f919d63..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapReader.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef QPID_AMQP_MAPREADER_H -#define QPID_AMQP_MAPREADER_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 "CharSequence.h" -#include - -namespace qpid { -namespace amqp { - -/** - * Reading AMQP 1.0 encoded data which is constrained to be a symbol - * keyeed map. The keys are assumed never to be described, the values - * may be. - */ -class MapReader : public Reader -{ - public: - virtual void onNullValue(const CharSequence& /*key*/, const Descriptor*) {} - virtual void onBooleanValue(const CharSequence& /*key*/, bool, const Descriptor*) {} - virtual void onUByteValue(const CharSequence& /*key*/, uint8_t, const Descriptor*) {} - virtual void onUShortValue(const CharSequence& /*key*/, uint16_t, const Descriptor*) {} - virtual void onUIntValue(const CharSequence& /*key*/, uint32_t, const Descriptor*) {} - virtual void onULongValue(const CharSequence& /*key*/, uint64_t, const Descriptor*) {} - virtual void onByteValue(const CharSequence& /*key*/, int8_t, const Descriptor*) {} - virtual void onShortValue(const CharSequence& /*key*/, int16_t, const Descriptor*) {} - virtual void onIntValue(const CharSequence& /*key*/, int32_t, const Descriptor*) {} - virtual void onLongValue(const CharSequence& /*key*/, int64_t, const Descriptor*) {} - virtual void onFloatValue(const CharSequence& /*key*/, float, const Descriptor*) {} - virtual void onDoubleValue(const CharSequence& /*key*/, double, const Descriptor*) {} - virtual void onUuidValue(const CharSequence& /*key*/, const CharSequence&, const Descriptor*) {} - virtual void onTimestampValue(const CharSequence& /*key*/, int64_t, const Descriptor*) {} - - virtual void onBinaryValue(const CharSequence& /*key*/, const CharSequence&, const Descriptor*) {} - virtual void onStringValue(const CharSequence& /*key*/, const CharSequence&, const Descriptor*) {} - virtual void onSymbolValue(const CharSequence& /*key*/, const CharSequence&, const Descriptor*) {} - - /** - * @return true to step into elements of the compound value, false - * to skip over it - */ - virtual bool onStartListValue(const CharSequence& /*key*/, uint32_t /*count*/, const Descriptor*) { return true; } - virtual bool onStartMapValue(const CharSequence& /*key*/, uint32_t /*count*/, const Descriptor*) { return true; } - virtual bool onStartArrayValue(const CharSequence& /*key*/, uint32_t /*count*/, const Constructor&, const Descriptor*) { return true; } - virtual void onEndListValue(const CharSequence& /*key*/, uint32_t /*count*/, const Descriptor*) {} - virtual void onEndMapValue(const CharSequence& /*key*/, uint32_t /*count*/, const Descriptor*) {} - virtual void onEndArrayValue(const CharSequence& /*key*/, uint32_t /*count*/, const Descriptor*) {} - - - //this class implements the Reader interface, thus acting as a transformer into a more map oriented scheme - 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 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; - int keyType; - - void clearKey(); -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_MAPREADER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/MapSizeCalculator.cpp b/qpid/cpp/src/qpid/amqp/MapSizeCalculator.cpp deleted file mode 100644 index 2da152108f..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapSizeCalculator.cpp +++ /dev/null @@ -1,151 +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 "MapSizeCalculator.h" -#include "CharSequence.h" -#include "Descriptor.h" - -namespace qpid { -namespace amqp { - -MapSizeCalculator::MapSizeCalculator() : size(0), count(0) {} - -void MapSizeCalculator::handleKey(const CharSequence& key) -{ - ++count; - size += getEncodedSize(key); -} - -size_t MapSizeCalculator::getEncodedSize(const CharSequence& s) -{ - return 1/*typecode*/ + (s.size < 256 ? 1 : 4)/*size field*/ + s.size; -} - -void MapSizeCalculator::handleVoid(const CharSequence& key) -{ - handleKey(key); - size += 1;/*typecode*/; -} - -void MapSizeCalculator::handleBool(const CharSequence& key, bool /*value*/) -{ - handleKey(key); - size += 1;/*typecode*/; -} - -void MapSizeCalculator::handleUint8(const CharSequence& key, uint8_t /*value*/) -{ - handleKey(key); - size += 1/*typecode*/ + 1/*value*/; -} - -void MapSizeCalculator::handleUint16(const CharSequence& key, uint16_t /*value*/) -{ - handleKey(key); - size += 1/*typecode*/ + 2/*value*/; -} - -void MapSizeCalculator::handleUint32(const CharSequence& key, uint32_t value) -{ - handleKey(key); - size += 1;/*typecode*/; - if (value > 0) { - if (value < 256) size += 1/*UINT_SMALL*/; - else size += 4/*UINT*/; - }//else UINT_ZERO -} - -void MapSizeCalculator::handleUint64(const CharSequence& key, uint64_t value) -{ - handleKey(key); - size += 1;/*typecode*/; - if (value > 0) { - if (value < 256) size += 1/*ULONG_SMALL*/; - else size += 8/*ULONG*/; - }//else ULONG_ZERO -} - -void MapSizeCalculator::handleInt8(const CharSequence& key, int8_t /*value*/) -{ - handleKey(key); - size += 1/*typecode*/ + 1/*value*/; -} - -void MapSizeCalculator::handleInt16(const CharSequence& key, int16_t /*value*/) -{ - handleKey(key); - size += 1/*typecode*/ + 2/*value*/; -} - -void MapSizeCalculator::handleInt32(const CharSequence& key, int32_t /*value*/) -{ - handleKey(key); - size += 1/*typecode*/ + 4/*value*/; -} - -void MapSizeCalculator::handleInt64(const CharSequence& key, int64_t /*value*/) -{ - handleKey(key); - size += 1/*typecode*/ + 8/*value*/; -} - -void MapSizeCalculator::handleFloat(const CharSequence& key, float /*value*/) -{ - handleKey(key); - size += 1/*typecode*/ + 4/*value*/; -} - -void MapSizeCalculator::handleDouble(const CharSequence& key, double /*value*/) -{ - handleKey(key); - size += 1/*typecode*/ + 8/*value*/; -} - -void MapSizeCalculator::handleString(const CharSequence& key, const CharSequence& value, const CharSequence& /*encoding*/) -{ - handleKey(key); - size += getEncodedSize(value); -} - -size_t MapSizeCalculator::getSize() const -{ - return size; -} - -size_t MapSizeCalculator::getCount() const -{ - return count; -} - -size_t MapSizeCalculator::getTotalSizeRequired(const Descriptor* d) const -{ - size_t result(size); - if (d) result += d->getSize(); - result += 1/*typecode*/; - if (count * 2 > 255 || size > 255) { - result += 4/*size*/ + 4/*count*/; - } else { - result += 1/*size*/ + 1/*count*/; - } - return result; -} - - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/MapSizeCalculator.h b/qpid/cpp/src/qpid/amqp/MapSizeCalculator.h deleted file mode 100644 index 35c9ad732d..0000000000 --- a/qpid/cpp/src/qpid/amqp/MapSizeCalculator.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef QPID_AMQP_MAPSIZECALCULATOR_H -#define QPID_AMQP_MAPSIZECALCULATOR_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 "MapHandler.h" -#include - -namespace qpid { -namespace amqp { -struct Descriptor; - -/** - * Utility to calculate the encoded size for map data - */ -class MapSizeCalculator : public MapHandler -{ - public: - MapSizeCalculator(); - void handleVoid(const CharSequence& key); - void handleBool(const CharSequence& key, bool value); - void handleUint8(const CharSequence& key, uint8_t value); - void handleUint16(const CharSequence& key, uint16_t value); - void handleUint32(const CharSequence& key, uint32_t value); - void handleUint64(const CharSequence& key, uint64_t value); - void handleInt8(const CharSequence& key, int8_t value); - void handleInt16(const CharSequence& key, int16_t value); - void handleInt32(const CharSequence& key, int32_t value); - void handleInt64(const CharSequence& key, int64_t value); - void handleFloat(const CharSequence& key, float value); - void handleDouble(const CharSequence& key, double value); - void handleString(const CharSequence& key, const CharSequence& value, const CharSequence& encoding); - /** - * @returns the encoded size of the map entries (i.e. does not - * include the count field, typecode or any other metadata for the - * map as a whole) - */ - size_t getSize() const; - size_t getCount() const; - /** - * @returns the total encoded size for a map containing the - * handled values (i.e. including the metadata for the map as a - * whole) - */ - size_t getTotalSizeRequired(const Descriptor* d=0) const; - private: - size_t size; - size_t count; - - void handleKey(const CharSequence& key); - static size_t getEncodedSize(const CharSequence&); -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_MAPSIZECALCULATOR_H*/ diff --git a/qpid/cpp/src/qpid/amqp/MessageEncoder.cpp b/qpid/cpp/src/qpid/amqp/MessageEncoder.cpp deleted file mode 100644 index 71e7e75111..0000000000 --- a/qpid/cpp/src/qpid/amqp/MessageEncoder.cpp +++ /dev/null @@ -1,312 +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/amqp/MessageEncoder.h" -#include "qpid/amqp/MapEncoder.h" -#include "qpid/amqp/MapSizeCalculator.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { -namespace amqp { - -namespace { -size_t optimisable(const MessageEncoder::Header& msg) -{ - if (msg.getDeliveryCount()) return 5; - else if (msg.isFirstAcquirer()) return 4; - else if (msg.hasTtl()) return 3; - else if (msg.getPriority() != 4) return 2; - else if (msg.isDurable()) return 1; - else return 0; -} - -size_t optimisable(const MessageEncoder::Properties& msg) -{ - if (msg.hasReplyToGroupId()) return 13; - else if (msg.hasGroupSequence()) return 12; - else if (msg.hasGroupId()) return 11; - else if (msg.hasCreationTime()) return 10; - else if (msg.hasAbsoluteExpiryTime()) return 9; - else if (msg.hasContentEncoding()) return 8; - else if (msg.hasContentType()) return 7; - else if (msg.hasCorrelationId()) return 6; - else if (msg.hasReplyTo()) return 5; - else if (msg.hasSubject()) return 4; - else if (msg.hasTo()) return 3; - else if (msg.hasUserId()) return 2; - else if (msg.hasMessageId()) return 1; - else return 0; -} -size_t encodedSize(const std::string& s) -{ - size_t total = s.size(); - if (total > 255) total += 4; - else total += 1; - return total; -} -const std::string BINARY("binary"); -} - -void MessageEncoder::writeHeader(const Header& msg) -{ - size_t fields(optimise ? optimisable(msg) : 5); - if (fields) { - void* token = startList8(&qpid::amqp::message::HEADER); - writeBoolean(msg.isDurable()); - if (fields > 1) writeUByte(msg.getPriority()); - - if (msg.getTtl()) writeUInt(msg.getTtl()); - else if (fields > 2) writeNull(); - - if (msg.isFirstAcquirer()) writeBoolean(true); - else if (fields > 3) writeNull(); - - if (msg.getDeliveryCount()) writeUInt(msg.getDeliveryCount()); - else if (fields > 4) writeNull(); - endList8(fields, token); - } -} - - -void MessageEncoder::writeProperties(const Properties& msg) -{ - size_t fields(optimise ? optimisable(msg) : 13); - if (fields) { - void* token = startList32(&qpid::amqp::message::PROPERTIES); - if (msg.hasMessageId()) writeString(msg.getMessageId()); - else writeNull(); - - if (msg.hasUserId()) writeBinary(msg.getUserId()); - else if (fields > 1) writeNull(); - - if (msg.hasTo()) writeString(msg.getTo()); - else if (fields > 2) writeNull(); - - if (msg.hasSubject()) writeString(msg.getSubject()); - else if (fields > 3) writeNull(); - - if (msg.hasReplyTo()) writeString(msg.getReplyTo()); - else if (fields > 4) writeNull(); - - if (msg.hasCorrelationId()) writeString(msg.getCorrelationId()); - else if (fields > 5) writeNull(); - - if (msg.hasContentType()) writeSymbol(msg.getContentType()); - else if (fields > 6) writeNull(); - - if (msg.hasContentEncoding()) writeSymbol(msg.getContentEncoding()); - else if (fields > 7) writeNull(); - - if (msg.hasAbsoluteExpiryTime()) writeTimestamp(msg.getAbsoluteExpiryTime()); - else if (fields > 8) writeNull(); - - if (msg.hasCreationTime()) writeTimestamp(msg.getCreationTime()); - else if (fields > 9) writeNull(); - - if (msg.hasGroupId()) writeString(msg.getGroupId()); - else if (fields > 10) writeNull(); - - if (msg.hasGroupSequence()) writeUInt(msg.getGroupSequence()); - else if (fields > 11) writeNull(); - - if (msg.hasReplyToGroupId()) writeString(msg.getReplyToGroupId()); - else if (fields > 12) writeNull(); - - endList32(fields, token); - } -} - -void MessageEncoder::writeApplicationProperties(const ApplicationProperties& properties) -{ - MapSizeCalculator calc; - properties.handle(calc); - size_t required = calc.getTotalSizeRequired(&qpid::amqp::message::APPLICATION_PROPERTIES); - assert(required <= getSize() - getPosition()); - MapEncoder encoder(skip(required), required); - encoder.writeMetaData(calc.getSize(), calc.getCount()*2, &qpid::amqp::message::APPLICATION_PROPERTIES); - properties.handle(encoder); -} - -void MessageEncoder::writeApplicationProperties(const qpid::types::Variant::Map& properties) -{ - writeApplicationProperties(properties, !optimise || properties.size()*2 > 255 || getEncodedSizeForElements(properties) > 255); -} - -void MessageEncoder::writeApplicationProperties(const qpid::types::Variant::Map& properties, bool large) -{ - writeMap(properties, &qpid::amqp::message::APPLICATION_PROPERTIES, large); -} - -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); -} - -size_t MessageEncoder::getEncodedSize(const Header& h, const Properties& p, const ApplicationProperties& ap, const std::string& d) -{ - return getEncodedSize(h) + getEncodedSize(p) + getEncodedSize(ap) + getEncodedSizeForContent(d); -} - -size_t MessageEncoder::getEncodedSize(const Properties& p, const qpid::types::Variant::Map& ap, const std::string& d) -{ - size_t total(getEncodedSize(p)); - //application-properties: - total += 3/*descriptor*/ + getEncodedSize(ap, true); - //body: - if (d.size()) total += 3/*descriptor*/ + 1/*code*/ + encodedSize(d); - - return total; -} - -size_t MessageEncoder::getEncodedSizeForContent(const std::string& d) -{ - if (d.size()) return 3/*descriptor*/ + 1/*code*/ + encodedSize(d); - else return 0; -} - -size_t MessageEncoder::getEncodedSize(const Header& h) -{ - //NOTE: this does not take optional optimisation into account, - //i.e. it is a 'worst case' estimate for required buffer space - size_t total(3/*descriptor*/ + 1/*code*/ + 1/*size*/ + 1/*count*/ + 5/*codes for each field*/); - if (h.getPriority() != 4) total += 1; - if (h.getDeliveryCount()) total += 4; - if (h.hasTtl()) total += 4; - return total; -} - -size_t MessageEncoder::getEncodedSize(const Properties& p) -{ - //NOTE: this does not take optional optimisation into account, - //i.e. it is a 'worst case' estimate for required buffer space - size_t total(3/*descriptor*/ + 1/*code*/ + 4/*size*/ + 4/*count*/ + 13/*codes for each field*/); - if (p.hasMessageId()) total += encodedSize(p.getMessageId()); - if (p.hasUserId()) total += encodedSize(p.getUserId()); - if (p.hasTo()) total += encodedSize(p.getTo()); - if (p.hasSubject()) total += encodedSize(p.getSubject()); - if (p.hasReplyTo()) total += encodedSize(p.getReplyTo()); - if (p.hasCorrelationId()) total += encodedSize(p.getCorrelationId()); - if (p.hasContentType()) total += encodedSize(p.getContentType()); - if (p.hasContentEncoding()) total += encodedSize(p.getContentEncoding()); - if (p.hasAbsoluteExpiryTime()) total += 8; - if (p.hasCreationTime()) total += 8; - if (p.hasGroupId()) total += encodedSize(p.getGroupId()); - if (p.hasGroupSequence()) total += 4; - if (p.hasReplyToGroupId()) total += encodedSize(p.getReplyToGroupId()); - return total; -} - -size_t MessageEncoder::getEncodedSize(const ApplicationProperties& p) -{ - MapSizeCalculator calc; - p.handle(calc); - return calc.getTotalSizeRequired(&qpid::amqp::message::APPLICATION_PROPERTIES); -} - -size_t MessageEncoder::getEncodedSizeForElements(const qpid::types::Variant::Map& 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) + 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; -} - - -size_t MessageEncoder::getEncodedSize(const qpid::types::Variant::Map& map, bool alwaysUseLargeMap) -{ - size_t total = getEncodedSizeForElements(map); - - //its not just the count that determines whether we can use a small map, but the aggregate size: - if (alwaysUseLargeMap || map.size()*2 > 255 || total > 255) total += 4/*size*/ + 4/*count*/; - else total += 1/*size*/ + 1/*count*/; - - total += 1 /*code for map itself*/; - - 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 deleted file mode 100644 index 05e1714004..0000000000 --- a/qpid/cpp/src/qpid/amqp/MessageEncoder.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef QPID_AMQP_MESSAGEENCODER_H -#define QPID_AMQP_MESSAGEENCODER_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/amqp/Encoder.h" -#include "qpid/types/Variant.h" - -namespace qpid { -namespace amqp { -class MapHandler; -/** - * - */ -class MessageEncoder : public Encoder -{ - public: - class Header - { - public: - virtual ~Header() {} - virtual bool isDurable() const = 0; - virtual uint8_t getPriority() 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; - }; - - class Properties - { - public: - virtual ~Properties() {} - virtual bool hasMessageId() const = 0; - virtual std::string getMessageId() const = 0; - virtual bool hasUserId() const = 0; - virtual std::string getUserId() const = 0; - virtual bool hasTo() const = 0; - virtual std::string getTo() const = 0; - virtual bool hasSubject() const = 0; - virtual std::string getSubject() const = 0; - virtual bool hasReplyTo() const = 0; - virtual std::string getReplyTo() const = 0; - virtual bool hasCorrelationId() const = 0; - virtual std::string getCorrelationId() const = 0; - virtual bool hasContentType() const = 0; - virtual std::string getContentType() const = 0; - virtual bool hasContentEncoding() const = 0; - virtual std::string getContentEncoding() const = 0; - virtual bool hasAbsoluteExpiryTime() const = 0; - virtual int64_t getAbsoluteExpiryTime() const = 0; - virtual bool hasCreationTime() const = 0; - virtual int64_t getCreationTime() const = 0; - virtual bool hasGroupId() const = 0; - virtual std::string getGroupId() const = 0; - virtual bool hasGroupSequence() const = 0; - virtual uint32_t getGroupSequence() const = 0; - virtual bool hasReplyToGroupId() const = 0; - virtual std::string getReplyToGroupId() const = 0; - }; - - class ApplicationProperties - { - public: - virtual ~ApplicationProperties() {} - virtual void handle(MapHandler&) const = 0; - }; - - 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); - - 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&); - - 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&); - - 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&); -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_MESSAGEENCODER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/MessageId.cpp b/qpid/cpp/src/qpid/amqp/MessageId.cpp deleted file mode 100644 index 69ec4ce7f5..0000000000 --- a/qpid/cpp/src/qpid/amqp/MessageId.cpp +++ /dev/null @@ -1,82 +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/amqp/MessageId.h" -#include -#include - -namespace qpid { -namespace amqp { - -MessageId::MessageId() : type(NONE) -{ -} -void MessageId::assign(std::string& s) const -{ - switch (type) { - case NONE: - s = std::string(); - break; - case BYTES: - if (value.bytes) s.assign(value.bytes.data, value.bytes.size); - break; - case UUID: - s = qpid::types::Uuid(value.bytes).str(); - break; - case ULONG: - s = boost::lexical_cast(value.ulong); - break; - } -} - -MessageId::operator bool() const -{ - return type!=NONE; -} - -std::string MessageId::str() const -{ - std::string s; - assign(s); - return s; -} - -void MessageId::set(qpid::amqp::CharSequence bytes, qpid::types::VariantType t) -{ - switch (t) { - case qpid::types::VAR_STRING: - type = BYTES; - break; - case qpid::types::VAR_UUID: - type = UUID; - assert(bytes.size == 16); - break; - default: - assert(false); - } - value.bytes = bytes; -} -void MessageId::set(uint64_t ulong) -{ - type = ULONG; - value.ulong = ulong; -} - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/MessageId.h b/qpid/cpp/src/qpid/amqp/MessageId.h deleted file mode 100644 index 4505469148..0000000000 --- a/qpid/cpp/src/qpid/amqp/MessageId.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QPID_AMQP_MESSAGEID_H -#define QPID_AMQP_MESSAGEID_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/amqp/CharSequence.h" -#include "qpid/types/Variant.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace amqp { - -struct MessageId -{ - union - { - qpid::amqp::CharSequence bytes; - uint64_t ulong; - } value; - enum - { - NONE, - BYTES, - UUID, - ULONG - } type; - - QPID_COMMON_EXTERN MessageId(); - QPID_COMMON_EXTERN operator bool() const; - QPID_COMMON_EXTERN std::string str() const; - QPID_COMMON_EXTERN void assign(std::string&) const; - QPID_COMMON_EXTERN void set(qpid::amqp::CharSequence bytes, qpid::types::VariantType t); - QPID_COMMON_EXTERN void set(uint64_t ulong); - -}; - -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_MESSAGEID_H*/ diff --git a/qpid/cpp/src/qpid/amqp/MessageReader.cpp b/qpid/cpp/src/qpid/amqp/MessageReader.cpp deleted file mode 100644 index ab90472067..0000000000 --- a/qpid/cpp/src/qpid/amqp/MessageReader.cpp +++ /dev/null @@ -1,685 +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/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" - -using namespace qpid::amqp::message; - -namespace qpid { -namespace amqp { -namespace { - -//header fields: -const size_t DURABLE(0); -const size_t PRIORITY(1); -const size_t TTL(2); -const size_t FIRST_ACQUIRER(3); -const size_t DELIVERY_COUNT(4); - -//properties fields: -const size_t MESSAGE_ID(0); -const size_t USER_ID(1); -const size_t TO(2); -const size_t SUBJECT(3); -const size_t REPLY_TO(4); -const size_t CORRELATION_ID(5); -const size_t CONTENT_TYPE(6); -const size_t CONTENT_ENCODING(7); -const size_t ABSOLUTE_EXPIRY_TIME(8); -const size_t CREATION_TIME(9); -const size_t GROUP_ID(10); -const size_t GROUP_SEQUENCE(11); -const size_t REPLY_TO_GROUP_ID(12); - - -const Descriptor* nested(const Descriptor* d) -{ - if (d && d->nested) return d->nested.get(); - else return 0; -} -} - -MessageReader::HeaderReader::HeaderReader(MessageReader& p) : parent(p), index(0) {} -void MessageReader::HeaderReader::onBoolean(bool v, const Descriptor*) // durable, first-acquirer -{ - if (index == DURABLE) { - parent.onDurable(v); - } else if (index == FIRST_ACQUIRER) { - parent.onFirstAcquirer(v); - } else { - QPID_LOG(warning, "Unexpected message format, got boolean at index " << index << " of headers"); - } - ++index; -} -void MessageReader::HeaderReader::onUByte(uint8_t v, const Descriptor*) // priority -{ - if (index == PRIORITY) { - parent.onPriority(v); - } else { - QPID_LOG(warning, "Unexpected message format, got ubyte at index " << index << " of headers"); - } - ++index; -} -void MessageReader::HeaderReader::onUInt(uint32_t v, const Descriptor*) // ttl, delivery-count -{ - if (index == TTL) { - parent.onTtl(v); - } else if (index == DELIVERY_COUNT) { - parent.onDeliveryCount(v); - } else { - QPID_LOG(warning, "Unexpected message format, got uint at index " << index << " of headers"); - } - ++index; -} -void MessageReader::HeaderReader::onNull(const Descriptor*) -{ - ++index; -} - -MessageReader::PropertiesReader::PropertiesReader(MessageReader& p) : parent(p), index(0) {} -void MessageReader::PropertiesReader::onUuid(const CharSequence& v, const Descriptor*) // message-id, correlation-id -{ - if (index == MESSAGE_ID) { - parent.onMessageId(v, qpid::types::VAR_UUID); - } else if (index == CORRELATION_ID) { - parent.onCorrelationId(v, qpid::types::VAR_UUID); - } else { - QPID_LOG(warning, "Unexpected message format, got uuid at index " << index << " of properties"); - } - ++index; -} -void MessageReader::PropertiesReader::onULong(uint64_t v, const Descriptor*) // message-id, correlation-id -{ - if (index == MESSAGE_ID) { - parent.onMessageId(v); - } else if (index == CORRELATION_ID) { - parent.onCorrelationId(v); - } else { - QPID_LOG(warning, "Unexpected message format, got long at index " << index << " of properties"); - } - ++index; -} -void MessageReader::PropertiesReader::onBinary(const CharSequence& v, const Descriptor*) // message-id, correlation-id, user-id -{ - if (index == MESSAGE_ID) { - parent.onMessageId(v, qpid::types::VAR_STRING); - } else if (index == CORRELATION_ID) { - parent.onCorrelationId(v, qpid::types::VAR_STRING); - } else if (index == USER_ID) { - parent.onUserId(v); - } else { - QPID_LOG(warning, "Unexpected message format, got binary at index " << index << " of properties"); - } - ++index; -} -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, qpid::types::VAR_STRING); - } else if (index == CORRELATION_ID) { - parent.onCorrelationId(v, qpid::types::VAR_STRING); - } else if (index == GROUP_ID) { - parent.onGroupId(v); - } else if (index == REPLY_TO_GROUP_ID) { - parent.onReplyToGroupId(v); - } else if (index == SUBJECT) { - parent.onSubject(v); - } else if (index == TO) { - parent.onTo(v); - } else if (index == REPLY_TO) { - parent.onReplyTo(v); - } else { - QPID_LOG(warning, "Unexpected message format, got string at index " << index << " of properties"); - } - ++index; -} -void MessageReader::PropertiesReader::onSymbol(const CharSequence& v, const Descriptor*) // content-type, content-encoding -{ - if (index == CONTENT_TYPE) { - parent.onContentType(v); - } else if (index == CONTENT_ENCODING) { - parent.onContentEncoding(v); - } else { - QPID_LOG(warning, "Unexpected message format, got symbol at index " << index << " of properties"); - } - ++index; -} -void MessageReader::PropertiesReader::onTimestamp(int64_t v, const Descriptor*) // absolute-expiry-time, creation-time -{ - if (index == ABSOLUTE_EXPIRY_TIME) { - parent.onAbsoluteExpiryTime(v); - } else if (index == CREATION_TIME) { - parent.onCreationTime(v); - } else { - QPID_LOG(warning, "Unexpected message format, got timestamp at index " << index << " of properties"); - } - ++index; -} -void MessageReader::PropertiesReader::onUInt(uint32_t v, const Descriptor*) // group-sequence -{ - if (index == GROUP_SEQUENCE) { - parent.onGroupSequence(v); - } else { - QPID_LOG(warning, "Unexpected message format, got uint at index " << index << " of properties"); - } - ++index; -} -void MessageReader::PropertiesReader::onNull(const Descriptor*) -{ - ++index; -} -void MessageReader::PropertiesReader::onBoolean(bool, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (boolean)"); - ++index; -} -void MessageReader::PropertiesReader::onUByte(uint8_t, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (ubyte)"); - ++index; -} -void MessageReader::PropertiesReader::onUShort(uint16_t, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (ushort)"); - ++index; -} -void MessageReader::PropertiesReader::onByte(int8_t, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (byte)"); - ++index; -} -void MessageReader::PropertiesReader::onShort(int16_t, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (short)"); - ++index; -} -void MessageReader::PropertiesReader::onInt(int32_t, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (int)"); - ++index; -} -void MessageReader::PropertiesReader::onLong(int64_t, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (long)"); - ++index; -} -void MessageReader::PropertiesReader::onFloat(float, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (float)"); - ++index; -} -void MessageReader::PropertiesReader::onDouble(double, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (double)"); - ++index; -} -bool MessageReader::PropertiesReader::onStartList(uint32_t /*count*/, const CharSequence& /*elements*/, const CharSequence& /*complete*/, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (list)"); - ++index; - return false; -} -bool MessageReader::PropertiesReader::onStartMap(uint32_t /*count*/, const CharSequence& /*elements*/, const CharSequence& /*complete*/, const Descriptor*) -{ - QPID_LOG(info, "skipping message property at index " << index << " unexpected type (map)"); - ++index; - return false; -} -bool MessageReader::PropertiesReader::onStartArray(uint32_t /*count*/, const CharSequence&, const Constructor&, const Descriptor*) -{ - 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& elements, const CharSequence& raw, const Descriptor* descriptor) -{ - if (delegate) { - return delegate->onStartList(count, elements, raw, descriptor); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got no descriptor for list."); - return false; - } else if (descriptor->match(HEADER_SYMBOL, HEADER_CODE)) { - delegate = &headerReader; - return true; - } else if (descriptor->match(PROPERTIES_SYMBOL, PROPERTIES_CODE)) { - delegate = &propertiesReader; - return true; - } 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, nested(descriptor)); - return false; - } else { - QPID_LOG(warning, "Unexpected described list: " << *descriptor); - return false; - } - } -} -void MessageReader::onEndList(uint32_t count, const Descriptor* descriptor) -{ - if (delegate) { - if (descriptor && (descriptor->match(HEADER_SYMBOL, HEADER_CODE) || descriptor->match(PROPERTIES_SYMBOL, PROPERTIES_CODE))) { - delegate = 0; - } else { - delegate->onEndList(count, descriptor); - } - } -} - -//delivery-annotations, message-annotations, application-properties, amqp-value -bool MessageReader::onStartMap(uint32_t count, const CharSequence& elements, const CharSequence& raw, const Descriptor* descriptor) -{ - if (delegate) { - 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(elements, raw); - return false; - } else if (descriptor->match(MESSAGE_ANNOTATIONS_SYMBOL, MESSAGE_ANNOTATIONS_CODE)) { - onMessageAnnotations(elements, raw); - return false; - } else if (descriptor->match(FOOTER_SYMBOL, FOOTER_CODE)) { - onFooter(elements, raw); - return false; - } else if (descriptor->match(APPLICATION_PROPERTIES_SYMBOL, APPLICATION_PROPERTIES_CODE)) { - onApplicationProperties(elements, raw); - return false; - } else if (descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - onAmqpValue(elements, qpid::amqp::typecodes::MAP_NAME, nested(descriptor)); - return false; - } else { - QPID_LOG(warning, "Unexpected described map: " << *descriptor); - return false; - } - } -} - -void MessageReader::onEndMap(uint32_t count, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onEndMap(count, descriptor); - } -} - -//data, amqp-value -void MessageReader::onBinary(const CharSequence& bytes, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onBinary(bytes, descriptor); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got binary value with no 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, nested(descriptor)); - } else { - QPID_LOG(warning, "Unexpected binary value with descriptor: " << *descriptor); - } - } - -} - -//amqp-value -void MessageReader::onNull(const Descriptor* descriptor) -{ - if (delegate) { - delegate->onNull(descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant v; - onAmqpValue(v, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got null value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected null value with descriptor: " << *descriptor); - } - } - } -} -void MessageReader::onString(const CharSequence& v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onString(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - onAmqpValue(v, qpid::amqp::typecodes::STRING_NAME, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got string value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected string value with descriptor: " << *descriptor); - } - } - } -} -void MessageReader::onSymbol(const CharSequence& v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onSymbol(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - onAmqpValue(v, qpid::amqp::typecodes::SYMBOL_NAME, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got symbol value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected symbol value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onBoolean(bool v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onBoolean(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got boolean value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected boolean value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onUByte(uint8_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onUByte(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got ubyte value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected ubyte value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onUShort(uint16_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onUShort(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got ushort value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected ushort value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onUInt(uint32_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onUInt(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got uint value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected uint value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onULong(uint64_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onULong(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got ulong value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected ulong value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onByte(int8_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onByte(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got byte value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected byte value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onShort(int16_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onShort(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got short value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected short value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onInt(int32_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onInt(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got int value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected int value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onLong(int64_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onLong(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got long value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected long value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onFloat(float v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onFloat(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got float value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected float value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onDouble(double v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onDouble(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got double value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected double value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onUuid(const CharSequence& v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onUuid(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - onAmqpValue(v, qpid::amqp::typecodes::UUID_NAME, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got uuid value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected uuid value with descriptor: " << *descriptor); - } - } - } -} - -void MessageReader::onTimestamp(int64_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onTimestamp(v, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - qpid::types::Variant body = v; - onAmqpValue(body, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got timestamp value with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected timestamp value with descriptor: " << *descriptor); - } - } - } -} - -bool MessageReader::onStartArray(uint32_t count, const CharSequence& raw, const Constructor& constructor, const Descriptor* descriptor) -{ - if (delegate) { - return delegate->onStartArray(count, raw, constructor, descriptor); - } else { - if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) { - //TODO: might be better to decode this here - onAmqpValue(raw, qpid::amqp::typecodes::ARRAY_NAME, nested(descriptor)); - } else { - if (!descriptor) { - QPID_LOG(warning, "Expected described type but got array with no descriptor."); - } else { - QPID_LOG(warning, "Unexpected array with descriptor: " << *descriptor); - } - } - return false; - } -} - -void MessageReader::onEndArray(uint32_t v, const Descriptor* descriptor) -{ - if (delegate) { - delegate->onEndArray(v, descriptor); - } -} - -MessageReader::MessageReader() : headerReader(*this), propertiesReader(*this), delegate(0) -{ - bare.init(); -} - -void MessageReader::onDescriptor(const Descriptor& descriptor, const char* position) -{ - if (bare.data) { - if (descriptor.match(FOOTER_SYMBOL, FOOTER_CODE)) { - bare.size = position - bare.data; - } - } else { - if (descriptor.match(PROPERTIES_SYMBOL, PROPERTIES_CODE) || descriptor.match(APPLICATION_PROPERTIES_SYMBOL, APPLICATION_PROPERTIES_CODE) - || descriptor.match(AMQP_SEQUENCE_SYMBOL, AMQP_SEQUENCE_CODE) || descriptor.match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE) || descriptor.match(DATA_SYMBOL, DATA_CODE)) { - bare.data = position; - } - } -} - -CharSequence MessageReader::getBareMessage() const { return bare; } - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/MessageReader.h b/qpid/cpp/src/qpid/amqp/MessageReader.h deleted file mode 100644 index 2fb588546f..0000000000 --- a/qpid/cpp/src/qpid/amqp/MessageReader.h +++ /dev/null @@ -1,161 +0,0 @@ -#ifndef QPID_AMQP_MESSAGEREADER_H -#define QPID_AMQP_MESSAGEREADER_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/amqp/CharSequence.h" -#include "qpid/amqp/Reader.h" -#include "qpid/types/Variant.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace amqp { - -/** - * Reader for an AMQP 1.0 message - */ -class MessageReader : public Reader -{ - public: - QPID_COMMON_EXTERN MessageReader(); - - //header, properties, amqp-sequence, amqp-value - 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 CharSequence&, const Descriptor*); - QPID_COMMON_EXTERN void onEndMap(uint32_t, const Descriptor*); - - //data, amqp-value - QPID_COMMON_EXTERN void onBinary(const CharSequence&, const Descriptor*); - - //amqp-value - QPID_COMMON_EXTERN void onNull(const Descriptor*); - QPID_COMMON_EXTERN void onString(const CharSequence&, const Descriptor*); - QPID_COMMON_EXTERN void onSymbol(const CharSequence&, 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 bool onStartArray(uint32_t, const CharSequence&, const Constructor&, const Descriptor*); - QPID_COMMON_EXTERN void onEndArray(uint32_t, const Descriptor*); - QPID_COMMON_EXTERN void onDescriptor(const Descriptor&, const char*); - - //header: - virtual void onDurable(bool) = 0; - virtual void onPriority(uint8_t) = 0; - virtual void onTtl(uint32_t) = 0; - virtual void onFirstAcquirer(bool) = 0; - virtual void onDeliveryCount(uint32_t) = 0; - - //properties: - virtual void onMessageId(uint64_t) = 0; - virtual void onMessageId(const CharSequence&, qpid::types::VariantType) = 0; - virtual void onUserId(const CharSequence&) = 0; - virtual void onTo(const CharSequence&) = 0; - virtual void onSubject(const CharSequence&) = 0; - virtual void onReplyTo(const CharSequence&) = 0; - virtual void onCorrelationId(uint64_t) = 0; - virtual void onCorrelationId(const CharSequence&, qpid::types::VariantType) = 0; - virtual void onContentType(const CharSequence&) = 0; - virtual void onContentEncoding(const CharSequence&) = 0; - virtual void onAbsoluteExpiryTime(int64_t) = 0; - virtual void onCreationTime(int64_t) = 0; - virtual void onGroupId(const CharSequence&) = 0; - virtual void onGroupSequence(uint32_t) = 0; - virtual void onReplyToGroupId(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, const Descriptor*) = 0; - virtual void onAmqpValue(const qpid::types::Variant&, const Descriptor*) = 0; - - virtual void onFooter(const CharSequence& /*values*/, const CharSequence& /*full*/) = 0; - - QPID_COMMON_EXTERN CharSequence getBareMessage() const; - - private: - - class HeaderReader : public Reader - { - public: - HeaderReader(MessageReader&); - void onBoolean(bool v, const Descriptor*); // durable, first-acquirer - void onUByte(uint8_t v, const Descriptor*); // priority - void onUInt(uint32_t v, const Descriptor*); // ttl, delivery-count - void onNull(const Descriptor*); - private: - MessageReader& parent; - size_t index; - }; - class PropertiesReader : public Reader - { - public: - PropertiesReader(MessageReader&); - void onUuid(const CharSequence& v, const Descriptor*); // message-id, correlation-id - void onULong(uint64_t v, const Descriptor*); // message-id, correlation-id - void onBinary(const CharSequence& v, const Descriptor*); // message-id, correlation-id, user-id - void onString(const CharSequence& v, const Descriptor*); // message-id, correlation-id, group-id, reply-to-group-id, subject, to, reply-to - void onSymbol(const CharSequence& v, const Descriptor*); // content-type, content-encoding - 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; - }; - HeaderReader headerReader; - PropertiesReader propertiesReader; - Reader* delegate; - CharSequence bare; -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_MESSAGEREADER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/Reader.h b/qpid/cpp/src/qpid/amqp/Reader.h deleted file mode 100644 index 32f33dc33f..0000000000 --- a/qpid/cpp/src/qpid/amqp/Reader.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef QPID_AMQP_READER_H -#define QPID_AMQP_READER_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 - -namespace qpid { -namespace amqp { -struct CharSequence; -struct Constructor; -struct Descriptor; - -/** - * Allows an event-driven, callback-based approach to processing an - * AMQP encoded data stream. By sublassing and implementing the - * methods of interest, readers can be constructed for different - * contexts. - */ -class Reader -{ - public: - virtual ~Reader() {} - virtual void onNull(const Descriptor*) {} - virtual void onBoolean(bool, const Descriptor*) {} - virtual void onUByte(uint8_t, const Descriptor*) {} - virtual void onUShort(uint16_t, const Descriptor*) {} - virtual void onUInt(uint32_t, const Descriptor*) {} - virtual void onULong(uint64_t, const Descriptor*) {} - virtual void onByte(int8_t, const Descriptor*) {} - virtual void onShort(int16_t, const Descriptor*) {} - virtual void onInt(int32_t, const Descriptor*) {} - virtual void onLong(int64_t, const Descriptor*) {} - virtual void onFloat(float, const Descriptor*) {} - virtual void onDouble(double, const Descriptor*) {} - virtual void onUuid(const CharSequence&, const Descriptor*) {} - virtual void onTimestamp(int64_t, const Descriptor*) {} - - virtual void onBinary(const CharSequence&, const Descriptor*) {} - virtual void onString(const CharSequence&, const Descriptor*) {} - virtual void onSymbol(const CharSequence&, const Descriptor*) {} - - /** - * @return true to get elements of the compound value, false - * to skip over it - */ - 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*) {} - virtual void onEndArray(uint32_t /*count*/, const Descriptor*) {} - - virtual void onDescriptor(const Descriptor&, const char*) {} - - virtual bool proceed() { return true; } - private: -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_READER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/Sasl.cpp b/qpid/cpp/src/qpid/amqp/Sasl.cpp deleted file mode 100644 index a7c2eea35b..0000000000 --- a/qpid/cpp/src/qpid/amqp/Sasl.cpp +++ /dev/null @@ -1,141 +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/amqp/Sasl.h" -#include "qpid/amqp/Decoder.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/amqp/Encoder.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/framing/ProtocolInitiation.h" -#include - -namespace qpid { -namespace amqp { - -Sasl::Sasl(const std::string& i) : id(i), buffer(2*512/*AMQP 1.0's MAX_MIN_FRAME_SIZE - is this enough though?*/), encoder(&buffer[0], buffer.size()) {} -Sasl::~Sasl() {} - -void* Sasl::startFrame() -{ - //write sasl frame header, leaving 4 bytes for total size - char* start = encoder.skip(4); - encoder.write((uint8_t) 0x02);//data offset - encoder.write((uint8_t) 0x01);//frame type - encoder.write((uint16_t) 0x0000);//ignored - return start; -} - -void Sasl::endFrame(void* frame) -{ - //now backfill the frame size - char* start = (char*) frame; - char* current = &buffer[encoder.getPosition()]; - uint32_t frameSize = current - start; - Encoder backfill(start, 4); - backfill.write(frameSize); - QPID_LOG(trace, "Completed encoding of frame of " << frameSize << " bytes"); -} - - -std::size_t Sasl::read(const char* data, size_t available) -{ - size_t consumed = 0; - while (!stopReading() && available - consumed > 4/*framesize*/) { - Decoder decoder(data+consumed, available-consumed); - //read frame-header - uint32_t frameSize = decoder.readUInt(); - if (frameSize > decoder.getSize()) break;//don't have all the data for this frame yet - - QPID_LOG(trace, "Reading SASL frame of size " << frameSize); - decoder.resetSize(frameSize); - uint8_t dataOffset = decoder.readUByte(); - uint8_t frameType = decoder.readUByte(); - if (frameType != 0x01) { - QPID_LOG(error, "Expected SASL frame; got type " << frameType); - } - uint16_t ignored = decoder.readUShort(); - if (ignored) { - QPID_LOG(info, "Got non null bytes at end of SASL frame header"); - } - - //body is at offset 4*dataOffset from the start - size_t skip = dataOffset*4 - 8; - if (skip) { - QPID_LOG(info, "Offset for sasl frame was not as expected"); - decoder.advance(skip); - } - decoder.read(*this); - consumed += decoder.getPosition(); - } - return consumed; -} - -std::size_t Sasl::write(char* data, size_t size) -{ - size_t available = encoder.getPosition(); - if (available) { - size_t encoded = available > size ? size : available; - ::memcpy(data, &buffer[0], encoded); - size_t remainder = encoder.getPosition() - encoded; - if (remainder) { - //shuffle - ::memcpy(&buffer[0], &buffer[size], remainder); - } - encoder.resetPosition(remainder); - return encoded; - } else { - return 0; - } -} - -std::size_t Sasl::readProtocolHeader(const char* buffer, std::size_t size) -{ - framing::ProtocolInitiation pi(qpid::framing::ProtocolVersion(1,0,qpid::framing::ProtocolVersion::SASL)); - if (size >= pi.encodedSize()) { - qpid::framing::Buffer out(const_cast(buffer), size); - pi.decode(out); - QPID_LOG_CAT(debug, protocol, id << " read protocol header: " << pi); - return pi.encodedSize(); - } else { - return 0; - } -} -std::size_t Sasl::writeProtocolHeader(char* buffer, std::size_t size) -{ - framing::ProtocolInitiation pi(qpid::framing::ProtocolVersion(1,0,qpid::framing::ProtocolVersion::SASL)); - if (size >= pi.encodedSize()) { - QPID_LOG_CAT(debug, protocol, id << " writing protocol header: " << pi); - qpid::framing::Buffer out(buffer, size); - pi.encode(out); - return pi.encodedSize(); - } else { - QPID_LOG_CAT(warning, protocol, id << " insufficient buffer for protocol header: " << size) - return 0; - } -} - -bool Sasl::stopReading() -{ - return false; -} - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/Sasl.h b/qpid/cpp/src/qpid/amqp/Sasl.h deleted file mode 100644 index 24a8de7dc4..0000000000 --- a/qpid/cpp/src/qpid/amqp/Sasl.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef QPID_AMQP_SASL_H -#define QPID_AMQP_SASL_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/amqp/Encoder.h" -#include "qpid/amqp/Reader.h" -#include -#include - -namespace qpid { -namespace amqp { - -/** - * Base for SASL client and server utilities - */ -class Sasl : protected Reader -{ - public: - 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 buffer; - Encoder encoder; - - void* startFrame(); - void endFrame(void*); - QPID_COMMON_EXTERN virtual bool stopReading(); -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_SASL_H*/ diff --git a/qpid/cpp/src/qpid/amqp/SaslClient.cpp b/qpid/cpp/src/qpid/amqp/SaslClient.cpp deleted file mode 100644 index d8a38750c5..0000000000 --- a/qpid/cpp/src/qpid/amqp/SaslClient.cpp +++ /dev/null @@ -1,154 +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/amqp/SaslClient.h" -#include "qpid/amqp/Decoder.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/amqp/Encoder.h" -#include "qpid/log/Statement.h" - -using namespace qpid::amqp::sasl; - -namespace qpid { -namespace amqp { - -SaslClient::SaslClient(const std::string& id) : Sasl(id) {} -SaslClient::~SaslClient() {} -void SaslClient::init(const std::string& mechanism, const std::string* response, const std::string* hostname) -{ - void* frame = startFrame(); - - void* token = encoder.startList32(&SASL_INIT); - encoder.writeSymbol(mechanism); - if (response) encoder.writeBinary(*response); - else encoder.writeNull(); - if (hostname) encoder.writeString(*hostname); - else encoder.writeNull(); - encoder.endList32(3, token); - - endFrame(frame); - QPID_LOG_CAT(debug, protocol, id << " Sent SASL-INIT(" << mechanism << ", " << (response ? *response : "null") << ", " << (hostname ? *hostname : "null") << ")"); -} -void SaslClient::response(const std::string* r) -{ - void* frame = startFrame(); - - void* token = encoder.startList32(&SASL_RESPONSE); - if (r) encoder.writeBinary(*r); - else encoder.writeNull(); - encoder.endList32(1, token); - - endFrame(frame); - QPID_LOG_CAT(debug, protocol, id << " Sent SASL-RESPONSE(" << (r ? *r : "null") << ")"); -} - - -namespace { -const std::string SPACE(" "); -class SaslMechanismsReader : public Reader -{ - public: - SaslMechanismsReader(SaslClient& c) : client(c), expected(0) {} - void onSymbol(const CharSequence& mechanism, const Descriptor*) - { - if (expected) { - mechanisms << mechanism.str() << SPACE; - } else { - client.mechanisms(mechanism.str()); - } - } - bool onStartArray(uint32_t count, const CharSequence&, const Constructor&, const Descriptor*) - { - expected = count; - return true; - } - void onEndArray(uint32_t, const Descriptor*) - { - client.mechanisms(mechanisms.str()); - } - private: - SaslClient& client; - uint32_t expected; - std::stringstream mechanisms; -}; -class SaslChallengeReader : public Reader -{ - public: - SaslChallengeReader(SaslClient& c) : client(c) {} - void onNull(const Descriptor*) { client.challenge(); } - void onBinary(const CharSequence& c, const Descriptor*) { client.challenge(c.str()); } - private: - SaslClient& client; -}; -class SaslOutcomeReader : public Reader -{ - public: - SaslOutcomeReader(SaslClient& c, bool e) : client(c), expectExtraData(e) {} - void onUByte(uint8_t c, const Descriptor*) - { - if (expectExtraData) code = c; - else client.outcome(c); - } - void onBinary(const CharSequence& extra, const Descriptor*) { client.outcome(code, extra.str()); } - void onNull(const Descriptor*) { client.outcome(code); } - private: - SaslClient& client; - bool expectExtraData; - uint8_t code; -}; -} - -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"); - } else if (descriptor->match(SASL_MECHANISMS_SYMBOL, SASL_MECHANISMS_CODE)) { - QPID_LOG(trace, "Reading SASL-MECHANISMS"); - Decoder decoder(arguments.data, arguments.size); - if (count != 1) QPID_LOG(error, "Invalid SASL-MECHANISMS frame; exactly one field expected, got " << count); - SaslMechanismsReader reader(*this); - decoder.read(reader); - } else if (descriptor->match(SASL_CHALLENGE_SYMBOL, SASL_CHALLENGE_CODE)) { - QPID_LOG(trace, "Reading SASL-CHALLENGE"); - Decoder decoder(arguments.data, arguments.size); - if (count != 1) QPID_LOG(error, "Invalid SASL-CHALLENGE frame; exactly one field expected, got " << count); - SaslChallengeReader reader(*this); - decoder.read(reader); - } else if (descriptor->match(SASL_OUTCOME_SYMBOL, SASL_OUTCOME_CODE)) { - QPID_LOG(trace, "Reading SASL-OUTCOME"); - Decoder decoder(arguments.data, arguments.size); - if (count == 1) { - SaslOutcomeReader reader(*this, false); - decoder.read(reader); - } else if (count == 2) { - SaslOutcomeReader reader(*this, true); - decoder.read(reader); - } else { - QPID_LOG(error, "Invalid SASL-OUTCOME frame; got " << count << " fields"); - } - } else { - QPID_LOG(error, "Unexpected descriptor in SASL negotiation: " << *descriptor); - } - return false; -} - - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/SaslClient.h b/qpid/cpp/src/qpid/amqp/SaslClient.h deleted file mode 100644 index d22887de1a..0000000000 --- a/qpid/cpp/src/qpid/amqp/SaslClient.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef QPID_AMQP_SASLCLIENT_H -#define QPID_AMQP_SASLCLIENT_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 -#include "qpid/amqp/Sasl.h" - -namespace qpid { -namespace amqp { - -/** - * Utility for decoding and encoding SASL frames by the peer acting as - * the SASL client. - */ -class SaslClient : public Sasl -{ - public: - 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; - - 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: - QPID_COMMON_EXTERN bool onStartList(uint32_t count, const CharSequence& arguments, const CharSequence&, const Descriptor* descriptor); - -}; - -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_SASLCLIENT_H*/ diff --git a/qpid/cpp/src/qpid/amqp/SaslServer.cpp b/qpid/cpp/src/qpid/amqp/SaslServer.cpp deleted file mode 100644 index 250858bda0..0000000000 --- a/qpid/cpp/src/qpid/amqp/SaslServer.cpp +++ /dev/null @@ -1,183 +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/amqp/SaslServer.h" -#include "qpid/amqp/Constructor.h" -#include "qpid/amqp/Decoder.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/amqp/Encoder.h" -#include "qpid/amqp/typecodes.h" -#include "qpid/log/Statement.h" -#include "qpid/StringUtils.h" -#include -#include - -using namespace qpid::amqp::sasl; -using namespace qpid::amqp::typecodes; - -namespace qpid { -namespace amqp { -namespace { -const std::string SPACE(" "); -const std::string NULL_("NULL"); -} - -SaslServer::SaslServer(const std::string& id) : Sasl(id) {} -SaslServer::~SaslServer() {} - -void SaslServer::mechanisms(const std::string& mechanisms) -{ - void* frameToken = startFrame(); - - std::vector parts = split(mechanisms, SPACE); - void* listToken = encoder.startList32(&SASL_MECHANISMS); - if (parts.size() > 1) { - void* arrayToken = encoder.startArray8(Constructor(SYMBOL8)); - for (std::vector::const_iterator i = parts.begin();i != parts.end(); ++i) { - uint8_t size = i->size() > std::numeric_limits::max() ? std::numeric_limits::max() : i->size(); - encoder.write(size); - encoder.writeBytes(i->data(), size); - } - encoder.endArray8(parts.size(), arrayToken); - } else { - encoder.writeSymbol(mechanisms); - } - encoder.endList32(1, listToken); - - endFrame(frameToken); - QPID_LOG_CAT(debug, protocol, id << " Sent SASL-MECHANISMS(" << mechanisms << ") " << encoder.getPosition()); -} -void SaslServer::challenge(const std::string* c) -{ - void* frameToken = startFrame(); - - void* listToken = encoder.startList32(&SASL_CHALLENGE); - if (c) encoder.writeBinary(*c); - else encoder.writeNull(); - encoder.endList32(1, listToken); - - endFrame(frameToken); - QPID_LOG_CAT(debug, protocol, id << " Sent SASL-CHALLENGE(" << (c ? *c : NULL_) << ") " << encoder.getPosition()); -} -void SaslServer::completed(bool succeeded) -{ - void* frameToken = startFrame(); - - void* listToken = encoder.startList8(&SASL_OUTCOME); - encoder.writeUByte(succeeded ? 0 : 1); - encoder.endList8(1, listToken); - - endFrame(frameToken); - QPID_LOG_CAT(debug, protocol, id << " Sent SASL-OUTCOME(" << (succeeded ? 0 : 1) << ") " << encoder.getPosition()); -} - -namespace { -class SaslInitReader : public Reader -{ - public: - SaslInitReader(SaslServer& s, uint32_t e) : server(s), expected(e), hasResponse(false), index(0) {} - void onNull(const Descriptor*) - { - ++index; - if (index == 2) { - if (--expected == 0) { - server.init(mechanism, 0, 0); - } - } else if (index == 3) { - server.init(mechanism, hasResponse ? &response : 0, 0); - } else { - QPID_LOG(warning, "Unexpected sequence of fields for SASL-INIT: got null for field " << index); - } - } - void onBinary(const CharSequence& r, const Descriptor*) - { - if (++index != 2) QPID_LOG(warning, "Unexpected sequence of fields for SASL-INIT: got binary for field " << index); - response = r.str(); - hasResponse = true; - if (--expected == 0) { - server.init(mechanism, &response, 0); - } - } - void onString(const CharSequence& h, const Descriptor*) - { - if (--expected || ++index != 3) { - QPID_LOG(warning, "Unexpected sequence of fields for SASL-INIT: got string for field " << index); - } else { - std::string hostname = h.str(); - server.init(mechanism, hasResponse ? &response : 0, &hostname); - } - } - void onSymbol(const CharSequence& m, const Descriptor*) - { - if (++index != 1) QPID_LOG(warning, "Unexpected sequence of fields for SASL-INIT: got symbol for field " << index); - if (--expected) { - mechanism = m.str(); - } else { - server.init(m.str(), 0, 0); - } - } - private: - SaslServer& server; - uint32_t expected; - std::string mechanism; - std::string response; - bool hasResponse; - uint32_t index; -}; - -class SaslResponseReader : public Reader -{ - public: - SaslResponseReader(SaslServer& s) : server(s) {} - void onNull(const Descriptor*) { server.response(0); } - void onBinary(const CharSequence& r, const Descriptor*) - { - std::string s = r.str(); - server.response(&s); - } - private: - SaslServer& server; -}; -} - -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"); - } else if (descriptor->match(SASL_INIT_SYMBOL, SASL_INIT_CODE)) { - QPID_LOG(trace, "Reading SASL-INIT"); - Decoder decoder(arguments.data, arguments.size); - if (count < 1 || count > 3) QPID_LOG(error, "Invalid SASL-INIT frame; got " << count << " fields"); - SaslInitReader reader(*this, count); - decoder.read(reader); - } else if (descriptor->match(SASL_RESPONSE_SYMBOL, SASL_RESPONSE_CODE)) { - QPID_LOG(trace, "Reading SASL-RESPONSE (" << std::string(arguments.data, arguments.size) << ") " << count << " elements"); - Decoder decoder(arguments.data, arguments.size); - if (count != 1) QPID_LOG(error, "Invalid SASL-RESPONSE frame; exactly one field expected, got " << count); - SaslResponseReader reader(*this); - decoder.read(reader); - } else { - QPID_LOG(error, "Unexpected descriptor in SASL negotiation: " << *descriptor); - } - return false; -} - -}} // namespace qpid::amqp diff --git a/qpid/cpp/src/qpid/amqp/SaslServer.h b/qpid/cpp/src/qpid/amqp/SaslServer.h deleted file mode 100644 index 68d0854488..0000000000 --- a/qpid/cpp/src/qpid/amqp/SaslServer.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_AMQP_SASLSERVER_H -#define QPID_AMQP_SASLSERVER_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/amqp/Sasl.h" - -namespace qpid { -namespace amqp { - -/** - * Utility for decoding and encoding SASL frames by the peer acting as - * the SASL server. - */ -class SaslServer : public Sasl -{ - public: - 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; - - 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: - QPID_COMMON_EXTERN bool onStartList(uint32_t count, const CharSequence& arguments, const CharSequence&, const Descriptor* descriptor); -}; -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_SASLSERVER_H*/ diff --git a/qpid/cpp/src/qpid/amqp/descriptors.h b/qpid/cpp/src/qpid/amqp/descriptors.h deleted file mode 100644 index 276514e2e5..0000000000 --- a/qpid/cpp/src/qpid/amqp/descriptors.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef QPID_AMQP_DESCRIPTORS_H -#define QPID_AMQP_DESCRIPTORS_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 "Descriptor.h" - -namespace qpid { -namespace amqp { - -// NOTE: If you add descriptor symbols and codes here, you must also update the DescriptorMap -// constructor in Descriptor.cpp. - -namespace message { -const std::string HEADER_SYMBOL("amqp:header:list"); -const std::string PROPERTIES_SYMBOL("amqp:properties:list"); -const std::string DELIVERY_ANNOTATIONS_SYMBOL("amqp:delivery-annotations:map"); -const std::string MESSAGE_ANNOTATIONS_SYMBOL("amqp:message-annotations:map"); -const std::string APPLICATION_PROPERTIES_SYMBOL("amqp:application-properties:map"); -const std::string AMQP_SEQUENCE_SYMBOL("amqp:amqp-sequence:list"); -const std::string AMQP_VALUE_SYMBOL("amqp:amqp-value:*"); -const std::string DATA_SYMBOL("amqp:data:binary"); -const std::string FOOTER_SYMBOL("amqp:footer:map"); -const std::string ACCEPTED_SYMBOL("amqp:accepted:list"); - -const uint64_t HEADER_CODE(0x70); -const uint64_t DELIVERY_ANNOTATIONS_CODE(0x71); -const uint64_t MESSAGE_ANNOTATIONS_CODE(0x72); -const uint64_t PROPERTIES_CODE(0x73); -const uint64_t APPLICATION_PROPERTIES_CODE(0x74); -const uint64_t DATA_CODE(0x75); -const uint64_t AMQP_SEQUENCE_CODE(0x76); -const uint64_t AMQP_VALUE_CODE(0x77); -const uint64_t FOOTER_CODE(0x78); -const uint64_t ACCEPTED_CODE(0x24); - -const Descriptor HEADER(HEADER_CODE); -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); -} - -namespace sasl { -const std::string SASL_MECHANISMS_SYMBOL("amqp:sasl-mechanisms:list"); -const std::string SASL_INIT_SYMBOL("amqp:sasl-init:list"); -const std::string SASL_CHALLENGE_SYMBOL("amqp:sasl-challenge:list"); -const std::string SASL_RESPONSE_SYMBOL("amqp:sasl-response:list"); -const std::string SASL_OUTCOME_SYMBOL("amqp:sasl-outcome:list"); - -const uint64_t SASL_MECHANISMS_CODE(0x40); -const uint64_t SASL_INIT_CODE(0x41); -const uint64_t SASL_CHALLENGE_CODE(0x42); -const uint64_t SASL_RESPONSE_CODE(0x43); -const uint64_t SASL_OUTCOME_CODE(0x44); - -const Descriptor SASL_MECHANISMS(SASL_MECHANISMS_CODE); -const Descriptor SASL_INIT(SASL_INIT_CODE); -const Descriptor SASL_CHALLENGE(SASL_CHALLENGE_CODE); -const Descriptor SASL_RESPONSE(SASL_RESPONSE_CODE); -const Descriptor SASL_OUTCOME(SASL_OUTCOME_CODE); -} - -namespace filters { -const std::string LEGACY_DIRECT_FILTER_SYMBOL("apache.org:legacy-amqp-direct-binding:string"); -const std::string LEGACY_TOPIC_FILTER_SYMBOL("apache.org:legacy-amqp-topic-binding:string"); -const std::string LEGACY_HEADERS_FILTER_SYMBOL("apache.org:legacy-amqp-headers-binding:map"); -const std::string NO_LOCAL_FILTER_SYMBOL("apache.org:no-local-filter:list"); -const std::string SELECTOR_FILTER_SYMBOL("apache.org:selector-filter:string"); -const std::string XQUERY_FILTER_SYMBOL("apache.org:xquery-filter:string"); - -const uint64_t LEGACY_DIRECT_FILTER_CODE(0x0000468C00000000ULL); -const uint64_t LEGACY_TOPIC_FILTER_CODE(0x0000468C00000001ULL); -const uint64_t LEGACY_HEADERS_FILTER_CODE(0x0000468C00000002ULL); -const uint64_t NO_LOCAL_FILTER_CODE(0x0000468C00000003ULL); -const uint64_t SELECTOR_FILTER_CODE(0x0000468C00000004ULL); -const uint64_t XQUERY_FILTER_CODE(0x0000468C00000005ULL); -} - -namespace lifetime_policy { -const std::string DELETE_ON_CLOSE_SYMBOL("amqp:delete-on-close:list"); -const std::string DELETE_ON_NO_LINKS_SYMBOL("amqp:delete-on-no-links:list"); -const std::string DELETE_ON_NO_MESSAGES_SYMBOL("amqp:delete-on-no-messages:list"); -const std::string DELETE_ON_NO_LINKS_OR_MESSAGES_SYMBOL("amqp:delete-on-no-links-or-messages:list"); - -const uint64_t DELETE_ON_CLOSE_CODE(0x2B); -const uint64_t DELETE_ON_NO_LINKS_CODE(0x2C); -const uint64_t DELETE_ON_NO_MESSAGES_CODE(0x2D); -const uint64_t DELETE_ON_NO_LINKS_OR_MESSAGES_CODE(0x2E); -} - -namespace transaction { -const std::string DECLARE_SYMBOL("amqp:declare:list"); -const std::string DISCHARGE_SYMBOL("amqp:discharge:list"); -const std::string DECLARED_SYMBOL("amqp:declared:list"); -const std::string TRANSACTIONAL_STATE_SYMBOL("amqp:transactional-state:list"); - -const uint64_t DECLARE_CODE(0x31); -const uint64_t DISCHARGE_CODE(0x32); -const uint64_t DECLARED_CODE(0x33); -const uint64_t TRANSACTIONAL_STATE_CODE(0x34); -} - -namespace error_conditions { -//note these are not actually descriptors -const std::string INTERNAL_ERROR("amqp:internal-error"); -const std::string NOT_FOUND("amqp:not-found"); -const std::string UNAUTHORIZED_ACCESS("amqp:unauthorized-access"); -const std::string DECODE_ERROR("amqp:decode-error"); -const std::string NOT_ALLOWED("amqp:not-allowed"); -const std::string NOT_IMPLEMENTED("amqp:not-implemented"); -const std::string RESOURCE_LIMIT_EXCEEDED("amqp:resource-limit-exceeded"); -const std::string RESOURCE_DELETED("amqp:resource-deleted"); -const std::string PRECONDITION_FAILED("amqp:precondition-failed"); -namespace transaction { -const std::string UNKNOWN_ID("amqp:transaction:unknown-id"); -const std::string ROLLBACK("amqp:transaction:rollback"); -} -} -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_DESCRIPTORS_H*/ diff --git a/qpid/cpp/src/qpid/amqp/typecodes.h b/qpid/cpp/src/qpid/amqp/typecodes.h deleted file mode 100644 index 915b75ca3f..0000000000 --- a/qpid/cpp/src/qpid/amqp/typecodes.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef QPID_AMQP_TYPECODES_H -#define QPID_AMQP_TYPECODES_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 amqp { - -namespace typecodes -{ -const uint8_t DESCRIPTOR(0x0); - -const uint8_t NULL_VALUE(0x40); - -const uint8_t BOOLEAN(0x56); -const uint8_t BOOLEAN_TRUE(0x41); -const uint8_t BOOLEAN_FALSE(0x42); - -const uint8_t UBYTE(0x50); -const uint8_t USHORT(0x60); -const uint8_t UINT(0x70); -const uint8_t UINT_SMALL(0x52); -const uint8_t UINT_ZERO(0x43); -const uint8_t ULONG(0x80); -const uint8_t ULONG_SMALL(0x53); -const uint8_t ULONG_ZERO(0x44); - -const uint8_t BYTE(0x51); -const uint8_t SHORT(0x61); -const uint8_t INT(0x71); -const uint8_t INT_SMALL(0x54); -const uint8_t LONG(0x81); -const uint8_t LONG_SMALL(0x55); - -const uint8_t FLOAT(0x72); -const uint8_t DOUBLE(0x82); - -const uint8_t DECIMAL32(0x74); -const uint8_t DECIMAL64(0x84); -const uint8_t DECIMAL128(0x94); - -const uint8_t CHAR_UTF32(0x73); -const uint8_t TIMESTAMP(0x83); -const uint8_t UUID(0x98); - -const uint8_t BINARY8(0xa0); -const uint8_t BINARY32(0xb0); -const uint8_t STRING8(0xa1); -const uint8_t STRING32(0xb1); -const uint8_t SYMBOL8(0xa3); -const uint8_t SYMBOL32(0xb3); - -typedef std::pair CodePair; -const CodePair SYMBOL(SYMBOL8, SYMBOL32); -const CodePair STRING(STRING8, STRING32); -const CodePair BINARY(BINARY8, BINARY32); - -const uint8_t LIST0(0x45); -const uint8_t LIST8(0xc0); -const uint8_t LIST32(0xd0); -const uint8_t MAP8(0xc1); -const uint8_t MAP32(0xd1); -const uint8_t ARRAY8(0xe0); -const uint8_t ARRAY32(0xf0); - - -const std::string NULL_NAME("null"); -const std::string BOOLEAN_NAME("bool"); - -const std::string UBYTE_NAME("ubyte"); -const std::string USHORT_NAME("ushort"); -const std::string UINT_NAME("uint"); -const std::string ULONG_NAME("ulong"); - -const std::string BYTE_NAME("byte"); -const std::string SHORT_NAME("short"); -const std::string INT_NAME("int"); -const std::string LONG_NAME("long"); - -const std::string FLOAT_NAME("float"); -const std::string DOUBLE_NAME("double"); - -const std::string TIMESTAMP_NAME("timestamp"); -const std::string UUID_NAME("uuid"); - -const std::string BINARY_NAME("binary"); -const std::string STRING_NAME("string"); -const std::string SYMBOL_NAME("symbol"); - -const std::string LIST_NAME("list"); -const std::string MAP_NAME("map"); -const std::string ARRAY_NAME("array"); -} - -}} // namespace qpid::amqp - -#endif /*!QPID_AMQP_TYPECODES_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/Codecs.cpp b/qpid/cpp/src/qpid/amqp_0_10/Codecs.cpp deleted file mode 100644 index 49d152cc05..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/Codecs.cpp +++ /dev/null @@ -1,586 +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/amqp_0_10/Codecs.h" -#include "qpid/amqp_0_10/CodecsInternal.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/log/Statement.h" -#include -#include -#include - -using namespace qpid::framing; -using namespace qpid::types; - -namespace qpid { -namespace amqp_0_10 { - -namespace { -const std::string iso885915("iso-8859-15"); -const std::string utf8("utf8"); -const std::string utf16("utf16"); -const std::string binary("binary"); -const std::string amqp0_10_binary("amqp0-10:binary"); -const std::string amqp0_10_bit("amqp0-10:bit"); -const std::string amqp0_10_datetime("amqp0-10:datetime"); -const std::string amqp0_10_struct("amqp0-10:struct"); -} - -template void convert(const T& from, U& to, F f) -{ - std::transform(from.begin(), from.end(), std::inserter(to, to.begin()), f); -} - -Variant::Map::value_type toVariantMapEntry(const FieldTable::value_type& in); - -template void translate(boost::shared_ptr in, U& u, F f) -{ - T t; - getEncodedValue(in, t); - convert(t, u, f); -} - -void setEncodingFor(Variant& out, uint8_t code) -{ - switch(code){ - case 0x80: - case 0x90: - case 0xa0: - out.setEncoding(amqp0_10_binary); - break; - case 0x84: - case 0x94: - out.setEncoding(iso885915); - break; - case 0x85: - case 0x95: - out.setEncoding(utf8); - break; - case 0x86: - case 0x96: - out.setEncoding(utf16); - break; - case 0xab: - out.setEncoding(amqp0_10_struct); - break; - default: - //do nothing - break; - } -} - -qpid::types::Uuid getUuid(FieldValue& value) -{ - unsigned char data[16]; - value.getFixedWidthValue<16>(data); - return qpid::types::Uuid(data); -} - -Variant toVariant(boost::shared_ptr in) -{ - Variant out; - //based on AMQP 0-10 typecode, pick most appropriate variant type - switch (in->getType()) { - //Fixed Width types: - case 0x00: out.setEncoding(amqp0_10_binary); - case 0x01: out = in->getIntegerValue(); break; - case 0x02: out = in->getIntegerValue(); break; - case 0x04: break; //TODO: iso-8859-15 char - case 0x08: out = static_cast(in->getIntegerValue()); break; - case 0x10: out.setEncoding(amqp0_10_binary); - case 0x11: out = in->getIntegerValue(); break; - case 0x12: out = in->getIntegerValue(); break; - case 0x20: out.setEncoding(amqp0_10_binary); - case 0x21: out = in->getIntegerValue(); break; - case 0x22: out = in->getIntegerValue(); break; - case 0x23: out = in->get(); break; - case 0x27: break; //TODO: utf-32 char - case 0x30: out.setEncoding(amqp0_10_binary); - case 0x31: out = in->getIntegerValue(); break; - case 0x38: out.setEncoding(amqp0_10_datetime); //treat datetime as uint64_t, but set encoding - case 0x32: out = in->getIntegerValue(); break; - case 0x33: out = in->get(); break; - - case 0x48: out = getUuid(*in); break; - - //TODO: figure out whether and how to map values with codes 0x40-0xd8 - - case 0xf0: break;//void, which is the default value for Variant - case 0xf1: out.setEncoding(amqp0_10_bit); break;//treat 'bit' as void, which is the default value for Variant - - //Variable Width types: - //strings: - case 0x80: - case 0x84: - case 0x85: - case 0x86: - case 0x90: - case 0x94: - case 0x95: - case 0x96: - case 0xa0: - case 0xab: - out = in->get(); - setEncodingFor(out, in->getType()); - break; - - case 0xa8: - out = Variant::Map(); - translate(in, out.asMap(), &toVariantMapEntry); - break; - - case 0xa9: - out = Variant::List(); - translate(in, out.asList(), &toVariant); - break; - case 0xaa: //convert amqp0-10 array into variant list - out = Variant::List(); - translate(in, out.asList(), &toVariant); - break; - - default: - //error? - break; - } - return out; -} - -Variant::Map::value_type toVariantMapEntry(const FieldTable::value_type& in) -{ - return Variant::Map::value_type(in.first, toVariant(in.second)); -} - -struct DecodeBuffer -{ - Buffer buffer; - - DecodeBuffer(const std::string& s) : buffer(const_cast(s.data()), s.size()) {} - - template void decode(T& t) { t.decode(buffer); } - -}; - -template void _decode(const std::string& data, U& value, F f) -{ - T t; - DecodeBuffer buffer(data); - buffer.decode(t); - convert(t, value, f); -} - -uint32_t encodedSize(const Variant& value) -{ - switch (value.getType()) { - case VAR_VOID: - return 0; - case VAR_BOOL: - case VAR_UINT8: - case VAR_INT8: - return 1; - case VAR_UINT16: - case VAR_INT16: - return 2; - break; - case VAR_UINT32: - case VAR_INT32: - case VAR_FLOAT: - return 4; - case VAR_UINT64: - case VAR_INT64: - case VAR_DOUBLE: - return 8; - case VAR_UUID: - return 16; - case VAR_MAP: - return encodedSize(value.asMap()); - case VAR_LIST: - return encodedSize(value.asList()); - case VAR_STRING: - return encodedSize(value.getString()); - default: - throw Exception("Couldn't encode Variant: Illegal type code"); - } -} - -uint32_t encodedSize(const Variant::Map& values) -{ - uint32_t size = 4/*size field*/ + 4/*count field*/; - for(Variant::Map::const_iterator i = values.begin(); i != values.end(); ++i) { - size += 1/*size of key*/ + (i->first).size() + 1/*typecode*/ + encodedSize(i->second); - } - return size; -} - -uint32_t encodedSize(const Variant::Map& values, const std::string& efield, const Variant& evalue) -{ - uint32_t size = 4/*size field*/ + 4/*count field*/; - for(Variant::Map::const_iterator i = values.begin(); i != values.end(); ++i) { - size += 1/*size of key*/ + (i->first).size() + 1/*typecode*/ + encodedSize(i->second); - } - size += 1/*size of key*/ + efield.size() + 1/*typecode*/ + encodedSize(evalue); - return size; -} - -uint32_t encodedSize(const Variant::List& values) -{ - uint32_t size = 4/*size field*/ + 4/*count field*/; - for(Variant::List::const_iterator i = values.begin(); i != values.end(); ++i) { - size += 1/*typecode*/ + encodedSize(*i); - } - return size; -} - -uint32_t encodedSize(const std::string& value) -{ - uint32_t size = value.size(); - if (size > std::numeric_limits::max()) { - return size + 4; /*Long size*/ - } else { - return size + 2; /*Short size*/ - } -} - -void encode(const std::string& value, const std::string& encoding, qpid::framing::Buffer& buffer) -{ - uint32_t size = value.size(); - if (size > std::numeric_limits::max()) { - if (encoding == utf8 || encoding == utf16 || encoding == iso885915) { - throw Exception(QPID_MSG("Could not encode " << encoding << " character string - too long (" << size << " bytes)")); - } else { - buffer.putOctet(0xa0); - buffer.putLong(size); - buffer.putRawData(value); - } - } else { - if (encoding == utf8) { - buffer.putOctet(0x95); - } else if (encoding == utf16) { - buffer.putOctet(0x96); - } else if (encoding == iso885915) { - buffer.putOctet(0x94); - } else { - buffer.putOctet(0x90); - } - buffer.putShort(size); - buffer.putRawData(value); - } -} - -void encode(const Variant& value, qpid::framing::Buffer& buffer) -{ - switch (value.getType()) { - case VAR_VOID: - buffer.putOctet(0xf0); - break; - case VAR_BOOL: - buffer.putOctet(0x08); - buffer.putOctet(value.asBool()); - break; - case VAR_INT8: - buffer.putOctet(0x01); - buffer.putInt8(value.asInt8()); - break; - case VAR_UINT8: - buffer.putOctet(0x02); - buffer.putOctet(value.asUint8()); - break; - case VAR_INT16: - buffer.putOctet(0x11); - buffer.putInt16(value.asInt16()); - break; - case VAR_UINT16: - buffer.putOctet(0x12); - buffer.putShort(value.asUint16()); - break; - case VAR_INT32: - buffer.putOctet(0x21); - buffer.putInt32(value.asInt32()); - break; - case VAR_UINT32: - buffer.putOctet(0x22); - buffer.putLong(value.asUint32()); - break; - case VAR_FLOAT: - buffer.putOctet(0x23); - buffer.putFloat(value.asFloat()); - break; - case VAR_INT64: - buffer.putOctet(0x31); - buffer.putInt64(value.asInt64()); - break; - case VAR_UINT64: - buffer.putOctet(0x32); - buffer.putLongLong(value.asUint64()); - break; - case VAR_DOUBLE: - buffer.putOctet(0x33); - buffer.putDouble(value.asDouble()); - break; - case VAR_UUID: - buffer.putOctet(0x48); - buffer.putBin128(value.asUuid().data()); - break; - case VAR_MAP: - buffer.putOctet(0xa8); - encode(value.asMap(), encodedSize(value.asMap()), buffer); - break; - case VAR_LIST: - buffer.putOctet(0xa9); - encode(value.asList(), encodedSize(value.asList()), buffer); - break; - case VAR_STRING: - encode(value.getString(), value.getEncoding(), buffer); - break; - } -} - -void encode(const Variant::Map& map, uint32_t len, qpid::framing::Buffer& buffer) -{ - uint32_t s = buffer.getPosition(); - buffer.putLong(len - 4);//exclusive of the size field itself - buffer.putLong(map.size()); - for (Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) { - buffer.putShortString(i->first); - encode(i->second, buffer); - } - (void) s; assert(s + len == buffer.getPosition()); -} - -void encode(const Variant::Map& map, const std::string& efield, const Variant& evalue, uint32_t len, qpid::framing::Buffer& buffer) -{ - uint32_t s = buffer.getPosition(); - buffer.putLong(len - 4);//exclusive of the size field itself - buffer.putLong(map.size() + 1 /* The extra field */ ); - for (Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) { - buffer.putShortString(i->first); - encode(i->second, buffer); - } - buffer.putShortString(efield); - encode(evalue, buffer); - - (void) s; assert(s + len == buffer.getPosition()); -} - -void encode(const Variant::List& list, uint32_t len, qpid::framing::Buffer& buffer) -{ - uint32_t s = buffer.getPosition(); - buffer.putLong(len - 4);//exclusive of the size field itself - buffer.putLong(list.size()); - for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { - encode(*i, buffer); - } - (void) s; assert(s + len == buffer.getPosition()); -} - -void decode(qpid::framing::Buffer&, Variant::Map&) -{ -} - - -void MapCodec::encode(const Variant::Map& value, std::string& data) -{ - uint32_t len = qpid::amqp_0_10::encodedSize(value); - std::vector space(len); - qpid::framing::Buffer buff(&space[0], len); - - qpid::amqp_0_10::encode(value, len, buff); - assert( len == buff.getPosition() ); - data.assign(&space[0], len); -} - -void MapCodec::decode(const std::string& data, Variant::Map& value) -{ - _decode(data, value, &toVariantMapEntry); -} - -size_t MapCodec::encodedSize(const Variant::Map& value) -{ - return qpid::amqp_0_10::encodedSize(value); -} - -void ListCodec::encode(const Variant::List& value, std::string& data) -{ - uint32_t len = qpid::amqp_0_10::encodedSize(value); - std::vector space(len); - qpid::framing::Buffer buff(&space[0], len); - - qpid::amqp_0_10::encode(value, len, buff); - assert( len == buff.getPosition() ); - data.assign(&space[0], len); -} - -void ListCodec::decode(const std::string& data, Variant::List& value) -{ - _decode(data, value, &toVariant); -} - -size_t ListCodec::encodedSize(const Variant::List& value) -{ - return qpid::amqp_0_10::encodedSize(value); -} - -void translate(const Variant::Map& from, FieldTable& to) -{ - // Create buffer of correct size to encode Variant::Map - uint32_t len = encodedSize(from); - std::vector space(len); - qpid::framing::Buffer buff(&space[0], len); - - // Encode Variant::Map into buffer directly - - // We pass the already calculated length in to avoid - // recalculating it. - encode(from, len, buff); - - // Give buffer to FieldTable - // Could speed this up a bit by avoiding copying - // the buffer we just created into the FieldTable - assert( len == buff.getPosition() ); - buff.reset(); - to.decode(buff); -} - -void translate(const Variant::Map& from, const std::string& efield, const Variant& evalue, FieldTable& to) -{ - // Create buffer of correct size to encode Variant::Map - uint32_t len = encodedSize(from, efield, evalue); - std::vector space(len); - qpid::framing::Buffer buff(&space[0], len); - - // Encode Variant::Map into buffer directly - - // We pass the already calculated length in to avoid - // recalculating it. - encode(from, efield, evalue, len, buff); - - // Give buffer to FieldTable - // Could speed this up a bit by avoiding copying - // the buffer we just created into the FieldTable - assert( len == buff.getPosition() ); - buff.reset(); - to.decode(buff); -} - -void translate(const FieldTable& from, Variant::Map& to) -{ - convert(from, to, &toVariantMapEntry); -} - -namespace { -boost::shared_ptr convertString(const std::string& value, const std::string& encoding); -FieldTableValue* toFieldTableValue(const Variant::Map& map); -ListValue* toListValue(const Variant::List& list); - -boost::shared_ptr toFieldValue(const Variant& in) -{ - boost::shared_ptr out; - switch (in.getType()) { - case VAR_VOID: out = boost::shared_ptr(new VoidValue()); break; - case VAR_BOOL: out = boost::shared_ptr(new BoolValue(in.asBool())); break; - case VAR_UINT8: out = boost::shared_ptr(new Unsigned8Value(in.asUint8())); break; - case VAR_UINT16: out = boost::shared_ptr(new Unsigned16Value(in.asUint16())); break; - case VAR_UINT32: out = boost::shared_ptr(new Unsigned32Value(in.asUint32())); break; - case VAR_UINT64: out = boost::shared_ptr(new Unsigned64Value(in.asUint64())); break; - case VAR_INT8: out = boost::shared_ptr(new Integer8Value(in.asInt8())); break; - case VAR_INT16: out = boost::shared_ptr(new Integer16Value(in.asInt16())); break; - case VAR_INT32: out = boost::shared_ptr(new Integer32Value(in.asInt32())); break; - case VAR_INT64: out = boost::shared_ptr(new Integer64Value(in.asInt64())); break; - case VAR_FLOAT: out = boost::shared_ptr(new FloatValue(in.asFloat())); break; - case VAR_DOUBLE: out = boost::shared_ptr(new DoubleValue(in.asDouble())); break; - case VAR_STRING: out = convertString(in.asString(), in.getEncoding()); break; - case VAR_UUID: out = boost::shared_ptr(new UuidValue(in.asUuid().data())); break; - case VAR_MAP: - out = boost::shared_ptr(toFieldTableValue(in.asMap())); - break; - case VAR_LIST: - out = boost::shared_ptr(toListValue(in.asList())); - } - return out; -} - -boost::shared_ptr convertString(const std::string& value, const std::string& encoding) -{ - bool large = value.size() > std::numeric_limits::max(); - if (encoding.empty() || encoding == amqp0_10_binary || encoding == binary) { - if (large) { - return boost::shared_ptr(new Var32Value(value, 0xa0)); - } else { - return boost::shared_ptr(new Var16Value(value, 0x90)); - } - } else if (encoding == utf8) { - if (!large) - return boost::shared_ptr(new Str16Value(value)); - throw Exception(QPID_MSG("Could not encode utf8 character string - too long (" << value.size() << " bytes)")); - } else if (encoding == utf16) { - if (!large) - return boost::shared_ptr(new Var16Value(value, 0x96)); - throw Exception(QPID_MSG("Could not encode utf16 character string - too long (" << value.size() << " bytes)")); - } else if (encoding == iso885915) { - if (!large) - return boost::shared_ptr(new Var16Value(value, 0x94)); - throw Exception(QPID_MSG("Could not encode iso-8859-15 character string - too long (" << value.size() << " bytes)")); - } else { - // the encoding was not recognised - QPID_LOG(warning, "Unknown byte encoding: [" << encoding << "], encoding as vbin32."); - return boost::shared_ptr(new Var32Value(value, 0xa0)); - } -} - -FieldTable::value_type toFieldTableEntry(const Variant::Map::value_type& in) -{ - return FieldTable::value_type(in.first, toFieldValue(in.second)); -} - -FieldTableValue* toFieldTableValue(const Variant::Map& map) -{ - FieldTable ft; - convert(map, ft, &toFieldTableEntry); - return new FieldTableValue(ft); -} - -ListValue* toListValue(const Variant::List& list) -{ - List l; - convert(list, l, &toFieldValue); - return new ListValue(l); -} -} - -void translate(const types::Variant& from, boost::shared_ptr to) -{ - to = toFieldValue(from); -} - -void translate(const boost::shared_ptr from, Variant& to) -{ - to = toVariant(from); -} - -boost::shared_ptr translate(const types::Variant& from) -{ - return toFieldValue(from); -} - -const std::string ListCodec::contentType("amqp/list"); -const std::string MapCodec::contentType("amqp/map"); - -}} // namespace qpid::amqp_0_10 diff --git a/qpid/cpp/src/qpid/amqp_0_10/Codecs.h b/qpid/cpp/src/qpid/amqp_0_10/Codecs.h deleted file mode 100644 index 79d76bcc4b..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/Codecs.h +++ /dev/null @@ -1,87 +0,0 @@ -#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 from, - qpid::types::Variant& to); -QPID_COMMON_EXTERN void translate(const types::Variant& from, - boost::shared_ptr to); -QPID_COMMON_EXTERN boost::shared_ptr translate(const types::Variant& from); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_CODECS_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/CodecsInternal.h b/qpid/cpp/src/qpid/amqp_0_10/CodecsInternal.h deleted file mode 100644 index cf9a7d0447..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/CodecsInternal.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_AMQP_0_10_CODECSINTERNAL_H -#define QPID_AMQP_0_10_CODECSINTERNAL_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" - -namespace qpid { -namespace framing { -class Buffer; -} -namespace amqp_0_10 { -QPID_COMMON_EXTERN void encode(const qpid::types::Variant::Map& map, uint32_t len, qpid::framing::Buffer& buffer); -QPID_COMMON_EXTERN void encode(const qpid::types::Variant::List& list, uint32_t len, qpid::framing::Buffer& buffer); -QPID_COMMON_EXTERN void encode(const qpid::types::Variant& value, qpid::framing::Buffer& buffer); -QPID_COMMON_EXTERN void encode(const std::string& value, const std::string& encoding, qpid::framing::Buffer& buffer); -QPID_COMMON_EXTERN uint32_t encodedSize(const qpid::types::Variant::Map& values); -QPID_COMMON_EXTERN uint32_t encodedSize(const qpid::types::Variant::List& values); -QPID_COMMON_EXTERN uint32_t encodedSize(const std::string& value); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_CODECSINTERNAL_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp b/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp deleted file mode 100644 index 866f98071b..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp +++ /dev/null @@ -1,150 +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/amqp_0_10/Connection.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/ProtocolInitiation.h" - -namespace qpid { -namespace amqp_0_10 { - -using framing::InternalErrorException; -using sys::Mutex; - -Connection::Connection(sys::OutputControl& o, const std::string& id, bool _isClient) - : pushClosed(false), popClosed(false), output(o), identifier(id), initialized(false), - isClient(_isClient), buffered(0), version(0,10) -{} - -void Connection::setInputHandler(std::auto_ptr c) { - connection = c; -} - -size_t Connection::decode(const char* buffer, size_t size) { - framing::Buffer in(const_cast(buffer), size); - if (isClient && !initialized) { - //read in protocol header - framing::ProtocolInitiation pi; - if (pi.decode(in)) { - if(!(pi==version)) - throw Exception(QPID_MSG("Unsupported version: " << pi - << " supported version " << version)); - QPID_LOG(trace, "RECV [" << identifier << "]: INIT(" << pi << ")"); - initialized = true; - } - } - framing::AMQFrame frame; - while(!pushClosed && frame.decode(in)) { - QPID_LOG(trace, "RECV [" << identifier << "]: " << frame); - connection->received(frame); - } - return in.getPosition(); -} - -bool Connection::canEncode() { - Mutex::ScopedLock l(frameQueueLock); - if (!popClosed) { - Mutex::ScopedUnlock u(frameQueueLock); - connection->doOutput(); - } - return !popClosed && ((!isClient && !initialized) || !frameQueue.empty()); -} - -bool Connection::isClosed() const { - Mutex::ScopedLock l(frameQueueLock); - return pushClosed && popClosed; -} - -size_t Connection::encode(char* buffer, size_t size) { - { // Swap frameQueue data into workQueue to avoid holding lock while we encode. - Mutex::ScopedLock l(frameQueueLock); - if (popClosed) return 0; // Can't pop any more frames. - assert(workQueue.empty()); - workQueue.swap(frameQueue); - } - framing::Buffer out(buffer, size); - if (!isClient && !initialized) { - framing::ProtocolInitiation pi(getVersion()); - pi.encode(out); - initialized = true; - QPID_LOG(trace, "SENT [" << identifier << "]: INIT(" << pi << ")"); - } - size_t frameSize=0; - size_t encoded=0; - while (!workQueue.empty() && ((frameSize=workQueue.front().encodedSize()) <= out.available())) { - workQueue.front().encode(out); - QPID_LOG(trace, "SENT [" << identifier << "]: " << workQueue.front()); - workQueue.pop_front(); - encoded += frameSize; - if (workQueue.empty() && out.available() > 0) { - // try to get more output - connection->doOutput(); - Mutex::ScopedLock l(frameQueueLock); - workQueue.swap(frameQueue); // Need to get any new frames into the work queue - } - } - assert(workQueue.empty() || workQueue.front().encodedSize() <= size); - if (!workQueue.empty() && workQueue.front().encodedSize() > size) - throw InternalErrorException(QPID_MSG("Frame too large for buffer.")); - { - Mutex::ScopedLock l(frameQueueLock); - buffered -= encoded; - // Put back any frames we did not encode. - frameQueue.insert(frameQueue.begin(), workQueue.begin(), workQueue.end()); - workQueue.clear(); - if (frameQueue.empty() && pushClosed) - popClosed = true; - } - return out.getPosition(); -} - -void Connection::abort() { output.abort(); } -void Connection::connectionEstablished() { output.connectionEstablished(); } -void Connection::activateOutput() { output.activateOutput(); } - -void Connection::close() { - // No more frames can be pushed onto the queue. - // Frames aleady on the queue can be popped. - Mutex::ScopedLock l(frameQueueLock); - pushClosed = true; -} - -void Connection::closed() { - connection->closed(); -} - -void Connection::handle(framing::AMQFrame& f) { - { - Mutex::ScopedLock l(frameQueueLock); - if (!pushClosed) - frameQueue.push_back(f); - buffered += f.encodedSize(); - } - activateOutput(); -} - -framing::ProtocolVersion Connection::getVersion() const { - return version; -} - -}} // namespace qpid::amqp_0_10 diff --git a/qpid/cpp/src/qpid/amqp_0_10/Connection.h b/qpid/cpp/src/qpid/amqp_0_10/Connection.h deleted file mode 100644 index 5f58df307d..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/Connection.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_AMQP_0_10_CONNECTION_H -#define QPID_AMQP_0_10_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 "qpid/framing/AMQFrame.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/ConnectionInputHandler.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/BrokerImportExport.h" -#include -#include -#include - -namespace qpid { - -namespace sys { -class ConnectionInputHandlerFactory; -} - -namespace amqp_0_10 { - -class Connection : public sys::ConnectionCodec, - public sys::ConnectionOutputHandler -{ - typedef std::deque FrameQueue; - - FrameQueue frameQueue; - FrameQueue workQueue; - bool pushClosed, popClosed; - mutable sys::Mutex frameQueueLock; - sys::OutputControl& output; - std::auto_ptr connection; - std::string identifier; - bool initialized; - bool isClient; - size_t buffered; - framing::ProtocolVersion version; - - public: - QPID_BROKER_EXTERN Connection(sys::OutputControl&, const std::string& id, bool isClient); - QPID_BROKER_EXTERN void setInputHandler(std::auto_ptr c); - size_t decode(const char* buffer, size_t size); - size_t encode(char* buffer, size_t size); - bool isClosed() const; - bool canEncode(); - void abort(); - void connectionEstablished(); - void activateOutput(); - void closed(); // connection closed by peer. - void close(); // closing from this end. - void handle(framing::AMQFrame&); - framing::ProtocolVersion getVersion() const; -}; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_CONNECTION_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.cpp b/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.cpp deleted file mode 100644 index bd0dcbfc85..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.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/amqp_0_10/SessionHandler.h" -#include "qpid/SessionState.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/AllInvoker.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" - - -#include - -namespace qpid { -namespace amqp_0_10 { -using namespace framing; -using namespace std; - -void SessionHandler::checkAttached() { - if (!getState()) - throw NotAttachedException(QPID_MSG("Channel " << channel.get() << " is not attached")); -} - -SessionHandler::SessionHandler(FrameHandler* out, ChannelId ch) - : channel(ch, out), peer(channel), - awaitingDetached(false), - sendReady(), receiveReady() {} - -SessionHandler::~SessionHandler() {} - -namespace { -bool isSessionControl(AMQMethodBody* m) { - return m && m->amqpClassId() == SESSION_CLASS_ID; -} - -session::DetachCode convert(uint8_t code) { - switch(code) { - case 0: return session::DETACH_CODE_NORMAL; - case 1: return session::DETACH_CODE_SESSION_BUSY; - case 2: return session::DETACH_CODE_TRANSPORT_BUSY; - case 3: return session::DETACH_CODE_NOT_ATTACHED; - case 4: default: return session::DETACH_CODE_UNKNOWN_IDS; - } -} - -} // namespace - -void SessionHandler::invoke(const AMQMethodBody& m) { - framing::invoke(*this, m); -} - -void SessionHandler::handleIn(AMQFrame& f) { - // Note on channel states: a channel is attached if session != 0 - AMQMethodBody* m = f.getBody()->getMethod(); - try { - // Ignore all but detach controls while awaiting detach - if (awaitingDetached) { - if (!isSessionControl(m)) return; - if (m->amqpMethodId() != SESSION_DETACH_METHOD_ID && - m->amqpMethodId() != SESSION_DETACHED_METHOD_ID) - return; - } - if (isSessionControl(m)) { - invoke(*m); - } - else { - // Drop frames if we are detached. - if (!getState()) return; - if (!receiveReady) - throw IllegalStateException(QPID_MSG(getState()->getId() << ": Not ready to receive data")); - if (!getState()->receiverRecord(f)) - return; // Ignore duplicates. - if (getState()->receiverNeedKnownCompleted()) - sendCompletion(); - getInHandler()->handle(f); - } - } - catch(const SessionException& e) { - executionException(e.code, e.what()); - framing::AMQP_AllProxy::Execution execution(channel); - AMQMethodBody* m = f.getMethod(); - SequenceNumber commandId; - if (getState()) commandId = getState()->receiverGetCurrent(); - execution.exception(e.code, commandId, m ? m->amqpClassId() : 0, m ? m->amqpMethodId() : 0, 0, e.what(), FieldTable()); - detaching(); - sendDetach(); - } - catch(const ChannelException& e){ - channelException(e.code, e.what()); - peer.detached(name, e.code); - } - catch(const ConnectionException& e) { - connectionException(e.code, e.getMessage()); - } - catch(const std::exception& e) { - connectionException(connection::CLOSE_CODE_FRAMING_ERROR, e.what()); - } -} - -void SessionHandler::handleException(const qpid::SessionException& e) -{ - QPID_LOG(error, "Execution exception (during output): " << e.what()); - executionException(e.code, e.what()); // Let subclass handle this first. - framing::AMQP_AllProxy::Execution execution(channel); - execution.exception(e.code, 0, 0, 0, 0, e.what(), FieldTable()); - detaching(); - sendDetach(); -} - -namespace { -bool isCommand(const AMQFrame& f) { - return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_COMMAND; -} -} // namespace - -void SessionHandler::handleOut(AMQFrame& f) { - checkAttached(); - if (!sendReady) - throw IllegalStateException(QPID_MSG(getState()->getId() << ": Not ready to send data")); - getState()->senderRecord(f); - if (isCommand(f) && getState()->senderNeedFlush()) { - peer.flush(false, false, true); - getState()->senderRecordFlush(); - } - channel.handle(f); -} - -void SessionHandler::attach(const std::string& name_, bool force) { - // Save the name for possible session-busy exception. Session-busy - // can be thrown before we have attached the handler to a valid - // SessionState, and in that case we need the name to send peer.detached - name = name_; - if (getState() && name == getState()->getId().getName()) - return; // Idempotent - if (getState()) - throw TransportBusyException( - QPID_MSG("Channel " << channel.get() << " already attached to " << getState()->getId())); - setState(name, force); - QPID_LOG(debug, "Attached channel " << channel.get() << " to " << getState()->getId()); - peer.attached(name); - if (getState()->hasState()) - peer.flush(true, true, true); - else - sendCommandPoint(getState()->senderGetCommandPoint()); -} - -#define CHECK_NAME(NAME, MSG) do { \ - checkAttached(); \ - if (NAME != getState()->getId().getName()) \ - throw InvalidArgumentException( \ - QPID_MSG(MSG << ": incorrect session name: " << NAME \ - << ", expecting: " << getState()->getId().getName())); \ - } while(0) - - -void SessionHandler::attached(const std::string& name) { - CHECK_NAME(name, "session.attached"); -} - -void SessionHandler::detach(const std::string& name) { - CHECK_NAME(name, "session.detach"); - peer.detached(name, session::DETACH_CODE_NORMAL); - handleDetach(); -} - -void SessionHandler::detached(const std::string& /*name*/, uint8_t code) { - awaitingDetached = false; - // Special case for detached: Don't throw if we are not attached. Doing so - // can lead to an endless game of "detached tennis" on federated brokers. - if (!getState()) return; // Already detached. - if (code != session::DETACH_CODE_NORMAL) { - sendReady = receiveReady = false; - channelException(convert(code), Msg() << "Channel " << channel.get() - << " received session.detached from peer"); - } else { - handleDetach(); - } -} - -void SessionHandler::handleDetach() { - sendReady = receiveReady = false; -} - -void SessionHandler::requestTimeout(uint32_t t) { - checkAttached(); - getState()->setTimeout(t); - peer.timeout(getState()->getTimeout()); -} - -void SessionHandler::timeout(uint32_t t) { - checkAttached(); - getState()->setTimeout(t); -} - -void SessionHandler::commandPoint(const SequenceNumber& id, uint64_t offset) { - checkAttached(); - getState()->receiverSetCommandPoint(SessionPoint(id, offset)); - if (!receiveReady) { - receiveReady = true; - readyToReceive(); - } -} - -void SessionHandler::expected(const SequenceSet& commands, const Array& /*fragments*/) { - checkAttached(); - if (getState()->hasState()) { // Replay - if (commands.empty()) throw IllegalStateException( - QPID_MSG(getState()->getId() << ": has state but client is attaching as new session.")); - // TODO aconway 2008-05-12: support replay of partial commands. - // Here we always round down to the last command boundary. - SessionPoint expectedPoint = commands.empty() ? SequenceNumber(0) : SessionPoint(commands.front(),0); - SessionState::ReplayRange replay = getState()->senderExpected(expectedPoint); - sendCommandPoint(expectedPoint); - std::for_each(replay.begin(), replay.end(), out); // replay - } - else - sendCommandPoint(getState()->senderGetCommandPoint()); -} - -void SessionHandler::confirmed(const SequenceSet& commands, const Array& /*fragments*/) { - checkAttached(); - // Ignore non-contiguous confirmations. - if (!commands.empty() && commands.front() >= getState()->senderGetReplayPoint()) - getState()->senderConfirmed(commands.rangesBegin()->last()); -} - -void SessionHandler::completed(const SequenceSet& commands, bool timelyReply) { - checkAttached(); - getState()->senderCompleted(commands); - if (getState()->senderNeedKnownCompleted() || timelyReply) { - peer.knownCompleted(commands); - getState()->senderRecordKnownCompleted(); - } -} - -void SessionHandler::knownCompleted(const SequenceSet& commands) { - checkAttached(); - getState()->receiverKnownCompleted(commands); -} - -void SessionHandler::flush(bool expected, bool confirmed, bool completed) { - checkAttached(); - if (expected) { - SequenceSet expectSet; - if (getState()->hasState()) - expectSet.add(getState()->receiverGetExpected().command); - peer.expected(expectSet, Array()); - } - if (confirmed) { - SequenceSet confirmSet; - if (!getState()->receiverGetUnknownComplete().empty()) - confirmSet.add(getState()->receiverGetUnknownComplete().front(), - getState()->receiverGetReceived().command); - peer.confirmed(confirmSet, Array()); - } - if (completed) - peer.completed(getState()->receiverGetUnknownComplete(), true); -} - -void SessionHandler::gap(const SequenceSet& /*commands*/) { - checkAttached(); - throw NotImplementedException("session.gap not supported"); -} - -void SessionHandler::sendDetach() -{ - checkAttached(); - awaitingDetached = true; - peer.detach(getState()->getId().getName()); -} - -void SessionHandler::sendCompletion() { - checkAttached(); - const SequenceSet& c = getState()->receiverGetUnknownComplete(); - peer.completed(c, getState()->receiverNeedKnownCompleted()); -} - -void SessionHandler::sendAttach(bool force) { - QPID_LOG(debug, "SessionHandler::sendAttach attach id=" << getState()->getId()); - peer.attach(getState()->getId().getName(), force); - if (getState()->hasState()) - peer.flush(true, true, true); - else - sendCommandPoint(getState()->senderGetCommandPoint()); -} - -void SessionHandler::sendCommandPoint(const SessionPoint& point) { - peer.commandPoint(point.command, point.offset); - if (!sendReady) { - sendReady = true; - readyToSend(); - } -} - -void SessionHandler::markReadyToSend() { - if (!sendReady) { - sendReady = true; - } -} - -void SessionHandler::sendTimeout(uint32_t t) { - checkAttached(); - peer.requestTimeout(t); -} - -void SessionHandler::sendFlush() { - peer.flush(false, true, true); -} - -bool SessionHandler::ready() const { - return sendReady && receiveReady; -} - - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.h b/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.h deleted file mode 100644 index 8b072fa05c..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/SessionHandler.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef QPID_AMQP_0_10_SESSIONHANDLER_H -#define QPID_AMQP_0_10_SESSIONHANDLER_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/ChannelHandler.h" -#include "qpid/framing/AMQP_AllProxy.h" -#include "qpid/framing/AMQP_AllOperations.h" -#include "qpid/SessionState.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { - -struct SessionException; - -namespace amqp_0_10 { - -/** - * Base SessionHandler with logic common to both client and broker. - * - * A SessionHandler is associated with a channel and can be attached - * to a session state. - */ - -class QPID_COMMON_CLASS_EXTERN SessionHandler : public framing::AMQP_AllOperations::SessionHandler, - public framing::FrameHandler::InOutHandler -{ - public: - QPID_COMMON_EXTERN SessionHandler(framing::FrameHandler* out=0, uint16_t channel=0); - QPID_COMMON_EXTERN ~SessionHandler(); - - void setChannel(uint16_t ch) { channel = ch; } - uint16_t getChannel() const { return channel.get(); } - - void setOutHandler(framing::FrameHandler& h) { channel.next = &h; } - - virtual SessionState* getState() = 0; - virtual framing::FrameHandler* getInHandler() = 0; - - // Non-protocol methods, called locally to initiate some action. - QPID_COMMON_EXTERN void sendDetach(); - QPID_COMMON_EXTERN void sendCompletion(); - QPID_COMMON_EXTERN void sendAttach(bool force); - QPID_COMMON_EXTERN void sendTimeout(uint32_t t); - QPID_COMMON_EXTERN void sendFlush(); - QPID_COMMON_EXTERN void markReadyToSend();//TODO: only needed for inter-broker bridge; cleanup - QPID_COMMON_EXTERN void handleException(const qpid::SessionException& e); - - /** True if the handler is ready to send and receive */ - QPID_COMMON_EXTERN bool ready() const; - - // Protocol methods - QPID_COMMON_EXTERN void attach(const std::string& name, bool force); - QPID_COMMON_EXTERN void attached(const std::string& name); - QPID_COMMON_EXTERN void detach(const std::string& name); - QPID_COMMON_EXTERN void detached(const std::string& name, uint8_t code); - - QPID_COMMON_EXTERN void requestTimeout(uint32_t t); - QPID_COMMON_EXTERN void timeout(uint32_t t); - - QPID_COMMON_EXTERN void commandPoint(const framing::SequenceNumber& id, uint64_t offset); - QPID_COMMON_EXTERN void expected(const framing::SequenceSet& commands, const framing::Array& fragments); - QPID_COMMON_EXTERN void confirmed(const framing::SequenceSet& commands,const framing::Array& fragments); - QPID_COMMON_EXTERN void completed(const framing::SequenceSet& commands, bool timelyReply); - QPID_COMMON_EXTERN void knownCompleted(const framing::SequenceSet& commands); - QPID_COMMON_EXTERN void flush(bool expected, bool confirmed, bool completed); - QPID_COMMON_EXTERN void gap(const framing::SequenceSet& commands); - - protected: - QPID_COMMON_EXTERN virtual void invoke(const framing::AMQMethodBody& m); - - virtual void setState(const std::string& sessionName, bool force) = 0; - virtual void connectionException(framing::connection::CloseCode code, const std::string& msg) = 0; - virtual void channelException(framing::session::DetachCode, const std::string& msg) = 0; - virtual void executionException(framing::execution::ErrorCode, const std::string& msg) = 0; - virtual void detaching() = 0; - - // Notification of events - virtual void readyToSend() {} - virtual void readyToReceive() {} - - QPID_COMMON_EXTERN virtual void handleDetach(); - QPID_COMMON_EXTERN virtual void handleIn(framing::AMQFrame&); - QPID_COMMON_EXTERN virtual void handleOut(framing::AMQFrame&); - - framing::ChannelHandler channel; - - private: - void checkAttached(); - void sendCommandPoint(const SessionPoint&); - - framing::AMQP_AllProxy::Session peer; - std::string name; - bool awaitingDetached; - bool sendReady, receiveReady; -}; -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_SESSIONHANDLER_H*/ diff --git a/qpid/cpp/src/qpid/assert.cpp b/qpid/cpp/src/qpid/assert.cpp deleted file mode 100644 index 801bfa6ae5..0000000000 --- a/qpid/cpp/src/qpid/assert.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_ASSERT_CPP -#define QPID_ASSERT_CPP - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 -#include -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { - -void assert_fail(char const * expr, char const * function, char const * file, long line) { - std::ostringstream msg; - msg << "Assertion failed: " << expr << " in function " << function - << "(" << file << ":" << line << ")"; - QPID_LOG(critical, msg.str()); -#ifdef NDEBUG - throw framing::InternalErrorException(msg.str()); -#else - std::cerr << msg.str() << std::endl; - abort(); -#endif -} - -} // namespace qpid - -#endif /*!QPID_ASSERT_CPP*/ diff --git a/qpid/cpp/src/qpid/assert.h b/qpid/cpp/src/qpid/assert.h deleted file mode 100644 index 49e7c5355d..0000000000 --- a/qpid/cpp/src/qpid/assert.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef QPID_ASSERT_H -#define QPID_ASSERT_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 - -/** - * Abort if !expr in debug mode, throw an exception if NDEBUG is set. - */ -#define QPID_ASSERT(expr) ((expr) ? static_cast(0) : ::qpid::assert_fail(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) - -namespace qpid { - -void assert_fail(char const * expr, char const * function, char const * file, long line); - -} // namespace qpid - -#endif /*!QPID_ASSERT_H*/ diff --git a/qpid/cpp/src/qpid/broker/AclModule.h b/qpid/cpp/src/qpid/broker/AclModule.h deleted file mode 100644 index 6f3b69390b..0000000000 --- a/qpid/cpp/src/qpid/broker/AclModule.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef QPID_ACLMODULE_ACL_H -#define QPID_ACLMODULE_ACL_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/acl/AclLexer.h" -#include -#include - -namespace qpid { -namespace broker { - - class Connection; - - class AclModule - { - - public: - - // Some ACLs are invoked on every message transfer. - // doTransferAcl prevents time consuming ACL calls on a per-message basis. - virtual bool doTransferAcl()=0; - - virtual uint16_t getMaxConnectTotal()=0; - - virtual bool userAclRules()=0; - - virtual bool authorise( - const std::string& id, - const acl::Action& action, - const acl::ObjectType& objType, - const std::string& name, - std::map* params=0)=0; - - virtual bool authorise( - const std::string& id, - const acl::Action& action, - const acl::ObjectType& objType, - const std::string& ExchangeName, - const std::string& RoutingKey)=0; - - // Add specialized authorise() methods as required. - - /** Approve connection by counting connections total, per-IP, and - * per-user. - */ - virtual bool approveConnection (const Connection& connection)=0; - - /** Approve queue creation by counting per-user. - */ - virtual bool approveCreateQueue(const std::string& userId, const std::string& queueName)=0; - virtual void recordDestroyQueue(const std::string& queueName)=0; - - virtual ~AclModule() {}; - }; -}} // namespace qpid::broker - -#endif // QPID_ACLMODULE_ACL_H diff --git a/qpid/cpp/src/qpid/broker/AsyncCommandCallback.cpp b/qpid/cpp/src/qpid/broker/AsyncCommandCallback.cpp deleted file mode 100644 index 0b52c6b5c5..0000000000 --- a/qpid/cpp/src/qpid/broker/AsyncCommandCallback.cpp +++ /dev/null @@ -1,70 +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 "AsyncCommandCallback.h" -#include "SessionOutputException.h" - - -namespace qpid { -namespace broker { - -using namespace framing; - -AsyncCommandCallback::AsyncCommandCallback(SessionState& ss, Command f, bool sync) : - AsyncCommandContext(ss), command(f), channel(ss.getChannel()), syncPoint(sync) -{} - -void AsyncCommandCallback::completed(bool sync) { - if (sync) - doCommand(); // In initiating thread, execute now. - else - completerContext->schedule( - boost::bind(&AsyncCommandCallback::complete, - boost::intrusive_ptr(this))); -} - -boost::intrusive_ptr AsyncCommandCallback::clone() { - return new AsyncCommandCallback(*this); -} - -void AsyncCommandCallback::complete() { - try{ - doCommand(); - } catch (const SessionException& e) { - throw SessionOutputException(e, channel); - } catch (const std::exception& e) { - throw SessionOutputException(InternalErrorException(e.what()), channel); - } -} - -void AsyncCommandCallback::doCommand() { - SessionState* session = completerContext->getSession(); - if (session && session->isAttached()) { - std::string result = command(); // Execute the command now. - // Send completion now unless this is a syncPoint and there are incomplete commands. - if (!(syncPoint && session->addPendingExecutionSync(id))) - session->completeCommand(id, false, requiresSync, result); - } - else - throw InternalErrorException("Cannot complete command, no session"); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/AsyncCommandCallback.h b/qpid/cpp/src/qpid/broker/AsyncCommandCallback.h deleted file mode 100644 index 15884ae8d9..0000000000 --- a/qpid/cpp/src/qpid/broker/AsyncCommandCallback.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_BROKER_ASYNCCOMMANDCALLBACK_H -#define QPID_BROKER_ASYNCCOMMANDCALLBACK_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/SessionState.h" -#include "qpid/broker/AsyncCompletion.h" - -namespace qpid { -namespace broker { - -/** - * An AsyncCompletion::Callback that executes the final part of an - * async-completed command in the proper context: - * - * - Complete synchronously: Called in the initiating thread. - * - Complete asynchronously: Scheduled on the IO thread. - * - * Errors thrown by the command are returned to the correct session on the client - * even if we are executed via an IO callback. - */ -class AsyncCommandCallback : public SessionState::AsyncCommandContext { - public: - /** Command function returns a string containing the encoded result of the - * command, or empty for no result. It may raise an exception. - */ - typedef boost::function Command; - - /** - * @param syncPoint: if true have this command complete only when all - * preceeding commands are complete, like execution.sync. - */ - AsyncCommandCallback(SessionState& ss, Command f, bool syncPoint=false); - - void completed(bool sync); - - boost::intrusive_ptr clone(); - - private: - void complete(); - void doCommand(); - - Command command; - uint16_t channel; - bool syncPoint; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_ASYNCCOMMANDCALLBACK_H*/ diff --git a/qpid/cpp/src/qpid/broker/AsyncCompletion.h b/qpid/cpp/src/qpid/broker/AsyncCompletion.h deleted file mode 100644 index cb5d58977b..0000000000 --- a/qpid/cpp/src/qpid/broker/AsyncCompletion.h +++ /dev/null @@ -1,209 +0,0 @@ -#ifndef _AsyncCompletion_ -#define _AsyncCompletion_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/RefCounted.h" -#include - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace broker { - -/** - * Class to implement asynchronous notification of completion. - * - * Use-case: An "initiator" needs to wait for a set of "completers" to - * finish a unit of work before an action can occur. This object - * tracks the progress of the set of completers, and allows the action - * to occur once all completers have signalled that they are done. - * - * The initiator and completers may be running in separate threads. - * - * The initiating thread is the thread that initiates the action, - * i.e. the connection read thread. - * - * A completing thread is any thread that contributes to completion, - * e.g. a store thread that does an async write. - * There may be zero or more completers. - * - * When the work is complete, a callback is invoked. The callback - * may be invoked in the Initiator thread, or one of the Completer - * threads. The callback is passed a flag indicating whether or not - * the callback is running under the context of the Initiator thread. - * - * Use model: - * 1) Initiator thread invokes begin() - * 2) After begin() has been invoked, zero or more Completers invoke - * startCompleter(). Completers may be running in the same or - * different thread as the Initiator, as long as they guarantee that - * startCompleter() is invoked at least once before the Initiator invokes end(). - * 3) Completers may invoke finishCompleter() at any time, even after the - * initiator has invoked end(). finishCompleter() may be called from any - * thread. - * 4) startCompleter()/finishCompleter() calls "nest": for each call to - * startCompleter(), a corresponding call to finishCompleter() must be made. - * Once the last finishCompleter() is called, the Completer must no longer - * reference the completion object. - * 5) The Initiator invokes end() at the point where it has finished - * dispatching work to the Completers, and is prepared for the callback - * handler to be invoked. Note: if there are no outstanding Completers - * pending when the Initiator invokes end(), the callback will be invoked - * directly, and the sync parameter will be set true. This indicates to the - * Initiator that the callback is executing in the context of the end() call, - * and the Initiator is free to optimize the handling of the completion, - * assuming no need for synchronization with Completer threads. - */ - -class AsyncCompletion : public virtual RefCounted -{ - public: - - /** Supplied by the Initiator to the end() method, allows for a callback - * when all outstanding completers are done. If the callback cannot be - * made during the end() call, the clone() method must supply a copy of - * this callback object that persists after end() returns. The cloned - * callback object will be used by the last completer thread, and - * released when the callback returns. - */ - class Callback : public RefCounted - { - public: - // Normally RefCounted objects cannot be copied. - // Allow Callback objects to be copied (by subclasses implementing clone()) - // The copy has an initial refcount of 0 - Callback(const Callback&) : RefCounted() {} - Callback() {} - - virtual void completed(bool) = 0; - virtual boost::intrusive_ptr clone() = 0; - }; - - private: - mutable qpid::sys::AtomicValue completionsNeeded; - mutable qpid::sys::Monitor callbackLock; - bool inCallback, active; - - void invokeCallback(bool sync) { - qpid::sys::Mutex::ScopedLock l(callbackLock); - if (active) { - if (callback.get()) { - boost::intrusive_ptr save = callback; - callback = boost::intrusive_ptr(); // Nobody else can run callback. - inCallback = true; - { - qpid::sys::Mutex::ScopedUnlock ul(callbackLock); - save->completed(sync); - } - inCallback = false; - callbackLock.notifyAll(); - } - active = false; - } - } - - protected: - /** Invoked when all completers have signalled that they have completed - * (via calls to finishCompleter()). bool == true if called via end() - */ - boost::intrusive_ptr callback; - - public: - AsyncCompletion() : completionsNeeded(0), inCallback(false), active(true) {}; - virtual ~AsyncCompletion() { cancel(); } - - - /** True when all outstanding operations have compeleted - */ - bool isDone() - { - return !active; - } - - /** Called to signal the start of an asynchronous operation. The operation - * is considered pending until finishCompleter() is called. - * E.g. called when initiating an async store operation. - */ - void startCompleter() { ++completionsNeeded; } - - /** Called by completer to signal that it has finished the operation started - * when startCompleter() was invoked. - * e.g. called when async write complete. - */ - void finishCompleter() - { - if (--completionsNeeded == 0) { - invokeCallback(false); - } - } - - /** called by initiator before any calls to startCompleter can be done. - */ - void begin() - { - ++completionsNeeded; - } - - /** called by initiator after all potential completers have called - * startCompleter(). - */ - void end(Callback& cb) - { - assert(completionsNeeded.get() > 0); // ensure begin() has been called! - // the following only "decrements" the count if it is 1. This means - // there are no more outstanding completers and we are done. - if (completionsNeeded.boolCompareAndSwap(1, 0)) { - // done! Complete immediately - cb.completed(true); - return; - } - - // the compare-and-swap did not succeed. This means there are - // outstanding completers pending (count > 1). Get a persistent - // Callback object to use when the last completer is done. - // Decrement after setting up the callback ensures that pending - // completers cannot touch the callback until it is ready. - callback = cb.clone(); - if (--completionsNeeded == 0) { - // note that a completer may have completed during the - // callback setup or decrement: - invokeCallback(true); - } - } - - /** may be called by Initiator to cancel the callback. Will wait for - * callback to complete if in progress. - */ - virtual void cancel() { - qpid::sys::Mutex::ScopedLock l(callbackLock); - while (inCallback) callbackLock.wait(); - callback = boost::intrusive_ptr(); - active = false; - } -}; - -}} // qpid::broker:: -#endif /*!_AsyncCompletion_*/ diff --git a/qpid/cpp/src/qpid/broker/Bridge.cpp b/qpid/cpp/src/qpid/broker/Bridge.cpp deleted file mode 100644 index d6cd3e20e7..0000000000 --- a/qpid/cpp/src/qpid/broker/Bridge.cpp +++ /dev/null @@ -1,474 +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/broker/Bridge.h" - -#include "qpid/broker/Broker.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/SessionState.h" - -#include "qpid/management/ManagementAgent.h" -#include "qpid/types/Variant.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/framing/Uuid.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Statement.h" -#include - -using qpid::framing::FieldTable; -using qpid::framing::Uuid; -using qpid::framing::Buffer; -using qpid::framing::AMQFrame; -using qpid::framing::AMQContentBody; -using qpid::framing::AMQHeaderBody; -using qpid::framing::MessageProperties; -using qpid::framing::MessageTransferBody; -using qpid::types::Variant; -using qpid::management::ManagementAgent; -using std::string; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace { -const std::string QPID_REPLICATE("qpid.replicate"); -const std::string NONE("none"); -const uint8_t EXPLICIT_ACK(0); // msg.accept required to be sent -const uint8_t IMPLIED_ACK(1); // msg.accept assumed, not sent -} - -namespace qpid { -namespace broker { - -void Bridge::PushHandler::handle(framing::AMQFrame& frame) -{ - conn->received(frame); -} - -Bridge::Bridge(const std::string& _name, Link* _link, framing::ChannelId _id, - CancellationListener l, const _qmf::ArgsLinkBridge& _args, - InitializeCallback init, const std::string& _queueName, const string& ae) : - link(_link), channel(_id), args(_args), - listener(l), name(_name), - queueName(_queueName.empty() ? "qpid.bridge_queue_" + name + "_" + link->getBroker()->getFederationTag() - : _queueName), - altEx(ae), persistenceId(0), - conn(0), initialize(init), detached(false), - useExistingQueue(!_queueName.empty()), - sessionName("qpid.bridge_session_" + name + "_" + link->getBroker()->getFederationTag()) -{ - // If both acks (i_sync) and limited credit is configured, then we'd - // better be able to sync before running out of credit or we - // may stall (note: i_credit==0 means "unlimited") - if (args.i_credit && args.i_sync && args.i_sync > args.i_credit) - throw Exception("The credit value must be greater than configured sync (ack) interval."); - - ManagementAgent* agent = link->getBroker()->getManagementAgent(); - if (agent != 0) { - mgmtObject = _qmf::Bridge::shared_ptr(new _qmf::Bridge - (agent, this, link, name, args.i_durable, args.i_src, args.i_dest, - args.i_key, args.i_srcIsQueue, args.i_srcIsLocal, - args.i_tag, args.i_excludes, args.i_dynamic, args.i_sync, - args.i_credit)); - mgmtObject->set_channelId(channel); - agent->addObject(mgmtObject); - } - QPID_LOG(debug, "Bridge " << name << " created from " << args.i_src << " to " << args.i_dest); -} - -Bridge::~Bridge() -{ - mgmtObject->resourceDestroy(); -} - -void Bridge::create(amqp_0_10::Connection& c) -{ - detached = false; // Reset detached in case we are recovering. - conn = &c; - - SessionHandler& sessionHandler = c.getChannel(channel); - sessionHandler.setErrorListener(shared_from_this()); - if (args.i_srcIsLocal) { - if (args.i_dynamic) - throw Exception("Dynamic routing not supported for push routes"); - // Point the bridging commands at the local connection handler - pushHandler.reset(new PushHandler(&c)); - channelHandler.reset(new framing::ChannelHandler(channel, pushHandler.get())); - - session.reset(new framing::AMQP_ServerProxy::Session(*channelHandler)); - peer.reset(new framing::AMQP_ServerProxy(*channelHandler)); - - session->attach(sessionName, false); - session->commandPoint(0,0); - } else { - sessionHandler.attachAs(sessionName); - // Point the bridging commands at the remote peer broker - peer.reset(new framing::AMQP_ServerProxy(sessionHandler.out)); - } - - if (args.i_srcIsLocal) sessionHandler.getSession()->disableReceiverTracking(); - - if (initialize) { - initialize(*this, sessionHandler); // custom subscription initializer supplied - } else { - // will a temp queue be created for this bridge? - const bool temp_queue = !args.i_srcIsQueue && !useExistingQueue; - // UI convention: user specifies 0 for infinite credit - const uint32_t credit = (args.i_credit == 0) ? LinkRegistry::INFINITE_CREDIT : args.i_credit; - // use explicit acks only for non-temp queues, useless for temp queues since they are - // destroyed when the session drops (can't resend unacked msgs) - const uint8_t ack_mode = (args.i_sync && !temp_queue) ? EXPLICIT_ACK : IMPLIED_ACK; - - // configure command.sync frequency - FieldTable options; - uint32_t freq = 0; - if (ack_mode == EXPLICIT_ACK) { // user explicitly configured syncs - freq = uint32_t(args.i_sync); - } else if (credit && credit != LinkRegistry::INFINITE_CREDIT) { - // force occasional sync to keep from stalling due to lack of credit - freq = (credit + 1)/2; - } - if (freq) - options.setInt("qpid.sync_frequency", freq); - - // create a subscription on the remote - if (args.i_srcIsQueue) { - peer->getMessage().subscribe(args.i_src, args.i_dest, ack_mode, 0, false, "", 0, options); - peer->getMessage().flow(args.i_dest, 0, credit); // message credit - peer->getMessage().flow(args.i_dest, 1, LinkRegistry::INFINITE_CREDIT); // byte credit - QPID_LOG(debug, "Activated bridge " << name << " for route from queue " << args.i_src << " to " << args.i_dest); - } else { - if (!useExistingQueue) { - FieldTable queueSettings; - - if (args.i_tag.size()) { - queueSettings.setString("qpid.trace.id", args.i_tag); - } else { - const string& peerTag = c.getFederationPeerTag(); - if (peerTag.size()) - queueSettings.setString("qpid.trace.id", peerTag); - } - - if (args.i_excludes.size()) { - queueSettings.setString("qpid.trace.exclude", args.i_excludes); - } else { - const string& localTag = link->getBroker()->getFederationTag(); - if (localTag.size()) - queueSettings.setString("qpid.trace.exclude", localTag); - } - - bool durable = false;//should this be an arg, or would we use srcIsQueue for durable queues? - bool exclusive = true; // only exclusive if the queue is owned by the bridge - bool autoDelete = exclusive && !durable;//auto delete transient queues? - peer->getQueue().declare(queueName, altEx, false, durable, exclusive, autoDelete, queueSettings); - } - if (!args.i_dynamic) - peer->getExchange().bind(queueName, args.i_src, args.i_key, FieldTable()); - peer->getMessage().subscribe(queueName, args.i_dest, ack_mode, 0, false, "", 0, options); - peer->getMessage().flow(args.i_dest, 0, credit); - peer->getMessage().flow(args.i_dest, 1, LinkRegistry::INFINITE_CREDIT); - if (args.i_dynamic) { - Exchange::shared_ptr exchange = link->getBroker()->getExchanges().get(args.i_src); - if (exchange.get() == 0) - throw Exception("Exchange not found for dynamic route"); - exchange->registerDynamicBridge(this); - QPID_LOG(debug, "Activated bridge " << name << " for dynamic route for exchange " << args.i_src); - } else { - QPID_LOG(debug, "Activated bridge " << name << " for static route from exchange " << args.i_src << " to " << args.i_dest); - } - } - } - if (args.i_srcIsLocal) sessionHandler.getSession()->enableReceiverTracking(); -} - -void Bridge::cancel(amqp_0_10::Connection& c) -{ - // If &c != conn then we have failed over so the old connection is closed. - if (&c == conn && resetProxy()) { - peer->getMessage().cancel(args.i_dest); - peer->getSession().detach(sessionName); - } - QPID_LOG(debug, "Cancelled bridge " << name); -} - -/** Notify the bridge that the connection has closed */ -void Bridge::closed() -{ - if (args.i_dynamic) { - Exchange::shared_ptr exchange = link->getBroker()->getExchanges().find(args.i_src); - if (exchange.get()) exchange->removeDynamicBridge(this); - } - QPID_LOG(debug, "Closed bridge " << name); -} - -/** Shut down the bridge */ -void Bridge::close() -{ - listener(this); // ask the LinkRegistry to destroy us -} - -void Bridge::setPersistenceId(uint64_t pId) const -{ - persistenceId = pId; -} - - -const std::string Bridge::ENCODED_IDENTIFIER("bridge.v2"); -const std::string Bridge::ENCODED_IDENTIFIER_V1("bridge"); - -bool Bridge::isEncodedBridge(const std::string& key) -{ - return key == ENCODED_IDENTIFIER || key == ENCODED_IDENTIFIER_V1; -} - - -Bridge::shared_ptr Bridge::decode(LinkRegistry& links, Buffer& buffer) -{ - string kind; - buffer.getShortString(kind); - - string host; - uint16_t port; - string src; - string dest; - string key; - string id; - string excludes; - string name; - - Link::shared_ptr link; - if (kind == ENCODED_IDENTIFIER_V1) { - /** previous versions identified the bridge by host:port, not by name, and - * transport wasn't provided. Try to find a link using those paramters. - */ - buffer.getShortString(host); - port = buffer.getShort(); - - link = links.getLink(host, port); - if (!link) { - QPID_LOG(error, "Bridge::decode() failed: cannot find Link for host=" << host << ", port=" << port); - return Bridge::shared_ptr(); - } - } else { - string linkName; - - buffer.getShortString(name); - buffer.getShortString(linkName); - link = links.getLink(linkName); - if (!link) { - QPID_LOG(error, "Bridge::decode() failed: cannot find Link named='" << linkName << "'"); - return Bridge::shared_ptr(); - } - } - - bool durable(buffer.getOctet()); - buffer.getShortString(src); - buffer.getShortString(dest); - buffer.getShortString(key); - bool is_queue(buffer.getOctet()); - bool is_local(buffer.getOctet()); - buffer.getShortString(id); - buffer.getShortString(excludes); - bool dynamic(buffer.getOctet()); - uint16_t sync = buffer.getShort(); - uint32_t credit = buffer.getLong(); - - if (kind == ENCODED_IDENTIFIER_V1) { - /** previous versions did not provide a name for the bridge, so create one - */ - name = createName(link->getName(), src, dest, key); - } - - return links.declare(name, *link, durable, src, dest, key, is_queue, - is_local, id, excludes, dynamic, sync, credit).first; -} - -void Bridge::encode(Buffer& buffer) const -{ - buffer.putShortString(ENCODED_IDENTIFIER); - buffer.putShortString(name); - buffer.putShortString(link->getName()); - buffer.putOctet(args.i_durable ? 1 : 0); - buffer.putShortString(args.i_src); - buffer.putShortString(args.i_dest); - buffer.putShortString(args.i_key); - buffer.putOctet(args.i_srcIsQueue ? 1 : 0); - buffer.putOctet(args.i_srcIsLocal ? 1 : 0); - buffer.putShortString(args.i_tag); - buffer.putShortString(args.i_excludes); - buffer.putOctet(args.i_dynamic ? 1 : 0); - buffer.putShort(args.i_sync); - buffer.putLong(args.i_credit); -} - -uint32_t Bridge::encodedSize() const -{ - return ENCODED_IDENTIFIER.size() + 1 // +1 byte length - + name.size() + 1 - + link->getName().size() + 1 - + 1 // durable - + args.i_src.size() + 1 - + args.i_dest.size() + 1 - + args.i_key.size() + 1 - + 1 // srcIsQueue - + 1 // srcIsLocal - + args.i_tag.size() + 1 - + args.i_excludes.size() + 1 - + 1 // dynamic - + 2 // sync - + 4; // credit -} - -management::ManagementObject::shared_ptr Bridge::GetManagementObject(void) const -{ - return mgmtObject; -} - -management::Manageable::status_t Bridge::ManagementMethod(uint32_t methodId, - management::Args& /*args*/, - string&) -{ - if (methodId == _qmf::Bridge::METHOD_CLOSE) { - //notify that we are closed - QPID_LOG(debug, "Bridge::close() method called on bridge '" << name << "'"); - close(); - return management::Manageable::STATUS_OK; - } else { - return management::Manageable::STATUS_UNKNOWN_METHOD; - } -} - -void Bridge::propagateBinding(const string& key, const string& tagList, - const string& op, const string& origin, - qpid::framing::FieldTable* extra_args) -{ - const string& localTag = link->getBroker()->getFederationTag(); - const string& peerTag = conn->getFederationPeerTag(); - - if (tagList.find(peerTag) == tagList.npos) { - FieldTable bindArgs; - if (extra_args) { - for (qpid::framing::FieldTable::ValueMap::iterator i=extra_args->begin(); i != extra_args->end(); ++i) { - bindArgs.insert((*i)); - } - } - string newTagList(tagList + string(tagList.empty() ? "" : ",") + localTag); - - bindArgs.setString(QPID_REPLICATE, NONE); - bindArgs.setString(qpidFedOp, op); - bindArgs.setString(qpidFedTags, newTagList); - if (origin.empty()) - bindArgs.setString(qpidFedOrigin, localTag); - else - bindArgs.setString(qpidFedOrigin, origin); - - conn->requestIOProcessing( - weakCallback( - boost::bind(&Bridge::ioThreadPropagateBinding, _1, - queueName, args.i_src, key, bindArgs), - this)); - } -} - -void Bridge::sendReorigin() -{ - FieldTable bindArgs; - - bindArgs.setString(qpidFedOp, fedOpReorigin); - bindArgs.setString(qpidFedTags, link->getBroker()->getFederationTag()); - - conn->requestIOProcessing( - weakCallback( - boost::bind(&Bridge::ioThreadPropagateBinding, _1, - queueName, args.i_src, args.i_key, bindArgs), - this)); -} - -bool Bridge::resetProxy() -{ - SessionHandler& sessionHandler = conn->getChannel(channel); - if (!sessionHandler.getSession()) peer.reset(); - else peer.reset(new framing::AMQP_ServerProxy(sessionHandler.out)); - return peer.get(); -} - -void Bridge::ioThreadPropagateBinding(const string& queue, const string& exchange, const string& key, FieldTable args) -{ - if (resetProxy()) { - peer->getExchange().bind(queue, exchange, key, args); - } else { - // link's periodic maintenance visit will attempt to recover - } -} - -bool Bridge::containsLocalTag(const string& tagList) const -{ - const string& localTag = link->getBroker()->getFederationTag(); - return (tagList.find(localTag) != tagList.npos); -} - -const string& Bridge::getLocalTag() const -{ - return link->getBroker()->getFederationTag(); -} - -// SessionHandler::ErrorListener methods. -void Bridge::connectionException( - framing::connection::CloseCode code, const std::string& msg) -{ - if (errorListener) errorListener->connectionException(code, msg); -} - -void Bridge::channelException( - framing::session::DetachCode code, const std::string& msg) -{ - if (errorListener) errorListener->channelException(code, msg); -} - -void Bridge::executionException( - framing::execution::ErrorCode code, const std::string& msg) -{ - if (errorListener) errorListener->executionException(code, msg); -} - -void Bridge::incomingExecutionException( - framing::execution::ErrorCode code, const std::string& msg) -{ - if (errorListener) errorListener->incomingExecutionException(code, msg); -} - -void Bridge::detach() { - detached = true; - if (errorListener) errorListener->detach(); -} - -std::string Bridge::createName(const std::string& linkName, - const std::string& src, - const std::string& dest, - const std::string& key) -{ - std::stringstream keystream; - keystream << linkName << "!" << src << "!" << dest << "!" << key; - return keystream.str(); -} - -}} diff --git a/qpid/cpp/src/qpid/broker/Bridge.h b/qpid/cpp/src/qpid/broker/Bridge.h deleted file mode 100644 index 3eac8f2af2..0000000000 --- a/qpid/cpp/src/qpid/broker/Bridge.h +++ /dev/null @@ -1,158 +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. - * - */ -#ifndef _Bridge_ -#define _Bridge_ - -#include "qpid/broker/PersistableConfig.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/framing/ChannelHandler.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/management/Manageable.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/SessionHandler.h" -#include "qmf/org/apache/qpid/broker/ArgsLinkBridge.h" -#include "qmf/org/apache/qpid/broker/Bridge.h" - -#include -#include -#include - -namespace qpid { -namespace broker { -namespace amqp_0_10 { -class Connection; -} -class Link; -class LinkRegistry; - -class Bridge : public PersistableConfig, - public management::Manageable, - public Exchange::DynamicBridge, - public SessionHandler::ErrorListener, - public boost::enable_shared_from_this -{ - public: - typedef boost::shared_ptr shared_ptr; - typedef boost::function CancellationListener; - typedef boost::function InitializeCallback; - - Bridge(const std::string& name, Link* link, framing::ChannelId id, CancellationListener l, - const qmf::org::apache::qpid::broker::ArgsLinkBridge& args, - InitializeCallback init, const std::string& queueName="", - const std::string& altExchange="" - ); - ~Bridge(); - - QPID_BROKER_EXTERN void close(); - bool isDurable() { return args.i_durable; } - framing::ChannelId getChannel() const { return channel; } - Link *getLink() const { return link; } - const std::string getSrc() const { return args.i_src; } - const std::string getDest() const { return args.i_dest; } - const std::string getKey() const { return args.i_key; } - - bool isDetached() const { return detached; } - - management::ManagementObject::shared_ptr GetManagementObject() const; - management::Manageable::status_t ManagementMethod(uint32_t methodId, - management::Args& args, - std::string& text); - - // PersistableConfig: - void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - uint32_t encodedSize() const; - void encode(framing::Buffer& buffer) const; - const std::string& getName() const { return name; } - - static const std::string ENCODED_IDENTIFIER; - static const std::string ENCODED_IDENTIFIER_V1; - static Bridge::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer); - static bool isEncodedBridge(const std::string& key); - - // Exchange::DynamicBridge methods - void propagateBinding(const std::string& key, const std::string& tagList, const std::string& op, const std::string& origin, qpid::framing::FieldTable* extra_args=0); - void sendReorigin(); - void ioThreadPropagateBinding(const std::string& queue, const std::string& exchange, const std::string& key, framing::FieldTable args); - bool containsLocalTag(const std::string& tagList) const; - const std::string& getLocalTag() const; - - // Methods needed by initialization functions - std::string getQueueName() const { return queueName; } - const qmf::org::apache::qpid::broker::ArgsLinkBridge& getArgs() { return args; } - - /** create a name for a bridge (if none supplied by user config) */ - static std::string createName(const std::string& linkName, - const std::string& src, - const std::string& dest, - const std::string& key); - - // SessionHandler::ErrorListener methods. - void connectionException(framing::connection::CloseCode code, const std::string& msg); - void channelException(framing::session::DetachCode, const std::string& msg); - void executionException(framing::execution::ErrorCode, const std::string& msg); - void incomingExecutionException(framing::execution::ErrorCode, const std::string& msg); - void detach(); - - void setErrorListener(boost::shared_ptr e) { errorListener = e; } - private: - struct PushHandler : framing::FrameHandler { - PushHandler(amqp_0_10::Connection* c) { conn = c; } - void handle(framing::AMQFrame& frame); - amqp_0_10::Connection* conn; - }; - - std::auto_ptr pushHandler; - std::auto_ptr channelHandler; - std::auto_ptr session; - std::auto_ptr peer; - - Link* const link; - const framing::ChannelId channel; - qmf::org::apache::qpid::broker::ArgsLinkBridge args; - qmf::org::apache::qpid::broker::Bridge::shared_ptr mgmtObject; - CancellationListener listener; - std::string name; - std::string queueName; - std::string altEx; - mutable uint64_t persistenceId; - amqp_0_10::Connection* conn; - InitializeCallback initialize; - bool detached; // Set when session is detached. - bool resetProxy(); - - // connection Management (called by owning Link) - void create(amqp_0_10::Connection& c); - void cancel(amqp_0_10::Connection& c); - void closed(); - friend class Link; // to call create, cancel, closed() - boost::shared_ptr errorListener; - - const bool useExistingQueue; - const std::string sessionName; -}; - - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/Broker.cpp b/qpid/cpp/src/qpid/broker/Broker.cpp deleted file mode 100644 index 77674692ab..0000000000 --- a/qpid/cpp/src/qpid/broker/Broker.cpp +++ /dev/null @@ -1,1683 +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/broker/Broker.h" - -#include "qpid/broker/AclModule.h" -#include "qpid/broker/BrokerOptions.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/MessageStoreModule.h" -#include "qpid/broker/NameGenerator.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/RecoveryManagerImpl.h" -#include "qpid/broker/SaslAuthenticator.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/broker/Link.h" -#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" -#include "qmf/org/apache/qpid/broker/ArgsBrokerConnect.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerCreate.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerDelete.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerQuery.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerEcho.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerGetLogLevel.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerQueueMoveMessages.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerSetLogLevel.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerGetLogHiresTimestamp.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerSetLogHiresTimestamp.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerSetTimestampConfig.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerGetTimestampConfig.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerQueueRedirect.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h" -#include "qmf/org/apache/qpid/broker/EventBind.h" -#include "qmf/org/apache/qpid/broker/EventUnbind.h" -#include "qmf/org/apache/qpid/broker/EventQueueRedirect.h" -#include "qmf/org/apache/qpid/broker/EventQueueRedirectCancelled.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/management/ManagementDirectExchange.h" -#include "qpid/management/ManagementTopicExchange.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/TransportFactory.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/ConnectionInputHandlerFactory.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/Address.h" -#include "qpid/StringUtils.h" -#include "qpid/Url.h" -#include "qpid/Version.h" -#include "config.h" - -#include -#include - -#include -#include -#include - -using qpid::sys::TransportAcceptor; -using qpid::sys::TransportConnector; -using qpid::sys::Poller; -using qpid::sys::Dispatcher; -using qpid::sys::Thread; -using qpid::framing::FrameHandler; -using qpid::framing::ChannelId; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::management::getCurrentPublisher; -using qpid::types::Variant; -using std::string; -using std::make_pair; - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -const std::string empty; -const std::string amq_direct("amq.direct"); -const std::string amq_topic("amq.topic"); -const std::string amq_fanout("amq.fanout"); -const std::string amq_match("amq.match"); -const std::string qpid_management("qpid.management"); -const std::string knownHostsNone("none"); - -BrokerOptions::BrokerOptions(const std::string& name) : - qpid::Options(name), - noDataDir(0), - port(DEFAULT_PORT), - workerThreads(5), - connectionBacklog(10), - enableMgmt(1), - mgmtPublish(1), - mgmtPubInterval(10*sys::TIME_SEC), - queueCleanInterval(60*sys::TIME_SEC*10),//10 minutes - auth(SaslAuthenticator::available()), - realm("QPID"), - replayFlushLimit(0), - replayHardLimit(0), - queueLimit(100*1048576/*100M default limit*/), - tcpNoDelay(true), - requireEncrypted(false), - knownHosts(knownHostsNone), - qmf2Support(true), - qmf1Support(false), - queueFlowStopRatio(80), - queueFlowResumeRatio(70), - queueThresholdEventRatio(80), - defaultMsgGroup("qpid.no-group"), - timestampRcvMsgs(false), // set the 0.10 timestamp delivery property - linkMaintenanceInterval(2*sys::TIME_SEC), - linkHeartbeatInterval(120*sys::TIME_SEC), - dtxDefaultTimeout(60), // 60s - dtxMaxTimeout(3600), // 3600s - maxNegotiateTime(10000) // 10s -{ - int c = sys::SystemInfo::concurrency(); - workerThreads=c+1; - std::string home = getHome(); - - if (home.length() == 0) - dataDir += DEFAULT_DATA_DIR_LOCATION; - else - dataDir += home; - dataDir += DEFAULT_DATA_DIR_NAME; - - addOptions() - ("data-dir", optValue(dataDir,"DIR"), "Directory to contain persistent data generated by the broker") - ("no-data-dir", optValue(noDataDir), "Don't use a data directory. No persistent configuration will be loaded or stored") - ("paging-dir", optValue(pagingDir,"DIR"), "Directory in which paging files will be created for paged queues") - ("port,p", optValue(port,"PORT"), "Tells the broker to listen on PORT") - ("interface", optValue(listenInterfaces, "|"), "Which network interfaces to use to listen for incoming connections") - ("listen-disable", optValue(listenDisabled, ""), "Transports to disable listening") - ("protocols", optValue(protocols, ""), "Which protocol versions to allow") - ("worker-threads", optValue(workerThreads, "N"), "Sets the broker thread pool size") - ("connection-backlog", optValue(connectionBacklog, "N"), "Sets the connection backlog limit for the server socket") - ("mgmt-enable,m", optValue(enableMgmt,"yes|no"), "Enable Management") - ("mgmt-publish", optValue(mgmtPublish,"yes|no"), "Enable Publish of Management Data ('no' implies query-only)") - ("mgmt-qmf2", optValue(qmf2Support,"yes|no"), "Enable broadcast of management information over QMF v2") - ("mgmt-qmf1", optValue(qmf1Support,"yes|no"), "Enable broadcast of management information over QMF v1") - ("mgmt-pub-interval", optValue(mgmtPubInterval, "SECONDS"), "Management Publish Interval") - ("queue-purge-interval", optValue(queueCleanInterval, "SECONDS"), - "Interval between attempts to purge any expired messages from queues") - ("auth", optValue(auth, "yes|no"), "Enable authentication, if disabled all incoming connections will be trusted") - ("realm", optValue(realm, "REALM"), "Use the given realm when performing authentication") - ("sasl-service-name", optValue(saslServiceName, "NAME"), "The service name to specify for SASL") - ("default-queue-limit", optValue(queueLimit, "BYTES"), "Default maximum size for queues (in bytes)") - ("tcp-nodelay", optValue(tcpNoDelay), "Set TCP_NODELAY on TCP connections") - ("require-encryption", optValue(requireEncrypted), "Only accept connections that are encrypted") - ("known-hosts-url", optValue(knownHosts, "URL or 'none'"), "URL to send as 'known-hosts' to clients ('none' implies empty list)") - ("sasl-config", optValue(saslConfigPath, "DIR"), "Allows SASL config path, if supported by platform, to be overridden. For default location on Linux, see Cyrus SASL documentation. There is no SASL config dir on Windows.") - ("default-flow-stop-threshold", optValue(queueFlowStopRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is activated.") - ("default-flow-resume-threshold", optValue(queueFlowResumeRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is de-activated.") - ("default-event-threshold-ratio", optValue(queueThresholdEventRatio, "%age of limit"), "The ratio of any specified queue limit at which an event will be raised") - ("default-message-group", optValue(defaultMsgGroup, "GROUP-IDENTIFER"), "Group identifier to assign to messages delivered to a message group queue that do not contain an identifier.") - ("enable-timestamp", optValue(timestampRcvMsgs, "yes|no"), "Add current time to each received message.") - ("link-maintenance-interval", optValue(linkMaintenanceInterval, "SECONDS"), - "Interval to check federation link health and re-connect if need be") - ("link-heartbeat-interval", optValue(linkHeartbeatInterval, "SECONDS"), - "Heartbeat interval for a federation link") - ("dtx-default-timeout", optValue(dtxDefaultTimeout, "SECONDS"), "Default timeout for DTX transaction before aborting it") - ("dtx-max-timeout", optValue(dtxMaxTimeout, "SECONDS"), "Maximum allowed timeout for DTX transaction. A value of zero disables maximum timeout limit checks and allows arbitrarily large timeout settings.") - ("max-negotiate-time", optValue(maxNegotiateTime, "MILLISECONDS"), "Maximum time a connection can take to send the initial protocol negotiation") - ("federation-tag", optValue(fedTag, "NAME"), "Override the federation tag") - ; -} - -namespace { -// Arguments to declare a non-replicated exchange. -framing::FieldTable noReplicateArgs() { - framing::FieldTable args; - args.setString("qpid.replicate", "none"); - return args; -} -} - -Broker::LogPrefix::LogPrefix() : - std::string(Msg() << "Broker (pid=" << sys::SystemInfo::getProcessId() << ") ") { - QPID_LOG(notice, *this << "start-up"); -} - -Broker::LogPrefix::~LogPrefix() { QPID_LOG(notice, *this << "shut-down"); } - -Broker::Broker(const BrokerOptions& conf) : - poller(new Poller), - timer(new qpid::sys::Timer), - config(conf), - managementAgent(conf.enableMgmt ? new ManagementAgent(conf.qmf1Support, - conf.qmf2Support) - : 0), - disabledListeningTransports(conf.listenDisabled.begin(), conf.listenDisabled.end()), - store(new NullMessageStore), - acl(0), - dataDir(conf.noDataDir ? std::string() : conf.dataDir), - pagingDir(!conf.pagingDir.empty() ? conf.pagingDir : - dataDir.isEnabled() ? dataDir.getPath() + BrokerOptions::DEFAULT_PAGED_QUEUE_DIR : - std::string() ), - queues(this), - exchanges(this), - links(this), - dtxManager(*timer.get(), conf.dtxDefaultTimeout), - sessionManager( - qpid::SessionState::Configuration( - conf.replayFlushLimit*1024, // convert kb to bytes. - conf.replayHardLimit*1024), - *this), - queueCleaner(queues, poller, timer.get()), - recoveryInProgress(false), - protocolRegistry(std::set(conf.protocols.begin(), conf.protocols.end()), this), - timestampRcvMsgs(conf.timestampRcvMsgs), - getKnownBrokers(boost::bind(&Broker::getKnownBrokersImpl, this)) -{ - if (!dataDir.isEnabled()) { - QPID_LOG (info, "No data directory - Disabling persistent configuration"); - } - System* system = new System (dataDir.isEnabled() ? dataDir.getPath() : string(), this); - systemObject = System::shared_ptr(system); - try { - if (conf.enableMgmt) { - QPID_LOG(info, "Management enabled"); - managementAgent->configure(dataDir.isEnabled() ? dataDir.getPath() : string(), conf.mgmtPublish, - conf.mgmtPubInterval/sys::TIME_SEC, this, conf.workerThreads + 3); - managementAgent->setName("apache.org", "qpidd"); - _qmf::Package packageInitializer(managementAgent.get()); - - mgmtObject = _qmf::Broker::shared_ptr(new _qmf::Broker(managementAgent.get(), this, system, "amqp-broker")); - mgmtObject->set_systemRef(system->GetManagementObject()->getObjectId()); - mgmtObject->set_port(conf.port); - mgmtObject->set_workerThreads(conf.workerThreads); - mgmtObject->set_connBacklog(conf.connectionBacklog); - mgmtObject->set_mgmtPubInterval(conf.mgmtPubInterval/sys::TIME_SEC); - mgmtObject->set_mgmtPublish(conf.mgmtPublish); - mgmtObject->set_version(qpid::version); - if (dataDir.isEnabled()) - mgmtObject->set_dataDir(dataDir.getPath()); - else - mgmtObject->clr_dataDir(); - - managementAgent->addObject(mgmtObject, 0, true); - - // Since there is currently no support for virtual hosts, a placeholder object - // representing the implied single virtual host is added here to keep the - // management schema correct. - Vhost* vhost = new Vhost(this, this); - vhostObject = Vhost::shared_ptr(vhost); - if (conf.fedTag.empty()) { - framing::Uuid uuid(managementAgent->getUuid()); - federationTag = uuid.str(); - } else - federationTag = conf.fedTag; - vhostObject->setFederationTag(federationTag); - - queues.setParent(vhost); - exchanges.setParent(vhost); - links.setParent(vhost); - } else { - // Management is disabled so there is no broker management ID. - // Create a unique uuid to use as the federation tag. - if (conf.fedTag.empty()) { - framing::Uuid uuid(true); - federationTag = uuid.str(); - } else - federationTag = conf.fedTag; - } - - // Early-Initialize plugins - Plugin::earlyInitAll(*this); - - QueueFlowLimit::setDefaults(conf.queueLimit, conf.queueFlowStopRatio, conf.queueFlowResumeRatio); - MessageGroupManager::setDefaults(conf.defaultMsgGroup); - - // If no plugin store module registered itself, set up the null store. - if (NullMessageStore::isNullStore(store.get())) - setStore(); - - framing::FieldTable args; - - // Default exchnge is not replicated. - exchanges.declare(empty, DirectExchange::typeName, false, false, noReplicateArgs()); - - RecoveredObjects objects; - if (store.get() != 0) { - RecoveryManagerImpl recoverer( - queues, exchanges, links, dtxManager, protocolRegistry, objects); - recoveryInProgress = true; - store->recover(recoverer); - recoveryInProgress = false; - } - - //ensure standard exchanges exist (done after recovery from store) - declareStandardExchange(amq_direct, DirectExchange::typeName); - declareStandardExchange(amq_topic, TopicExchange::typeName); - declareStandardExchange(amq_fanout, FanOutExchange::typeName); - declareStandardExchange(amq_match, HeadersExchange::typeName); - - if(conf.enableMgmt) { - exchanges.declare(qpid_management, ManagementTopicExchange::typeName, false, false, noReplicateArgs()); - Exchange::shared_ptr mExchange = exchanges.get(qpid_management); - Exchange::shared_ptr dExchange = exchanges.get(amq_direct); - managementAgent->setExchange(mExchange, dExchange); - boost::dynamic_pointer_cast(mExchange)->setManagmentAgent(managementAgent.get(), 1); - - std::string qmfTopic("qmf.default.topic"); - std::string qmfDirect("qmf.default.direct"); - - std::pair topicPair( - exchanges.declare(qmfTopic, ManagementTopicExchange::typeName, false, false, noReplicateArgs())); - std::pair directPair( - exchanges.declare(qmfDirect, ManagementDirectExchange::typeName, false, false, noReplicateArgs())); - - boost::dynamic_pointer_cast(directPair.first)->setManagmentAgent(managementAgent.get(), 2); - boost::dynamic_pointer_cast(topicPair.first)->setManagmentAgent(managementAgent.get(), 2); - - managementAgent->setExchangeV2(topicPair.first, directPair.first); - } - else - QPID_LOG(info, "Management not enabled"); - - // this feature affects performance, so let's be sure that gets logged! - if (conf.timestampRcvMsgs) { - QPID_LOG(notice, "Receive message timestamping is ENABLED."); - } - - /** - * SASL setup, can fail and terminate startup - */ - if (conf.auth) { - SaslAuthenticator::init(qpid::saslName, conf.saslConfigPath); - QPID_LOG(info, "SASL enabled"); - } else { - QPID_LOG(notice, "SASL disabled: No Authentication Performed"); - } - - // Initialize plugins - Plugin::initializeAll(*this); - //recover any objects via object factories - objects.restore(*this); - - // Assign to queues their users who created them (can be done after ACL is loaded in Plugin::initializeAll above - if ((getAcl()) && (store.get())) { - queues.eachQueue(boost::bind(&qpid::broker::Queue::updateAclUserQueueCount, _1)); - } - - if(conf.enableMgmt) { - if (getAcl()) { - mgmtObject->set_maxConns(getAcl()->getMaxConnectTotal()); - } - } - - if (conf.queueCleanInterval) { - queueCleaner.start(conf.queueCleanInterval); - } - - if (!conf.knownHosts.empty() && conf.knownHosts != knownHostsNone) { - knownBrokers.push_back(Url(conf.knownHosts)); - } - - } catch (const std::exception& e) { - QPID_LOG(critical, logPrefix << "start-up failed: " << e.what()); - finalize(); - throw; - } - QPID_LOG(info, logPrefix << "initialized"); -} - -void Broker::declareStandardExchange(const std::string& name, const std::string& type) -{ - bool storeEnabled = store.get() != NULL; - framing::FieldTable args; - // Standard exchanges are not replicated. - std::pair status = - exchanges.declare(name, type, storeEnabled, false, noReplicateArgs()); - if (status.second && storeEnabled) { - store->create(*status.first, framing::FieldTable ()); - } -} - -bool Broker::isAuthenticating() const -{ - return config.auth; -} - -bool Broker::requireEncrypted() const -{ - return config.requireEncrypted; -} - -std::string Broker::getRealm() const -{ - return config.realm; -} - -std::string Broker::getSaslServiceName() const -{ - return config.saslServiceName; -} - -bool Broker::getTcpNoDelay() const -{ - return config.tcpNoDelay; -} - -uint32_t Broker::getMaxNegotiateTime() const -{ - return config.maxNegotiateTime; -} - -uint16_t Broker::getPortOption() const -{ - return config.port; -} - -const std::vector& Broker::getListenInterfaces() const -{ - return config.listenInterfaces; -} - -int Broker::getConnectionBacklog() const -{ - return config.connectionBacklog; -} - -sys::Duration Broker::getLinkMaintenanceInterval() const -{ - return config.linkMaintenanceInterval; -} - -sys::Duration Broker::getLinkHeartbeatInterval() const -{ - return config.linkHeartbeatInterval; -} - -uint32_t Broker::getDtxMaxTimeout() const -{ - return config.dtxMaxTimeout; -} - -uint16_t Broker::getQueueThresholdEventRatio() const -{ - return config.queueThresholdEventRatio; -} - -uint Broker::getQueueLimit() const -{ - return config.queueLimit; -} - -boost::intrusive_ptr Broker::create(int16_t port) -{ - BrokerOptions config; - config.port=port; - return create(config); -} - -boost::intrusive_ptr Broker::create(const BrokerOptions& opts) -{ - return boost::intrusive_ptr(new Broker(opts)); -} - -void Broker::setStore (const boost::shared_ptr& _store) -{ - // Exit now if multiple store plugins are attempting to load - if (!NullMessageStore::isNullStore(store.get())) { - QPID_LOG(error, "Multiple store plugins are not supported"); - throw Exception(QPID_MSG("Failed to start broker: Multiple store plugins were loaded")); - } - - store.reset(new MessageStoreModule (_store)); - setStore(); -} - -void Broker::setStore () { - queues.setStore (store.get()); - dtxManager.setStore (store.get()); - links.setStore (store.get()); -} - -void Broker::run() { - if (config.workerThreads > 0) { - QPID_LOG(info, logPrefix << "running"); - Dispatcher d(poller); - int numIOThreads = config.workerThreads; - std::vector t(numIOThreads-1); - - // Run n-1 io threads - for (int i=0; ishutdown(); -} - -Broker::~Broker() { - QPID_LOG(info, logPrefix << "shutting down"); - if (mgmtObject != 0) - mgmtObject->debugStats("destroying"); - shutdown(); - finalize(); // Finalize any plugins. - if (config.auth) - SaslAuthenticator::fini(); - timer->stop(); - managementAgent.reset(); -} - -ManagementObject::shared_ptr Broker::GetManagementObject(void) const -{ - return mgmtObject; -} - -Manageable* Broker::GetVhostObject(void) const -{ - return vhostObject.get(); -} - -Manageable::status_t Broker::ManagementMethod (uint32_t methodId, - Args& args, - string& text) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - switch (methodId) - { - case _qmf::Broker::METHOD_ECHO : - QPID_LOG (debug, "Broker::echo(" - << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_sequence - << ", " - << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_body - << ")"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_CONNECT : { - /** Management is creating a Link to a remote broker using the host and port of - * the remote. This (old) interface does not allow management to specify a name - * for the link, nor does it allow multiple Links to the same remote. Use the - * "create()" broker method if these features are needed. - * TBD: deprecate this interface. - */ - QPID_LOG(info, "The Broker::connect() method will be removed in a future release of QPID." - " Please use the Broker::create() method with type='link' instead."); - _qmf::ArgsBrokerConnect& hp= - dynamic_cast<_qmf::ArgsBrokerConnect&>(args); - - string transport = hp.i_transport.empty() ? TCP_TRANSPORT : hp.i_transport; - QPID_LOG (debug, "Broker::connect() " << hp.i_host << ":" << hp.i_port << "; transport=" << transport << - "; durable=" << (hp.i_durable?"T":"F") << "; authMech=\"" << hp.i_authMechanism << "\""); - if (!getTransportInfo(transport).connectorFactory) { - QPID_LOG(error, "Transport '" << transport << "' not supported"); - text = "transport type not supported"; - return Manageable::STATUS_NOT_IMPLEMENTED; - } - - // Does a link to the remote already exist? If so, re-use the existing link - // - this behavior is backward compatible with previous releases. - if (!links.getLink(hp.i_host, hp.i_port, transport)) { - // new link, need to generate a unique name for it - std::pair response = - links.declare(Link::createName(transport, hp.i_host, hp.i_port), - hp.i_host, hp.i_port, transport, - hp.i_durable, hp.i_authMechanism, hp.i_username, hp.i_password); - if (!response.first) { - text = "Unable to create Link"; - status = Manageable::STATUS_PARAMETER_INVALID; - break; - } - } - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_QUEUEMOVEMESSAGES : { - _qmf::ArgsBrokerQueueMoveMessages& moveArgs= - dynamic_cast<_qmf::ArgsBrokerQueueMoveMessages&>(args); - QPID_LOG (debug, "Broker::queueMoveMessages()"); - if (queueMoveMessages(moveArgs.i_srcQueue, moveArgs.i_destQueue, moveArgs.i_qty, - moveArgs.i_filter, getCurrentPublisher()) >=0) - status = Manageable::STATUS_OK; - else - return Manageable::STATUS_PARAMETER_INVALID; - break; - } - case _qmf::Broker::METHOD_SETLOGLEVEL : - setLogLevel(dynamic_cast<_qmf::ArgsBrokerSetLogLevel&>(args).i_level); - QPID_LOG (debug, "Broker::setLogLevel()"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_GETLOGLEVEL : - dynamic_cast<_qmf::ArgsBrokerGetLogLevel&>(args).o_level = getLogLevel(); - QPID_LOG (debug, "Broker::getLogLevel()"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_CREATE : - { - _qmf::ArgsBrokerCreate& a = dynamic_cast<_qmf::ArgsBrokerCreate&>(args); - createObject(a.i_type, a.i_name, a.i_properties, a.i_strict, getCurrentPublisher()); - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_DELETE : - { - _qmf::ArgsBrokerDelete& a = dynamic_cast<_qmf::ArgsBrokerDelete&>(args); - deleteObject(a.i_type, a.i_name, a.i_options, getCurrentPublisher()); - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_QUERY : - { - _qmf::ArgsBrokerQuery& a = dynamic_cast<_qmf::ArgsBrokerQuery&>(args); - status = queryObject(a.i_type, a.i_name, a.o_results, getCurrentPublisher()); - break; - } - case _qmf::Broker::METHOD_GETTIMESTAMPCONFIG: - { - _qmf::ArgsBrokerGetTimestampConfig& a = dynamic_cast<_qmf::ArgsBrokerGetTimestampConfig&>(args); - status = getTimestampConfig(a.o_receive, getCurrentPublisher()); - break; - } - case _qmf::Broker::METHOD_SETTIMESTAMPCONFIG: - { - _qmf::ArgsBrokerSetTimestampConfig& a = dynamic_cast<_qmf::ArgsBrokerSetTimestampConfig&>(args); - status = setTimestampConfig(a.i_receive, getCurrentPublisher()); - break; - } - - case _qmf::Broker::METHOD_GETLOGHIRESTIMESTAMP: - { - dynamic_cast<_qmf::ArgsBrokerGetLogHiresTimestamp&>(args).o_logHires = getLogHiresTimestamp(); - QPID_LOG (debug, "Broker::getLogHiresTimestamp()"); - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_SETLOGHIRESTIMESTAMP: - { - setLogHiresTimestamp(dynamic_cast<_qmf::ArgsBrokerSetLogHiresTimestamp&>(args).i_logHires); - QPID_LOG (debug, "Broker::setLogHiresTimestamp()"); - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_QUEUEREDIRECT: - { - string srcQueue(dynamic_cast<_qmf::ArgsBrokerQueueRedirect&>(args).i_sourceQueue); - string tgtQueue(dynamic_cast<_qmf::ArgsBrokerQueueRedirect&>(args).i_targetQueue); - QPID_LOG (debug, "Broker::queueRedirect source queue:" << srcQueue << " to target queue " << tgtQueue); - status = queueRedirect(srcQueue, tgtQueue, getCurrentPublisher()); - break; - } - case _qmf::Broker::METHOD_SHUTDOWN : - { - QPID_LOG (info, "Broker received shutdown command"); - shutdown(); - } - default: - QPID_LOG (debug, "Broker ManagementMethod not implemented: id=" << methodId << "]"); - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } - - return status; -} - -namespace -{ -const std::string TYPE_QUEUE("queue"); -const std::string TYPE_EXCHANGE("exchange"); -const std::string TYPE_TOPIC("topic"); -const std::string TYPE_BINDING("binding"); -const std::string TYPE_LINK("link"); -const std::string TYPE_BRIDGE("bridge"); -const std::string DURABLE("durable"); -const std::string AUTO_DELETE("auto-delete"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string EXCHANGE_TYPE("exchange-type"); -const std::string QUEUE_NAME("queue"); -const std::string EXCHANGE_NAME("exchange"); - -const std::string ATTRIBUTE_TIMESTAMP_0_10("timestamp-0.10"); - -const std::string _TRUE("true"); -const std::string _FALSE("false"); - -// parameters for creating a Link object, see mgmt schema -const std::string HOST("host"); -const std::string PORT("port"); -const std::string TRANSPORT("transport"); -const std::string AUTH_MECHANISM("authMechanism"); -const std::string USERNAME("username"); -const std::string PASSWORD("password"); - -// parameters for creating a Bridge object, see mgmt schema -const std::string LINK("link"); -const std::string SRC("src"); -const std::string DEST("dest"); -const std::string KEY("key"); -const std::string TAG("tag"); -const std::string EXCLUDES("excludes"); -const std::string SRC_IS_QUEUE("srcIsQueue"); -const std::string SRC_IS_LOCAL("srcIsLocal"); -const std::string DYNAMIC("dynamic"); -const std::string SYNC("sync"); -const std::string CREDIT("credit"); - -// parameters for deleting a Queue object -const std::string IF_EMPTY("if_empty"); -const std::string IF_UNUSED("if_unused"); -} - -struct InvalidBindingIdentifier : public qpid::Exception -{ - InvalidBindingIdentifier(const std::string& name) : qpid::Exception(name) {} - std::string getPrefix() const { return "invalid binding"; } -}; - -struct BindingIdentifier -{ - std::string exchange; - std::string queue; - std::string key; - - BindingIdentifier(const std::string& name) - { - std::vector path; - split(path, name, "/"); - switch (path.size()) { - case 1: - queue = path[0]; - break; - case 2: - exchange = path[0]; - queue = path[1]; - break; - case 3: - exchange = path[0]; - queue = path[1]; - key = path[2]; - break; - default: - throw InvalidBindingIdentifier(name); - } - } -}; - -struct ObjectAlreadyExists : public qpid::Exception -{ - ObjectAlreadyExists(const std::string& name) : qpid::Exception(name) {} - std::string getPrefix() const { return "object already exists"; } -}; - -struct UnknownObjectType : public qpid::Exception -{ - UnknownObjectType(const std::string& type) : qpid::Exception(type) {} - std::string getPrefix() const { return "unknown object type"; } -}; - -struct ReservedObjectName : public qpid::Exception -{ - ReservedObjectName(const std::string& type) : qpid::Exception(type) {} - std::string getPrefix() const { return std::string("names prefixed with '") - + QPID_NAME_PREFIX + std::string("' are reserved"); } -}; - -struct UnsupportedTransport : public qpid::Exception -{ - UnsupportedTransport(const std::string& type) : qpid::Exception(type) {} - std::string getPrefix() const { return "transport is not supported"; } -}; - -struct InvalidParameter : public qpid::Exception -{ - InvalidParameter(const std::string& type) : qpid::Exception(type) {} - std::string getPrefix() const { return "invalid parameter to method call"; } -}; - -void Broker::createObject(const std::string& type, const std::string& name, - const Variant::Map& properties, bool /*strict*/, const Connection* context) -{ - std::string userId; - std::string connectionId; - if (context) { - userId = context->getUserId(); - connectionId = context->getMgmtId(); - } - //TODO: implement 'strict' option (check there are no unrecognised properties) - QPID_LOG (debug, "Broker::create(" << type << ", " << name << "," << properties << ")"); - if (objectFactory.createObject(*this, type, name, properties, userId, connectionId)) { - QPID_LOG (debug, "Broker::create(" << type << ", " << name << "," << properties << ") handled by registered factory"); - } else if (type == TYPE_QUEUE) { - bool durable(false); - bool autodelete(false); - std::string alternateExchange; - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == DURABLE) durable = i->second; - else if (i->first == AUTO_DELETE) autodelete = i->second; - else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - QueueSettings settings(durable, autodelete); - Variant::Map unused; - settings.populate(extensions, unused); - qpid::amqp_0_10::translate(unused, settings.storeSettings); - //TODO: unused doesn't take store settings into account... so can't yet implement strict - QPID_LOG(debug, "Broker did not use the following settings (store module may): " << unused); - - std::pair, bool> result = - createQueue(name, settings, 0, alternateExchange, userId, connectionId); - if (!result.second) { - throw ObjectAlreadyExists(name); - } - } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) { - bool durable(false); - bool autodelete(false); - std::string exchangeType("topic"); - std::string alternateExchange; - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == DURABLE) durable = i->second; - else if (i->first == AUTO_DELETE) autodelete = i->second; - else if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString(); - else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - framing::FieldTable arguments; - qpid::amqp_0_10::translate(extensions, arguments); - - try { - std::pair, bool> result = - createExchange(name, exchangeType, durable, autodelete, alternateExchange, arguments, userId, connectionId); - if (!result.second) { - throw ObjectAlreadyExists(name); - } - } catch (const UnknownExchangeTypeException&) { - throw Exception(QPID_MSG("Invalid exchange type: " << exchangeType)); - } - } else if (type == TYPE_BINDING) { - BindingIdentifier binding(name); - std::string exchangeType("topic"); - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - framing::FieldTable arguments; - qpid::amqp_0_10::translate(extensions, arguments); - - bind(binding.queue, binding.exchange, binding.key, arguments, 0, userId, connectionId); - - } else if (type == TYPE_LINK) { - - QPID_LOG (debug, "createObject: Link; name=" << name << "; args=" << properties ); - - if (name.compare(0, QPID_NAME_PREFIX.length(), QPID_NAME_PREFIX) == 0) { - QPID_LOG(error, "Link name='" << name << "' cannot use the reserved prefix '" << QPID_NAME_PREFIX << "'"); - throw ReservedObjectName(name); - } - - std::string host; - uint16_t port = 0; - std::string transport = TCP_TRANSPORT; - bool durable = false; - std::string authMech, username, password; - - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - if (i->first == HOST) host = i->second.asString(); - else if (i->first == PORT) port = i->second.asUint16(); - else if (i->first == TRANSPORT) transport = i->second.asString(); - else if (i->first == DURABLE) durable = bool(i->second); - else if (i->first == AUTH_MECHANISM) authMech = i->second.asString(); - else if (i->first == USERNAME) username = i->second.asString(); - else if (i->first == PASSWORD) password = i->second.asString(); - else { - // TODO: strict checking here - } - } - - if (!getTransportInfo(transport).connectorFactory) { - QPID_LOG(error, "Transport '" << transport << "' not supported."); - throw UnsupportedTransport(transport); - } - - std::pair, bool> rc; - rc = links.declare(name, host, port, transport, durable, authMech, username, password); - if (!rc.first) { - QPID_LOG (error, "Failed to create Link object, name=" << name << " remote=" << host << ":" << port << - "; transport=" << transport << "; durable=" << (durable?"T":"F") << "; authMech=\"" << authMech << "\""); - throw InvalidParameter(name); - } - if (!rc.second) { - QPID_LOG (error, "Failed to create a new Link object, name=" << name << " already exists."); - throw ObjectAlreadyExists(name); - } - - } else if (type == TYPE_BRIDGE) { - - QPID_LOG (debug, "createObject: Bridge; name=" << name << "; args=" << properties ); - - if (name.compare(0, QPID_NAME_PREFIX.length(), QPID_NAME_PREFIX) == 0) { - QPID_LOG(error, "Bridge name='" << name << "' cannot use the reserved prefix '" << QPID_NAME_PREFIX << "'"); - throw ReservedObjectName(name); - } - - std::string linkName; - std::string src; - std::string dest; - std::string key; - std::string id; - std::string excludes; - std::string queueName; - bool durable = false; - bool srcIsQueue = false; - bool srcIsLocal = false; - bool dynamic = false; - uint16_t sync = 0; - uint32_t credit = LinkRegistry::INFINITE_CREDIT; - - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - - if (i->first == LINK) linkName = i->second.asString(); - else if (i->first == SRC) src = i->second.asString(); - else if (i->first == DEST) dest = i->second.asString(); - else if (i->first == KEY) key = i->second.asString(); - else if (i->first == TAG) id = i->second.asString(); - else if (i->first == EXCLUDES) excludes = i->second.asString(); - else if (i->first == SRC_IS_QUEUE) srcIsQueue = bool(i->second); - else if (i->first == SRC_IS_LOCAL) srcIsLocal = bool(i->second); - else if (i->first == DYNAMIC) dynamic = bool(i->second); - else if (i->first == SYNC) sync = i->second.asUint16(); - else if (i->first == CREDIT) credit = i->second.asUint32(); - else if (i->first == DURABLE) durable = bool(i->second); - else if (i->first == QUEUE_NAME) queueName = i->second.asString(); - else { - // TODO: strict checking here - } - } - - boost::shared_ptr link; - if (linkName.empty() || !(link = links.getLink(linkName))) { - QPID_LOG(error, "Link '" << linkName << "' not found; bridge create failed."); - throw InvalidParameter(name); - } - std::pair rc = - links.declare(name, *link, durable, src, dest, key, srcIsQueue, srcIsLocal, id, excludes, - dynamic, sync, credit, - 0, - queueName); - - if (!rc.first) { - QPID_LOG (error, "Failed to create Bridge object, name=" << name << " link=" << linkName << - "; src=" << src << "; dest=" << dest << "; key=" << key); - throw InvalidParameter(name); - } - if (!rc.second) { - QPID_LOG (error, "Failed to create a new Bridge object, name=" << name << " already exists."); - throw ObjectAlreadyExists(name); - } - } else { - throw UnknownObjectType(type); - } -} - -void Broker::deleteObject(const std::string& type, const std::string& name, - const Variant::Map& options, const Connection* context) -{ - std::string userId; - std::string connectionId; - if (context) { - userId = context->getUserId(); - connectionId = context->getMgmtId(); - } - QPID_LOG (debug, "Broker::delete(" << type << ", " << name << "," << options << ")"); - if (objectFactory.deleteObject(*this, type, name, options, userId, connectionId)) { - QPID_LOG (debug, "Broker::delete(" << type << ", " << name << "," << options << ") handled by registered factory"); - } else if (type == TYPE_QUEUE) { - // extract ifEmpty and ifUnused from options - bool ifUnused = false, ifEmpty = false; - for (Variant::Map::const_iterator i = options.begin(); i != options.end(); ++i) { - if (i->first == IF_UNUSED) ifUnused = i->second.asBool(); - else if (i->first == IF_EMPTY) ifEmpty = i->second.asBool(); - } - deleteQueue(name, userId, connectionId, - boost::bind(&Broker::checkDeleteQueue, this, _1, ifUnused, ifEmpty)); - } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) { - deleteExchange(name, userId, connectionId); - } else if (type == TYPE_BINDING) { - BindingIdentifier binding(name); - unbind(binding.queue, binding.exchange, binding.key, 0, userId, connectionId); - } else if (type == TYPE_LINK) { - boost::shared_ptr link = links.getLink(name); - if (link) { - link->close(); - } - } else if (type == TYPE_BRIDGE) { - boost::shared_ptr bridge = links.getBridge(name); - if (bridge) { - bridge->close(); - } - } else { - throw UnknownObjectType(type); - } -} - -void Broker::checkDeleteQueue(Queue::shared_ptr queue, bool ifUnused, bool ifEmpty) -{ - if(ifEmpty && queue->getMessageCount() > 0) { - throw qpid::framing::PreconditionFailedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; queue not empty")); - } else if(ifUnused && queue->getConsumerCount() > 0) { - throw qpid::framing::PreconditionFailedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; queue in use")); - } -} - -Manageable::status_t Broker::queryObject(const std::string& type, - const std::string& name, - Variant::Map& results, - const Connection* context) -{ - std::string userId; - std::string connectionId; - if (context) { - userId = context->getUserId(); - connectionId = context->getMgmtId(); - } - QPID_LOG (debug, "Broker::query(" << type << ", " << name << ")"); - - if (type == TYPE_QUEUE) - return queryQueue( name, userId, connectionId, results ); - - if (type == TYPE_EXCHANGE || - type == TYPE_TOPIC || - type == TYPE_BINDING) - return Manageable::STATUS_NOT_IMPLEMENTED; - - throw UnknownObjectType(type); -} - -Manageable::status_t Broker::queryQueue( const std::string& name, - const std::string& userId, - const std::string& /*connectionId*/, - Variant::Map& results ) -{ - (void) results; - if (acl) { - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_QUEUE, name, NULL) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue query request from " << userId)); - } - - boost::shared_ptr q(queues.find(name)); - if (!q) { - QPID_LOG(error, "Query failed: queue not found, name=" << name); - return Manageable::STATUS_UNKNOWN_OBJECT; - } - q->query( results ); - return Manageable::STATUS_OK;; -} - -Manageable::status_t Broker::getTimestampConfig(bool& receive, - const Connection* context) -{ - std::string name; // none needed for broker - std::string userId = context->getUserId(); - if (acl && !acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_BROKER, name, NULL)) { - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied broker timestamp get request from " << userId)); - } - receive = timestampRcvMsgs; - return Manageable::STATUS_OK; -} - -Manageable::status_t Broker::setTimestampConfig(const bool receive, - const Connection* context) -{ - std::string name; // none needed for broker - std::string userId = context->getUserId(); - if (acl && !acl->authorise(userId, acl::ACT_UPDATE, acl::OBJ_BROKER, name, NULL)) { - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied broker timestamp set request from " << userId)); - } - timestampRcvMsgs = receive; - QPID_LOG(notice, "Receive message timestamping is " << ((timestampRcvMsgs) ? "ENABLED." : "DISABLED.")); - return Manageable::STATUS_OK; -} - -void Broker::setLogLevel(const std::string& level) -{ - QPID_LOG(notice, "Changing log level to " << level); - std::vector selectors; - split(selectors, level, ", "); - qpid::log::Logger::instance().reconfigure(selectors); -} - -std::string Broker::getLogLevel() -{ - std::string level; - std::string sep(""); - const std::vector& selectors = qpid::log::Logger::instance().getOptions().selectors; - for (std::vector::const_iterator i = selectors.begin(); i != selectors.end(); ++i) { - level += sep + *i; - sep = ","; - } - const std::vector& disselectors = qpid::log::Logger::instance().getOptions().deselectors; - for (std::vector::const_iterator i = disselectors.begin(); i != disselectors.end(); ++i) { - level += sep + "!" + *i; - sep = ","; - } - return level; -} - -void Broker::setLogHiresTimestamp(bool enabled) -{ - QPID_LOG(notice, "Changing log hires timestamp to " << enabled); - qpid::log::Logger::instance().setHiresTimestamp(enabled); -} - -bool Broker::getLogHiresTimestamp() -{ - return qpid::log::Logger::instance().getHiresTimestamp(); -} - - -Manageable::status_t Broker::queueRedirect(const std::string& srcQueue, - const std::string& tgtQueue, - const Connection* context) -{ - Queue::shared_ptr srcQ(queues.find(srcQueue)); - if (!srcQ) { - QPID_LOG(error, "Queue redirect failed: source queue not found: " - << srcQueue); - return Manageable::STATUS_UNKNOWN_OBJECT; - } - - if (!tgtQueue.empty()) { - // NonBlank target queue creates partnership - Queue::shared_ptr tgtQ(queues.find(tgtQueue)); - if (!tgtQ) { - QPID_LOG(error, "Queue redirect failed: target queue not found: " - << tgtQueue); - return Manageable::STATUS_UNKNOWN_OBJECT; - } - - if (srcQueue.compare(tgtQueue) == 0) { - QPID_LOG(error, "Queue redirect source queue: " - << tgtQueue << " cannot be its own target"); - return Manageable::STATUS_USER; - } - - if (srcQ->isAutoDelete()) { - QPID_LOG(error, "Queue redirect source queue: " - << srcQueue << " is autodelete and can not be part of redirect"); - return Manageable::STATUS_USER; - } - - if (tgtQ->isAutoDelete()) { - QPID_LOG(error, "Queue redirect target queue: " - << tgtQueue << " is autodelete and can not be part of redirect"); - return Manageable::STATUS_USER; - } - - if (srcQ->getRedirectPeer()) { - QPID_LOG(error, "Queue redirect source queue: " - << srcQueue << " is already redirected"); - return Manageable::STATUS_USER; - } - - if (tgtQ->getRedirectPeer()) { - QPID_LOG(error, "Queue redirect target queue: " - << tgtQueue << " is already redirected"); - return Manageable::STATUS_USER; - } - - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_QUEUENAME, tgtQ->getName())); - if (!acl->authorise((context)?context->getUserId():"", acl::ACT_REDIRECT, acl::OBJ_QUEUE, srcQ->getName(), ¶ms)) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied redirect request from " << ((context)?context->getUserId():"(uknown)"))); - } - - // Start the backup overflow partnership - srcQ->setRedirectPeer(tgtQ, true); - tgtQ->setRedirectPeer(srcQ, false); - - // Set management state - srcQ->setMgmtRedirectState(tgtQueue, true, true); - tgtQ->setMgmtRedirectState(srcQueue, true, false); - - // Management event - if (managementAgent.get()) { - managementAgent->raiseEvent(_qmf::EventQueueRedirect(srcQueue, tgtQueue)); - } - - QPID_LOG(info, "Queue redirect complete. queue: " - << srcQueue << " target queue: " << tgtQueue); - return Manageable::STATUS_OK; - } else { - // Blank target queue destroys partnership - Queue::shared_ptr tgtQ(srcQ->getRedirectPeer()); - if (!tgtQ) { - QPID_LOG(error, "Queue redirect source queue: " - << srcQueue << " is not in redirected"); - return Manageable::STATUS_USER; - } - - if (!srcQ->isRedirectSource()) { - QPID_LOG(error, "Queue redirect source queue: " - << srcQueue << " is not a redirect source"); - return Manageable::STATUS_USER; - } - - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_QUEUENAME, tgtQ->getName())); - if (!acl->authorise((context)?context->getUserId():"", acl::ACT_REDIRECT, acl::OBJ_QUEUE, srcQ->getName(), ¶ms)) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied redirect request from " << ((context)?context->getUserId():"(uknown)"))); - } - - queueRedirectDestroy(srcQ, tgtQ, true); - - return Manageable::STATUS_OK; - } -} - - -void Broker::queueRedirectDestroy(Queue::shared_ptr srcQ, - Queue::shared_ptr tgtQ, - bool moveMsgs) { - QPID_LOG(notice, "Queue redirect destroyed. queue: " << srcQ->getName() - << " target queue: " << tgtQ->getName()); - - tgtQ->setMgmtRedirectState(empty, false, false); - srcQ->setMgmtRedirectState(empty, false, false); - - if (moveMsgs) { - // TODO: this 'move' works in the static case but has no - // actual locking that does what redirect needs when - // there is a lot of traffic in flight. - tgtQ->move(srcQ, 0); - } - - Queue::shared_ptr np; - - tgtQ->setRedirectPeer(np, false); - srcQ->setRedirectPeer(np, false); - - if (managementAgent.get()) { - managementAgent->raiseEvent(_qmf::EventQueueRedirectCancelled(srcQ->getName(), tgtQ->getName())); - } -} - -const Broker::TransportInfo& Broker::getTransportInfo(const std::string& name) const { - static TransportInfo nullTransportInfo; - TransportMap::const_iterator i - = name.empty() ? transportMap.begin() : transportMap.find(name); - if (i == transportMap.end()) return nullTransportInfo; - else return i->second; -} - -uint16_t Broker::getPort(const std::string& name) const { - if (int p = getTransportInfo(name).port) { - return p; - } else { - throw NoSuchTransportException(QPID_MSG("No such transport: '" << name << "'")); - } -} - -bool Broker::shouldListen(std::string transport) { - return disabledListeningTransports.count(transport)==0; -} - -void Broker::disableListening(std::string transport) { - disabledListeningTransports.insert(transport); -} - -void Broker::registerTransport(const std::string& name, boost::shared_ptr a, boost::shared_ptr c, uint16_t p) { - transportMap[name] = TransportInfo(a, c, p); - Url::addProtocol(name); -} - -void Broker::accept() { - unsigned accepting = 0; - for (TransportMap::const_iterator i = transportMap.begin(); i != transportMap.end(); i++) { - if (i->second.acceptor) { - i->second.acceptor->accept(poller, &protocolRegistry); - ++accepting; - } - } - if ( accepting==0 ) { - throw Exception(QPID_MSG("Failed to start broker: No transports are listening for incoming connections")); - } -} - -void Broker::connect( - const std::string& name, - const std::string& host, const std::string& port, const std::string& transport, - boost::function2 failed) -{ - connect(name, host, port, transport, &protocolRegistry, failed); -} - -void Broker::connect( - const std::string& name, - const std::string& host, const std::string& port, const std::string& transport, - sys::ConnectionCodec::Factory* f, boost::function2 failed) -{ - boost::shared_ptr tcf = getTransportInfo(transport).connectorFactory; - if (tcf) tcf->connect(poller, name, host, port, f, failed); - else throw NoSuchTransportException(QPID_MSG("Unsupported transport type: " << transport)); -} - -int32_t Broker::queueMoveMessages( - const std::string& srcQueue, - const std::string& destQueue, - uint32_t qty, - const Variant::Map& filter, - const Connection* context) -{ - Queue::shared_ptr src_queue = queues.find(srcQueue); - if (!src_queue) - return -1; - Queue::shared_ptr dest_queue = queues.find(destQueue); - if (!dest_queue) - return -1; - - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_QUEUENAME, dest_queue->getName())); - if (!acl->authorise((context)?context->getUserId():"", acl::ACT_MOVE, acl::OBJ_QUEUE, src_queue->getName(), ¶ms)) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied move request from " << ((context)?context->getUserId():"(uknown)"))); - } - - return (int32_t) src_queue->move(dest_queue, qty, &filter); -} - - -boost::shared_ptr Broker::getPoller() { return poller; } - -std::vector -Broker::getKnownBrokersImpl() -{ - return knownBrokers; -} - -bool Broker::deferDeliveryImpl(const std::string&, const Message&) -{ return false; } - -const std::string Broker::TCP_TRANSPORT("tcp"); - -std::pair, bool> Broker::createQueue( - const std::string& name, - const QueueSettings& constSettings, - const OwnershipToken* owner, - const std::string& alternateExchange, - const std::string& userId, - const std::string& connectionId) -{ - QueueSettings settings(constSettings); // So we can modify them - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_DURABLE, settings.durable ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_EXCLUSIVE, owner ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_AUTODELETE, settings.autodelete ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_POLICYTYPE, settings.getLimitPolicy())); - params.insert(make_pair(acl::PROP_PAGING, settings.paging ? _TRUE : _FALSE)); - if (settings.paging) { - params.insert(make_pair(acl::PROP_MAXPAGES, boost::lexical_cast(settings.maxPages ? settings.maxPages : DEFAULT_MAX_PAGES))); - params.insert(make_pair(acl::PROP_MAXPAGEFACTOR, boost::lexical_cast(settings.pageFactor ? settings.pageFactor : DEFAULT_PAGE_FACTOR))); - } - if (settings.maxDepth.hasCount()) - params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast(settings.maxDepth.getCount() ? settings.maxDepth.getCount() : std::numeric_limits::max()))); - if (settings.maxDepth.hasSize()) - params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast(settings.maxDepth.getSize() ? settings.maxDepth.getSize() : std::numeric_limits::max()))); - else - params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast(config.queueLimit))); - if (settings.durable) { - params.insert(make_pair(acl::PROP_MAXFILECOUNT, boost::lexical_cast(settings.maxFileCount ? settings.maxFileCount : 8))); - params.insert(make_pair(acl::PROP_MAXFILESIZE, boost::lexical_cast(settings.maxFileSize ? settings.maxFileSize : 24))); - } - - if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_QUEUE,name,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << userId)); - - if (!queues.find(name)) - if (!acl->approveCreateQueue(userId,name) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << userId)); - } - - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = exchanges.get(alternateExchange); - if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); - } - - // Identify queues that won't survive a failover: exclusive, auto-delete with no delay. - if (owner && settings.autodelete && !settings.autoDeleteDelay) - settings.isTemporary = true; - - std::pair result = - queues.declare(name, settings, alternate, false/*recovering*/, - owner, connectionId, userId); - if (result.second) { - //add default binding: - result.first->bind(exchanges.getDefault(), name); - QPID_LOG_CAT(debug, model, "Create queue. name:" << name - << " user:" << userId - << " rhost:" << connectionId - << " durable:" << (settings.durable ? "T" : "F") - << " owner:" << owner - << " autodelete:" << (settings.autodelete ? "T" : "F") - << " alternateExchange:" << alternateExchange ); - } - return result; -} - -void Broker::deleteQueue(const std::string& name, const std::string& userId, - const std::string& connectionId, QueueFunctor check) -{ - QPID_LOG_CAT(debug, model, "Deleting queue. name:" << name - << " user:" << userId - << " rhost:" << connectionId - ); - Queue::shared_ptr queue = queues.find(name); - if (queue) { - if (acl) { - std::map params; - boost::shared_ptr altEx = queue->getAlternateExchange(); - params.insert(make_pair(acl::PROP_ALTERNATE, (altEx) ? altEx->getName() : "" )); - params.insert(make_pair(acl::PROP_DURABLE, queue->isDurable() ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_EXCLUSIVE, queue->hasExclusiveOwner() ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_AUTODELETE, queue->isAutoDelete() ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_POLICYTYPE, queue->getSettings().getLimitPolicy())); - - if (!acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_QUEUE,name,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue delete request from " << userId)); - } - if (check) check(queue); - if (acl) - acl->recordDestroyQueue(name); - Queue::shared_ptr peerQ(queue->getRedirectPeer()); - if (peerQ) - queueRedirectDestroy(queue->isRedirectSource() ? queue : peerQ, - queue->isRedirectSource() ? peerQ : queue, - false); - queues.destroy(name, connectionId, userId); - } else { - throw framing::NotFoundException(QPID_MSG("Delete failed. No such queue: " << name)); - } -} - -std::pair Broker::createExchange( - const std::string& name, - const std::string& type, - bool durable, - bool autodelete, - const std::string& alternateExchange, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_TYPE, type)); - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_AUTODELETE, autodelete ? _TRUE : _FALSE)); - if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_EXCHANGE,name,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << userId)); - } - - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = exchanges.get(alternateExchange); - if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); - } - - std::pair result; - result = exchanges.declare( - name, type, durable, autodelete, arguments, alternate, connectionId, userId); - if (result.second) { - if (durable) { - store->create(*result.first, arguments); - } - QPID_LOG_CAT(debug, model, "Create exchange. name:" << name - << " user:" << userId - << " rhost:" << connectionId - << " type:" << type - << " alternateExchange:" << alternateExchange - << " durable:" << (durable ? "T" : "F") - << " autodelete:" << (autodelete ? "T" : "F")); - } - return result; -} - -void Broker::deleteExchange(const std::string& name, const std::string& userId, - const std::string& connectionId) -{ - QPID_LOG_CAT(debug, model, "Deleting exchange. name:" << name - << " user:" << userId - << " rhost:" << connectionId); - if (name.empty()) { - throw framing::InvalidArgumentException(QPID_MSG("Delete not allowed for default exchange")); - } - Exchange::shared_ptr exchange(exchanges.get(name)); - if (!exchange) throw framing::NotFoundException(QPID_MSG("Delete failed. No such exchange: " << name)); - - if (acl) { - std::map params; - Exchange::shared_ptr altEx = exchange->getAlternate(); - params.insert(make_pair(acl::PROP_TYPE, exchange->getType())); - params.insert(make_pair(acl::PROP_ALTERNATE, (altEx) ? altEx->getName() : "" )); - params.insert(make_pair(acl::PROP_DURABLE, exchange->isDurable() ? _TRUE : _FALSE)); - - if (!acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_EXCHANGE,name,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange delete request from " << userId)); - } - - if (exchange->inUseAsAlternate()) throw framing::NotAllowedException(QPID_MSG("Cannot delete " << name <<", in use as alternate-exchange.")); - if (exchange->isDurable()) store->destroy(*exchange); - if (exchange->getAlternate()) exchange->getAlternate()->decAlternateUsers(); - exchanges.destroy(name, connectionId, userId); -} - -void Broker::bind(const std::string& queueName, - const std::string& exchangeName, - const std::string& key, - const qpid::framing::FieldTable& arguments, - const OwnershipToken* owner, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - - if (!acl->authorise(userId,acl::ACT_BIND,acl::OBJ_EXCHANGE,exchangeName,¶ms)) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange bind request from " << userId)); - } - if (exchangeName.empty()) { - throw framing::InvalidArgumentException(QPID_MSG("Bind not allowed for default exchange")); - } - - Queue::shared_ptr queue = queues.find(queueName); - Exchange::shared_ptr exchange = exchanges.get(exchangeName); - if (!queue) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such queue: " << queueName)); - } else if (!exchange) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName)); - } else if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(owner)) { - throw framing::ResourceLockedException(QPID_MSG("Cannot bind queue " - << queue->getName() << "; it is exclusive to another session")); - } else { - if (queue->bind(exchange, key, arguments)) { - getBrokerObservers().bind(exchange, queue, key, arguments); - if (managementAgent.get()) { - managementAgent->raiseEvent(_qmf::EventBind(connectionId, userId, exchangeName, - queueName, key, ManagementAgent::toMap(arguments))); - } - QPID_LOG_CAT(debug, model, "Create binding. exchange:" << exchangeName - << " queue:" << queueName - << " key:" << key - << " arguments:" << arguments - << " user:" << userId - << " rhost:" << connectionId); - } - } -} - -void Broker::unbind(const std::string& queueName, - const std::string& exchangeName, - const std::string& key, - const OwnershipToken* owner, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - if (!acl->authorise(userId,acl::ACT_UNBIND,acl::OBJ_EXCHANGE,exchangeName,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange unbind request from " << userId)); - } - if (exchangeName.empty()) { - throw framing::InvalidArgumentException(QPID_MSG("Unbind not allowed for default exchange")); - } - Queue::shared_ptr queue = queues.find(queueName); - Exchange::shared_ptr exchange = exchanges.get(exchangeName); - if (!queue) { - throw framing::NotFoundException(QPID_MSG("Unbind failed. No such queue: " << queueName)); - } else if (!exchange) { - throw framing::NotFoundException(QPID_MSG("Unbind failed. No such exchange: " << exchangeName)); - } else if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(owner)) { - throw framing::ResourceLockedException(QPID_MSG("Cannot unbind queue " - << queue->getName() << "; it is exclusive to another session")); - } else { - if (exchange->unbind(queue, key, 0)) { - if (exchange->isDurable() && queue->isDurable()) { - store->unbind(*exchange, *queue, key, qpid::framing::FieldTable()); - } - getBrokerObservers().unbind( - exchange, queue, key, framing::FieldTable()); - if (managementAgent.get()) { - managementAgent->raiseEvent(_qmf::EventUnbind(connectionId, userId, exchangeName, queueName, key)); - } - QPID_LOG_CAT(debug, model, "Delete binding. exchange:" << exchangeName - << " queue:" << queueName - << " key:" << key - << " user:" << userId - << " rhost:" << connectionId); - } - } -} - -// FIXME aconway 2012-04-27: access to linkClientProperties is -// not properly thread safe, you could lose fields if 2 threads -// attempt to add a field concurrently. - -framing::FieldTable Broker::getLinkClientProperties() const { - sys::Mutex::ScopedLock l(linkClientPropertiesLock); - return linkClientProperties; -} - -void Broker::setLinkClientProperties(const framing::FieldTable& ft) { - sys::Mutex::ScopedLock l(linkClientPropertiesLock); - linkClientProperties = ft; -} - -}} // namespace qpid::broker - diff --git a/qpid/cpp/src/qpid/broker/Broker.h b/qpid/cpp/src/qpid/broker/Broker.h deleted file mode 100644 index af1144eeb0..0000000000 --- a/qpid/cpp/src/qpid/broker/Broker.h +++ /dev/null @@ -1,350 +0,0 @@ -#ifndef QPID_BROKER_BROKER_H -#define QPID_BROKER_BROKER_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/BrokerImportExport.h" - -#include "qpid/DataDir.h" -#include "qpid/Options.h" -#include "qpid/Plugin.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/ObjectFactory.h" -#include "qpid/broker/Protocol.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/SessionManager.h" -#include "qpid/broker/QueueCleaner.h" -#include "qpid/broker/Vhost.h" -#include "qpid/broker/System.h" -#include "qpid/broker/ConsumerFactory.h" -#include "qpid/broker/ConnectionObservers.h" -#include "qpid/broker/SessionHandlerObserver.h" -#include "qpid/broker/BrokerObservers.h" -#include "qpid/management/Manageable.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Runnable.h" - -#include - -#include -#include - -namespace qpid { -namespace sys { -class TransportAcceptor; -class TransportConnector; -class Poller; -class Timer; -} - -struct Url; - -namespace broker { - -class AclModule; -struct BrokerOptions; -class Message; -struct QueueSettings; - -static const uint16_t DEFAULT_PORT=5672; - -struct NoSuchTransportException : qpid::Exception -{ - NoSuchTransportException(const std::string& s) : Exception(s) {} - virtual ~NoSuchTransportException() throw() {} -}; - -/** - * A broker instance. - */ -class Broker : public sys::Runnable, public Plugin::Target, - public management::Manageable, - public RefCounted -{ - struct TransportInfo { - boost::shared_ptr acceptor; - boost::shared_ptr connectorFactory; - uint16_t port; - - TransportInfo() : - port(0) - {} - - TransportInfo(boost::shared_ptr a, boost::shared_ptr c, uint16_t p) : - acceptor(a), - connectorFactory(c), - port(p) - {} - }; - typedef std::map TransportMap; - - void declareStandardExchange(const std::string& name, const std::string& type); - void setStore (); - void setLogLevel(const std::string& level); - std::string getLogLevel(); - void setLogHiresTimestamp(bool enabled); - bool getLogHiresTimestamp(); - void createObject(const std::string& type, const std::string& name, - const qpid::types::Variant::Map& properties, bool strict, const Connection* context); - void deleteObject(const std::string& type, const std::string& name, - const qpid::types::Variant::Map& options, const Connection* context); - void checkDeleteQueue(boost::shared_ptr queue, bool ifUnused, bool ifEmpty); - Manageable::status_t queryObject(const std::string& type, const std::string& name, - qpid::types::Variant::Map& results, const Connection* context); - Manageable::status_t queryQueue( const std::string& name, - const std::string& userId, - const std::string& connectionId, - qpid::types::Variant::Map& results); - Manageable::status_t getTimestampConfig(bool& receive, - const Connection* context); - Manageable::status_t setTimestampConfig(const bool receive, - const Connection* context); - Manageable::status_t queueRedirect(const std::string& srcQueue, const std::string& tgtQueue, const Connection* context); - void queueRedirectDestroy(boost::shared_ptr srcQ, boost::shared_ptr tgtQ, bool moveMsgs); - - // This must be the first member of Broker. It logs a start-up message - // at the start of Broker construction and a shut-down message at the - // end of destruction. - struct LogPrefix : public std::string { - LogPrefix(); - ~LogPrefix(); - } logPrefix; - - boost::shared_ptr poller; - std::auto_ptr timer; - const BrokerOptions& config; - std::auto_ptr managementAgent; - std::set disabledListeningTransports; - TransportMap transportMap; - std::auto_ptr store; - AclModule* acl; - DataDir dataDir; - DataDir pagingDir; - ConnectionObservers connectionObservers; - SessionHandlerObservers sessionHandlerObservers; - BrokerObservers brokerObservers; - - QueueRegistry queues; - ExchangeRegistry exchanges; - LinkRegistry links; - DtxManager dtxManager; - SessionManager sessionManager; - qmf::org::apache::qpid::broker::Broker::shared_ptr mgmtObject; - Vhost::shared_ptr vhostObject; - System::shared_ptr systemObject; - QueueCleaner queueCleaner; - std::vector knownBrokers; - std::vector getKnownBrokersImpl(); - bool deferDeliveryImpl(const std::string& queue, - const Message& msg); - std::string federationTag; - bool recoveryInProgress; - ConsumerFactories consumerFactories; - ProtocolRegistry protocolRegistry; - ObjectFactoryRegistry objectFactory; - - mutable sys::Mutex linkClientPropertiesLock; - framing::FieldTable linkClientProperties; - bool timestampRcvMsgs; - - public: - QPID_BROKER_EXTERN virtual ~Broker(); - - QPID_BROKER_EXTERN Broker(const BrokerOptions& configuration); - static QPID_BROKER_EXTERN boost::intrusive_ptr create(const BrokerOptions& configuration); - static QPID_BROKER_EXTERN boost::intrusive_ptr create(int16_t port = DEFAULT_PORT); - - /** - * Return listening port. If called before bind this is - * the configured port. If called after it is the actual - * port, which will be different if the configured port is - * 0. - */ - QPID_BROKER_EXTERN virtual uint16_t getPort(const std::string& name) const; - - /** - * Run the broker. Implements Runnable::run() so the broker - * can be run in a separate thread. - */ - QPID_BROKER_EXTERN virtual void run(); - - /** Shut down the broker */ - QPID_BROKER_EXTERN virtual void shutdown(); - - QPID_BROKER_EXTERN void setStore (const boost::shared_ptr& store); - bool hasStore() const { return store.get(); } - MessageStore& getStore() { return *store; } - void setAcl (AclModule* _acl) {acl = _acl;} - AclModule* getAcl() { return acl; } - QueueRegistry& getQueues() { return queues; } - ExchangeRegistry& getExchanges() { return exchanges; } - LinkRegistry& getLinks() { return links; } - DtxManager& getDtxManager() { return dtxManager; } - const DataDir& getDataDir() { return dataDir; } - const DataDir& getPagingDir() { return pagingDir; } - ProtocolRegistry& getProtocolRegistry() { return protocolRegistry; } - ObjectFactoryRegistry& getObjectFactoryRegistry() { return objectFactory; } - - SessionManager& getSessionManager() { return sessionManager; } - const std::string& getFederationTag() const { return federationTag; } - - QPID_BROKER_EXTERN management::ManagementObject::shared_ptr GetManagementObject() const; - QPID_BROKER_EXTERN management::Manageable* GetVhostObject() const; - QPID_BROKER_EXTERN management::Manageable::status_t ManagementMethod( - uint32_t methodId, management::Args& args, std::string& text); - - // Should we listen using this protocol or not? - QPID_BROKER_EXTERN bool shouldListen(std::string transport); - - // Turn off listening for a protocol - QPID_BROKER_EXTERN void disableListening(std::string transport); - - /** Add to the broker's protocolFactorys */ - QPID_BROKER_EXTERN void registerTransport( - const std::string& name, - boost::shared_ptr, boost::shared_ptr, - uint16_t port); - - /** Accept connections */ - QPID_BROKER_EXTERN void accept(); - - /** Create a connection to another broker. */ - void connect(const std::string& name, - const std::string& host, const std::string& port, - const std::string& transport, - boost::function2 failed); - QPID_BROKER_EXTERN void connect(const std::string& name, - const std::string& host, const std::string& port, - const std::string& transport, - sys::ConnectionCodec::Factory*, - boost::function2 failed); - - - /** Move messages from one queue to another. - A zero quantity means to move all messages - Return -1 if one of the queues does not exist, otherwise - the number of messages moved. - */ - QPID_BROKER_EXTERN int32_t queueMoveMessages( - const std::string& srcQueue, - const std::string& destQueue, - uint32_t qty, - const qpid::types::Variant::Map& filter, - const Connection* context); - - QPID_BROKER_EXTERN const TransportInfo& getTransportInfo( - const std::string& name = TCP_TRANSPORT) const; - - /** Expose poller so plugins can register their descriptors. */ - QPID_BROKER_EXTERN boost::shared_ptr getPoller(); - - /** Timer for local tasks affecting only this broker */ - sys::Timer& getTimer() { return *timer; } - - boost::function ()> getKnownBrokers; - - static QPID_BROKER_EXTERN const std::string TCP_TRANSPORT; - - management::ManagementAgent* getManagementAgent() { return managementAgent.get(); } - - typedef boost::function1 > QueueFunctor; - - QPID_BROKER_EXTERN std::pair, bool> createQueue( - const std::string& name, - const QueueSettings& settings, - const OwnershipToken* owner, - const std::string& alternateExchange, - const std::string& userId, - const std::string& connectionId); - - QPID_BROKER_EXTERN void deleteQueue( - const std::string& name, - const std::string& userId, - const std::string& connectionId, - QueueFunctor check = QueueFunctor()); - - QPID_BROKER_EXTERN std::pair createExchange( - const std::string& name, - const std::string& type, - bool durable, - bool autodelete, - const std::string& alternateExchange, - const qpid::framing::FieldTable& args, - const std::string& userId, const std::string& connectionId); - - QPID_BROKER_EXTERN void deleteExchange( - const std::string& name, const std::string& userId, - const std::string& connectionId); - - QPID_BROKER_EXTERN void bind( - const std::string& queue, - const std::string& exchange, - const std::string& key, - const qpid::framing::FieldTable& arguments, - const OwnershipToken* owner, - const std::string& userId, - const std::string& connectionId); - - QPID_BROKER_EXTERN void unbind( - const std::string& queue, - const std::string& exchange, - const std::string& key, - const OwnershipToken* owner, - const std::string& userId, - const std::string& connectionId); - - ConsumerFactories& getConsumerFactories() { return consumerFactories; } - ConnectionObservers& getConnectionObservers() { return connectionObservers; } - SessionHandlerObservers& getSessionHandlerObservers() { return sessionHandlerObservers; } - BrokerObservers& getBrokerObservers() { return brokerObservers; } - - /** Properties to be set on outgoing link connections */ - QPID_BROKER_EXTERN framing::FieldTable getLinkClientProperties() const; - QPID_BROKER_EXTERN void setLinkClientProperties(const framing::FieldTable&); - - bool inRecovery() const { return recoveryInProgress; } - bool isTimestamping() const { return timestampRcvMsgs; } - QPID_BROKER_EXTERN bool isAuthenticating() const; - QPID_BROKER_EXTERN bool requireEncrypted() const; - QPID_BROKER_EXTERN std::string getRealm() const; - QPID_BROKER_EXTERN std::string getSaslServiceName() const; - QPID_BROKER_EXTERN bool getTcpNoDelay() const; - QPID_BROKER_EXTERN uint16_t getPortOption() const; - QPID_BROKER_EXTERN const std::vector& getListenInterfaces() const; - QPID_BROKER_EXTERN int getConnectionBacklog() const; - uint32_t getMaxNegotiateTime() const; - sys::Duration getLinkMaintenanceInterval() const; - QPID_BROKER_EXTERN sys::Duration getLinkHeartbeatInterval() const; - uint32_t getDtxMaxTimeout() const; - uint16_t getQueueThresholdEventRatio() const; - uint getQueueLimit() const; - - /** Information identifying this system */ - boost::shared_ptr getSystem() const { return systemObject; } -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/BrokerImportExport.h b/qpid/cpp/src/qpid/broker/BrokerImportExport.h deleted file mode 100644 index ee05788063..0000000000 --- a/qpid/cpp/src/qpid/broker/BrokerImportExport.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_BROKER_IMPORT_EXPORT_H -#define QPID_BROKER_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. - */ - -#if defined(WIN32) && !defined(QPID_DECLARE_STATIC) -# if defined(BROKER_EXPORT) || defined (qpidbroker_EXPORTS) -# define QPID_BROKER_EXTERN __declspec(dllexport) -# else -# define QPID_BROKER_EXTERN __declspec(dllimport) -# endif -# ifdef _MSC_VER -# define QPID_BROKER_CLASS_EXTERN -# define QPID_BROKER_INLINE_EXTERN QPID_BROKER_EXTERN -# else -# define QPID_BROKER_CLASS_EXTERN QPID_BROKER_EXTERN -# define QPID_BROKER_INLINE_EXTERN -# endif -#else -# define QPID_BROKER_EXTERN -# define QPID_BROKER_CLASS_EXTERN -# define QPID_BROKER_INLINE_EXTERN -#endif - -#endif diff --git a/qpid/cpp/src/qpid/broker/BrokerObserver.h b/qpid/cpp/src/qpid/broker/BrokerObserver.h deleted file mode 100644 index a9573b9e12..0000000000 --- a/qpid/cpp/src/qpid/broker/BrokerObserver.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_BROKER_BROKEROBSERVER_H -#define QPID_BROKER_BROKEROBSERVER_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 -#include - -namespace qpid { - -namespace framing { -class FieldTable; -} - -namespace broker { -class Queue; -class Exchange; -class TxBuffer; -class DtxBuffer; - -/** - * Observer for changes to configuration (aka wiring) - * - * NOTE: create and destroy functions are called with - * the registry lock held. This is necessary to ensure - * they are called in the correct sequence. - */ -class BrokerObserver -{ - public: - virtual ~BrokerObserver() {} - virtual void queueCreate(const boost::shared_ptr&) {} - virtual void queueDestroy(const boost::shared_ptr&) {} - virtual void exchangeCreate(const boost::shared_ptr&) {} - virtual void exchangeDestroy(const boost::shared_ptr&) {} - virtual void bind(const boost::shared_ptr& , - const boost::shared_ptr& , - const std::string& /*key*/, - const framing::FieldTable& /*args*/) {} - virtual void unbind(const boost::shared_ptr&, - const boost::shared_ptr& , - const std::string& /*key*/, - const framing::FieldTable& /*args*/) {} - virtual void startTx(const boost::intrusive_ptr&) {} - virtual void startDtx(const boost::intrusive_ptr&) {} -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_BROKEROBSERVER_H*/ diff --git a/qpid/cpp/src/qpid/broker/BrokerObservers.h b/qpid/cpp/src/qpid/broker/BrokerObservers.h deleted file mode 100644 index 67427adcb1..0000000000 --- a/qpid/cpp/src/qpid/broker/BrokerObservers.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef QPID_BROKER_BROKEROBSERVERS_H -#define QPID_BROKER_BROKEROBSERVERS_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 "BrokerObserver.h" -#include "Observers.h" - -namespace qpid { -namespace broker { - -/** - * Collection of BrokerObserver. - */ -class BrokerObservers : public Observers { - public: - void queueCreate(const boost::shared_ptr& q) { - each(boost::bind(&BrokerObserver::queueCreate, _1, q)); - } - void queueDestroy(const boost::shared_ptr& q) { - each(boost::bind(&BrokerObserver::queueDestroy, _1, q)); - } - void exchangeCreate(const boost::shared_ptr& e) { - each(boost::bind(&BrokerObserver::exchangeCreate, _1, e)); - } - void exchangeDestroy(const boost::shared_ptr& e) { - each(boost::bind(&BrokerObserver::exchangeDestroy, _1, e)); - } - void bind(const boost::shared_ptr& exchange, - const boost::shared_ptr& queue, - const std::string& key, - const framing::FieldTable& args) { - each(boost::bind(&BrokerObserver::bind, _1, exchange, queue, key, args)); - } - void unbind(const boost::shared_ptr& exchange, - const boost::shared_ptr& queue, - const std::string& key, - const framing::FieldTable& args) { - each(boost::bind(&BrokerObserver::unbind, _1, exchange, queue, key, args)); - } - void startTx(const boost::intrusive_ptr& tx) { - each(boost::bind(&BrokerObserver::startTx, _1, tx)); - } - void startDtx(const boost::intrusive_ptr& dtx) { - each(boost::bind(&BrokerObserver::startDtx, _1, dtx)); - } - - private: - template void each(F f) { Observers::each(f); } -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_BROKEROBSERVERS_H*/ diff --git a/qpid/cpp/src/qpid/broker/BrokerOptions.h b/qpid/cpp/src/qpid/broker/BrokerOptions.h deleted file mode 100644 index 7207c17f91..0000000000 --- a/qpid/cpp/src/qpid/broker/BrokerOptions.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef QPID_BROKER_BROKEROPTIONS_H -#define QPID_BROKER_BROKEROPTIONS_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/Options.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/IntegerTypes.h" - -#include "qpid/broker/BrokerImportExport.h" - -#include -#include - -namespace qpid { -namespace broker { - -struct BrokerOptions : public qpid::Options -{ - static const std::string DEFAULT_DATA_DIR_LOCATION; - static const std::string DEFAULT_DATA_DIR_NAME; - static const std::string DEFAULT_PAGED_QUEUE_DIR; - - QPID_BROKER_EXTERN BrokerOptions(const std::string& name="Broker Options"); - - bool noDataDir; - std::string dataDir; - std::string pagingDir; - uint16_t port; - std::vector listenInterfaces; - std::vector listenDisabled; - std::vector protocols; - int workerThreads; - int connectionBacklog; - bool enableMgmt; - bool mgmtPublish; - sys::Duration mgmtPubInterval; - sys::Duration queueCleanInterval; - bool auth; - std::string realm; - std::string saslServiceName; - size_t replayFlushLimit; - size_t replayHardLimit; - uint queueLimit; - bool tcpNoDelay; - bool requireEncrypted; - std::string knownHosts; - std::string saslConfigPath; - bool qmf2Support; - bool qmf1Support; - uint queueFlowStopRatio; // producer flow control: on - uint queueFlowResumeRatio; // producer flow control: off - uint16_t queueThresholdEventRatio; - std::string defaultMsgGroup; - bool timestampRcvMsgs; - sys::Duration linkMaintenanceInterval; - sys::Duration linkHeartbeatInterval; - uint32_t dtxDefaultTimeout; // Default timeout of a DTX transaction - uint32_t dtxMaxTimeout; // Maximal timeout of a DTX transaction - uint32_t maxNegotiateTime; // Max time in ms for connection with no negotiation - std::string fedTag; - -private: - std::string getHome(); -}; - -}} - -#endif // QPID_BROKER_BROKEROPTIONS_H diff --git a/qpid/cpp/src/qpid/broker/Connection.h b/qpid/cpp/src/qpid/broker/Connection.h deleted file mode 100644 index 8cab18f37b..0000000000 --- a/qpid/cpp/src/qpid/broker/Connection.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef QPID_BROKER_CONNECTION_H -#define QPID_BROKER_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 "OwnershipToken.h" -#include -#include - -namespace qpid { -namespace management { -class ObjectId; -} -namespace types { -class Variant; -} - -namespace broker { - -/** - * Protocol independent connection abstraction. - */ -class Connection : public OwnershipToken { -public: - virtual ~Connection() {} - virtual const management::ObjectId getObjectId() const = 0; - virtual const std::string& getUserId() const = 0; - virtual const std::string& getMgmtId() const = 0; - virtual const std::map& getClientProperties() const = 0; - virtual bool isLink() const = 0; - virtual void abort() = 0; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_CONNECTION_H*/ diff --git a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp b/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp deleted file mode 100644 index 545b164ef4..0000000000 --- a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp +++ /dev/null @@ -1,471 +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/broker/ConnectionHandler.h" - -#include "qpid/SaslFactory.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/SecureConnection.h" -#include "qpid/Url.h" -#include "qpid/framing/AllInvoker.h" -#include "qpid/framing/ConnectionStartOkBody.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/Time.h" -#include "qpid/broker/AclModule.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qmf/org/apache/qpid/broker/EventClientConnectFail.h" -#include "qpid/Version.h" - -using namespace qpid; -using namespace qpid::broker; - -using std::string; - -using namespace qpid::framing; -using qpid::sys::SecurityLayer; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ -const std::string en_US = "en_US"; -const std::string QPID_FED_LINK = "qpid.fed_link"; -const std::string QPID_FED_TAG = "qpid.federation_tag"; -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); -const std::string SPACE(" "); -} - -void ConnectionHandler::close(connection::CloseCode code, const string& text) -{ - handler->proxy.close(code, text); -} - -void ConnectionHandler::heartbeat() -{ - handler->proxy.heartbeat(); -} - -bool ConnectionHandler::handle(const framing::AMQMethodBody& method) -{ - //Need special handling for start-ok, in order to distinguish - //between null and empty response - if (method.isA()) { - handler->startOk(dynamic_cast(method)); - return true; - } else { - return invoke(static_cast(*handler), method); - } -} - -void ConnectionHandler::handle(framing::AMQFrame& frame) -{ - AMQMethodBody* method=frame.getBody()->getMethod(); - try{ - if (method && handle(*method)) { - // This is a connection control frame, nothing more to do. - } else if (isOpen()) { - handler->connection.getChannel(frame.getChannel()).in(frame); - } else { - handler->connection.close( - connection::CLOSE_CODE_FRAMING_ERROR, - "Connection not yet open, invalid frame received."); - } - }catch(ConnectionException& e){ - handler->connection.close(e.code, e.what()); - }catch(std::exception& e){ - handler->connection.close(connection::CLOSE_CODE_CONNECTION_FORCED, e.what()); - } -} - -void ConnectionHandler::setSecureConnection(SecureConnection* secured) -{ - handler->secured = secured; -} - -ConnectionHandler::ConnectionHandler(qpid::broker::amqp_0_10::Connection& connection, bool isClient) : - handler(new Handler(connection, isClient)) {} - -ConnectionHandler::Handler::Handler(qpid::broker::amqp_0_10::Connection& c, bool isClient) : - proxy(c.getOutput()), - connection(c), serverMode(!isClient), secured(0), - isOpen(false) -{ - if (serverMode) { - FieldTable properties; - Array mechanisms(0x95); - boost::shared_ptr sysInfo = connection.getBroker().getSystem(); - - properties.setString("product", qpid::product); - properties.setString("version", qpid::version); - if (sysInfo) { - properties.setString("platform", sysInfo->getOsName()); - properties.setString("host", sysInfo->getNodeName()); - } - properties.setString(QPID_FED_TAG, connection.getBroker().getFederationTag()); - - authenticator = SaslAuthenticator::createAuthenticator(c); - authenticator->getMechanisms(mechanisms); - - Array locales(0x95); - boost::shared_ptr l(new Str16Value(en_US)); - locales.add(l); - proxy.start(properties, mechanisms, locales); - } - - maxFrameSize = (64 * 1024) - 1; -} - - -ConnectionHandler::Handler::~Handler() {} - - -void ConnectionHandler::Handler::startOk(const framing::FieldTable& /*clientProperties*/, - const string& /*mechanism*/, - const string& /*response*/, - const string& /*locale*/) -{ - //Need special handling for start-ok, in order to distinguish - //between null and empty response -> should never use this method - assert(false); -} - -void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body) -{ - const framing::FieldTable& clientProperties = body.getClientProperties(); - qmf::org::apache::qpid::broker::Connection::shared_ptr mgmtObject = connection.getMgmtObject(); - types::Variant::Map properties; - qpid::amqp_0_10::translate(clientProperties, properties); - - if (mgmtObject != 0) { - string procName = clientProperties.getAsString(CLIENT_PROCESS_NAME); - uint32_t pid = clientProperties.getAsInt(CLIENT_PID); - uint32_t ppid = clientProperties.getAsInt(CLIENT_PPID); - - mgmtObject->set_remoteProperties(properties); - if (!procName.empty()) - mgmtObject->set_remoteProcessName(procName); - if (pid != 0) - mgmtObject->set_remotePid(pid); - if (ppid != 0) - mgmtObject->set_remoteParentPid(ppid); - } - try { - authenticator->start(body.getMechanism(), body.hasResponse() ? &body.getResponse() : 0); - } catch (std::exception& /*e*/) { - management::ManagementAgent* agent = connection.getAgent(); - bool logEnabled; - QPID_LOG_TEST_CAT(debug, model, logEnabled); - if (logEnabled || agent) - { - string error; - string uid; - authenticator->getError(error); - authenticator->getUid(uid); - if (agent && mgmtObject) { - agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error, - mgmtObject->get_remoteProperties())); - } - QPID_LOG_CAT(debug, model, "Failed connection. rhost:" << connection.getMgmtId() - << " user:" << uid - << " reason:" << error ); - } - throw; - } - - connection.setClientProperties(properties); - if (clientProperties.isSet(QPID_FED_TAG)) { - connection.setFederationPeerTag(clientProperties.getAsString(QPID_FED_TAG)); - } -} - -void ConnectionHandler::Handler::secureOk(const string& response) -{ - try { - authenticator->step(response); - } catch (std::exception& /*e*/) { - management::ManagementAgent* agent = connection.getAgent(); - bool logEnabled; - QPID_LOG_TEST_CAT(debug, model, logEnabled); - if (logEnabled || agent) - { - string error; - string uid; - authenticator->getError(error); - authenticator->getUid(uid); - if (agent && connection.getMgmtObject()) { - agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error, - connection.getMgmtObject()->get_remoteProperties())); - } - QPID_LOG_CAT(debug, model, "Failed connection. rhost:" << connection.getMgmtId() - << " user:" << uid - << " reason:" << error ); - } - throw; - } -} - -void ConnectionHandler::Handler::tuneOk(uint16_t /*channelmax*/, - uint16_t framemax, uint16_t heartbeat) -{ - if (framemax) connection.setFrameMax(framemax); - connection.setHeartbeatInterval(heartbeat); -} - -void ConnectionHandler::Handler::open(const string& /*virtualHost*/, - const framing::Array& /*capabilities*/, bool /*insist*/) -{ - if (connection.getUserId().empty() && connection.getBroker().isAuthenticating()) { - throw ConnectionForcedException("Not authenticated!"); - } - - if (connection.isFederationLink()) { - AclModule* acl = connection.getBroker().getAcl(); - if (acl && acl->userAclRules()) { - if (!acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){ - connection.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED, - QPID_MSG("ACL denied " << connection.getUserId() - << " creating a federation link")); - return; - } - } else { - if (connection.getBroker().isAuthenticating()) { - connection.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED, - QPID_MSG("User " << connection.getUserId() - << " federation connection denied. Systems with authentication " - "enabled must specify ACL create link rules.")); - return; - } - } - QPID_LOG(info, "Connection is a federation link"); - } - std::vector urls = connection.getBroker().getKnownBrokers(); - framing::Array array(0x95); // str16 array - for (std::vector::iterator i = urls.begin(); i < urls.end(); ++i) - array.add(boost::shared_ptr(new Str16Value(i->str()))); - - //install security layer if one has been negotiated: - if (secured) { - std::auto_ptr sl = authenticator->getSecurityLayer(connection.getFrameMax()); - if (sl.get()) secured->activateSecurityLayer(sl); - } - - isOpen = true; - proxy.openOk(array); -} - - -void ConnectionHandler::Handler::close(uint16_t replyCode, const string& replyText) -{ - if (replyCode != 200) { - QPID_LOG(warning, "Client closed connection with " << replyCode << ": " << replyText); - } - - if (replyCode == framing::connection::CLOSE_CODE_CONNECTION_FORCED) - connection.notifyConnectionForced(replyText); - - proxy.closeOk(); - connection.getOutput().close(); -} - -void ConnectionHandler::Handler::closeOk(){ - connection.getOutput().close(); -} - -void ConnectionHandler::Handler::heartbeat(){ - // For general case, do nothing - the purpose of heartbeats is - // just to make sure that there is some traffic on the connection - // within the heart beat interval, we check for the traffic and - // don't need to do anything in response to heartbeats. The - // exception is when we are in fact the client to another broker - // (i.e. an inter-broker link), in which case we echo the - // heartbeat back to the peer - if (!serverMode) proxy.heartbeat(); -} - -void ConnectionHandler::Handler::start(const FieldTable& serverProperties, - const framing::Array& supportedMechanisms, - const framing::Array& /*locales*/) -{ - if (serverMode) { - throw ConnectionForcedException("Invalid protocol sequence."); - } - - - string requestedMechanism = connection.getAuthMechanism(); - - std::string username = connection.getUsername(); - - std::string password = connection.getPassword(); - std::string host = connection.getHost(); - std::string service("qpidd"); - - if ( connection.getBroker().isAuthenticating() ) { - sasl = SaslFactory::getInstance().create( username, - password, - service, - host, - 0, // TODO -- mgoulish Fri Sep 24 2010 - 256, - false ); // disallow interaction - } - std::string supportedMechanismsList; - Array::const_iterator i; - - /* - If no specific mechanism has been requested, just make - a list of all of them, and assert that the one the caller - requested is there. ( If *any* are supported! ) - */ - if ( requestedMechanism.empty() ) { - for ( i = supportedMechanisms.begin(); i != supportedMechanisms.end(); ++i) { - if (i != supportedMechanisms.begin()) - supportedMechanismsList += SPACE; - supportedMechanismsList += (*i)->get(); - } - } - else { - /* - The caller has requested a mechanism. If it's available, - make sure it ends up at the head of the list. - */ - for ( i = supportedMechanisms.begin(); i != supportedMechanisms.end(); ++i) { - string currentMechanism = (*i)->get(); - - if ( requestedMechanism == currentMechanism ) { - supportedMechanismsList = currentMechanism + SPACE + supportedMechanismsList; - } else { - if (i != supportedMechanisms.begin()) - supportedMechanismsList += SPACE; - supportedMechanismsList += currentMechanism; - } - } - } - - if (serverProperties.isSet(QPID_FED_TAG)) { - connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG)); - } - - FieldTable ft = connection.getBroker().getLinkClientProperties(); - ft.setInt(QPID_FED_LINK,1); - ft.setString(QPID_FED_TAG, connection.getBroker().getFederationTag()); - - string response; - if (sasl.get()) { - const qpid::sys::SecuritySettings& ss = connection.getExternalSecuritySettings(); - if (sasl->start ( requestedMechanism.empty() - ? supportedMechanismsList - : requestedMechanism, - response, - & ss )) { - proxy.startOk ( ft, sasl->getMechanism(), response, en_US ); - } else { - //response was null - ConnectionStartOkBody body; - body.setClientProperties(ft); - body.setMechanism(sasl->getMechanism()); - //Don't set response, as none was given - body.setLocale(en_US); - proxy.send(body); - } - } - else { - response = ((char)0) + username + ((char)0) + password; - proxy.startOk ( ft, requestedMechanism, response, en_US ); - } - -} - -void ConnectionHandler::Handler::secure(const string& challenge ) -{ - if (serverMode) { - throw ConnectionForcedException("Invalid protocol sequence."); - } - - if (sasl.get()) { - string response = sasl->step(challenge); - proxy.secureOk(response); - } - else { - proxy.secureOk(""); - } -} - -void ConnectionHandler::Handler::tune(uint16_t channelMax, - uint16_t maxFrameSizeProposed, - uint16_t /*heartbeatMin*/, - uint16_t heartbeatMax) -{ - if (serverMode) { - throw ConnectionForcedException("Invalid protocol sequence."); - } - - maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed); - connection.setFrameMax(maxFrameSize); - - // this method is only ever called when this Connection - // is a federation link where this Broker is acting as - // a client to another Broker - sys::Duration interval = connection.getBroker().getLinkHeartbeatInterval(); - uint16_t intervalSec = static_cast(interval/sys::TIME_SEC); - uint16_t hb = std::min(intervalSec, heartbeatMax); - connection.setHeartbeat(hb); - connection.startLinkHeartbeatTimeoutTask(); - - proxy.tuneOk(channelMax, maxFrameSize, hb); - proxy.open("/", Array(), true); -} - -void ConnectionHandler::Handler::openOk(const framing::Array& knownHosts) -{ - if (serverMode) { - throw ConnectionForcedException("Invalid protocol sequence."); - } - - for (Array::ValueVector::const_iterator i = knownHosts.begin(); i != knownHosts.end(); ++i) { - Url url((*i)->get()); - connection.getKnownHosts().push_back(url); - } - - if (sasl.get()) { - std::auto_ptr securityLayer = sasl->getSecurityLayer(maxFrameSize); - - if ( securityLayer.get() ) { - secured->activateSecurityLayer(securityLayer, true); - } - - saslUserId = sasl->getUserId(); - } - - isOpen = true; -} - -void ConnectionHandler::Handler::redirect(const string& /*host*/, const framing::Array& /*knownHosts*/) -{ - -} diff --git a/qpid/cpp/src/qpid/broker/ConnectionHandler.h b/qpid/cpp/src/qpid/broker/ConnectionHandler.h deleted file mode 100644 index 93bd62d5d0..0000000000 --- a/qpid/cpp/src/qpid/broker/ConnectionHandler.h +++ /dev/null @@ -1,118 +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. - * - */ -#ifndef _ConnectionAdapter_ -#define _ConnectionAdapter_ - -#include -#include "qpid/Sasl.h" -#include "qpid/broker/SaslAuthenticator.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQP_AllOperations.h" -#include "qpid/framing/AMQP_AllProxy.h" -#include "qpid/framing/ConnectionStartOkBody.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/Exception.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/broker/System.h" - - - -namespace qpid { - -namespace sys { -struct SecuritySettings; -} - - -namespace broker { - -namespace amqp_0_10 { -class Connection; -} -class SecureConnection; - -class ConnectionHandler : public framing::FrameHandler -{ - struct Handler : public framing::AMQP_AllOperations::ConnectionHandler - { - framing::AMQP_AllProxy::Connection proxy; - amqp_0_10::Connection& connection; - bool serverMode; - std::auto_ptr authenticator; - SecureConnection* secured; - bool isOpen; - - Handler(amqp_0_10::Connection& connection, bool isClient); - ~Handler(); - void startOk(const qpid::framing::ConnectionStartOkBody& body); - void startOk(const qpid::framing::FieldTable& clientProperties, - const std::string& mechanism, const std::string& response, - const std::string& locale); - void secureOk(const std::string& response); - void tuneOk(uint16_t channelMax, uint16_t frameMax, uint16_t heartbeat); - void heartbeat(); - void open(const std::string& virtualHost, - const framing::Array& capabilities, bool insist); - void close(uint16_t replyCode, const std::string& replyText); - void closeOk(); - - void start(const qpid::framing::FieldTable& serverProperties, - const framing::Array& mechanisms, - const framing::Array& locales); - - void secure(const std::string& challenge); - - void tune(uint16_t channelMax, - uint16_t frameMax, - uint16_t heartbeatMin, - uint16_t heartbeatMax); - - void openOk(const framing::Array& knownHosts); - - void redirect(const std::string& host, const framing::Array& knownHosts); - - std::auto_ptr sasl; - typedef boost::function GetSecuritySettings; - std::string saslUserId; - uint16_t maxFrameSize; - }; - std::auto_ptr handler; - - bool handle(const qpid::framing::AMQMethodBody& method); - void close(framing::connection::CloseCode code, const std::string& text); - public: - ConnectionHandler(amqp_0_10::Connection& connection, bool isClient ); - void heartbeat(); - void handle(framing::AMQFrame& frame); - void setSecureConnection(SecureConnection* secured); - bool isOpen() { return handler->isOpen; } - friend class amqp_0_10::Connection; -}; - - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/ConnectionObserver.h b/qpid/cpp/src/qpid/broker/ConnectionObserver.h deleted file mode 100644 index eea2981185..0000000000 --- a/qpid/cpp/src/qpid/broker/ConnectionObserver.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_BROKER_CONNECTIONOBSERVER_H -#define QPID_BROKER_CONNECTIONOBSERVER_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 - -namespace qpid { -namespace broker { - -class Connection; - -/** - * Observer that is informed of connection events. For use by - * plug-ins that want to be notified of, or influence, connection - * events. - */ -class ConnectionObserver -{ - public: - virtual ~ConnectionObserver() {} - - /** Called when a connection is first established. */ - virtual void connection(Connection&) {} - - /** Called when the opening negotiation is done and the connection is authenticated. - * @exception Throwing an exception will abort the connection. - */ - virtual void opened(Connection&) {} - - /** Called when a connection is closed. */ - virtual void closed(Connection&) {} - - /** Called when a connection is forced closed. */ - virtual void forced(Connection&, const std::string& /*message*/) {} -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_CONNECTIONOBSERVER_H*/ diff --git a/qpid/cpp/src/qpid/broker/ConnectionObservers.h b/qpid/cpp/src/qpid/broker/ConnectionObservers.h deleted file mode 100644 index 8b9fb67aa5..0000000000 --- a/qpid/cpp/src/qpid/broker/ConnectionObservers.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef QPID_BROKER_CONNECTIONOBSERVERS_H -#define QPID_BROKER_CONNECTIONOBSERVERS_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 "ConnectionObserver.h" -#include "Observers.h" - -namespace qpid { -namespace broker { - -/** - * A collection of connection observers. - */ -class ConnectionObservers : public Observers -{ - public: - void connection(Connection& c) { - each(boost::bind(&ConnectionObserver::connection, _1, boost::ref(c))); - } - - void opened(Connection& c) { - each(boost::bind(&ConnectionObserver::opened, _1, boost::ref(c))); - } - - void closed(Connection& c) { - each(boost::bind(&ConnectionObserver::closed, _1, boost::ref(c))); - } - - void forced(Connection& c, const std::string& text) { - each(boost::bind(&ConnectionObserver::forced, _1, boost::ref(c), text)); - } -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_CONNECTIONOBSERVERS_H*/ diff --git a/qpid/cpp/src/qpid/broker/Consumer.h b/qpid/cpp/src/qpid/broker/Consumer.h deleted file mode 100644 index 4a0621243c..0000000000 --- a/qpid/cpp/src/qpid/broker/Consumer.h +++ /dev/null @@ -1,108 +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. - * - */ -#ifndef _Consumer_ -#define _Consumer_ - -#include "qpid/broker/QueueCursor.h" -#include "qpid/broker/OwnershipToken.h" -#include -#include - -namespace qpid { -namespace broker { - -class DeliveryRecord; -class Message; -class Queue; -class QueueListeners; - -/** - * Base class for consumers which represent a subscription to a queue. - */ -class Consumer : public QueueCursor { - const bool acquires; - // inListeners allows QueueListeners to efficiently track if this - // instance is registered for notifications without having to - // search its containers - bool inListeners; - // the name is generated by broker and is unique within broker scope. It is not - // provided or known by the remote Consumer. - const std::string name; - public: - typedef boost::shared_ptr shared_ptr; - - Consumer(const std::string& _name, SubscriptionType type, const std::string& _tag) - : QueueCursor(type), acquires(type == CONSUMER), inListeners(false), name(_name), tag(_tag) {} - virtual ~Consumer(){} - - bool preAcquires() const { return acquires; } - const std::string& getName() const { return name; } - - virtual bool deliver(const QueueCursor& cursor, const Message& msg) = 0; - virtual void notify() = 0; - virtual bool filter(const Message&) { return true; } - virtual bool accept(const Message&) { return true; } - virtual OwnershipToken* getSession() = 0; - virtual void cancel() = 0; - - /** Returns true if the browser wants acquired as well as - * available messages. - */ - virtual bool browseAcquired() const { return false; }; - - /** Called when the peer has acknowledged receipt of the message. - * Not to be confused with accept() above, which is asking if - * this consumer will consume/browse the message. - */ - virtual void acknowledged(const DeliveryRecord&) = 0; - - /** Called if queue has been deleted, if true suppress the error message. - * Used by HA ReplicatingSubscriptions where such errors are normal. - */ - virtual bool hideDeletedError() { return false; } - - /** If false, the consumer is not counted for purposes of auto-deletion or - * immediate messages. This is used for "system" consumers that are created - * by the broker for internal purposes as opposed to consumers that are - * created by normal clients. - */ - virtual bool isCounted() { return true; } - - QueueCursor getCursor() const { return *this; } - void setCursor(const QueueCursor& qc) { static_cast(*this) = qc; } - - const std::string& getTag() const { return tag; } - - /** Called when there are no more messages immediately available for this consumer on the queue */ - virtual void stopped() {} - - protected: - //framing::SequenceNumber position; - const std::string tag; // from AMQP 0-10 Message.subscribe command - - private: - friend class QueueListeners; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/ConsumerFactory.h b/qpid/cpp/src/qpid/broker/ConsumerFactory.h deleted file mode 100644 index 1c0f2571e2..0000000000 --- a/qpid/cpp/src/qpid/broker/ConsumerFactory.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef QPID_BROKER_CONSUMERFACTORY_H -#define QPID_BROKER_CONSUMERFACTORY_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. - * - */ - -// TODO aconway 2011-11-25: it's ugly exposing SemanticState::ConsumerImpl in public. -// Refactor to use a more abstract interface. - -#include - -namespace qpid { -namespace broker { - -class SemanticState; -class SemanticStateConsumerImpl; - -/** - * Base class for consumer factoires. Plugins can register a - * ConsumerFactory via Broker:: getConsumerFactories() Each time a - * conumer is created, each factory is tried in turn till one returns - * non-0. - */ -class ConsumerFactory -{ - public: - virtual ~ConsumerFactory() {} - - virtual boost::shared_ptr create( - SemanticState* parent, - const std::string& name, boost::shared_ptr queue, - bool ack, bool acquire, bool exclusive, const std::string& tag, - const std::string& resumeId, uint64_t resumeTtl, const framing::FieldTable& arguments) = 0; -}; - -/** A set of factories held by the broker - * THREAD UNSAFE: see notes on member functions. - */ -class ConsumerFactories { - public: - typedef std::vector > Factories; - - /** Thread safety: May only be called during plug-in initialization. */ - void add(const boost::shared_ptr& cf) { factories.push_back(cf); } - - /** Thread safety: May only be called after plug-in initialization. */ - const Factories& get() const { return factories; } - - private: - Factories factories; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_CONSUMERFACTORY_H*/ diff --git a/qpid/cpp/src/qpid/broker/Credit.cpp b/qpid/cpp/src/qpid/broker/Credit.cpp deleted file mode 100644 index c0e0b3b3d3..0000000000 --- a/qpid/cpp/src/qpid/broker/Credit.cpp +++ /dev/null @@ -1,151 +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/broker/Credit.h" - -namespace qpid { -namespace broker { - -const uint32_t CreditBalance::INFINITE_CREDIT(0xFFFFFFFF); -CreditBalance::CreditBalance() : balance(0) {} -CreditBalance::~CreditBalance() {} -void CreditBalance::clear() { balance = 0; } -void CreditBalance::grant(uint32_t value) -{ - if (balance != INFINITE_CREDIT) { - if (value == INFINITE_CREDIT) { - balance = INFINITE_CREDIT; - } else if (INFINITE_CREDIT - balance > value) { - balance += value; - } else { - balance = INFINITE_CREDIT - 1; - } - } -} -void CreditBalance::consume(uint32_t value) { if (!unlimited()) balance -= value; } -bool CreditBalance::check(uint32_t required) const { return balance >= required; } -uint32_t CreditBalance::remaining() const { return balance; } -uint32_t CreditBalance::allocated() const { return balance; } -bool CreditBalance::unlimited() const { return balance == INFINITE_CREDIT; } - -CreditWindow::CreditWindow() : used(0) {} -bool CreditWindow::check(uint32_t required) const { return CreditBalance::check(used + required); } -void CreditWindow::consume(uint32_t value) { if (!unlimited()) used += value; } -void CreditWindow::move(uint32_t value) { if (!unlimited()) used -= value; } -uint32_t CreditWindow::remaining() const { return allocated() - used; } -uint32_t CreditWindow::consumed() const { return used; } - -Credit::Credit() : windowing(true) {} -void Credit::setWindowMode(bool b) { windowing = b; } -bool Credit::isWindowMode() const { return windowing; } -void Credit::addByteCredit(uint32_t value) -{ - bytes().grant(value); -} -void Credit::addMessageCredit(uint32_t value) -{ - messages().grant(value); -} -void Credit::cancel() -{ - messages().clear(); - bytes().clear(); -} -void Credit::moveWindow(uint32_t m, uint32_t b) -{ - if (windowing) { - window.messages.move(m); - window.bytes.move(b); - } -} -void Credit::consume(uint32_t m, uint32_t b) -{ - messages().consume(m); - bytes().consume(b); -} -bool Credit::check(uint32_t m, uint32_t b) const -{ - return messages().check(m) && bytes().check(b); -} -CreditPair Credit::used() const -{ - CreditPair result; - if (windowing) { - result.messages = window.messages.consumed(); - result.bytes = window.bytes.consumed(); - } else { - result.messages = 0; - result.bytes = 0; - } - return result; -} -CreditPair Credit::allocated() const -{ - CreditPair result; - result.messages = messages().allocated(); - result.bytes = bytes().allocated(); - return result; -} -Credit::operator bool() const -{ - return check(1,1); -} -CreditBalance& Credit::messages() -{ - if (windowing) return window.messages; - else return balance.messages; -} -CreditBalance& Credit::bytes() -{ - if (windowing) return window.bytes; - else return balance.bytes; -} -const CreditBalance& Credit::messages() const -{ - if (windowing) return window.messages; - else return balance.messages; -} -const CreditBalance& Credit::bytes() const -{ - if (windowing) return window.bytes; - else return balance.bytes; -} -std::ostream& operator<<(std::ostream& out, const CreditBalance& b) -{ - if (b.unlimited()) return out << "unlimited"; - else return out << b.balance; -} -std::ostream& operator<<(std::ostream& out, const CreditWindow& w) -{ - if (w.unlimited()) return out << ((CreditBalance) w); - else return out << w.remaining() << " (from window of " << w.allocated() << ")"; -} -template -std::ostream& operator<<(std::ostream& out, const CreditPair& pair) -{ - return out << "messages: " << pair.messages << " bytes: " << pair.bytes; -} -std::ostream& operator<<(std::ostream& out, const Credit& c) -{ - if (c.windowing) return out << c.window; - else return out << c.balance; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/Credit.h b/qpid/cpp/src/qpid/broker/Credit.h deleted file mode 100644 index 7f98c8d071..0000000000 --- a/qpid/cpp/src/qpid/broker/Credit.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef QPID_BROKER_CREDIT_H -#define QPID_BROKER_CREDIT_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 -#include - -namespace qpid { -namespace broker { - -class CreditBalance { - public: - CreditBalance(); - virtual ~CreditBalance(); - void clear(); - void grant(uint32_t value); - virtual void consume(uint32_t value); - virtual bool check(uint32_t required) const; - virtual uint32_t remaining() const; - uint32_t allocated() const; - bool unlimited() const; - static const uint32_t INFINITE_CREDIT; - friend std::ostream& operator<<(std::ostream&, const CreditBalance&); - private: - uint32_t balance; -}; - -class CreditWindow : public CreditBalance { - public: - CreditWindow(); - bool check(uint32_t required) const; - void consume(uint32_t value); - void move(uint32_t value); - uint32_t remaining() const; - uint32_t consumed() const; - friend std::ostream& operator<<(std::ostream&, const CreditWindow&); - private: - uint32_t used; -}; - -template struct CreditPair -{ - T messages; - T bytes; -}; - -class Credit { - public: - Credit(); - void setWindowMode(bool); - bool isWindowMode() const; - void addByteCredit(uint32_t); - void addMessageCredit(uint32_t); - void consume(uint32_t messages, uint32_t bytes); - void moveWindow(uint32_t messages, uint32_t bytes); - bool check(uint32_t messages, uint32_t bytes) const; - void cancel(); - operator bool() const; - CreditPair allocated() const; - CreditPair used() const; - friend std::ostream& operator<<(std::ostream&, const Credit&); - private: - CreditPair balance; - CreditPair window; - bool windowing; - CreditBalance& bytes(); - CreditBalance& messages(); - const CreditBalance& bytes() const; - const CreditBalance& messages() const; -}; - -std::ostream& operator<<(std::ostream&, const Credit&); - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_CREDIT_H*/ diff --git a/qpid/cpp/src/qpid/broker/Daemon.cpp b/qpid/cpp/src/qpid/broker/Daemon.cpp deleted file mode 100644 index 9f7a5b3f2d..0000000000 --- a/qpid/cpp/src/qpid/broker/Daemon.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * - * 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. - * - */ - -/* - * TODO: Note this is really a Posix specific implementation and so should be - * refactored together with windows/QpiddBroker into a more coherent daemon driver/ - * platform specific split - */ -#include "qpid/broker/Daemon.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" -#include "qpid/sys/posix/PidFile.h" - -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -using namespace std; -using qpid::sys::PidFile; - -Daemon::Daemon(std::string _pidDir) : pidDir(_pidDir) { - struct stat s; - pid = -1; - pipeFds[0] = pipeFds[1] = -1; - - if (::stat(pidDir.c_str(), &s)) { - if (errno == ENOENT) { - if (::mkdir(pidDir.c_str(), 0755)) - throw Exception ("Can't create PID directory: " + pidDir); - } - else - throw Exception ("PID directory not found: " + pidDir); - } -} - -string Daemon::pidFile(string pidDir, uint16_t port) { - ostringstream path; - path << pidDir << "/qpidd." << port << ".pid"; - return path.str(); -} - -/* - * Rewritten using low-level IO, for compatibility - * with earlier Boost versions, i.e. 103200. - */ -void Daemon::fork() -{ - if(::pipe(pipeFds) < 0) throw ErrnoException("Can't create pipe"); - if ((pid = ::fork()) < 0) throw ErrnoException("Daemon fork failed"); - if (pid == 0) { // Child - try { - QPID_LOG(debug, "Forked daemon child process"); - - // File descriptors - if(::close(pipeFds[0])<0) throw ErrnoException("Cannot close read pipe"); - if(::close(0)<0) throw ErrnoException("Cannot close stdin"); - if(::close(1)<0) throw ErrnoException("Cannot close stdout"); - if(::close(2)<0) throw ErrnoException("Cannot close stderr"); - int fd=::open("/dev/null",O_RDWR); // stdin - if(fd != 0) throw ErrnoException("Cannot re-open stdin"); - if(::dup(fd)<0) throw ErrnoException("Cannot re-open stdout"); - if(::dup(fd)<0) throw ErrnoException("Cannot re-open stderror"); - - // Misc - if(setsid()<0) throw ErrnoException("Cannot set session ID"); - if(chdir(pidDir.c_str()) < 0) throw ErrnoException("Cannot change directory to "+pidDir); - umask(027); - - // Child behavior - child(); - } - catch (const exception& e) { - uint16_t port = 0; - if (write(pipeFds[1], &port, sizeof(uint16_t))) {}; - - std::string pipeFailureMessage = e.what(); - if (write(pipeFds[1], - pipeFailureMessage.c_str(), - strlen(pipeFailureMessage.c_str()) - )) {}; - } - } - else { // Parent - close(pipeFds[1]); // Write side. - parent(); - } -} - -Daemon::~Daemon() { - if (!lockFile.empty()) - unlink(lockFile.c_str()); -} - -uint16_t Daemon::wait(int timeout) { // parent waits for child. - try { - errno = 0; - struct timeval tv; - tv.tv_sec = timeout; - tv.tv_usec = 0; - - /* - * Rewritten using low-level IO, for compatibility - * with earlier Boost versions, i.e. 103200. - */ - fd_set fds; - FD_ZERO(&fds); - FD_SET(pipeFds[0], &fds); - int n=select(FD_SETSIZE, &fds, 0, 0, &tv); - if(n==0) throw Exception("Timed out waiting for daemon (If store recovery is in progress, use longer wait time)"); - if(n<0) throw ErrnoException("Error waiting for daemon"); - uint16_t port = 0; - /* - * Read the child's port number from the pipe. - */ - int desired_read = sizeof(uint16_t); - if ( desired_read > ::read(pipeFds[0], & port, desired_read) ) - throw Exception("Cannot read from child process."); - - /* - * If the port number is 0, the child has put an error message - * on the pipe. Get it and throw it. - */ - if ( 0 == port ) { - // Skip whitespace - char c = ' '; - while ( isspace(c) ) { - if ( 1 > ::read(pipeFds[0], &c, 1) ) - throw Exception("Child port == 0, and no error message on pipe."); - } - - // Get Message - string errmsg; - do { - errmsg += c; - } while (::read(pipeFds[0], &c, 1)); - throw Exception("Daemon startup failed"+ - (errmsg.empty() ? string(".") : ": " + errmsg)); - } - return port; - } - catch (const std::exception& e) { - // Print directly to cerr. The caller will catch and log the - // exception, but in the case of a daemon parent process we - // also need to be sure the error goes to stderr. A - // dameon's logging configuration normally does not log to - // stderr. - std::cerr << e.what() << endl; - throw; - } -} - - -/* - * When the child is ready, it writes its pid to the - * lockfile and its port number on the pipe back to - * its parent process. This indicates that the - * child has successfully daemonized. When the parent - * hears the good news, it ill exit. - */ -void Daemon::ready(uint16_t port) { // child - lockFile = pidFile(pidDir, port); - PidFile lf(lockFile, true); - - /* - * Write the PID to the lockfile. - */ - lf.writePid(); - - /* - * Write the port number to the parent. - */ - int desired_write = sizeof(uint16_t); - if ( desired_write > ::write(pipeFds[1], & port, desired_write) ) { - throw ErrnoException("Error writing to parent" ); - } - - QPID_LOG(debug, "Daemon ready on port: " << port); -} - -/* - * The parent process reads the child's pid - * from the lockfile. - */ -pid_t Daemon::getPid(string _pidDir, uint16_t port) { - string name = pidFile(_pidDir, port); - PidFile lf(name, false); - pid_t pid = lf.readPid(); - if (kill(pid, 0) < 0 && errno != EPERM) { - unlink(name.c_str()); - throw Exception("Removing stale lock file "+name); - } - return pid; -} - - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/Daemon.h b/qpid/cpp/src/qpid/broker/Daemon.h deleted file mode 100644 index 2bb9fc5577..0000000000 --- a/qpid/cpp/src/qpid/broker/Daemon.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef _broker_Daemon_h -#define _broker_Daemon_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 -#include -#include -#include - - -namespace qpid { -namespace broker { - -/** - * Tools for forking and managing a daemon process. - * NB: Only one Daemon instance is allowed in a process. - */ -class Daemon : private boost::noncopyable -{ - public: - /** Check daemon is running on port, throw exception if not */ - static pid_t getPid(std::string pidDir, uint16_t port); - - Daemon(std::string pidDir); - - virtual ~Daemon(); - - /** - * Fork a daemon process. - * Call parent() in the parent process, child() in the child. - */ - void fork(); - - protected: - - /** Called in parent process */ - virtual void parent() = 0; - - /** Called in child process */ - virtual void child() = 0; - - /** Call from parent(): wait for child to indicate it is ready. - * @timeout in seconds to wait for response. - * @return port passed by child to ready(). - */ - uint16_t wait(int timeout); - - /** Call from child(): Notify the parent we are ready and write the - * PID file. - *@param port returned by parent call to wait(). - */ - void ready(uint16_t port); - - private: - static std::string pidFile(std::string pidDir, uint16_t port); - - pid_t pid; - int pipeFds[2]; - std::string lockFile; - std::string pidDir; -}; - -}} // namespace qpid::broker - -#endif /*!_broker_Daemon_h*/ diff --git a/qpid/cpp/src/qpid/broker/Deliverable.h b/qpid/cpp/src/qpid/broker/Deliverable.h deleted file mode 100644 index 4dc67fdcfc..0000000000 --- a/qpid/cpp/src/qpid/broker/Deliverable.h +++ /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. - * - */ -#ifndef _Deliverable_ -#define _Deliverable_ - -#include "qpid/broker/AsyncCompletion.h" -#include "qpid/sys/IntegerTypes.h" -#include - -namespace qpid { - namespace broker { - class Message; - class Queue; - - class Deliverable : public AsyncCompletion { - public: - bool delivered; - Deliverable() : delivered(false) {} - - virtual Message& getMessage() = 0; - - virtual void deliverTo(const boost::shared_ptr& queue) = 0; - virtual ~Deliverable(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/DeliverableMessage.cpp b/qpid/cpp/src/qpid/broker/DeliverableMessage.cpp deleted file mode 100644 index 31823709ce..0000000000 --- a/qpid/cpp/src/qpid/broker/DeliverableMessage.cpp +++ /dev/null @@ -1,38 +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/broker/DeliverableMessage.h" -#include "qpid/broker/Queue.h" - -using namespace qpid::broker; - -DeliverableMessage::DeliverableMessage(const Message& _msg, TxBuffer* _txn) : msg(_msg), txn(_txn) {} - -void DeliverableMessage::deliverTo(const boost::shared_ptr& queue) -{ - queue->deliver(msg, txn); - delivered = true; -} - -Message& DeliverableMessage::getMessage() -{ - return msg; -} diff --git a/qpid/cpp/src/qpid/broker/DeliverableMessage.h b/qpid/cpp/src/qpid/broker/DeliverableMessage.h deleted file mode 100644 index 6e8275770d..0000000000 --- a/qpid/cpp/src/qpid/broker/DeliverableMessage.h +++ /dev/null @@ -1,45 +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. - * - */ -#ifndef _DeliverableMessage_ -#define _DeliverableMessage_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" - -namespace qpid { - namespace broker { - class TxBuffer; - class QPID_BROKER_CLASS_EXTERN DeliverableMessage : public Deliverable - { - Message msg; - TxBuffer* txn; - public: - QPID_BROKER_EXTERN DeliverableMessage(const Message& msg, TxBuffer* txn); - QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr& queue); - QPID_BROKER_EXTERN Message& getMessage(); - virtual ~DeliverableMessage(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/DeliveryId.h b/qpid/cpp/src/qpid/broker/DeliveryId.h deleted file mode 100644 index 05b19f032e..0000000000 --- a/qpid/cpp/src/qpid/broker/DeliveryId.h +++ /dev/null @@ -1,35 +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. - * - */ -#ifndef _DeliveryId_ -#define _DeliveryId_ - -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceNumberSet.h" - -namespace qpid { -namespace broker { - - typedef framing::SequenceNumber DeliveryId; - typedef framing::SequenceNumberSet DeliveryIds; -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/DeliveryRecord.cpp b/qpid/cpp/src/qpid/broker/DeliveryRecord.cpp deleted file mode 100644 index 06ecf62ed4..0000000000 --- a/qpid/cpp/src/qpid/broker/DeliveryRecord.cpp +++ /dev/null @@ -1,168 +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/broker/DeliveryRecord.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/broker/Consumer.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/MessageTransferBody.h" - -using namespace qpid; -using namespace qpid::broker; -using std::string; - -DeliveryRecord::DeliveryRecord(const QueueCursor& _msg, - framing::SequenceNumber _msgId, - framing::SequenceNumber _replicationId, - const Queue::shared_ptr& _queue, - const std::string& _tag, - const boost::shared_ptr& _consumer, - bool _acquired, - bool accepted, - bool _windowing, - uint32_t _credit) : msg(_msg), - queue(_queue), - tag(_tag), - consumer(_consumer), - acquired(_acquired), - acceptExpected(!accepted), - cancelled(false), - completed(false), - ended(accepted && acquired), - windowing(_windowing), - credit(_credit), - msgId(_msgId), - replicationId(_replicationId) -{} - -bool DeliveryRecord::setEnded() -{ - ended = true; - QPID_LOG(debug, "DeliveryRecord::setEnded() id=" << id); - return isRedundant(); -} - -void DeliveryRecord::requeue() -{ - if (acquired && !ended) { - queue->release(msg); - } -} - -void DeliveryRecord::release(bool setRedelivered) -{ - if (acquired && !ended) { - queue->release(msg, setRedelivered); - acquired = false; - setEnded(); - } else { - QPID_LOG(debug, "Ignoring release for " << id << " acquired=" << acquired << ", ended =" << ended); - } -} - -void DeliveryRecord::complete() -{ - completed = true; -} - -bool DeliveryRecord::accept(TransactionContext* ctxt) { - if (!ended) { - if (consumer) consumer->acknowledged(*this); - if (acquired) queue->dequeue(ctxt, msg); - setEnded(); - QPID_LOG(debug, "Accepted " << id); - } - return isRedundant(); -} - -void DeliveryRecord::dequeue(TransactionContext* ctxt) const -{ - if (acquired && !ended) { - queue->dequeue(ctxt, msg); - } -} - -void DeliveryRecord::committed() const -{ - if (acquired && !ended) { - queue->dequeueCommitted(msg); - } -} - -void DeliveryRecord::reject() -{ - if (acquired && !ended) { - queue->reject(msg); - setEnded(); - } -} - -uint32_t DeliveryRecord::getCredit() const -{ - return credit; -} - -void DeliveryRecord::acquire(DeliveryIds& results) { - if (queue->acquire(msg, tag)) { - acquired = true; - results.push_back(id); - if (!acceptExpected) { - if (ended) { QPID_LOG(error, "Can't dequeue ended message"); } - else { queue->dequeue(0, msg); setEnded(); } - } - } else { - QPID_LOG(info, "Message already acquired " << id.getValue()); - } -} - -void DeliveryRecord::cancel(const std::string& cancelledTag) -{ - if (tag == cancelledTag) - cancelled = true; -} - -AckRange DeliveryRecord::findRange(DeliveryRecords& records, DeliveryId first, DeliveryId last) -{ - DeliveryRecords::iterator start = lower_bound(records.begin(), records.end(), first); - // Find end - position it just after the last record in range - DeliveryRecords::iterator end = lower_bound(records.begin(), records.end(), last); - if (end != records.end() && end->getId() == last) ++end; - return AckRange(start, end); -} - - -namespace qpid { -namespace broker { - -std::ostream& operator<<(std::ostream& out, const DeliveryRecord& r) -{ - out << "{" << "id=" << r.id.getValue(); - out << ", tag=" << r.tag << "}"; - out << ", queue=" << r.queue->getName() << "}"; - return out; -} - - -}} diff --git a/qpid/cpp/src/qpid/broker/DeliveryRecord.h b/qpid/cpp/src/qpid/broker/DeliveryRecord.h deleted file mode 100644 index 37ce8dc709..0000000000 --- a/qpid/cpp/src/qpid/broker/DeliveryRecord.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef QPID_BROKER_DELIVERYRECORD_H -#define QPID_BROKER_DELIVERYRECORD_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 -#include -#include -#include -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueueCursor.h" -#include "qpid/broker/DeliveryId.h" -#include "qpid/broker/Message.h" - -namespace qpid { -namespace broker { - -class Queue; -class TransactionContext; -class SemanticState; -struct AckRange; -class Consumer; - -/** - * Record of a delivery for which an ack is outstanding. - */ -class DeliveryRecord -{ - QueueCursor msg; - mutable boost::shared_ptr queue; - std::string tag; // name of consumer - boost::shared_ptr consumer; - DeliveryId id; - bool acquired : 1; - bool acceptExpected : 1; - bool cancelled : 1; - bool completed : 1; - bool ended : 1; - bool windowing : 1; - - /** - * Record required credit on construction as the pointer to the - * message may be reset once we no longer need to deliver it - * (e.g. when it is accepted), but we will still need to be able - * to reallocate credit when it is completed (which could happen - * after that). - */ - uint32_t credit; - framing::SequenceNumber msgId; - framing::SequenceNumber replicationId; - - public: - QPID_BROKER_EXTERN DeliveryRecord(const QueueCursor& msgCursor, - framing::SequenceNumber msgId, - framing::SequenceNumber replicationId, - const boost::shared_ptr& queue, - const std::string& tag, - const boost::shared_ptr& consumer, - bool acquired, - bool accepted, - bool windowing, - uint32_t credit=0 // Only used if msg is empty. - ); - - bool coveredBy(const framing::SequenceSet* const range) const { return range->contains(id); } - - void dequeue(TransactionContext* ctxt = 0) const; - void requeue(); - void release(bool setRedelivered); - void reject(); - void cancel(const std::string& tag); - void acquire(DeliveryIds& results); - void complete(); - bool accept(TransactionContext* ctxt); // Returns isRedundant() - bool setEnded(); // Returns isRedundant() - void committed() const; - - bool isAcquired() const { return acquired; } - bool isComplete() const { return completed; } - bool isRedundant() const { return ended && (!windowing || completed || cancelled); } - bool isCancelled() const { return cancelled; } - bool isAccepted() const { return !acceptExpected; } - bool isEnded() const { return ended; } - bool isWindowing() const { return windowing; } - - uint32_t getCredit() const; - const std::string& getTag() const { return tag; } - - void setId(DeliveryId _id) { id = _id; } - - typedef std::deque DeliveryRecords; - static AckRange findRange(DeliveryRecords& records, DeliveryId first, DeliveryId last); - const QueueCursor& getMessage() const { return msg; } - framing::SequenceNumber getId() const { return id; } - framing::SequenceNumber getMessageId() const { return msgId; } - framing::SequenceNumber getReplicationId() const { return replicationId; } - boost::shared_ptr getQueue() const { return queue; } - - friend std::ostream& operator<<(std::ostream&, const DeliveryRecord&); -}; - -inline bool operator<(const DeliveryRecord& a, const DeliveryRecord& b) { return a.getId() < b.getId(); } -inline bool operator<(const framing::SequenceNumber& a, const DeliveryRecord& b) { return a < b.getId(); } -inline bool operator<(const DeliveryRecord& a, const framing::SequenceNumber& b) { return a.getId() < b; } - -struct AcquireFunctor -{ - DeliveryIds& results; - - AcquireFunctor(DeliveryIds& _results) : results(_results) {} - - void operator()(DeliveryRecord& record) - { - record.acquire(results); - } -}; - -typedef DeliveryRecord::DeliveryRecords DeliveryRecords; - -struct AckRange -{ - DeliveryRecords::iterator start; - DeliveryRecords::iterator end; - AckRange(DeliveryRecords::iterator _start, DeliveryRecords::iterator _end) : start(_start), end(_end) {} -}; - -} -} - - -#endif /*!QPID_BROKER_DELIVERYRECORD_H*/ diff --git a/qpid/cpp/src/qpid/broker/DirectExchange.cpp b/qpid/cpp/src/qpid/broker/DirectExchange.cpp deleted file mode 100644 index be66bc2e5f..0000000000 --- a/qpid/cpp/src/qpid/broker/DirectExchange.cpp +++ /dev/null @@ -1,214 +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/log/Statement.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/DirectExchange.h" -#include - -using namespace qpid::broker; - -using std::string; - -using namespace qpid::framing; -using namespace qpid::sys; -using qpid::management::Manageable; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ - const std::string qpidExclusiveBinding("qpid.exclusive-binding"); -} - -DirectExchange::DirectExchange(const string& _name, Manageable* _parent, Broker* b) : Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -DirectExchange::DirectExchange(const string& _name, bool _durable, bool autodelete, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, autodelete, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -bool DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - string fedOp(fedOpBind); - string fedTags; - string fedOrigin; - bool exclusiveBinding = false; - if (args) { - fedOp = args->getAsString(qpidFedOp); - fedTags = args->getAsString(qpidFedTags); - fedOrigin = args->getAsString(qpidFedOrigin); - exclusiveBinding = !!args->get(qpidExclusiveBinding); // only direct exchanges take exclusive bindings - } - - bool propagate = false; - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - Mutex::ScopedLock l(lock); - Binding::shared_ptr b(new Binding(routingKey, queue, this, args ? *args : FieldTable(), fedOrigin)); - BoundKey& bk = bindings[routingKey]; - if (exclusiveBinding) bk.queues.clear(); - - QPID_LOG(debug, "Bind key [" << routingKey << "] to queue " << queue->getName() - << " (origin=" << fedOrigin << ")"); - - if (bk.queues.add_unless(b, MatchQueue(queue))) { - b->startManagement(); - propagate = bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - // queue already present - still need to track fedOrigin - bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } else if (fedOp == fedOpUnbind) { - Mutex::ScopedLock l(lock); - BoundKey& bk = bindings[routingKey]; - - QPID_LOG(debug, "Bind - fedOpUnbind key [" << routingKey << "] queue " << queue->getName() - << " (origin=" << fedOrigin << ")" << " (count=" << bk.fedBinding.count() << ")"); - - propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin); - if (bk.fedBinding.countFedBindings(queue->getName()) == 0) - unbind(queue, routingKey, args); - - } else if (fedOp == fedOpReorigin) { - /** gather up all the keys that need rebinding in a local vector - * while holding the lock. Then propagate once the lock is - * released - */ - std::vector keys2prop; - { - Mutex::ScopedLock l(lock); - for (Bindings::iterator iter = bindings.begin(); - iter != bindings.end(); iter++) { - const BoundKey& bk = iter->second; - if (bk.fedBinding.hasLocal()) { - keys2prop.push_back(iter->first); - } - } - } /* lock dropped */ - for (std::vector::const_iterator key = keys2prop.begin(); - key != keys2prop.end(); key++) { - propagateFedOp( *key, string(), fedOpBind, string()); - } - } - - routeIVE(); - if (propagate) - propagateFedOp(routingKey, fedTags, fedOp, fedOrigin); - return true; -} - -bool DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - bool empty = false; - - QPID_LOG(debug, "Unbinding key [" << routingKey << "] from queue " << queue->getName() - << " on exchange " << getName() << " origin=" << fedOrigin << ")" ); - { - Mutex::ScopedLock l(lock); - BoundKey& bk = bindings[routingKey]; - if (bk.queues.remove_if(MatchQueue(queue))) { - propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - if (bk.queues.empty()) { - bindings.erase(routingKey); - if (bindings.empty()) empty = true; - } - } else { - return false; - } - } - - // If I delete my local binding, propagate this unbind to any upstream brokers - if (propagate) - propagateFedOp(routingKey, string(), fedOpUnbind, string()); - if (empty) checkAutodelete(); - return true; -} - -void DirectExchange::route(Deliverable& msg) -{ - const string& routingKey = msg.getMessage().getRoutingKey(); - PreRoute pr(msg, this); - ConstBindingList b; - { - Mutex::ScopedLock l(lock); - Bindings::iterator i = bindings.find(routingKey); - if (i != bindings.end()) b = i->second.queues.snapshot(); - } - doRoute(msg, b); -} - - -bool DirectExchange::isBound(Queue::shared_ptr queue, const string* const routingKey, const FieldTable* const) -{ - Mutex::ScopedLock l(lock); - if (routingKey) { - Bindings::iterator i = bindings.find(*routingKey); - - if (i == bindings.end()) - return false; - if (!queue) - return true; - - Queues::ConstPtr p = i->second.queues.snapshot(); - return p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end(); - } else if (!queue) { - //if no queue or routing key is specified, just report whether any bindings exist - return bindings.size() > 0; - } else { - for (Bindings::iterator i = bindings.begin(); i != bindings.end(); i++) { - Queues::ConstPtr p = i->second.queues.snapshot(); - if (p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end()) return true; - } - return false; - } - - return false; -} - -DirectExchange::~DirectExchange() { - if (mgmtExchange != 0) - mgmtExchange->debugStats("destroying"); -} - -const std::string DirectExchange::typeName("direct"); - -bool DirectExchange::hasBindings() -{ - Mutex::ScopedLock l(lock); - return !bindings.empty(); -} diff --git a/qpid/cpp/src/qpid/broker/DirectExchange.h b/qpid/cpp/src/qpid/broker/DirectExchange.h deleted file mode 100644 index cbf9aa5975..0000000000 --- a/qpid/cpp/src/qpid/broker/DirectExchange.h +++ /dev/null @@ -1,74 +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. - * - */ -#ifndef _DirectExchange_ -#define _DirectExchange_ - -#include -#include -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace broker { -class DirectExchange : public virtual Exchange { - typedef qpid::sys::CopyOnWriteArray Queues; - struct BoundKey { - Queues queues; - FedBinding fedBinding; - }; - typedef std::map Bindings; - Bindings bindings; - qpid::sys::Mutex lock; - -public: - QPID_BROKER_EXTERN static const std::string typeName; - - QPID_BROKER_EXTERN DirectExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN DirectExchange(const std::string& _name, - bool _durable, bool autodelete, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(boost::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - virtual bool unbind(boost::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - QPID_BROKER_EXTERN virtual void route(Deliverable& msg); - QPID_BROKER_EXTERN virtual bool isBound(boost::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~DirectExchange(); - - virtual bool supportsDynamicBinding() { return true; } - protected: - bool hasBindings(); -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/DtxAck.cpp b/qpid/cpp/src/qpid/broker/DtxAck.cpp deleted file mode 100644 index c558681d62..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxAck.cpp +++ /dev/null @@ -1,77 +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/broker/DtxAck.h" -#include "qpid/log/Statement.h" - -using std::bind1st; -using std::bind2nd; -using std::mem_fun_ref; -using namespace qpid::broker; - -DtxAck::DtxAck(const qpid::framing::SequenceSet& acked, DeliveryRecords& unacked) -{ - remove_copy_if(unacked.begin(), unacked.end(), inserter(pending, pending.end()), - not1(bind2nd(mem_fun_ref(&DeliveryRecord::coveredBy), &acked))); -} - -DtxAck::DtxAck(DeliveryRecords& unacked) { - pending = unacked; -} - -bool DtxAck::prepare(TransactionContext* ctxt) throw() -{ - try{ - //record dequeue in the store - for (DeliveryRecords::iterator i = pending.begin(); i != pending.end(); i++) { - i->dequeue(ctxt); - } - return true; - }catch(...){ - QPID_LOG(error, "Failed to prepare"); - return false; - } -} - -void DtxAck::commit() throw() -{ - try { - for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::committed)); - pending.clear(); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } - -} - -void DtxAck::rollback() throw() -{ - try { - for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::requeue)); - pending.clear(); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to complete rollback: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to complete rollback (unknown error)"); - } - -} diff --git a/qpid/cpp/src/qpid/broker/DtxAck.h b/qpid/cpp/src/qpid/broker/DtxAck.h deleted file mode 100644 index 5775edf5de..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxAck.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef QPID_BROKER_DTXACK_H -#define QPID_BROKER_DTXACK_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 -#include -#include -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/TxOp.h" - -namespace qpid { -namespace broker { -class DtxAck : public TxOp{ - DeliveryRecords pending; - - public: - DtxAck(const framing::SequenceSet& acked, DeliveryRecords& unacked); - DtxAck(DeliveryRecords& unacked); - 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&) {} - - virtual ~DtxAck(){} - const DeliveryRecords& getPending() const { return pending; } -}; - -}} // qpid::broker - -#endif /*!QPID_BROKER_DTXACK_H*/ diff --git a/qpid/cpp/src/qpid/broker/DtxBuffer.cpp b/qpid/cpp/src/qpid/broker/DtxBuffer.cpp deleted file mode 100644 index 13177d3b72..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxBuffer.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/broker/DtxBuffer.h" - -using namespace qpid::broker; -using qpid::sys::Mutex; - -DtxBuffer::DtxBuffer( - const std::string& _xid, - bool ended_, bool suspended_, bool failed_, bool expired_) - : xid(_xid), ended(ended_), suspended(suspended_), failed(failed_), expired(expired_) -{} - -DtxBuffer::~DtxBuffer() {} - -void DtxBuffer::markEnded() -{ - Mutex::ScopedLock locker(lock); - ended = true; -} - -bool DtxBuffer::isEnded() const -{ - Mutex::ScopedLock locker(lock); - return ended; -} - -void DtxBuffer::setSuspended(bool isSuspended) -{ - suspended = isSuspended; -} - -bool DtxBuffer::isSuspended() const -{ - return suspended; -} - -void DtxBuffer::fail() -{ - Mutex::ScopedLock locker(lock); - rollback(); - failed = true; - ended = true; -} - -bool DtxBuffer::isRollbackOnly() const -{ - Mutex::ScopedLock locker(lock); - return failed; -} - -std::string DtxBuffer::getXid() const -{ - return xid; -} - -void DtxBuffer::timedout() -{ - Mutex::ScopedLock locker(lock); - expired = true; - fail(); -} - -bool DtxBuffer::isExpired() const -{ - Mutex::ScopedLock locker(lock); - return expired; -} - -bool DtxBuffer::isFailed() const -{ - return failed; -} diff --git a/qpid/cpp/src/qpid/broker/DtxBuffer.h b/qpid/cpp/src/qpid/broker/DtxBuffer.h deleted file mode 100644 index 21ca76c8f4..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxBuffer.h +++ /dev/null @@ -1,59 +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. - * - */ -#ifndef _DtxBuffer_ -#define _DtxBuffer_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/TxBuffer.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace broker { -class DtxBuffer : public TxBuffer { - - mutable sys::Mutex lock; - const std::string xid; - bool ended; - bool suspended; - bool failed; - bool expired; - - public: - QPID_BROKER_EXTERN DtxBuffer( - const std::string& xid = "", - bool ended=false, bool suspended=false, bool failed=false, bool expired=false); - QPID_BROKER_EXTERN ~DtxBuffer(); - QPID_BROKER_EXTERN void markEnded(); - bool isEnded() const; - void setSuspended(bool suspended); - bool isSuspended() const; - void fail(); - bool isRollbackOnly() const; - void timedout(); - bool isExpired() const; - bool isFailed() const; - std::string getXid() const; -}; -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/DtxManager.cpp b/qpid/cpp/src/qpid/broker/DtxManager.cpp deleted file mode 100644 index 61dfad24d4..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxManager.cpp +++ /dev/null @@ -1,220 +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/broker/DtxManager.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/StructHelper.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Timer.h" -#include "qpid/ptr_map.h" - -#include -#include -#include - -#include - -using boost::intrusive_ptr; -using qpid::sys::Mutex; -using qpid::ptr_map_ptr; -using namespace qpid::broker; -using namespace qpid::framing; - -#if DEFINE_UNUSED -namespace { - typedef boost::function0 FireFunction; - struct DtxCleanup : public qpid::sys::TimerTask - { - FireFunction fireFunction; - - DtxCleanup(uint32_t timeout, FireFunction f); - void fire(); - }; - - DtxCleanup::DtxCleanup(uint32_t _timeout, FireFunction f) - : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxCleanup"), fireFunction(f){} - - void DtxCleanup::fire() - { - try { - fireFunction(); - } catch (qpid::ConnectionException& /*e*/) { - //assume it was explicitly cleaned up after a call to prepare, commit or rollback - } - } - -} -#endif - -DtxManager::DtxManager(qpid::sys::Timer& t, uint32_t _dtxDefaultTimeout) : - store(0), - timer(&t), - dtxDefaultTimeout(_dtxDefaultTimeout) -{ -} - -DtxManager::~DtxManager() {} - -void DtxManager::start(const std::string& xid, boost::intrusive_ptr ops) -{ - createWork(xid)->add(ops); -} - -void DtxManager::join(const std::string& xid, boost::intrusive_ptr ops) -{ - getWork(xid)->add(ops); -} - -void DtxManager::recover(const std::string& xid, std::auto_ptr txn, boost::intrusive_ptr ops) -{ - createWork(xid)->recover(txn, ops); -} - -bool DtxManager::prepare(const std::string& xid) -{ - QPID_LOG(debug, "preparing: " << convert(xid)); - try { - return getWork(xid)->prepare(); - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -bool DtxManager::commit(const std::string& xid, bool onePhase) -{ - QPID_LOG(debug, "committing: " << convert(xid)); - try { - bool result = getWork(xid)->commit(onePhase); - remove(xid); - return result; - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -void DtxManager::rollback(const std::string& xid) -{ - QPID_LOG(debug, "rolling back: " << convert(xid)); - try { - getWork(xid)->rollback(); - remove(xid); - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -DtxWorkRecord* DtxManager::getWork(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - throw NotFoundException(QPID_MSG("Unrecognised xid " << convert(xid))); - } - return ptr_map_ptr(i); -} - -bool DtxManager::exists(const std::string& xid) { - Mutex::ScopedLock locker(lock); - return work.find(xid) != work.end(); -} - -void DtxManager::remove(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - throw NotFoundException(QPID_MSG("Unrecognised xid " << convert(xid))); - } else { - work.erase(i); - } -} - -DtxWorkRecord* DtxManager::createWork(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i != work.end()) { - throw NotAllowedException(QPID_MSG("Xid " << convert(xid) << " is already known (use 'join' to add work to an existing xid)")); - } else { - std::string ncxid = xid; // Work around const correctness problems with work.insert - DtxWorkRecord* dtxWorkRecord = new DtxWorkRecord(xid, store); - work.insert(ncxid, dtxWorkRecord); - if (dtxDefaultTimeout>0) - setTimeout(xid, dtxDefaultTimeout); - return dtxWorkRecord; - } -} - -void DtxManager::setTimeout(const std::string& xid, uint32_t secs) -{ - DtxWorkRecord* record = getWork(xid); - intrusive_ptr timeout = record->getTimeout(); - if (timeout.get()) { - if (timeout->timeout == secs) return;//no need to do anything further if timeout hasn't changed - timeout->cancel(); - } - timeout = intrusive_ptr(new DtxTimeout(secs, *this, xid)); - record->setTimeout(timeout); - timer->add(timeout); -} - -uint32_t DtxManager::getTimeout(const std::string& xid) -{ - intrusive_ptr timeout = getWork(xid)->getTimeout(); - return !timeout ? 0 : timeout->timeout; -} - -void DtxManager::timedout(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - QPID_LOG(warning, "Transaction timeout failed: no record for xid"); - } else { - ptr_map_ptr(i)->timedout(); - //TODO: do we want to have a timed task to cleanup, or can we rely on an explicit completion? - //timer->add(new DtxCleanup(60*30/*30 mins*/, boost::bind(&DtxManager::remove, this, xid))); - } -} - -void DtxManager::setStore (TransactionalStore* _store) -{ - store = _store; -} - -std::string DtxManager::convert(const qpid::framing::Xid& xid) -{ - qpid::framing::StructHelper helper; - std::string encoded; - helper.encode(xid, encoded); - return encoded; -} - -qpid::framing::Xid DtxManager::convert(const std::string& xid) -{ - qpid::framing::StructHelper helper; - qpid::framing::Xid decoded; - helper.decode(decoded, xid); - return decoded; -} diff --git a/qpid/cpp/src/qpid/broker/DtxManager.h b/qpid/cpp/src/qpid/broker/DtxManager.h deleted file mode 100644 index e64c97c7dd..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxManager.h +++ /dev/null @@ -1,75 +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. - * - */ -#ifndef _DtxManager_ -#define _DtxManager_ - -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/DtxWorkRecord.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Xid.h" -#include "qpid/sys/Mutex.h" -#include "qpid/ptr_map.h" - -namespace qpid { -namespace sys { -class Timer; -} - -namespace broker { - -class DtxManager{ - typedef boost::ptr_map WorkMap; - - WorkMap work; - TransactionalStore* store; - qpid::sys::Mutex lock; - qpid::sys::Timer* timer; - uint32_t dtxDefaultTimeout; - - void remove(const std::string& xid); - DtxWorkRecord* createWork(const std::string& xid); - -public: - DtxManager(sys::Timer&, uint32_t _dtxDefaultTimeout=0); - ~DtxManager(); - void start(const std::string& xid, boost::intrusive_ptr work); - void join(const std::string& xid, boost::intrusive_ptr work); - void recover(const std::string& xid, std::auto_ptr txn, boost::intrusive_ptr work); - bool prepare(const std::string& xid); - bool commit(const std::string& xid, bool onePhase); - void rollback(const std::string& xid); - void setTimeout(const std::string& xid, uint32_t secs); - uint32_t getTimeout(const std::string& xid); - void timedout(const std::string& xid); - void setStore(TransactionalStore* store); - void setTimer(sys::Timer& t) { timer = &t; } - - DtxWorkRecord* getWork(const std::string& xid); - bool exists(const std::string& xid); - static std::string convert(const framing::Xid& xid); - static framing::Xid convert(const std::string& xid); -}; - -} -} - -#endif diff --git a/qpid/cpp/src/qpid/broker/DtxTimeout.cpp b/qpid/cpp/src/qpid/broker/DtxTimeout.cpp deleted file mode 100644 index f317df5713..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxTimeout.cpp +++ /dev/null @@ -1,37 +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/broker/DtxTimeout.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/sys/Time.h" -#include "qpid/log/Statement.h" - -using namespace qpid::broker; - -DtxTimeout::DtxTimeout(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid) - : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxTimeout-"+_xid), timeout(_timeout), mgr(_mgr), xid(_xid) -{ -} - -void DtxTimeout::fire() -{ - QPID_LOG(debug, "DTX transaction timeouted, XID=" << xid << ", timeout=" << timeout); - mgr.timedout(xid); -} diff --git a/qpid/cpp/src/qpid/broker/DtxTimeout.h b/qpid/cpp/src/qpid/broker/DtxTimeout.h deleted file mode 100644 index 1fcb4cee2a..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxTimeout.h +++ /dev/null @@ -1,50 +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. - * - */ -#ifndef _DtxTimeout_ -#define _DtxTimeout_ - -#include "qpid/Exception.h" -#include "qpid/sys/Timer.h" - -namespace qpid { -namespace broker { - -class DtxManager; - -struct DtxTimeoutException : public Exception { - DtxTimeoutException(const std::string& msg=std::string()) : Exception(msg) {} -}; - -struct DtxTimeout : public sys::TimerTask -{ - const uint32_t timeout; - DtxManager& mgr; - const std::string xid; - - DtxTimeout(uint32_t timeout, DtxManager& mgr, const std::string& xid); - void fire(); -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/DtxWorkRecord.cpp b/qpid/cpp/src/qpid/broker/DtxWorkRecord.cpp deleted file mode 100644 index 04d19dc43e..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxWorkRecord.cpp +++ /dev/null @@ -1,187 +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/broker/DtxWorkRecord.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/Timer.h" - -#include -#include -using boost::mem_fn; -using qpid::sys::Mutex; - -using namespace qpid::broker; -using namespace qpid::framing; - -DtxWorkRecord::DtxWorkRecord(const std::string& _xid, TransactionalStore* const _store) : - xid(_xid), store(_store), completed(false), rolledback(false), prepared(false), expired(false) {} - -DtxWorkRecord::~DtxWorkRecord() -{ - if (timeout.get()) { - timeout->cancel(); - } -} - -void DtxWorkRecord::setTimeout(boost::intrusive_ptr t) -{ timeout = t; } - -boost::intrusive_ptr DtxWorkRecord::getTimeout() -{ return timeout; } - -bool DtxWorkRecord::prepare() -{ - Mutex::ScopedLock locker(lock); - if (check()) { - txn = store->begin(xid); - if (prepare(txn.get())) { - store->prepare(*txn); - prepared = true; - } else { - abort(); - //TODO: this should probably be flagged as internal error - } - } else { - //some part of the work has been marked rollback only - abort(); - } - return prepared; -} - -bool DtxWorkRecord::prepare(TransactionContext* _txn) -{ - bool succeeded(true); - for (Work::iterator i = work.begin(); succeeded && i != work.end(); i++) { - succeeded = (*i)->prepare(_txn); - } - return succeeded; -} - -bool DtxWorkRecord::commit(bool onePhase) -{ - Mutex::ScopedLock locker(lock); - if (check()) { - if (prepared) { - //already prepared i.e. 2pc - if (onePhase) { - throw IllegalStateException(QPID_MSG("Branch with xid " << DtxManager::convert(xid) << " has been prepared, one-phase option not valid!")); - } - - store->commit(*txn); - txn.reset(); - - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::commit)); - return true; - } else { - //1pc commit optimisation, don't need a 2pc transaction context: - if (!onePhase) { - throw IllegalStateException(QPID_MSG("Branch with xid " << DtxManager::convert(xid) << " has not been prepared, one-phase option required!")); - } - std::auto_ptr localtxn = store->begin(); - if (prepare(localtxn.get())) { - store->commit(*localtxn); - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::commit)); - return true; - } else { - store->abort(*localtxn); - abort(); - //TODO: this should probably be flagged as internal error - return false; - } - } - } else { - //some part of the work has been marked rollback only - abort(); - return false; - } -} - -void DtxWorkRecord::rollback() -{ - Mutex::ScopedLock locker(lock); - check(); - abort(); -} - -void DtxWorkRecord::add(boost::intrusive_ptr ops) -{ - Mutex::ScopedLock locker(lock); - if (expired) { - throw DtxTimeoutException(QPID_MSG("Branch with xid " << DtxManager::convert(xid) << " has timed out.")); - } - if (completed) { - throw CommandInvalidException(QPID_MSG("Branch with xid " << DtxManager::convert(xid) << " has been completed!")); - } - work.push_back(ops); -} - -bool DtxWorkRecord::check() -{ - if (expired) { - throw DtxTimeoutException(); - } - if (!completed) { - //iterate through all DtxBuffers and ensure they are all ended - for (Work::iterator i = work.begin(); i != work.end(); i++) { - if (!(*i)->isEnded()) { - throw IllegalStateException(QPID_MSG("Branch with xid " << DtxManager::convert(xid) << " not completed!")); - } else if ((*i)->isRollbackOnly()) { - rolledback = true; - } - } - completed = true; - } - return !rolledback; -} - -void DtxWorkRecord::abort() -{ - if (txn.get()) { - store->abort(*txn); - txn.reset(); - } - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::rollback)); -} - -void DtxWorkRecord::recover(std::auto_ptr _txn, boost::intrusive_ptr ops) -{ - add(ops); - txn = _txn; - ops->markEnded(); - completed = true; - prepared = true; -} - -void DtxWorkRecord::timedout() -{ - Mutex::ScopedLock locker(lock); - expired = true; - rolledback = true; - if (!completed) { - for (Work::iterator i = work.begin(); i != work.end(); i++) { - if (!(*i)->isEnded()) { - (*i)->timedout(); - } - } - } - abort(); -} diff --git a/qpid/cpp/src/qpid/broker/DtxWorkRecord.h b/qpid/cpp/src/qpid/broker/DtxWorkRecord.h deleted file mode 100644 index 91fda797d1..0000000000 --- a/qpid/cpp/src/qpid/broker/DtxWorkRecord.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxWorkRecord_ -#define _DtxWorkRecord_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/TransactionalStore.h" - -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Mutex.h" - -#include -#include -#include - -#include - -namespace qpid { -namespace broker { - -struct DtxTimeout; - -/** - * Represents the work done under a particular distributed transaction - * across potentially multiple channels. Identified by a xid. Allows - * that work to be prepared, committed and rolled-back. - */ -class DtxWorkRecord -{ - typedef std::vector >Work; - - const std::string xid; - TransactionalStore* const store; - bool completed; - bool rolledback; - bool prepared; - bool expired; - boost::intrusive_ptr timeout; - Work work; - std::auto_ptr txn; - qpid::sys::Mutex lock; - - bool check(); - void abort(); - bool prepare(TransactionContext* txn); -public: - QPID_BROKER_EXTERN DtxWorkRecord(const std::string& xid, - TransactionalStore* const store); - QPID_BROKER_EXTERN ~DtxWorkRecord(); - QPID_BROKER_EXTERN bool prepare(); - QPID_BROKER_EXTERN bool commit(bool onePhase); - QPID_BROKER_EXTERN void rollback(); - QPID_BROKER_EXTERN void add(boost::intrusive_ptr ops); - void recover(std::auto_ptr txn, boost::intrusive_ptr ops); - void timedout(); - void setTimeout(boost::intrusive_ptr t); - boost::intrusive_ptr getTimeout(); - std::string getXid() const { return xid; } - bool isCompleted() const { return completed; } - bool isRolledback() const { return rolledback; } - bool isPrepared() const { return prepared; } - bool isExpired() const { return expired; } -}; - -}} // qpid::broker - -#endif diff --git a/qpid/cpp/src/qpid/broker/Exchange.cpp b/qpid/cpp/src/qpid/broker/Exchange.cpp deleted file mode 100644 index c9ed648735..0000000000 --- a/qpid/cpp/src/qpid/broker/Exchange.cpp +++ /dev/null @@ -1,504 +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/broker/Broker.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/sys/ExceptionHolder.h" -#include - -namespace qpid { -namespace broker { - -using std::string; - -using namespace qpid::framing; -using qpid::framing::Buffer; -using qpid::framing::FieldTable; -using qpid::sys::Mutex; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ - const std::string qpidMsgSequence("qpid.msg_sequence"); - const std::string qpidSequenceCounter("qpid.sequence_counter"); - const std::string qpidIVE("qpid.ive"); - const std::string QPID_MANAGEMENT("qpid.management"); -} - - -Exchange::PreRoute::PreRoute(Deliverable& msg, Exchange* _p):parent(_p) { - if (parent){ - if (parent->sequence || parent->ive) parent->sequenceLock.lock(); - - if (parent->sequence){ - parent->sequenceNo++; - msg.getMessage().addAnnotation(qpidMsgSequence,parent->sequenceNo); - } - if (parent->ive) { - parent->lastMsg = msg.getMessage(); - } - } -} - -Exchange::PreRoute::~PreRoute(){ - if (parent && (parent->sequence || parent->ive)){ - parent->sequenceLock.unlock(); - } -} - -namespace { -/** Store information about an exception to be thrown later. - * If multiple exceptions are stored, save the first of the "most severe" - * exceptions, SESSION is les sever than CONNECTION etc. - */ -class ExInfo { - public: - enum Type { NONE, SESSION, CONNECTION, OTHER }; - - ExInfo(string exchange) : type(NONE), exchange(exchange) {} - void store(Type type_, const qpid::sys::ExceptionHolder& exception_, const boost::shared_ptr& queue) { - QPID_LOG(warning, "Exchange " << exchange << " cannot deliver to queue " - << queue->getName() << ": " << exception_.what()); - if (type < type_) { // Replace less severe exception - type = type_; - exception = exception_; - } - } - - void raise() { - exception.raise(); - } - - private: - Type type; - string exchange; - qpid::sys::ExceptionHolder exception; -}; -} - -void Exchange::doRoute(Deliverable& msg, ConstBindingList b) -{ - int count = 0; - - if (b.get()) { - ExInfo error(getName()); // Save exception to throw at the end. - for(std::vector::const_iterator i = b->begin(); i != b->end(); i++, count++) { - try { - msg.deliverTo((*i)->queue); - if ((*i)->mgmtBinding != 0) - (*i)->mgmtBinding->inc_msgMatched(); - } - catch (const SessionException& e) { - error.store(ExInfo::SESSION, framing::createSessionException(e.code, e.what()),(*i)->queue); - } - catch (const ConnectionException& e) { - error.store(ExInfo::CONNECTION, framing::createConnectionException(e.code, e.what()), (*i)->queue); - } - catch (const std::exception& e) { - error.store(ExInfo::OTHER, qpid::sys::ExceptionHolder(new Exception(e.what())), (*i)->queue); - } - } - error.raise(); - } - - if (mgmtExchange != 0) - { - qmf::org::apache::qpid::broker::Exchange::PerThreadStats *eStats = mgmtExchange->getStatistics(); - uint64_t contentSize = msg.getMessage().getMessageSize(); - - eStats->msgReceives += 1; - eStats->byteReceives += contentSize; - if (count == 0) - { - //QPID_LOG(warning, "Exchange " << getName() << " could not route message; no matching binding found"); - eStats->msgDrops += 1; - eStats->byteDrops += contentSize; - if (brokerMgmtObject) - brokerMgmtObject->inc_discardsNoRoute(); - } - else - { - eStats->msgRoutes += count; - eStats->byteRoutes += count * contentSize; - } - - mgmtExchange->statisticsUpdated(); - } -} - -void Exchange::routeIVE(){ - if (ive && lastMsg){ - DeliverableMessage dmsg(lastMsg, 0); - route(dmsg); - } -} - - -Exchange::Exchange (const string& _name, Manageable* parent, Broker* b) : - name(_name), durable(false), autodelete(false), alternateUsers(0), otherUsers(0), persistenceId(0), sequence(false), - sequenceNo(0), ive(false), broker(b), destroyed(false) -{ - if (parent != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtExchange = _qmf::Exchange::shared_ptr(new _qmf::Exchange (agent, this, parent, _name)); - mgmtExchange->set_durable(durable); - mgmtExchange->set_autoDelete(autodelete); - agent->addObject(mgmtExchange, 0, durable); - if (broker) - brokerMgmtObject = boost::dynamic_pointer_cast(broker->GetManagementObject()); - } - } -} - -Exchange::Exchange(const string& _name, bool _durable, bool _autodelete, const qpid::framing::FieldTable& _args, - Manageable* parent, Broker* b) - : name(_name), durable(_durable), autodelete(_autodelete), alternateUsers(0), otherUsers(0), persistenceId(0), - args(_args), sequence(false), sequenceNo(0), ive(false), broker(b), destroyed(false) -{ - if (parent != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtExchange = _qmf::Exchange::shared_ptr(new _qmf::Exchange (agent, this, parent, _name)); - mgmtExchange->set_durable(durable); - mgmtExchange->set_autoDelete(autodelete); - mgmtExchange->set_arguments(ManagementAgent::toMap(args)); - agent->addObject(mgmtExchange, 0, durable); - if (broker) - brokerMgmtObject = boost::dynamic_pointer_cast(broker->GetManagementObject()); - } - } - - sequence = !!_args.get(qpidMsgSequence); - if (sequence) { - QPID_LOG(debug, "Configured exchange " << _name << " with Msg sequencing"); - args.setInt64(std::string(qpidSequenceCounter), sequenceNo); - } - - ive = !!_args.get(qpidIVE); - if (ive) { - QPID_LOG(debug, "Configured exchange " << _name << " with Initial Value"); - } -} - -Exchange::~Exchange () -{ - if (mgmtExchange != 0) - mgmtExchange->resourceDestroy (); -} - -void Exchange::setAlternate(Exchange::shared_ptr _alternate) -{ - alternate = _alternate; - alternate->incAlternateUsers(); - if (mgmtExchange != 0) { - if (alternate.get() != 0) - mgmtExchange->set_altExchange(alternate->GetManagementObject()->getObjectId()); - else - mgmtExchange->clr_altExchange(); - } -} - -void Exchange::setPersistenceId(uint64_t id) const -{ - persistenceId = id; -} - -Exchange::shared_ptr Exchange::decode(ExchangeRegistry& exchanges, Buffer& buffer) -{ - string name; - string type; - string altName; - FieldTable args; - - buffer.getShortString(name); - bool durable(buffer.getOctet()); - buffer.getShortString(type); - buffer.get(args); - // For backwards compatibility on restoring exchanges from before the alt-exchange update, perform check - if (buffer.available()) - buffer.getShortString(altName); - // Check autodelete bool; for backwards compatibility if the bool isn't present, assume false - bool _autodelete = ((buffer.available()) && (buffer.getInt8())); - - try { - Exchange::shared_ptr exch = exchanges.declare(name, type, durable, _autodelete, args).first; - exch->sequenceNo = args.getAsInt64(qpidSequenceCounter); - exch->alternateName.assign(altName); - return exch; - } catch (const UnknownExchangeTypeException&) { - QPID_LOG(warning, "Could not create exchange " << name << "; type " << type << " is not recognised"); - return Exchange::shared_ptr(); - } -} - -void Exchange::encode(Buffer& buffer) const -{ - buffer.putShortString(name); - buffer.putOctet(durable); - buffer.putShortString(getType()); - if (args.isSet(qpidSequenceCounter)) - args.setInt64(std::string(qpidSequenceCounter),sequenceNo); - buffer.put(args); - buffer.putShortString(alternate.get() ? alternate->getName() : string("")); - buffer.putInt8(isAutoDelete()); -} - -uint32_t Exchange::encodedSize() const -{ - return name.size() + 1/*short string size*/ - + 1 /*durable*/ - + getType().size() + 1/*short string size*/ - + (alternate.get() ? alternate->getName().size() : 0) + 1/*short string size*/ - + args.encodedSize() - + 1 /* autodelete bool as int_8 */; -} - -void Exchange::recoveryComplete(ExchangeRegistry& exchanges) -{ - if (!alternateName.empty()) { - Exchange::shared_ptr ae = exchanges.find(alternateName); - if (ae) setAlternate(ae); - else QPID_LOG(warning, "Could not set alternate exchange \"" - << alternateName << "\": does not exist."); - } -} - -ManagementObject::shared_ptr Exchange::GetManagementObject (void) const -{ - return mgmtExchange; -} - -void Exchange::registerDynamicBridge(DynamicBridge* db) -{ - if (!supportsDynamicBinding()) - throw Exception("Exchange type does not support dynamic binding"); - - { - Mutex::ScopedLock l(bridgeLock); - for (std::vector::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - (*iter)->sendReorigin(); - - bridgeVector.push_back(db); - } - - FieldTable args; - args.setString(qpidFedOp, fedOpReorigin); - bind(Queue::shared_ptr(), string(), &args); -} - -void Exchange::removeDynamicBridge(DynamicBridge* db) -{ - Mutex::ScopedLock l(bridgeLock); - for (std::vector::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - if (*iter == db) { - bridgeVector.erase(iter); - break; - } -} - -void Exchange::handleHelloRequest() -{ -} - -void Exchange::propagateFedOp(const string& routingKey, const string& tags, const string& op, const string& origin, qpid::framing::FieldTable* extra_args) -{ - Mutex::ScopedLock l(bridgeLock); - string myOp(op.empty() ? fedOpBind : op); - - for (std::vector::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - (*iter)->propagateBinding(routingKey, tags, op, origin, extra_args); -} - -Exchange::Binding::Binding(const string& _key, Queue::shared_ptr _queue, Exchange* _parent, - FieldTable _args, const string& _origin) - : parent(_parent), queue(_queue), key(_key), args(_args), origin(_origin) -{ -} - -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(); - mgmtBinding->resourceDestroy (); - } -} - -void Exchange::Binding::startManagement() -{ - if (parent != 0) - { - Broker* broker = parent->getBroker(); - if (broker != 0) { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) { - _qmf::Queue::shared_ptr mo = boost::dynamic_pointer_cast<_qmf::Queue>(queue->GetManagementObject()); - if (mo != 0) { - management::ObjectId queueId = mo->getObjectId(); - - mgmtBinding = _qmf::Binding::shared_ptr(new _qmf::Binding - (agent, this, (Manageable*) parent, queueId, key, ManagementAgent::toMap(args))); - if (!origin.empty()) - mgmtBinding->set_origin(origin); - agent->addObject(mgmtBinding); - mo->inc_bindingCount(); - } - } - } - } -} - -ManagementObject::shared_ptr Exchange::Binding::GetManagementObject () const -{ - return mgmtBinding; -} - -Exchange::MatchQueue::MatchQueue(Queue::shared_ptr q) : queue(q) {} - -bool Exchange::MatchQueue::operator()(Exchange::Binding::shared_ptr b) -{ - return b->queue == queue; -} - -//void Exchange::setProperties(Message& msg) { -// qpid::broker::amqp_0_10::MessageTransfer::setExchange(msg, getName()); -//} - -bool Exchange::routeWithAlternate(Deliverable& msg) -{ - route(msg); - if (!msg.delivered && alternate) { - alternate->route(msg); - } - return msg.delivered; -} - -void Exchange::setArgs(const framing::FieldTable& newArgs) { - args = newArgs; - if (mgmtExchange) mgmtExchange->set_arguments(ManagementAgent::toMap(args)); -} - -void Exchange::checkAutodelete() -{ - if (autodelete && !inUse() && broker) { - broker->getExchanges().destroy(name); - } -} -void Exchange::incAlternateUsers() -{ - Mutex::ScopedLock l(usersLock); - alternateUsers++; -} - -void Exchange::decAlternateUsers() -{ - Mutex::ScopedLock l(usersLock); - alternateUsers--; -} - -bool Exchange::inUseAsAlternate() -{ - Mutex::ScopedLock l(usersLock); - return alternateUsers > 0; -} - -void Exchange::incOtherUsers() -{ - Mutex::ScopedLock l(usersLock); - otherUsers++; -} -void Exchange::decOtherUsers(bool isControllingLink=false) -{ - Mutex::ScopedLock l(usersLock); - assert(otherUsers); - if (otherUsers) otherUsers--; - if (autodelete) { - if (isControllingLink) { - if (broker) broker->getExchanges().destroy(name); - } else if (!inUse() && !hasBindings()) { - checkAutodelete(); - } - } -} -bool Exchange::inUse() const -{ - Mutex::ScopedLock l(usersLock); - return alternateUsers > 0 || otherUsers > 0; -} -void Exchange::setDeletionListener(const std::string& key, boost::function0 listener) -{ - Mutex::ScopedLock l(usersLock); - if (listener) deletionListeners[key] = listener; -} -void Exchange::unsetDeletionListener(const std::string& key) -{ - Mutex::ScopedLock l(usersLock); - deletionListeners.erase(key); -} - -void Exchange::destroy() -{ - std::map > copy; - { - Mutex::ScopedLock l(usersLock); - destroyed = true; - deletionListeners.swap(copy); - } - for (std::map >::iterator i = copy.begin(); i != copy.end(); ++i) { - QPID_LOG(debug, "Exchange::destroy() notifying " << i->first); - if (i->second) i->second(); - } -} -bool Exchange::isDestroyed() const -{ - Mutex::ScopedLock l(usersLock); - return destroyed; -} -bool Exchange::isAutoDelete() const -{ - return autodelete; -} - -}} - diff --git a/qpid/cpp/src/qpid/broker/Exchange.h b/qpid/cpp/src/qpid/broker/Exchange.h deleted file mode 100644 index 3308d54e1b..0000000000 --- a/qpid/cpp/src/qpid/broker/Exchange.h +++ /dev/null @@ -1,268 +0,0 @@ -#ifndef _broker_Exchange_h -#define _broker_Exchange_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 -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/PersistableExchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Mutex.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Exchange.h" -#include "qmf/org/apache/qpid/broker/Binding.h" -#include "qmf/org/apache/qpid/broker/Broker.h" -#include -#include - -namespace qpid { -namespace broker { - -class Broker; -class ExchangeRegistry; - -class QPID_BROKER_CLASS_EXTERN Exchange : public PersistableExchange, public management::Manageable { -public: - struct Binding : public management::Manageable { - typedef boost::shared_ptr shared_ptr; - typedef std::vector vector; - - Exchange* parent; - boost::shared_ptr queue; - const std::string key; - const framing::FieldTable args; - std::string origin; - qmf::org::apache::qpid::broker::Binding::shared_ptr mgmtBinding; - - Binding(const std::string& key, boost::shared_ptr queue, Exchange* parent = 0, - framing::FieldTable args = framing::FieldTable(), const std::string& origin = std::string()); - ~Binding(); - void startManagement(); - management::ManagementObject::shared_ptr GetManagementObject() const; - }; - -private: - const std::string name; - const bool durable; - const bool autodelete; - std::string alternateName; - boost::shared_ptr alternate; - mutable qpid::sys::Mutex usersLock; - uint32_t alternateUsers; - uint32_t otherUsers; - std::map > deletionListeners; - mutable uint64_t persistenceId; - -protected: - mutable qpid::framing::FieldTable args; - bool sequence; - mutable qpid::sys::Mutex sequenceLock; - int64_t sequenceNo; - bool ive; - Message lastMsg; - - class PreRoute{ - public: - PreRoute(Deliverable& msg, Exchange* _p); - ~PreRoute(); - private: - Exchange* parent; - }; - - typedef boost::shared_ptr > > ConstBindingList; - typedef boost::shared_ptr< std::vector > > BindingList; - void doRoute(Deliverable& msg, ConstBindingList b); - void routeIVE(); - void checkAutodelete(); - virtual bool hasBindings() = 0; - - struct MatchQueue { - const boost::shared_ptr queue; - MatchQueue(boost::shared_ptr q); - bool operator()(Exchange::Binding::shared_ptr b); - }; - - /** A FedBinding keeps track of information that Federation needs - to know when to propagate changes. - - Dynamic federation needs to know which exchanges have at least - one local binding. The bindings on these exchanges need to be - propagated. - - Federated binds and unbinds need to know which federation - origins are associated with the bindings for each queue. When - origins are added or deleted, the corresponding bindings need - to be propagated. - - fedBindings[queueName] contains the origins associated with - the given queue. - */ - - class FedBinding { - uint32_t localBindings; - - typedef std::set originSet; - std::map fedBindings; - - public: - FedBinding() : localBindings(0) {} - bool hasLocal() const { return localBindings != 0; } - - /** Returns true if propagation is needed. */ - bool addOrigin(const std::string& queueName, const std::string& origin) { - if (origin.empty()) { - localBindings++; - return localBindings == 1; - } - fedBindings[queueName].insert(origin); - return true; - } - - /** Returns true if propagation is needed. */ - bool delOrigin(const std::string& queueName, const std::string& origin){ - if (origin.empty()) { // no remote == local binding - if (localBindings > 0) - localBindings--; - return localBindings == 0; - } - size_t match = fedBindings[queueName].erase(origin); - if (fedBindings[queueName].empty()) - fedBindings.erase(queueName); - return match != 0; - } - - uint32_t count() { - return localBindings + fedBindings.size(); - } - - uint32_t countFedBindings(const std::string& queueName) { - // don't use '[]' - it may increase size of fedBindings! - std::map::iterator i; - if ((i = fedBindings.find(queueName)) != fedBindings.end()) - return i->second.size(); - return 0; - } - }; - - qmf::org::apache::qpid::broker::Exchange::shared_ptr mgmtExchange; - qmf::org::apache::qpid::broker::Broker::shared_ptr brokerMgmtObject; - -public: - typedef boost::shared_ptr shared_ptr; - - QPID_BROKER_EXTERN explicit Exchange(const std::string& name, management::Manageable* parent = 0, - Broker* broker = 0); - QPID_BROKER_EXTERN Exchange(const std::string& _name, bool _durable, bool autodelete, const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_INLINE_EXTERN virtual ~Exchange(); - - const std::string& getName() const { return name; } - bool isDurable() { return durable; } - QPID_BROKER_EXTERN bool isAutoDelete() const; - QPID_BROKER_EXTERN const qpid::framing::FieldTable& getArgs() const { return args; } - QPID_BROKER_EXTERN void setArgs(const framing::FieldTable&); - - QPID_BROKER_EXTERN Exchange::shared_ptr getAlternate() { return alternate; } - QPID_BROKER_EXTERN void setAlternate(Exchange::shared_ptr _alternate); - - QPID_BROKER_EXTERN void incAlternateUsers(); - QPID_BROKER_EXTERN void decAlternateUsers(); - QPID_BROKER_EXTERN bool inUseAsAlternate(); - - QPID_BROKER_EXTERN void incOtherUsers(); - QPID_BROKER_EXTERN void decOtherUsers(bool isControllingLink); - QPID_BROKER_EXTERN bool inUse() const; - - virtual std::string getType() const = 0; - - /** - * bind() is used for two distinct purposes: - * - * 1. To create a binding, in the conventional sense - * - * 2. As a vehicle for any FedOp, currently including federated - * binding, federated unbinding, federated reorigin. - * - */ - - virtual bool bind(boost::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0; - virtual bool unbind(boost::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0; - virtual bool isBound(boost::shared_ptr queue, const std::string* const routingKey, const qpid::framing::FieldTable* const args) = 0; - //QPID_BROKER_EXTERN virtual void setProperties(Message&); - virtual void route(Deliverable& msg) = 0; - - //PersistableExchange: - QPID_BROKER_EXTERN void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - QPID_BROKER_EXTERN uint32_t encodedSize() const; - QPID_BROKER_EXTERN virtual void encode(framing::Buffer& buffer) const; - - static QPID_BROKER_EXTERN Exchange::shared_ptr decode(ExchangeRegistry& exchanges, framing::Buffer& buffer); - - // Manageable entry points - QPID_BROKER_EXTERN management::ManagementObject::shared_ptr GetManagementObject(void) const; - - // Federation hooks - class DynamicBridge { - public: - virtual ~DynamicBridge() {} - virtual void propagateBinding(const std::string& key, const std::string& tagList, const std::string& op, const std::string& origin, qpid::framing::FieldTable* extra_args=0) = 0; - virtual void sendReorigin() = 0; - virtual bool containsLocalTag(const std::string& tagList) const = 0; - virtual const std::string& getLocalTag() const = 0; - }; - - void registerDynamicBridge(DynamicBridge* db); - void removeDynamicBridge(DynamicBridge* db); - virtual bool supportsDynamicBinding() { return false; } - Broker* getBroker() const { return broker; } - /** - * Notify exchange that recovery has completed. - */ - void recoveryComplete(ExchangeRegistry& exchanges); - - bool routeWithAlternate(Deliverable& message); - - QPID_BROKER_EXTERN void destroy(); - QPID_BROKER_EXTERN bool isDestroyed() const; - - QPID_BROKER_EXTERN void setDeletionListener(const std::string& key, boost::function0 listener); - QPID_BROKER_EXTERN void unsetDeletionListener(const std::string& key); - -protected: - qpid::sys::Mutex bridgeLock; - std::vector bridgeVector; - Broker* broker; - bool destroyed; - - QPID_BROKER_EXTERN virtual void handleHelloRequest(); - void propagateFedOp(const std::string& routingKey, const std::string& tags, - const std::string& op, const std::string& origin, - qpid::framing::FieldTable* extra_args=0); -}; - -}} - -#endif /*!_broker_Exchange.cpp_h*/ diff --git a/qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp b/qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp deleted file mode 100644 index 73f1c80f48..0000000000 --- a/qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp +++ /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. - * - */ - -#include "qpid/broker/Broker.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/broker/Link.h" -#include "qpid/management/ManagementDirectExchange.h" -#include "qpid/management/ManagementTopicExchange.h" -#include "qpid/framing/reply_exceptions.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h" - -using namespace qpid::broker; -using namespace qpid::sys; -using std::pair; -using std::string; -using qpid::framing::FieldTable; -using qpid::management::ManagementAgent; -namespace _qmf = qmf::org::apache::qpid::broker; - -pair ExchangeRegistry::declare(const string& name, const string& type){ - - return declare(name, type, false, false, FieldTable()); -} - -pair ExchangeRegistry::declare( - const string& name, const string& type, bool durable, bool autodelete, const FieldTable& args, - Exchange::shared_ptr alternate, const string& connectionId, const string& userId) -{ - Exchange::shared_ptr exchange; - std::pair result; - { - RWlock::ScopedWlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i == exchanges.end()) { - if (type == TopicExchange::typeName){ - exchange = Exchange::shared_ptr(new TopicExchange(name, durable, autodelete, args, parent, broker)); - }else if(type == DirectExchange::typeName){ - exchange = Exchange::shared_ptr(new DirectExchange(name, durable, autodelete, args, parent, broker)); - }else if(type == FanOutExchange::typeName){ - exchange = Exchange::shared_ptr(new FanOutExchange(name, durable, autodelete, args, parent, broker)); - }else if (type == HeadersExchange::typeName) { - exchange = Exchange::shared_ptr(new HeadersExchange(name, durable, autodelete, args, parent, broker)); - }else if (type == ManagementDirectExchange::typeName) { - exchange = Exchange::shared_ptr(new ManagementDirectExchange(name, durable, args, parent, broker)); - }else if (type == ManagementTopicExchange::typeName) { - exchange = Exchange::shared_ptr(new ManagementTopicExchange(name, durable, args, parent, broker)); - }else if (type == Link::exchangeTypeName) { - exchange = Link::linkExchangeFactory(name); - }else{ - FunctionMap::iterator i = factory.find(type); - if (i == factory.end()) { - throw UnknownExchangeTypeException(type); - } else { - exchange = i->second(name, durable, autodelete, args, parent, broker); - } - } - exchanges[name] = exchange; - result = std::pair(exchange, true); - if (alternate) exchange->setAlternate(alternate); - // Call exchangeCreate inside the lock to ensure correct ordering. - if (broker) broker->getBrokerObservers().exchangeCreate(exchange); - } else { - result = std::pair(i->second, false); - } - if (broker && broker->getManagementAgent()) { - // Call raiseEvent inside the lock to ensure correct ordering. - broker->getManagementAgent()->raiseEvent( - _qmf::EventExchangeDeclare( - connectionId, - userId, - name, - type, - alternate ? alternate->getName() : string(), - durable, - false, - ManagementAgent::toMap(result.first->getArgs()), - result.second ? "created" : "existing")); - } - } - return result; -} - -void ExchangeRegistry::destroy( - const string& name, const string& connectionId, const string& userId) -{ - if (name.empty() || - (name.find("amq.") == 0 && - (name == "amq.direct" || name == "amq.fanout" || name == "amq.topic" || name == "amq.match")) || - name == "qpid.management") - throw framing::NotAllowedException(QPID_MSG("Cannot delete default exchange: '" << name << "'")); - { - RWlock::ScopedWlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i != exchanges.end()) { - if (broker) { - // Call exchangeDestroy and raiseEvent inside the lock to ensure - // correct ordering. - broker->getBrokerObservers().exchangeDestroy(i->second); - if (broker->getManagementAgent()) - broker->getManagementAgent()->raiseEvent( - _qmf::EventExchangeDelete(connectionId, userId, name)); - } - i->second->destroy(); - exchanges.erase(i); - - } - } -} - -Exchange::shared_ptr ExchangeRegistry::find(const string& name){ - RWlock::ScopedRlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i == exchanges.end()) - return Exchange::shared_ptr(); - else - return i->second; -} - -Exchange::shared_ptr ExchangeRegistry::get(const string& name) { - Exchange::shared_ptr ex = find(name); - if (!ex) throw framing::NotFoundException(QPID_MSG("Exchange not found: "<getName(), ex)).second; -} - -void ExchangeRegistry::registerType(const std::string& type, FactoryFunction f) -{ - factory[type] = f; -} - -void ExchangeRegistry::checkType(const std::string& type) -{ - if (type != TopicExchange::typeName && type != DirectExchange::typeName && type != FanOutExchange::typeName - && type != HeadersExchange::typeName && type != ManagementDirectExchange::typeName - && type != ManagementTopicExchange::typeName && type != Link::exchangeTypeName - && factory.find(type) == factory.end()) { - throw UnknownExchangeTypeException(type); - } -} - - -namespace -{ -const std::string EMPTY; -} - -Exchange::shared_ptr ExchangeRegistry::getDefault() -{ - return get(EMPTY); -} diff --git a/qpid/cpp/src/qpid/broker/ExchangeRegistry.h b/qpid/cpp/src/qpid/broker/ExchangeRegistry.h deleted file mode 100644 index fc741dce27..0000000000 --- a/qpid/cpp/src/qpid/broker/ExchangeRegistry.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _broker_ExchangeRegistry_h -#define _broker_ExchangeRegistry_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/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/management/Manageable.h" - -#include -#include - -#include -#include - -namespace qpid { -namespace broker { -namespace { -const std::string UNKNOWN_EXCHANGE_TYPE("Unknown exchange type: "); -} - -struct UnknownExchangeTypeException : std::exception -{ - const std::string message; - UnknownExchangeTypeException(const std::string& type) throw() : message(UNKNOWN_EXCHANGE_TYPE + type) {} - ~UnknownExchangeTypeException() throw() {} - const char* what() const throw() - { - return message.c_str(); - } -}; - -class ExchangeRegistry{ - public: - typedef boost::function6 FactoryFunction; - - ExchangeRegistry (Broker* b = 0) : parent(0), broker(b) {} - QPID_BROKER_EXTERN std::pair declare( - const std::string& name, const std::string& type); - - QPID_BROKER_EXTERN std::pair declare( - const std::string& name, - const std::string& type, - bool durable, - bool autodelete, - const qpid::framing::FieldTable& args = framing::FieldTable(), - Exchange::shared_ptr alternate = Exchange::shared_ptr(), - const std::string& connectionId = std::string(), - const std::string& userId = std::string()); - - QPID_BROKER_EXTERN void destroy( - const std::string& name, - const std::string& connectionId = std::string(), - const std::string& userId = std::string()); - - QPID_BROKER_EXTERN Exchange::shared_ptr getDefault(); - - /** - * Find the named exchange. Return 0 if not found. - */ - QPID_BROKER_EXTERN boost::shared_ptr find(const std::string& name); - - /** - * Get the named exchange. Throw exception if not found. - */ - QPID_BROKER_EXTERN boost::shared_ptr get(const std::string& name); - - - /** - * Register the manageable parent for declared exchanges - */ - void setParent (management::Manageable* _parent) { parent = _parent; } - - /** Register an exchange instance. - *@return true if registered, false if exchange with same name is already registered. - */ - QPID_BROKER_EXTERN bool registerExchange(const Exchange::shared_ptr&); - - QPID_BROKER_EXTERN void registerType(const std::string& type, FactoryFunction); - - QPID_BROKER_EXTERN void checkType(const std::string& type); - - /** Call f for each exchange in the registry. */ - template void eachExchange(F f) const { - qpid::sys::RWlock::ScopedRlock l(lock); - for (ExchangeMap::const_iterator i = exchanges.begin(); i != exchanges.end(); ++i) - f(i->second); - } - - private: - typedef std::map ExchangeMap; - typedef std::map FunctionMap; - - ExchangeMap exchanges; - FunctionMap factory; - mutable qpid::sys::RWlock lock; - management::Manageable* parent; - Broker* broker; -}; - -}} // namespace qpid::broker - - -#endif /*!_broker_ExchangeRegistry_h*/ diff --git a/qpid/cpp/src/qpid/broker/Fairshare.cpp b/qpid/cpp/src/qpid/broker/Fairshare.cpp deleted file mode 100644 index ec8ae9a037..0000000000 --- a/qpid/cpp/src/qpid/broker/Fairshare.cpp +++ /dev/null @@ -1,125 +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/broker/Fairshare.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/log/Statement.h" -#include -#include -#include - -namespace qpid { -namespace broker { - -Fairshare::Fairshare(size_t levels, uint limit) : - PriorityQueue(levels), - limits(levels, limit), priority(levels-1), count(0) {} - - -void Fairshare::setLimit(size_t level, uint limit) -{ - limits[level] = limit; -} - -bool Fairshare::limitReached() -{ - uint l = limits[priority]; - return l && ++count > l; -} - -uint Fairshare::currentLevel() -{ - if (limitReached()) { - return nextLevel(); - } else { - return priority; - } -} - -uint Fairshare::nextLevel() -{ - count = 1; - if (priority) --priority; - else priority = levels-1; - return priority; -} - -bool Fairshare::isNull() -{ - for (int i = 0; i < levels; i++) if (limits[i]) return false; - return true; -} - -bool Fairshare::getState(uint& p, uint& c) const -{ - p = priority; - c = count; - return true; -} - -bool Fairshare::setState(uint p, uint c) -{ - priority = p; - count = c; - return true; -} - -bool Fairshare::getState(const Messages& m, uint& priority, uint& count) -{ - const Fairshare* fairshare = dynamic_cast(&m); - return fairshare && fairshare->getState(priority, count); -} - -bool Fairshare::setState(Messages& m, uint priority, uint count) -{ - Fairshare* fairshare = dynamic_cast(&m); - return fairshare && fairshare->setState(priority, count); -} - -PriorityQueue::Priority Fairshare::firstLevel() -{ - return Priority(currentLevel()); -} - -bool Fairshare::nextLevel(Priority& p) -{ - int next = nextLevel(); - if (next == p.start) { - return false; - } else { - p.current = next; - return true; - } -} - -std::auto_ptr Fairshare::create(const QueueSettings& settings) -{ - std::auto_ptr fairshare(new Fairshare(settings.priorities, settings.defaultFairshare)); - for (uint i = 0; i < settings.priorities; i++) { - std::map::const_iterator l = settings.fairshare.find(i); - if (l != settings.fairshare.end()) fairshare->setLimit(i, l->second); - } - return std::auto_ptr(fairshare.release()); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/Fairshare.h b/qpid/cpp/src/qpid/broker/Fairshare.h deleted file mode 100644 index e7c8b04ecf..0000000000 --- a/qpid/cpp/src/qpid/broker/Fairshare.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_BROKER_FAIRSHARE_H -#define QPID_BROKER_FAIRSHARE_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/PriorityQueue.h" - -namespace qpid { -namespace broker { -struct QueueSettings; - -/** - * Modifies a basic priority queue by limiting the number of messages - * from each priority level that are dispatched before allowing - * dispatch from the next level. - */ -class Fairshare : public PriorityQueue -{ - public: - Fairshare(size_t levels, uint limit); - bool getState(uint& priority, uint& count) const; - bool setState(uint priority, uint count); - void setLimit(size_t level, uint limit); - bool isNull(); - static std::auto_ptr create(const QueueSettings& settings); - static bool getState(const Messages&, uint& priority, uint& count); - static bool setState(Messages&, uint priority, uint count); - private: - std::vector limits; - - uint priority; - uint count; - - uint currentLevel(); - uint nextLevel(); - bool limitReached(); - Priority firstLevel(); - bool nextLevel(Priority& ); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_FAIRSHARE_H*/ diff --git a/qpid/cpp/src/qpid/broker/FanOutExchange.cpp b/qpid/cpp/src/qpid/broker/FanOutExchange.cpp deleted file mode 100644 index 8c1d3f4954..0000000000 --- a/qpid/cpp/src/qpid/broker/FanOutExchange.cpp +++ /dev/null @@ -1,132 +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/log/Statement.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/FedOps.h" -#include - -using namespace qpid::broker; - -using std::string; - -using namespace qpid::framing; -using namespace qpid::sys; -namespace _qmf = qmf::org::apache::qpid::broker; - -FanOutExchange::FanOutExchange(const std::string& _name, Manageable* _parent, Broker* b) : - Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -FanOutExchange::FanOutExchange(const std::string& _name, bool _durable, bool autodelete, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, autodelete, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool FanOutExchange::bind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* args) -{ - string fedOp(args ? args->getAsString(qpidFedOp) : fedOpBind); - string fedTags(args ? args->getAsString(qpidFedTags) : ""); - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - Binding::shared_ptr binding (new Binding ("", queue, this, args ? *args : FieldTable(), fedOrigin)); - if (bindings.add_unless(binding, MatchQueue(queue))) { - binding->startManagement(); - propagate = fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - // queue already present - still need to track fedOrigin - fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } else if (fedOp == fedOpUnbind) { - propagate = fedBinding.delOrigin(queue->getName(), fedOrigin); - if (fedBinding.countFedBindings(queue->getName()) == 0) - unbind(queue, "", args); - } else if (fedOp == fedOpReorigin) { - if (fedBinding.hasLocal()) { - propagateFedOp(string(), string(), fedOpBind, string()); - } - } - - routeIVE(); - if (propagate) - propagateFedOp(string(), fedTags, fedOp, fedOrigin); - return true; -} - -bool FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - - QPID_LOG(debug, "Unbinding queue " << queue->getName() - << " from exchange " << getName() << " origin=" << fedOrigin << ")" ); - - if (bindings.remove_if(MatchQueue(queue))) { - propagate = fedBinding.delOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - } else { - return false; - } - - if (propagate) - propagateFedOp(string(), string(), fedOpUnbind, string()); - if (bindings.empty()) checkAutodelete(); - return true; -} - -void FanOutExchange::route(Deliverable& msg) -{ - PreRoute pr(msg, this); - doRoute(msg, bindings.snapshot()); -} - -bool FanOutExchange::isBound(Queue::shared_ptr queue, const string* const, const FieldTable* const) -{ - BindingsArray::ConstPtr ptr = bindings.snapshot(); - return ptr && std::find_if(ptr->begin(), ptr->end(), MatchQueue(queue)) != ptr->end(); -} - - -FanOutExchange::~FanOutExchange() { - if (mgmtExchange != 0) - mgmtExchange->debugStats("destroying"); -} - -const std::string FanOutExchange::typeName("fanout"); - -bool FanOutExchange::hasBindings() -{ - BindingsArray::ConstPtr ptr = bindings.snapshot(); - return ptr && !ptr->empty(); -} diff --git a/qpid/cpp/src/qpid/broker/FanOutExchange.h b/qpid/cpp/src/qpid/broker/FanOutExchange.h deleted file mode 100644 index a92ff7ce97..0000000000 --- a/qpid/cpp/src/qpid/broker/FanOutExchange.h +++ /dev/null @@ -1,74 +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. - * - */ -#ifndef _FanOutExchange_ -#define _FanOutExchange_ - -#include -#include -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/broker/Queue.h" - -namespace qpid { -namespace broker { - -class FanOutExchange : public virtual Exchange { - typedef qpid::sys::CopyOnWriteArray BindingsArray; - BindingsArray bindings; - FedBinding fedBinding; - public: - static const std::string typeName; - - QPID_BROKER_EXTERN FanOutExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN FanOutExchange(const std::string& _name, - bool _durable, bool autodelete, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~FanOutExchange(); - virtual bool supportsDynamicBinding() { return true; } - protected: - bool hasBindings(); -}; - -} -} - - - -#endif diff --git a/qpid/cpp/src/qpid/broker/FedOps.h b/qpid/cpp/src/qpid/broker/FedOps.h deleted file mode 100644 index dc4a38e244..0000000000 --- a/qpid/cpp/src/qpid/broker/FedOps.h +++ /dev/null @@ -1,38 +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. - * - */ - -/* - * Strings used to identify federated operations and operands. - */ - -namespace -{ - const std::string qpidFedOp("qpid.fed.op"); // a federation primitive - const std::string qpidFedTags("qpid.fed.tags"); // a unique id for a broker - const std::string qpidFedOrigin("qpid.fed.origin"); // the tag of the broker on which a propagated binding originated - - // Operands for qpidFedOp - each identifies a federation primitive - - const std::string fedOpBind("B"); - const std::string fedOpUnbind("U"); - const std::string fedOpReorigin("R"); - const std::string fedOpHello("H"); -} diff --git a/qpid/cpp/src/qpid/broker/FifoDistributor.cpp b/qpid/cpp/src/qpid/broker/FifoDistributor.cpp deleted file mode 100644 index e1c0d268ce..0000000000 --- a/qpid/cpp/src/qpid/broker/FifoDistributor.cpp +++ /dev/null @@ -1,45 +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/broker/Queue.h" -#include "qpid/broker/FifoDistributor.h" - -using namespace qpid::broker; - -FifoDistributor::FifoDistributor(Messages& container) - : messages(container) {} - -bool FifoDistributor::acquire(const std::string&, Message& msg) -{ - if (msg.getState() == AVAILABLE) { - msg.setState(ACQUIRED); - return true; - } else { - return false; - } -} - -void FifoDistributor::query(qpid::types::Variant::Map&) const -{ - // nothing to see here.... -} - diff --git a/qpid/cpp/src/qpid/broker/FifoDistributor.h b/qpid/cpp/src/qpid/broker/FifoDistributor.h deleted file mode 100644 index aa5ebe28c5..0000000000 --- a/qpid/cpp/src/qpid/broker/FifoDistributor.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _broker_FifoDistributor_h -#define _broker_FifoDistributor_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. - * - */ - -/** Simple MessageDistributor for FIFO Queues - the HEAD message is always the next - * available message for consumption. - */ - -#include "qpid/broker/MessageDistributor.h" - -namespace qpid { -namespace broker { - -class Messages; - -class FifoDistributor : public MessageDistributor -{ - public: - FifoDistributor(Messages& container); - - bool acquire(const std::string& consumer, Message& target); - void query(qpid::types::Variant::Map&) const; - - private: - Messages& messages; -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/HandlerImpl.h b/qpid/cpp/src/qpid/broker/HandlerImpl.h deleted file mode 100644 index c41438fd90..0000000000 --- a/qpid/cpp/src/qpid/broker/HandlerImpl.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _broker_HandlerImpl_h -#define _broker_HandlerImpl_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/broker/SemanticState.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/amqp_0_10/Connection.h" - -namespace qpid { -namespace broker { - -class Broker; - -/** - * Base template for protocol handler implementations. - * Provides convenience methods for getting common session objects. - */ -class HandlerImpl { - protected: - SemanticState& state; - SessionContext& session; - - HandlerImpl(SemanticState& s) : state(s), session(s.getSession()) {} - - framing::AMQP_ClientProxy& getProxy() { return session.getProxy(); } - amqp_0_10::Connection& getConnection() { return session.getConnection(); } - Broker& getBroker() { return session.getConnection().getBroker(); } -}; - -}} // namespace qpid::broker - - - -#endif /*!_broker_HandlerImpl_h*/ - - diff --git a/qpid/cpp/src/qpid/broker/HeadersExchange.cpp b/qpid/cpp/src/qpid/broker/HeadersExchange.cpp deleted file mode 100644 index 585c7ba764..0000000000 --- a/qpid/cpp/src/qpid/broker/HeadersExchange.cpp +++ /dev/null @@ -1,417 +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/broker/HeadersExchange.h" - -#include "qpid/amqp/CharSequence.h" -#include "qpid/amqp/MapHandler.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include - - -using namespace qpid::broker; - -using std::string; -using qpid::amqp::MapHandler; - -using namespace qpid::framing; -using namespace qpid::sys; -namespace _qmf = qmf::org::apache::qpid::broker; - -// TODO aconway 2006-09-20: More efficient matching algorithm. -// The current search algorithm really sucks. -// Fieldtables are heavy, maybe use shared_ptr to do handle-body. - -using namespace qpid::broker; - -namespace { - const std::string x_match("x-match"); - // possible values for x-match - const std::string all("all"); - const std::string any("any"); - const std::string empty; - - // federation related args and values - const std::string QPID_RESERVED("qpid."); - const std::string qpidFedOp("qpid.fed.op"); - const std::string qpidFedTags("qpid.fed.tags"); - const std::string qpidFedOrigin("qpid.fed.origin"); - - const std::string fedOpBind("B"); - const std::string fedOpUnbind("U"); - const std::string fedOpReorigin("R"); - const std::string fedOpHello("H"); - -std::string getMatch(const FieldTable* args) -{ - if (!args) { - throw InternalErrorException(QPID_MSG("No arguments given.")); - } - FieldTable::ValuePtr what = args->get(x_match); - if (!what) { - return empty; - } - if (!what->convertsTo()) { - throw InternalErrorException(QPID_MSG("Invalid x-match binding format to headers exchange. Must be a string [\"all\" or \"any\"]")); - } - return what->get(); -} -class Matcher : public MapHandler -{ - public: - Matcher(const FieldTable& b) : binding(b), matched(0) {} - void handleBool(const qpid::amqp::CharSequence& key, bool value) { processUint(std::string(key.data, key.size), value); } - void handleUint8(const qpid::amqp::CharSequence& key, uint8_t value) { processUint(std::string(key.data, key.size), value); } - void handleUint16(const qpid::amqp::CharSequence& key, uint16_t value) { processUint(std::string(key.data, key.size), value); } - void handleUint32(const qpid::amqp::CharSequence& key, uint32_t value) { processUint(std::string(key.data, key.size), value); } - void handleUint64(const qpid::amqp::CharSequence& key, uint64_t value) { processUint(std::string(key.data, key.size), value); } - void handleInt8(const qpid::amqp::CharSequence& key, int8_t value) { processInt(std::string(key.data, key.size), value); } - void handleInt16(const qpid::amqp::CharSequence& key, int16_t value) { processInt(std::string(key.data, key.size), value); } - void handleInt32(const qpid::amqp::CharSequence& key, int32_t value) { processInt(std::string(key.data, key.size), value); } - void handleInt64(const qpid::amqp::CharSequence& key, int64_t value) { processInt(std::string(key.data, key.size), value); } - void handleFloat(const qpid::amqp::CharSequence& key, float value) { processFloat(std::string(key.data, key.size), value); } - void handleDouble(const qpid::amqp::CharSequence& key, double value) { processFloat(std::string(key.data, key.size), value); } - void handleString(const qpid::amqp::CharSequence& key, const qpid::amqp::CharSequence& value, const qpid::amqp::CharSequence& /*encoding*/) - { - processString(std::string(key.data, key.size), std::string(value.data, value.size)); - } - void handleVoid(const qpid::amqp::CharSequence& key) - { - valueCheckRequired(std::string(key.data, key.size)); - } - bool matches() - { - std::string what = getMatch(&binding); - if (what == all) { - //must match all entries in the binding, except the match mode indicator - return matched == binding.size() - 1; - } else if (what == any) { - //match any of the entries in the binding - return matched > 0; - } else { - return false; - } - } - private: - bool valueCheckRequired(const std::string& key) - { - FieldTable::ValuePtr v = binding.get(key); - if (v) { - if (v->getType() == 0xf0/*VOID*/) { - ++matched; - return false; - } else { - return true; - } - } else { - return false; - } - } - - void processString(const std::string& key, const std::string& actual) - { - if (valueCheckRequired(key) && binding.getAsString(key) == actual) { - ++matched; - } - } - void processFloat(const std::string& key, double actual) - { - double bound; - if (valueCheckRequired(key) && binding.getDouble(key, bound) && bound == actual) { - ++matched; - } - } - void processInt(const std::string& key, int64_t actual) - { - if (valueCheckRequired(key) && binding.getAsInt64(key) == actual) { - ++matched; - } - } - void processUint(const std::string& key, uint64_t actual) - { - if (valueCheckRequired(key) && binding.getAsUInt64(key) == actual) { - ++matched; - } - } - const FieldTable& binding; - size_t matched; -}; -} - -HeadersExchange::HeadersExchange(const string& _name, Manageable* _parent, Broker* b) : - Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -HeadersExchange::HeadersExchange(const std::string& _name, bool _durable, bool autodelete, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, autodelete, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool HeadersExchange::bind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args) -{ - string fedOp(fedOpBind); - string fedTags; - string fedOrigin; - if (args) { - fedOp = args->getAsString(qpidFedOp); - fedTags = args->getAsString(qpidFedTags); - fedOrigin = args->getAsString(qpidFedOrigin); - } - - bool propagate = false; - - // The federation args get propagated directly, so we need to identify - // the non federation args in case a federated propagate is needed - FieldTable extra_args; - getNonFedArgs(args, extra_args); - - if (fedOp.empty() || fedOp == fedOpBind) { - // x-match arg MUST be present for a bind call - std::string x_match_value = getMatch(args); - - if (x_match_value != all && x_match_value != any) { - throw InternalErrorException(QPID_MSG("Invalid or missing x-match value binding to headers exchange. Must be a string [\"all\" or \"any\"]")); - } - - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()) { - MatchArgs matchArgs(queue, &extra_args); - MatchKey matchKey(queue, bindingKey); - for (std::vector::const_iterator i = p->begin(); i != p->end(); ++i) { - if (matchKey(*i) && !matchArgs(*i)) { - throw InternalErrorException(QPID_MSG("Exchange: " << getName() - << ", binding key: " << bindingKey - << " Duplicate binding key not allowed." )); - } - } - } - - { - Mutex::ScopedLock l(lock); - //NOTE: do not include the fed op/tags/origin in the - //arguments as when x-match is 'all' these would prevent - //matching (they are internally added properties - //controlling binding propagation but not relevant to - //actual routing) - Binding::shared_ptr binding (new Binding (bindingKey, queue, this, args ? *args : FieldTable())); - BoundKey bk(binding, extra_args); - if (bindings.add_unless(bk, MatchArgs(queue, &extra_args))) { - binding->startManagement(); - propagate = bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } // lock dropped - - } else if (fedOp == fedOpUnbind) { - Mutex::ScopedLock l(lock); - - FedUnbindModifier modifier(queue->getName(), fedOrigin); - bindings.modify_if(MatchKey(queue, bindingKey), modifier); - propagate = modifier.shouldPropagate; - if (modifier.shouldUnbind) { - unbind(queue, bindingKey, args); - } - - } else if (fedOp == fedOpReorigin) { - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()) - { - Mutex::ScopedLock l(lock); - for (std::vector::const_iterator i = p->begin(); i != p->end(); ++i) - { - if ((*i).fedBinding.hasLocal()) { - propagateFedOp( (*i).binding->key, string(), fedOpBind, string()); - } - } - } - } - routeIVE(); - if (propagate) { - FieldTable * prop_args = (extra_args.count() != 0 ? &extra_args : 0); - propagateFedOp(bindingKey, fedTags, fedOp, fedOrigin, prop_args); - } - - return true; -} - -bool HeadersExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable *args){ - bool propagate = false; - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - { - Mutex::ScopedLock l(lock); - - FedUnbindModifier modifier(queue->getName(), fedOrigin); - MatchKey match_key(queue, bindingKey); - bindings.modify_if(match_key, modifier); - propagate = modifier.shouldPropagate; - if (modifier.shouldUnbind) { - if (bindings.remove_if(match_key)) { - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - } else { - return false; - } - } - } - - if (propagate) { - propagateFedOp(bindingKey, string(), fedOpUnbind, string()); - } - if (bindings.empty()) checkAutodelete(); - return true; -} - - -void HeadersExchange::route(Deliverable& msg) -{ - PreRoute pr(msg, this); - - BindingList b(new std::vector >); - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()) { - for (std::vector::const_iterator i = p->begin(); i != p->end(); ++i) { - if (match(i->args, msg.getMessage())) { - /* check if a binding tothe same queue has not been already added to b */ - std::vector >::iterator bi = b->begin(); - while ((bi != b->end()) && ((*bi)->queue != i->binding->queue)) - ++bi; - if (bi == b->end()) - b->push_back(i->binding); - } - } - } - doRoute(msg, b); -} - - -bool HeadersExchange::isBound(Queue::shared_ptr queue, const string* const, const FieldTable* const args) -{ - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()){ - for (std::vector::const_iterator i = p->begin(); i != p->end(); ++i) { - if ( (!args || equal((*i).args, *args)) && (!queue || (*i).binding->queue == queue)) { - return true; - } - } - } - return false; -} - -void HeadersExchange::getNonFedArgs(const FieldTable* args, FieldTable& nonFedArgs) -{ - if (!args) - { - return; - } - - for (qpid::framing::FieldTable::ValueMap::const_iterator i=args->begin(); i != args->end(); ++i) - { - if (i->first.find(QPID_RESERVED) == 0) - { - continue; - } - nonFedArgs.insert((*i)); - } -} - -HeadersExchange::~HeadersExchange() { - if (mgmtExchange != 0) - mgmtExchange->debugStats("destroying"); -} - -const std::string HeadersExchange::typeName("headers"); - -namespace -{ - - bool match_values(const FieldValue& bind, const FieldValue& msg) { - return bind.getType() == 0xf0 || bind == msg; - } - -} - -bool HeadersExchange::match(const FieldTable& bindArgs, const Message& msg) { - Matcher matcher(bindArgs); - msg.processProperties(matcher); - return matcher.matches(); -} - -bool HeadersExchange::equal(const FieldTable& a, const FieldTable& b) { - typedef FieldTable::ValueMap Map; - for (Map::const_iterator i = a.begin(); - i != a.end(); - ++i) - { - Map::const_iterator j = b.find(i->first); - if (j == b.end()) return false; - if (!match_values(*(i->second), *(j->second))) return false; - } - return true; -} - -//--------- -HeadersExchange::MatchArgs::MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a) : queue(q), args(a) {} - -bool HeadersExchange::MatchArgs::operator()(const BoundKey & bk) -{ - return bk.binding->queue == queue && bk.binding->args == *args; -} - -//--------- -HeadersExchange::MatchKey::MatchKey(Queue::shared_ptr q, const std::string& k) : queue(q), key(k) {} - -bool HeadersExchange::MatchKey::operator()(const BoundKey & bk) -{ - return bk.binding->queue == queue && bk.binding->key == key; -} - -//---------- -HeadersExchange::FedUnbindModifier::FedUnbindModifier(const string& queueName, const string& origin) : queueName(queueName), fedOrigin(origin), shouldUnbind(false), shouldPropagate(false) {} -HeadersExchange::FedUnbindModifier::FedUnbindModifier() : shouldUnbind(false), shouldPropagate(false) {} - -bool HeadersExchange::FedUnbindModifier::operator()(BoundKey & bk) -{ - shouldPropagate = bk.fedBinding.delOrigin(queueName, fedOrigin); - if (bk.fedBinding.countFedBindings(queueName) == 0) - { - shouldUnbind = true; - } - return true; -} - -bool HeadersExchange::hasBindings() -{ - Bindings::ConstPtr ptr = bindings.snapshot(); - return ptr && !ptr->empty(); -} diff --git a/qpid/cpp/src/qpid/broker/HeadersExchange.h b/qpid/cpp/src/qpid/broker/HeadersExchange.h deleted file mode 100644 index 54c69491e9..0000000000 --- a/qpid/cpp/src/qpid/broker/HeadersExchange.h +++ /dev/null @@ -1,119 +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. - * - */ -#ifndef _HeadersExchange_ -#define _HeadersExchange_ - -#include -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/Queue.h" - -namespace qpid { -namespace broker { - - -class HeadersExchange : public virtual Exchange { - - struct BoundKey - { - Binding::shared_ptr binding; - qpid::framing::FieldTable args; - FedBinding fedBinding; - BoundKey(Binding::shared_ptr binding_, const qpid::framing::FieldTable& args_) : binding(binding_), args(args_) {} - }; - - struct MatchArgs - { - const Queue::shared_ptr queue; - const qpid::framing::FieldTable* args; - MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a); - bool operator()(const BoundKey & bk); - }; - - struct MatchKey - { - const Queue::shared_ptr queue; - const std::string& key; - MatchKey(Queue::shared_ptr q, const std::string& k); - bool operator()(const BoundKey & bk); - }; - - struct FedUnbindModifier - { - std::string queueName; - std::string fedOrigin; - bool shouldUnbind; - bool shouldPropagate; - FedUnbindModifier(); - FedUnbindModifier(const std::string& queueName, const std::string& origin); - bool operator()(BoundKey & bk); - }; - - typedef qpid::sys::CopyOnWriteArray Bindings; - - Bindings bindings; - qpid::sys::Mutex lock; - protected: - void getNonFedArgs(const framing::FieldTable* args, - framing::FieldTable& nonFedArgs); - bool hasBindings(); - - public: - QPID_BROKER_EXTERN static const std::string typeName; - - QPID_BROKER_EXTERN HeadersExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN HeadersExchange(const std::string& _name, - bool _durable, bool autodelete, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~HeadersExchange(); - - virtual bool supportsDynamicBinding() { return true; } - - static QPID_BROKER_EXTERN bool match(const qpid::framing::FieldTable& bindArgs, const qpid::broker::Message& msg); - static bool equal(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); -}; - - - -} -} - -#endif diff --git a/qpid/cpp/src/qpid/broker/IndexedDeque.h b/qpid/cpp/src/qpid/broker/IndexedDeque.h deleted file mode 100644 index e13a218ad0..0000000000 --- a/qpid/cpp/src/qpid/broker/IndexedDeque.h +++ /dev/null @@ -1,226 +0,0 @@ -#ifndef QPID_BROKER_INDEXEDDEQUE_H -#define QPID_BROKER_INDEXEDDEQUE_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/SequenceNumber.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Messages.h" -#include "qpid/broker/QueueCursor.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { -namespace broker { - -/** - * Template for a deque whose contents can be refered to by - * QueueCursor - */ -template class IndexedDeque -{ - public: - typedef boost::function1 Padding; - IndexedDeque(Padding p) : head(0), version(0), padding(p) {} - - bool index(const QueueCursor& cursor, size_t& result) - { - return cursor.valid && index(qpid::framing::SequenceNumber(cursor.position + 1), result); - } - - /** - * Finds the index for the message with the specified sequence number. - * - * @returns true if a message was found with the specified sequence, - * in which case the second parameter will be set to the index of that - * message; false if no message with that sequence exists, in which - * case the second parameter will be 0 if the sequence is less than - * that of the first message and non-zero if it is greater than that - * of the last message - */ - bool index(const qpid::framing::SequenceNumber& position, size_t& i) - { - //assuming a monotonic sequence, with no messages removed except - //from the ends of the deque, we can use the position to determine - //an index into the deque - if (messages.size()) { - qpid::framing::SequenceNumber front(messages.front().getSequence()); - if (position < front) { - i = 0; - } else { - i = position - front; - return i < messages.size(); - } - } - return false; - } - - bool deleted(const QueueCursor& cursor) - { - size_t i; - if (cursor.valid && index(cursor.position, i)) { - messages[i].setState(DELETED); - clean(); - return true; - } else { - return false; - } - } - - T& publish(const T& added) - { - // QPID-4046: let producer help clean the backlog of deleted messages - clean(); - //for ha replication, the queue can sometimes be reset by - //removing some of the more recent messages, in this case we - //need to ensure the DELETED records at the tail do not interfere with indexing - while (messages.size() && added.getSequence() <= messages.back().getSequence() && messages.back().getState() == DELETED) - messages.pop_back(); - if (messages.size() && added.getSequence() <= messages.back().getSequence()) throw qpid::Exception(QPID_MSG("Index out of sequence!")); - - //add padding to prevent gaps in sequence, which break the index - //calculation (needed for queue replication) - while (messages.size() && (added.getSequence() - messages.back().getSequence()) > 1) - messages.push_back(padding(messages.back().getSequence() + 1)); - - messages.push_back(added); - T& m = messages.back(); - m.setState(AVAILABLE); - if (head >= messages.size()) head = messages.size() - 1; - QPID_LOG(debug, "Message " << &m << " published, state is " << m.getState() << " (head is now " << head << ")"); - return m; - } - - T* release(const QueueCursor& cursor) - { - size_t i; - if (cursor.valid && index(cursor.position, i) && messages[i].getState() == ACQUIRED) { - messages[i].setState(AVAILABLE); - ++version; - QPID_LOG(debug, "Released message at position " << cursor.position << ", index " << i); - return &messages[i]; - } else { - if (!cursor.valid) { QPID_LOG(debug, "Could not release message; cursor was invalid");} - else { QPID_LOG(debug, "Could not release message at position " << cursor.position); } - return 0; - } - } - - bool reset(const QueueCursor& cursor) - { - return !cursor.valid || (cursor.type == CONSUMER && cursor.version != version); - } - - T* next(QueueCursor& cursor) - { - size_t i = 0; - if (reset(cursor)) i = head; //start from head - else index(cursor, i); //get first message that is greater than position - - if (cursor.valid) { - QPID_LOG(debug, "next() called for cursor at " << cursor.position << ", index set to " << i << " (of " << messages.size() << ")"); - } else { - QPID_LOG(debug, "next() called for invalid cursor, index started at " << i << " (of " << messages.size() << ")"); - } - while (i < messages.size()) { - T& m = messages[i++]; - if (m.getState() == DELETED) continue; - cursor.setPosition(m.getSequence(), version); - QPID_LOG(debug, "in next(), cursor set to " << cursor.position); - - if (cursor.check(m)) { - QPID_LOG(debug, "in next(), returning message at " << cursor.position); - return &m; - } - } - QPID_LOG(debug, "no message to return from next"); - return 0; - } - - size_t size() - { - size_t count(0); - for (size_t i = head; i < messages.size(); ++i) { - if (messages[i].getState() == AVAILABLE) ++count; - } - return count; - } - - T* find(const qpid::framing::SequenceNumber& position, QueueCursor* cursor) - { - size_t i = 0; - if (index(position, i)){ - T& m = messages[i]; - if (cursor) cursor->setPosition(position, version); - if (m.getState() == AVAILABLE || m.getState() == ACQUIRED) { - return &m; - } - } else if (cursor) { - if (i >= messages.size()) cursor->setPosition(position, version);//haven't yet got a message with that seq no - else if (i == 0) cursor->valid = false;//reset - } - return 0; - } - - T* find(const QueueCursor& cursor) - { - if (cursor.valid) return find(cursor.position, 0); - else return 0; - } - - void clean() - { - // QPID-4046: If a queue has multiple consumers, then it is possible for a large - // collection of deleted messages to build up. Limit the number of messages cleaned - // up on each call to clean(). - size_t count = 0; - while (messages.size() && messages.front().getState() == DELETED && count < 10) { - messages.pop_front(); - count += 1; - } - head = (head > count) ? head - count : 0; - QPID_LOG(debug, "clean(): " << messages.size() << " messages remain; head is now " << head); - } - - void foreach(Messages::Functor f) - { - for (typename Deque::iterator i = messages.begin(); i != messages.end(); ++i) { - if (i->getState() == AVAILABLE) { - f(*i); - } - } - clean(); - } - - void resetCursors() - { - ++version; - } - - typedef std::deque Deque; - Deque messages; - size_t head; - int32_t version; - Padding padding; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_INDEXEDDEQUE_H*/ diff --git a/qpid/cpp/src/qpid/broker/IngressCompletion.cpp b/qpid/cpp/src/qpid/broker/IngressCompletion.cpp deleted file mode 100644 index 51eafb8d86..0000000000 --- a/qpid/cpp/src/qpid/broker/IngressCompletion.cpp +++ /dev/null @@ -1,48 +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 "IngressCompletion.h" -#include "Queue.h" - -namespace qpid { -namespace broker { -IngressCompletion::~IngressCompletion() {} - -void IngressCompletion::enqueueAsync(boost::shared_ptr q) -{ - qpid::sys::Mutex::ScopedLock l(lock); - queues.push_back(q); -} - -void IngressCompletion::flush() -{ - Queues copy; - { - qpid::sys::Mutex::ScopedLock l(lock); - queues.swap(copy); - } - for (Queues::const_iterator i = copy.begin(); i != copy.end(); ++i) { - boost::shared_ptr q(i->lock()); - if (q) { - q->flush(); - } - } -} -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/IngressCompletion.h b/qpid/cpp/src/qpid/broker/IngressCompletion.h deleted file mode 100644 index ca21ec9837..0000000000 --- a/qpid/cpp/src/qpid/broker/IngressCompletion.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_BROKER_INGRESSCOMPLETION_H -#define QPID_BROKER_INGRESSCOMPLETION_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 "AsyncCompletion.h" -#include "qpid/sys/Mutex.h" -#include -#include -#include - -namespace qpid { -namespace broker { - -class Queue; -/** - * An AsyncCompletion object for async enqueues, that can be flushed - * when needed - */ -class IngressCompletion : public AsyncCompletion -{ - public: - QPID_BROKER_EXTERN virtual ~IngressCompletion(); - - void enqueueAsync(boost::shared_ptr); - void flush(); - private: - typedef std::vector > Queues; - Queues queues; - qpid::sys::Mutex lock; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_INGRESSCOMPLETION_H*/ diff --git a/qpid/cpp/src/qpid/broker/Link.cpp b/qpid/cpp/src/qpid/broker/Link.cpp deleted file mode 100644 index 037d1e16c6..0000000000 --- a/qpid/cpp/src/qpid/broker/Link.cpp +++ /dev/null @@ -1,799 +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/broker/Link.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/sys/Timer.h" -#include "qmf/org/apache/qpid/broker/EventBrokerLinkUp.h" -#include "qmf/org/apache/qpid/broker/EventBrokerLinkDown.h" -#include "boost/bind.hpp" -#include "qpid/log/Statement.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/broker/AclModule.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/NameGenerator.h" -#include "qpid/UrlArray.h" - -namespace qpid { -namespace broker { - -using framing::Buffer; -using framing::FieldTable; -using framing::UnauthorizedAccessException; -using framing::connection::CLOSE_CODE_CONNECTION_FORCED; -using management::ManagementAgent; -using management::ManagementObject; -using management::Manageable; -using management::Args; -using sys::Mutex; -using std::stringstream; -using std::string; -namespace _qmf = ::qmf::org::apache::qpid::broker; - - -namespace { - const std::string FAILOVER_EXCHANGE("amq.failover"); - const std::string FAILOVER_HEADER_KEY("amq.failover"); -} - - -struct LinkTimerTask : public sys::TimerTask { - LinkTimerTask(Link& l, sys::Timer& t) - : TimerTask(l.getBroker()->getLinkMaintenanceInterval(), - "Link retry timer"), - link(l), timer(t) {} - - void fire() { - link.maintenanceVisit(); - setupNextFire(); - timer.add(this); - } - - Link& link; - sys::Timer& timer; -}; - - - -/** LinkExchange is used by the link to subscribe to the remote broker's amq.failover exchange. - */ -class LinkExchange : public broker::Exchange -{ -public: - LinkExchange(const std::string& name) : Exchange(name), link(0) {} - ~LinkExchange() {}; - std::string getType() const { return Link::exchangeTypeName; } - - // Exchange methods - set up to prevent binding/unbinding etc from clients! - bool bind(boost::shared_ptr, const std::string&, const framing::FieldTable*) { return false; } - bool unbind(boost::shared_ptr, const std::string&, const framing::FieldTable*) { return false; } - bool isBound(boost::shared_ptr, const std::string* const, const framing::FieldTable* const) {return false;} - bool hasBindings() { return false; } - // Process messages sent from the remote's amq.failover exchange by extracting the failover URLs - // and saving them should the Link need to reconnect. - void route(broker::Deliverable& /*msg*/) - { - if (!link) return; - const framing::FieldTable* headers = 0;//TODO: msg.getMessage().getApplicationHeaders(); - framing::Array addresses; - if (headers && headers->getArray(FAILOVER_HEADER_KEY, addresses)) { - // convert the Array of addresses to a single Url container for used with setUrl(): - std::vector urlVec; - Url urls; - urlVec = urlArrayToVector(addresses); - for(size_t i = 0; i < urlVec.size(); ++i) - urls.insert(urls.end(), urlVec[i].begin(), urlVec[i].end()); - QPID_LOG(debug, "Remote broker has provided these failover addresses= " << urls); - link->setUrl(urls); - } - } - - void setLink(Link *_link) - { - assert(!link); - link = _link; - } - -private: - Link *link; -}; - - -boost::shared_ptr Link::linkExchangeFactory( const std::string& _name ) -{ - return Exchange::shared_ptr(new LinkExchange(_name)); -} - -Link::Link(const string& _name, - LinkRegistry* _links, - const string& _host, - uint16_t _port, - const string& _transport, - DestroyedListener l, - bool _durable, - const string& _authMechanism, - const string& _username, - const string& _password, - Broker* _broker, - Manageable* parent, - bool failover_) - : name(_name), links(_links), - configuredTransport(_transport), configuredHost(_host), configuredPort(_port), - host(_host), port(_port), transport(_transport), - durable(_durable), - authMechanism(_authMechanism), username(_username), password(_password), - persistenceId(0), broker(_broker), state(0), - visitCount(0), - currentInterval(1), - reconnectNext(0), // Index of next address for reconnecting in url. - nextFreeChannel(1), - freeChannels(1, framing::CHANNEL_MAX), - connection(0), - agent(0), - listener(l), - timerTask(new LinkTimerTask(*this, broker->getTimer())), - failover(failover_), - failoverChannel(0) -{ - if (parent != 0 && broker != 0) - { - agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtObject = _qmf::Link::shared_ptr(new _qmf::Link(agent, this, parent, name, durable)); - mgmtObject->set_host(host); - mgmtObject->set_port(port); - mgmtObject->set_transport(transport); - agent->addObject(mgmtObject, 0, durable); - } - } - setStateLH(STATE_WAITING); - startConnectionLH(); - broker->getTimer().add(timerTask); - - if (failover) { - stringstream exchangeName; - exchangeName << "qpid.link." << name; - std::pair rc = - broker->getExchanges().declare(exchangeName.str(), exchangeTypeName); - failoverExchange = boost::static_pointer_cast(rc.first); - assert(failoverExchange); - failoverExchange->setLink(this); - } -} - -Link::~Link () -{ - if (state == STATE_OPERATIONAL && connection != 0) { - closeConnection("closed by management"); - } - - if (mgmtObject != 0) - mgmtObject->resourceDestroy (); - - if (failover) - broker->getExchanges().destroy(failoverExchange->getName()); -} - -void Link::setStateLH (int newState) -{ - if (newState == state) - return; - - state = newState; - - switch (state) - { - case STATE_WAITING : mgmtObject->set_state("Waiting"); break; - case STATE_CONNECTING : mgmtObject->set_state("Connecting"); break; - case STATE_OPERATIONAL : mgmtObject->set_state("Operational"); break; - case STATE_FAILED : mgmtObject->set_state("Failed"); break; - case STATE_CLOSED : mgmtObject->set_state("Closed"); break; - case STATE_CLOSING : mgmtObject->set_state("Closing"); break; - } -} - -void Link::startConnectionLH () -{ - assert(state == STATE_WAITING); - try { - // Set the state before calling connect. It is possible that connect - // will fail synchronously and call Link::closed before returning. - setStateLH(STATE_CONNECTING); - broker->connect (name, host, boost::lexical_cast(port), transport, - boost::bind (&Link::closed, this, _1, _2)); - QPID_LOG (info, "Inter-broker link connecting to " << host << ":" << port); - } catch(const std::exception& e) { - QPID_LOG(error, "Link connection to " << host << ":" << port << " failed: " - << e.what()); - setStateLH(STATE_WAITING); - mgmtObject->set_lastError (e.what()); - } -} - -void Link::established(qpid::broker::amqp_0_10::Connection* c) -{ - stringstream addr; - addr << host << ":" << port; - QPID_LOG (info, "Inter-broker link established to " << addr.str()); - - if (agent) - agent->raiseEvent(_qmf::EventBrokerLinkUp(addr.str())); - bool isClosing = true; - { - Mutex::ScopedLock mutex(lock); - if (state != STATE_CLOSING) { - isClosing = false; - setStateLH(STATE_OPERATIONAL); - currentInterval = 1; - visitCount = 0; - connection = c; - c->requestIOProcessing ( - weakCallback(boost::bind(&Link::ioThreadProcessing, _1), this)); - } - } - if (isClosing) - destroy(); -} - - -void Link::setUrl(const Url& u) { - QPID_LOG(info, "Setting remote broker failover addresses for link '" << getName() << "' to these urls: " << u); - Mutex::ScopedLock mutex(lock); - url = u; - reconnectNext = 0; -} - - -namespace { -class DetachedCallback : public SessionHandler::ErrorListener { - public: - DetachedCallback(const Link& link) : name(link.getName()) {} - void connectionException(framing::connection::CloseCode, const std::string&) {} - void channelException(framing::session::DetachCode, const std::string&) {} - void executionException(framing::execution::ErrorCode, const std::string&) {} - void incomingExecutionException(framing::execution::ErrorCode, const std::string& ) {} - void detach() {} - private: - const std::string name; -}; -} - -void Link::opened() -{ - Mutex::ScopedLock mutex(lock); - if (!connection || state != STATE_OPERATIONAL) return; - - if (connection->GetManagementObject()) { - mgmtObject->set_connectionRef(connection->GetManagementObject()->getObjectId()); - } - - // Get default URL from known-hosts if not already set - if (url.empty()) { - const std::vector& known = connection->getKnownHosts(); - // Flatten vector of URLs into a single URL listing all addresses. - url.clear(); - for(size_t i = 0; i < known.size(); ++i) - url.insert(url.end(), known[i].begin(), known[i].end()); - reconnectNext = 0; - QPID_LOG(debug, "Known hosts for peer of inter-broker link: " << url); - } - - if (failover) { - // - // attempt to subscribe to failover exchange for updates from remote - // - - const std::string queueName = "qpid.link." + framing::Uuid(true).str(); - failoverChannel = nextChannel(); - - SessionHandler& sessionHandler = connection->getChannel(failoverChannel); - sessionHandler.setErrorListener( - boost::shared_ptr(new DetachedCallback(*this))); - failoverSession = queueName; - sessionHandler.attachAs(failoverSession); - - framing::AMQP_ServerProxy remoteBroker(sessionHandler.out); - - remoteBroker.getQueue().declare(queueName, - "", // alt-exchange - false, // passive - false, // durable - true, // exclusive - true, // auto-delete - FieldTable()); - remoteBroker.getExchange().bind(queueName, - FAILOVER_EXCHANGE, - "", // no key - FieldTable()); - remoteBroker.getMessage().subscribe(queueName, - failoverExchange->getName(), - 1, // implied-accept mode - 0, // pre-acquire mode - false, // exclusive - "", // resume-id - 0, // resume-ttl - FieldTable()); - remoteBroker.getMessage().flow(failoverExchange->getName(), 0, 0xFFFFFFFF); - remoteBroker.getMessage().flow(failoverExchange->getName(), 1, 0xFFFFFFFF); - } -} - - -// called when connection attempt fails (see startConnectionLH) -void Link::closed(int, std::string text) -{ - QPID_LOG (info, "Inter-broker link disconnected from " << host << ":" << port << " " << text); - - bool isClosing = false; - { - Mutex::ScopedLock mutex(lock); - - connection = 0; - - mgmtObject->set_connectionRef(qpid::management::ObjectId()); - if (state == STATE_OPERATIONAL && agent) { - stringstream addr; - addr << host << ":" << port; - agent->raiseEvent(_qmf::EventBrokerLinkDown(addr.str())); - } - - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - (*i)->closed(); - created.push_back(*i); - } - active.clear(); - - if (state == STATE_CLOSING) { - isClosing = true; - } else if (state != STATE_FAILED) { - setStateLH(STATE_WAITING); - mgmtObject->set_lastError (text); - } - } - if (isClosing) destroy(); -} - -// Cleans up the connection before destroying Link. Must be called in connection thread -// if the connection is active. Caller Note well: may call "delete this"! -void Link::destroy () -{ - Bridges toDelete; - - timerTask->cancel(); // call prior to locking so maintenance visit can finish - { - Mutex::ScopedLock mutex(lock); - - QPID_LOG (info, "Inter-broker link to " << configuredHost << ":" << configuredPort << " removed by management"); - closeConnection("closed by management"); - setStateLH(STATE_CLOSED); - - // Move the bridges to be deleted into a local vector so there is no - // corruption of the iterator caused by bridge deletion. - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - (*i)->closed(); - toDelete.push_back(*i); - } - active.clear(); - - for (Bridges::iterator i = created.begin(); i != created.end(); i++) - toDelete.push_back(*i); - created.clear(); - } - - // Now delete all bridges on this link (don't hold the lock for this). - for (Bridges::iterator i = toDelete.begin(); i != toDelete.end(); i++) - (*i)->close(); - toDelete.clear(); - // notify LinkRegistry that this Link has been destroyed. Will result in "delete - // this" if LinkRegistry is holding the last shared pointer to *this - listener(this); -} - -void Link::add(Bridge::shared_ptr bridge) -{ - Mutex::ScopedLock mutex(lock); - created.push_back (bridge); - if (connection) - connection->requestIOProcessing ( - weakCallback(boost::bind(&Link::ioThreadProcessing, _1), this)); - -} - -void Link::cancel(Bridge::shared_ptr bridge) -{ - bool needIOProcessing = false; - { - Mutex::ScopedLock mutex(lock); - - for (Bridges::iterator i = created.begin(); i != created.end(); i++) { - if ((*i).get() == bridge.get()) { - created.erase(i); - break; - } - } - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - if ((*i).get() == bridge.get()) { - cancellations.push_back(bridge); - bridge->closed(); - active.erase(i); - break; - } - } - needIOProcessing = !cancellations.empty(); - } - if (needIOProcessing && connection) - connection->requestIOProcessing ( - weakCallback(boost::bind(&Link::ioThreadProcessing, _1), this)); -} - -void Link::ioThreadProcessing() -{ - Mutex::ScopedLock mutex(lock); - - if (state != STATE_OPERATIONAL) - return; - - // check for bridge session errors and recover - if (!active.empty()) { - Bridges::iterator removed = std::remove_if( - active.begin(), active.end(), boost::bind(&Bridge::isDetached, _1)); - for (Bridges::iterator i = removed; i != active.end(); ++i) { - Bridge::shared_ptr bridge = *i; - bridge->closed(); - bridge->cancel(*connection); - created.push_back(bridge); - } - active.erase(removed, active.end()); - } - - //process any pending creates and/or cancellations (do - //cancellations first in case any of the creates represent - //recreation of cancelled subscriptions - if (!cancellations.empty()) { - for (Bridges::iterator i = cancellations.begin(); i != cancellations.end(); ++i) { - (*i)->cancel(*connection); - } - cancellations.clear(); - } - if (!created.empty()) { - for (Bridges::iterator i = created.begin(); i != created.end(); ++i) { - active.push_back(*i); - (*i)->create(*connection); - } - created.clear(); - } -} - -void Link::maintenanceVisit () -{ - Mutex::ScopedLock mutex(lock); - - switch (state) { - case STATE_WAITING: - visitCount++; - if (visitCount >= currentInterval) - { - visitCount = 0; - //switch host and port to next in url list if possible - if (!tryFailoverLH()) { - currentInterval *= 2; - if (currentInterval > MAX_INTERVAL) - currentInterval = MAX_INTERVAL; - startConnectionLH(); - } - } - break; - - case STATE_OPERATIONAL: - if ((!active.empty() || !created.empty() || !cancellations.empty()) && - connection && connection->isOpen()) - connection->requestIOProcessing ( - weakCallback(boost::bind(&Link::ioThreadProcessing, _1), this)); - break; - - default: // no-op for all other states - break; - } -} - -void Link::reconnectLH(const Address& a) -{ - host = a.host; - port = a.port; - transport = a.protocol; - - stringstream errorString; - errorString << "Failing over to " << a; - mgmtObject->set_lastError(errorString.str()); - mgmtObject->set_host(host); - mgmtObject->set_port(port); - mgmtObject->set_transport(transport); - - startConnectionLH(); -} - -bool Link::tryFailoverLH() { - assert(state == STATE_WAITING); - if (reconnectNext >= url.size()) reconnectNext = 0; - if (url.empty()) return false; - Address next = url[reconnectNext++]; - if (next.host != host || next.port != port || next.protocol != transport) { - QPID_LOG(info, "Inter-broker link '" << name << "' failing over to " << next); - reconnectLH(next); - return true; - } - return false; -} - -// Allocate channel from link free pool -framing::ChannelId Link::nextChannel() -{ - Mutex::ScopedLock mutex(lock); - if (!freeChannels.empty()) { - // A free channel exists. - for (framing::ChannelId i = 1; i <= framing::CHANNEL_MAX; i++) - { - // extract proposed free channel - framing::ChannelId c = nextFreeChannel; - // calculate next free channel - if (framing::CHANNEL_MAX == nextFreeChannel) - nextFreeChannel = 1; - else - nextFreeChannel += 1; - // if proposed channel is free, use it - if (freeChannels.contains(c)) - { - freeChannels -= c; - QPID_LOG(debug, "Link " << name << " allocates channel: " << c); - return c; - } - } - assert (false); - } - - throw Exception(Msg() << "Link " << name << " channel pool is empty"); -} - -// Return channel to link free pool -void Link::returnChannel(framing::ChannelId c) -{ - Mutex::ScopedLock mutex(lock); - QPID_LOG(debug, "Link " << name << " frees channel: " << c); - freeChannels += c; -} - -void Link::notifyConnectionForced(const string text) -{ - bool isClosing = false; - { - Mutex::ScopedLock mutex(lock); - if (state == STATE_CLOSING) { - isClosing = true; - } else { - setStateLH(STATE_FAILED); - mgmtObject->set_lastError(text); - } - } - if (isClosing) destroy(); -} - -void Link::setPersistenceId(uint64_t id) const -{ - persistenceId = id; -} - -const string& Link::getName() const -{ - return name; -} - -const std::string Link::ENCODED_IDENTIFIER("link.v2"); -const std::string Link::ENCODED_IDENTIFIER_V1("link"); - -bool Link::isEncodedLink(const std::string& key) -{ - return key == ENCODED_IDENTIFIER || key == ENCODED_IDENTIFIER_V1; -} - -Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer) -{ - string kind; - buffer.getShortString(kind); - - string host; - uint16_t port; - string transport; - string authMechanism; - string username; - string password; - string name; - - if (kind == ENCODED_IDENTIFIER) { - // newer version provides a link name. - buffer.getShortString(name); - } - buffer.getShortString(host); - port = buffer.getShort(); - buffer.getShortString(transport); - bool durable(buffer.getOctet()); - buffer.getShortString(authMechanism); - buffer.getShortString(username); - buffer.getShortString(password); - - if (kind == ENCODED_IDENTIFIER_V1) { - /** previous versions identified the Link by host:port, there was no name - * assigned. So create a name for the new Link. - */ - name = createName(transport, host, port); - } - - return links.declare(name, host, port, transport, durable, authMechanism, - username, password).first; -} - -void Link::encode(Buffer& buffer) const -{ - buffer.putShortString(ENCODED_IDENTIFIER); - buffer.putShortString(name); - buffer.putShortString(configuredHost); - buffer.putShort(configuredPort); - buffer.putShortString(configuredTransport); - buffer.putOctet(durable ? 1 : 0); - buffer.putShortString(authMechanism); - buffer.putShortString(username); - buffer.putShortString(password); -} - -uint32_t Link::encodedSize() const -{ - return ENCODED_IDENTIFIER.size() + 1 // +1 byte length - + name.size() + 1 - + configuredHost.size() + 1 // short-string (host) - + 2 // port - + configuredTransport.size() + 1 // short-string(transport) - + 1 // durable - + authMechanism.size() + 1 - + username.size() + 1 - + password.size() + 1; -} - -ManagementObject::shared_ptr Link::GetManagementObject(void) const -{ - return mgmtObject; -} - -void Link::close() { - QPID_LOG(debug, "Link::close(), link=" << name ); - bool destroy_now = false; - { - Mutex::ScopedLock mutex(lock); - if (state != STATE_CLOSING) { - int old_state = state; - setStateLH(STATE_CLOSING); - if (connection) { - //connection can only be closed on the connections own IO processing thread - connection->requestIOProcessing(boost::bind(&Link::destroy, shared_from_this())); - } else if (old_state == STATE_CONNECTING) { - // cannot destroy Link now since a connection request is outstanding. - // destroy the link after we get a response (see Link::established, - // Link::closed, Link::notifyConnectionForced, etc). - } else { - destroy_now = true; - } - } - } - if (destroy_now) destroy(); -} - - -Manageable::status_t Link::ManagementMethod (uint32_t op, Args& args, string& text) -{ - switch (op) - { - case _qmf::Link::METHOD_CLOSE : - close(); - return Manageable::STATUS_OK; - - case _qmf::Link::METHOD_BRIDGE : - /* TBD: deprecate this interface in favor of the Broker::create() method. The - * Broker::create() method allows the user to assign a name to the bridge. - */ - QPID_LOG(info, "The Link::bridge() method will be removed in a future release of QPID." - " Please use the Broker::create() method with type='bridge' instead."); - _qmf::ArgsLinkBridge& iargs = (_qmf::ArgsLinkBridge&) args; - QPID_LOG(debug, "Link::bridge() request received; src=" << iargs.i_src << - "; dest=" << iargs.i_dest << "; key=" << iargs.i_key); - - // Does a bridge already exist that has the src/dest/key? If so, re-use the - // existing bridge - this behavior is backward compatible with previous releases. - Bridge::shared_ptr bridge = links->getBridge(*this, iargs.i_src, iargs.i_dest, iargs.i_key); - if (!bridge) { - // need to create a new bridge on this link. - std::pair rc = - links->declare( Bridge::createName(name, iargs.i_src, iargs.i_dest, iargs.i_key), - *this, iargs.i_durable, - iargs.i_src, iargs.i_dest, iargs.i_key, iargs.i_srcIsQueue, - iargs.i_srcIsLocal, iargs.i_tag, iargs.i_excludes, - iargs.i_dynamic, iargs.i_sync, iargs.i_credit); - if (!rc.first) { - text = "invalid parameters"; - return Manageable::STATUS_PARAMETER_INVALID; - } - } - return Manageable::STATUS_OK; - } - - return Manageable::STATUS_UNKNOWN_METHOD; -} - -/** utility to clean up connection resources correctly */ -void Link::closeConnection( const std::string& reason) -{ - if (connection != 0) { - // cancel our subscription to the failover exchange - if (failover) { - SessionHandler& sessionHandler = connection->getChannel(failoverChannel); - if (sessionHandler.getSession()) { - framing::AMQP_ServerProxy remoteBroker(sessionHandler.out); - remoteBroker.getMessage().cancel(failoverExchange->getName()); - remoteBroker.getSession().detach(failoverSession); - } - } - connection->close(CLOSE_CODE_CONNECTION_FORCED, reason); - connection = 0; - } -} - -/** returns the current remote's address, and connection state */ -bool Link::getRemoteAddress(qpid::Address& addr) const -{ - addr.protocol = transport; - addr.host = host; - addr.port = port; - - return state == STATE_OPERATIONAL; -} - - -// FieldTable keys for internal state data -namespace { - const std::string FAILOVER_ADDRESSES("failover-addresses"); - const std::string FAILOVER_INDEX("failover-index"); -} - -std::string Link::createName(const std::string& transport, - const std::string& host, - uint16_t port) -{ - stringstream linkName; - linkName << QPID_NAME_PREFIX << transport << std::string(":") - << host << std::string(":") << port; - return linkName.str(); -} - -const std::string Link::exchangeTypeName("qpid.LinkExchange"); - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/Link.h b/qpid/cpp/src/qpid/broker/Link.h deleted file mode 100644 index c60632025c..0000000000 --- a/qpid/cpp/src/qpid/broker/Link.h +++ /dev/null @@ -1,208 +0,0 @@ -#ifndef _broker_Link_h -#define _broker_Link_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 -#include -#include "qpid/Url.h" -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/PersistableConfig.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/sys/Mutex.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/broker/Link.h" -#include - -namespace qpid { - -namespace sys { -class TimerTask; -} - -namespace broker { - -class LinkRegistry; -class Broker; -class LinkExchange; -namespace amqp_0_10 { -class Connection; -} - -class Link : public PersistableConfig, public management::Manageable, - public boost::enable_shared_from_this -{ - private: - mutable sys::Mutex lock; - const std::string name; - LinkRegistry* links; - - // these remain constant across failover - used to identify this link - const std::string configuredTransport; - const std::string configuredHost; - const uint16_t configuredPort; - // these reflect the current address of remote - will change during failover - std::string host; - uint16_t port; - std::string transport; - - bool durable; - - std::string authMechanism; - std::string username; - std::string password; - mutable uint64_t persistenceId; - qmf::org::apache::qpid::broker::Link::shared_ptr mgmtObject; - Broker* broker; - int state; - uint32_t visitCount; - uint32_t currentInterval; - Url url; // URL can contain many addresses. - size_t reconnectNext; // Index for next re-connect attempt - - typedef std::vector Bridges; - Bridges created; // Bridges pending creation - Bridges active; // Bridges active - Bridges cancellations; // Bridges pending cancellation - framing::ChannelId nextFreeChannel; - RangeSet freeChannels; - amqp_0_10::Connection* connection; - management::ManagementAgent* agent; - boost::function listener; - boost::intrusive_ptr timerTask; - boost::shared_ptr failoverExchange; // subscribed to remote's amq.failover exchange - bool failover; // Do we subscribe to a failover exchange? - uint failoverChannel; - std::string failoverSession; - - static const int STATE_WAITING = 1; - static const int STATE_CONNECTING = 2; - static const int STATE_OPERATIONAL = 3; - static const int STATE_FAILED = 4; - static const int STATE_CLOSED = 5; - static const int STATE_CLOSING = 6; // Waiting for outstanding connect to complete first - - static const uint32_t MAX_INTERVAL = 32; - - void setStateLH (int newState); - void startConnectionLH(); // Start the IO Connection - void destroy(); // Cleanup connection before link goes away - void ioThreadProcessing(); // Called on connection's IO thread by request - bool tryFailoverLH(); // Called during maintenance visit - void reconnectLH(const Address&); //called by LinkRegistry - - // connection management (called by LinkRegistry) - void established(amqp_0_10::Connection*); // Called when connection is created - void opened(); // Called when connection is open (after create) - void closed(int, std::string); // Called when connection goes away - void notifyConnectionForced(const std::string text); - void closeConnection(const std::string& reason); - - friend class LinkRegistry; // to call established, opened, closed - - public: - typedef boost::shared_ptr shared_ptr; - typedef boost::function DestroyedListener; - - Link(const std::string& name, - LinkRegistry* links, - const std::string& host, - uint16_t port, - const std::string& transport, - DestroyedListener l, - bool durable, - const std::string& authMechanism, - const std::string& username, - const std::string& password, - Broker* broker, - management::Manageable* parent = 0, - bool failover=true); - virtual ~Link(); - - /** these return the *configured* transport/host/port, which does not change over the - lifetime of the Link */ - std::string getHost() const { return configuredHost; } - uint16_t getPort() const { return configuredPort; } - std::string getTransport() const { return configuredTransport; } - - /** returns the current address of the remote, which may be different from the - configured transport/host/port due to failover. Returns true if connection is - active */ - QPID_BROKER_EXTERN bool getRemoteAddress(qpid::Address& addr) const; - - bool isDurable() { return durable; } - void maintenanceVisit (); - 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); - - QPID_BROKER_EXTERN void setUrl(const Url&); // Set URL for reconnection. - - // Close the link. - QPID_BROKER_EXTERN void close(); - - std::string getAuthMechanism() { return authMechanism; } - std::string getUsername() { return username; } - std::string getPassword() { return password; } - Broker* getBroker() { return broker; } - - bool isConnecting() const { return state == STATE_CONNECTING; } - - // PersistableConfig: - void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - uint32_t encodedSize() const; - void encode(framing::Buffer& buffer) const; - const std::string& getName() const; - - static const std::string ENCODED_IDENTIFIER; - static const std::string ENCODED_IDENTIFIER_V1; - static Link::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer); - static bool isEncodedLink(const std::string& key); - - // Manageable entry points - management::ManagementObject::shared_ptr GetManagementObject(void) const; - management::Manageable::status_t ManagementMethod(uint32_t, management::Args&, std::string&); - - // manage the exchange owned by this link - static const std::string exchangeTypeName; - static boost::shared_ptr linkExchangeFactory(const std::string& name); - - /** create a name for a link (if none supplied by user config) */ - static std::string createName(const std::string& transport, - const std::string& host, - uint16_t port); - - /** The current connction for this link. Note returns 0 if the link is not - * presently connected. - */ - amqp_0_10::Connection* getConnection() { return connection; } -}; -} -} - - -#endif /*!_broker_Link.cpp_h*/ diff --git a/qpid/cpp/src/qpid/broker/LinkRegistry.cpp b/qpid/cpp/src/qpid/broker/LinkRegistry.cpp deleted file mode 100644 index b3a78b98ca..0000000000 --- a/qpid/cpp/src/qpid/broker/LinkRegistry.cpp +++ /dev/null @@ -1,435 +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/broker/LinkRegistry.h" - -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/Link.h" -#include "qpid/log/Statement.h" -#include -#include - -namespace qpid { -namespace broker { - -using namespace qpid::sys; -using std::string; -using std::pair; -using std::stringstream; -using boost::intrusive_ptr; -using boost::format; -using boost::str; -namespace _qmf = qmf::org::apache::qpid::broker; - -// TODO: This constructor is only used by the store unit tests - -// That probably indicates that LinkRegistry isn't correctly -// factored: The persistence element should be factored separately -LinkRegistry::LinkRegistry () : - broker(0), - parent(0), store(0), - realm("") -{ -} - -class LinkRegistryConnectionObserver : public ConnectionObserver { - LinkRegistry& links; - public: - LinkRegistryConnectionObserver(LinkRegistry& l) : links(l) {} - void connection(Connection& in) - { - amqp_0_10::Connection* c = dynamic_cast(&in); - if (c) links.notifyConnection(c->getMgmtId(), c); - } - void opened(Connection& in) - { - amqp_0_10::Connection* c = dynamic_cast(&in); - if (c) links.notifyOpened(c->getMgmtId()); - } - void closed(Connection& in) - { - amqp_0_10::Connection* c = dynamic_cast(&in); - if (c) links.notifyClosed(c->getMgmtId()); - } - void forced(Connection& in, const string& text) - { - amqp_0_10::Connection* c = dynamic_cast(&in); - if (c) links.notifyConnectionForced(c->getMgmtId(), text); - } -}; - -LinkRegistry::LinkRegistry (Broker* _broker) : - broker(_broker), - parent(0), store(0), - realm(broker->getRealm()) -{ - broker->getConnectionObservers().add( - boost::shared_ptr(new LinkRegistryConnectionObserver(*this))); -} - -LinkRegistry::~LinkRegistry() {} - -/** find link by the *configured* remote address */ -boost::shared_ptr LinkRegistry::getLink(const std::string& host, - uint16_t port, - const std::string& transport) -{ - Mutex::ScopedLock locker(lock); - for (LinkMap::iterator i = links.begin(); i != links.end(); ++i) { - Link::shared_ptr& link = i->second; - if (link->getHost() == host && - link->getPort() == port && - (transport.empty() || link->getTransport() == transport)) - return link; - } - return boost::shared_ptr(); -} - -/** find link by name */ -boost::shared_ptr LinkRegistry::getLink(const std::string& name) -{ - Mutex::ScopedLock locker(lock); - LinkMap::iterator l = links.find(name); - if (l != links.end()) - return l->second; - return boost::shared_ptr(); -} - -pair LinkRegistry::declare(const string& name, - const string& host, - uint16_t port, - const string& transport, - bool durable, - const string& authMechanism, - const string& username, - const string& password, - bool failover) - -{ - Mutex::ScopedLock locker(lock); - - LinkMap::iterator i = links.find(name); - if (i == links.end()) - { - Link::shared_ptr link; - - link = Link::shared_ptr ( - new Link (name, this, host, port, transport, - boost::bind(&LinkRegistry::linkDestroyed, this, _1), - durable, authMechanism, username, password, broker, - parent, failover)); - if (durable && store && !broker->inRecovery()) - store->create(*link); - links[name] = link; - pendingLinks[name] = link; - QPID_LOG(debug, "Creating new link; name=" << name ); - return std::pair(link, true); - } - return std::pair(i->second, false); -} - -/** find bridge by link & route info */ -Bridge::shared_ptr LinkRegistry::getBridge(const Link& link, - const std::string& src, - const std::string& dest, - const std::string& key) -{ - Mutex::ScopedLock locker(lock); - for (BridgeMap::iterator i = bridges.begin(); i != bridges.end(); ++i) { - if (i->second->getSrc() == src && i->second->getDest() == dest && - i->second->getKey() == key && i->second->getLink() && - i->second->getLink()->getName() == link.getName()) { - return i->second; - } - } - return Bridge::shared_ptr(); -} - -/** find bridge by name */ -Bridge::shared_ptr LinkRegistry::getBridge(const std::string& name) -{ - Mutex::ScopedLock locker(lock); - BridgeMap::iterator b = bridges.find(name); - if (b != bridges.end()) - return b->second; - return Bridge::shared_ptr(); -} - -pair LinkRegistry::declare(const std::string& name, - Link& link, - bool durable, - const std::string& src, - const std::string& dest, - const std::string& key, - bool isQueue, - bool isLocal, - const std::string& tag, - const std::string& excludes, - bool dynamic, - uint16_t sync, - uint32_t credit, - Bridge::InitializeCallback init, - const std::string& queueName, - const std::string& altExchange -) -{ - Mutex::ScopedLock locker(lock); - - // Durable bridges are only valid on durable links - if (durable && !link.isDurable()) { - QPID_LOG(error, "Can't create a durable route '" << name << "' on a non-durable link '" << link.getName()); - return pair(Bridge::shared_ptr(), false); - } - - if (dynamic) { - Exchange::shared_ptr exchange = broker->getExchanges().get(src); - if (exchange.get() == 0) { - QPID_LOG(error, "Exchange not found, name='" << src << "'" ); - return pair(Bridge::shared_ptr(), false); - } - if (!exchange->supportsDynamicBinding()) { - QPID_LOG(error, "Exchange type does not support dynamic routing, name='" << src << "'"); - return pair(Bridge::shared_ptr(), false); - } - } - - BridgeMap::iterator b = bridges.find(name); - if (b == bridges.end()) - { - _qmf::ArgsLinkBridge args; - Bridge::shared_ptr bridge; - - args.i_durable = durable; - args.i_src = src; - args.i_dest = dest; - args.i_key = key; - args.i_srcIsQueue = isQueue; - args.i_srcIsLocal = isLocal; - args.i_tag = tag; - args.i_excludes = excludes; - args.i_dynamic = dynamic; - args.i_sync = sync; - args.i_credit = credit; - - bridge = Bridge::shared_ptr - (new Bridge (name, &link, link.nextChannel(), - boost::bind(&LinkRegistry::destroyBridge, this, _1), - args, init, queueName, altExchange)); - bridges[name] = bridge; - link.add(bridge); - if (durable && store && !broker->inRecovery()) - store->create(*bridge); - - QPID_LOG(debug, "Bridge '" << name <<"' declared on link '" << link.getName() << - "' from " << src << " to " << dest << " (" << key << ")"); - - return std::pair(bridge, true); - } - return std::pair(b->second, false); -} - -/** called back by the link when it has completed its cleanup and can be removed. */ -void LinkRegistry::linkDestroyed(Link *link) -{ - QPID_LOG(debug, "LinkRegistry::destroy(); link= " << link->getName()); - Mutex::ScopedLock locker(lock); - - pendingLinks.erase(link->getName()); - LinkMap::iterator i = links.find(link->getName()); - if (i != links.end()) - { - if (i->second->isDurable() && store) - store->destroy(*(i->second)); - links.erase(i); - } -} - -/** called back by bridge when its destruction has been requested */ -void LinkRegistry::destroyBridge(Bridge *bridge) -{ - QPID_LOG(debug, "LinkRegistry::destroy(); bridge= " << bridge->getName()); - Mutex::ScopedLock locker(lock); - - BridgeMap::iterator b = bridges.find(bridge->getName()); - if (b == bridges.end()) - return; - - Link *link = b->second->getLink(); - if (link) { - link->cancel(b->second); - link->returnChannel( bridge->getChannel() ); - } - if (b->second->isDurable()) - store->destroy(*(b->second)); - bridges.erase(b); -} - -void LinkRegistry::setStore (MessageStore* _store) -{ - store = _store; -} - -MessageStore* LinkRegistry::getStore() const { - return store; -} - -/** find the Link that corresponds to the given connection */ -Link::shared_ptr LinkRegistry::findLink(const std::string& connId) -{ - Mutex::ScopedLock locker(lock); - ConnectionMap::iterator c = connections.find(connId); - if (c != connections.end()) { - LinkMap::iterator l = links.find(c->second); - if (l != links.end()) - return l->second; - } - return Link::shared_ptr(); -} - -void LinkRegistry::notifyConnection(const std::string& key, amqp_0_10::Connection* c) -{ - // find a link that is attempting to connect to the remote, and - // create a mapping from connection id to link - QPID_LOG(debug, "LinkRegistry::notifyConnection(); key=" << key ); - std::string host; - Link::shared_ptr link; - { - Mutex::ScopedLock locker(lock); - LinkMap::iterator l = pendingLinks.find(key); - if (l != pendingLinks.end()) { - link = l->second; - pendingLinks.erase(l); - connections[key] = link->getName(); - QPID_LOG(debug, "LinkRegistry:: found pending =" << link->getName()); - } - } - - if (link) { - link->established(c); - c->setUserId(str(format("%1%@%2%") % link->getUsername() % realm)); - } -} - -void LinkRegistry::notifyOpened(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (link) link->opened(); -} - -void LinkRegistry::notifyClosed(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (link) { - { - Mutex::ScopedLock locker(lock); - pendingLinks[link->getName()] = link; - } - link->closed(0, "Closed by peer"); - } -} - -void LinkRegistry::notifyConnectionForced(const std::string& key, const std::string& text) -{ - Link::shared_ptr link = findLink(key); - if (link) { - { - Mutex::ScopedLock locker(lock); - pendingLinks[link->getName()] = link; - } - link->notifyConnectionForced(text); - } -} - -std::string LinkRegistry::getAuthMechanism(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (link) - return link->getAuthMechanism(); - return string("ANONYMOUS"); -} - -std::string LinkRegistry::getAuthCredentials(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - string result; - result += '\0'; - result += link->getUsername(); - result += '\0'; - result += link->getPassword(); - - return result; -} - -std::string LinkRegistry::getUsername(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getUsername(); -} - -/** note: returns the current remote host (may be different from the host originally - configured for the Link due to failover) */ -std::string LinkRegistry::getHost(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - qpid::Address addr; - link->getRemoteAddress(addr); - return addr.host; -} - -/** returns the current remote port (ditto above) */ -uint16_t LinkRegistry::getPort(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return 0; - - qpid::Address addr; - link->getRemoteAddress(addr); - return addr.port; -} - -std::string LinkRegistry::getPassword(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getPassword(); -} - -std::string LinkRegistry::getAuthIdentity(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getUsername(); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/LinkRegistry.h b/qpid/cpp/src/qpid/broker/LinkRegistry.h deleted file mode 100644 index a156a53624..0000000000 --- a/qpid/cpp/src/qpid/broker/LinkRegistry.h +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef _broker_LinkRegistry_h -#define _broker_LinkRegistry_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 -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/Address.h" -#include "qpid/sys/Mutex.h" -#include "qpid/management/Manageable.h" -#include -#include -#include - -namespace qpid { -namespace broker { -namespace amqp_0_10 { - class Connection; -} - class Link; - class Broker; - class LinkRegistry { - typedef std::map > LinkMap; - typedef std::map BridgeMap; - typedef std::map ConnectionMap; - - LinkMap links; /** indexed by name of Link */ - BridgeMap bridges; /** indexed by name of Bridge */ - ConnectionMap connections; /** indexed by connection identifier, gives link name */ - LinkMap pendingLinks; /** pending connection, indexed by name of Link */ - - qpid::sys::Mutex lock; - Broker* broker; - management::Manageable* parent; - MessageStore* store; - std::string realm; - - boost::shared_ptr findLink(const std::string& key); - - // Methods called by the connection observer, key is connection identifier - void notifyConnection (const std::string& key, amqp_0_10::Connection* c); - void notifyOpened (const std::string& key); - void notifyClosed (const std::string& key); - void notifyConnectionForced (const std::string& key, const std::string& text); - friend class LinkRegistryConnectionObserver; - - /** Notify the registry that a Link has been destroyed */ - void linkDestroyed(Link*); - /** Request to destroy a Bridge */ - void destroyBridge(Bridge*); - - public: - QPID_BROKER_EXTERN LinkRegistry (); // Only used in store tests - QPID_BROKER_EXTERN LinkRegistry (Broker* _broker); - QPID_BROKER_EXTERN ~LinkRegistry(); - - QPID_BROKER_EXTERN std::pair, bool> - declare(const std::string& name, - const std::string& host, - uint16_t port, - const std::string& transport, - bool durable, - const std::string& authMechanism, - const std::string& username, - const std::string& password, - bool failover=true); - - /** determine if Link exists */ - QPID_BROKER_EXTERN boost::shared_ptr - getLink(const std::string& name); - /** host,port,transport will be matched against the configured values, which may - be different from the current values due to failover */ - QPID_BROKER_EXTERN boost::shared_ptr - getLink(const std::string& configHost, - uint16_t configPort, - const std::string& configTransport = std::string()); - - QPID_BROKER_EXTERN std::pair - declare(const std::string& name, - Link& link, - bool durable, - const std::string& src, - const std::string& dest, - const std::string& key, - bool isQueue, - bool isLocal, - const std::string& id, - const std::string& excludes, - bool dynamic, - uint16_t sync, - uint32_t credit, - Bridge::InitializeCallback=0, - const std::string& queueName="", - const std::string& altExchange="" - ); - QPID_BROKER_EXTERN static const uint32_t INFINITE_CREDIT = 0xFFFFFFFF; - - /** determine if Bridge exists */ - QPID_BROKER_EXTERN Bridge::shared_ptr - getBridge(const std::string& name); - QPID_BROKER_EXTERN Bridge::shared_ptr - getBridge(const Link& link, - const std::string& src, - const std::string& dest, - const std::string& key); - - /** - * Register the manageable parent for declared queues - */ - void setParent (management::Manageable* _parent) { parent = _parent; } - - /** - * Set the store to use. May only be called once. - */ - QPID_BROKER_EXTERN void setStore (MessageStore*); - - /** - * Return the message store used. - */ - QPID_BROKER_EXTERN MessageStore* getStore() const; - - QPID_BROKER_EXTERN std::string getAuthMechanism (const std::string& key); - QPID_BROKER_EXTERN std::string getAuthCredentials (const std::string& key); - QPID_BROKER_EXTERN std::string getAuthIdentity (const std::string& key); - QPID_BROKER_EXTERN std::string getUsername (const std::string& key); - QPID_BROKER_EXTERN std::string getPassword (const std::string& key); - QPID_BROKER_EXTERN std::string getHost (const std::string& key); - QPID_BROKER_EXTERN uint16_t getPort (const std::string& key); - }; -} -} - - -#endif /*!_broker_LinkRegistry_h*/ diff --git a/qpid/cpp/src/qpid/broker/LossyLvq.cpp b/qpid/cpp/src/qpid/broker/LossyLvq.cpp deleted file mode 100644 index f59ecc1925..0000000000 --- a/qpid/cpp/src/qpid/broker/LossyLvq.cpp +++ /dev/null @@ -1,30 +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 "LossyLvq.h" -#include "MessageMap.h" - -namespace qpid { -namespace broker { - -LossyLvq::LossyLvq(const std::string& n, std::auto_ptr m, const QueueSettings& s, MessageStore* const ms, management::Manageable* p, Broker* b) - : Queue(n, s, ms, p, b), Lvq(n, m, s, ms, p, b), LossyQueue(n, s, ms, p, b) {} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/LossyLvq.h b/qpid/cpp/src/qpid/broker/LossyLvq.h deleted file mode 100644 index 2665ebe49f..0000000000 --- a/qpid/cpp/src/qpid/broker/LossyLvq.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_BROKER_LOSSYLVQ_H -#define QPID_BROKER_LOSSYLVQ_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/Lvq.h" -#include "qpid/broker/LossyQueue.h" - -namespace qpid { -namespace broker { -class MessageMap; - -// Disable inherited-by-dominance warning on MSVC. We know. It's ok. -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4250) -#endif - -/** - * Combination of LossyQueue and Lvq behaviours. - */ -class LossyLvq : public Lvq, public LossyQueue -{ - public: - LossyLvq(const std::string&, std::auto_ptr, const QueueSettings&, MessageStore* const, management::Manageable*, Broker*); -}; - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_LOSSYLVQ_H*/ diff --git a/qpid/cpp/src/qpid/broker/LossyQueue.cpp b/qpid/cpp/src/qpid/broker/LossyQueue.cpp deleted file mode 100644 index ee13d7733a..0000000000 --- a/qpid/cpp/src/qpid/broker/LossyQueue.cpp +++ /dev/null @@ -1,97 +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 "LossyQueue.h" -#include "QueueDepth.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -namespace { -bool isLowerPriorityThan(uint8_t priority, const Message& m) -{ - return m.getPriority() <= priority; -} -} - -LossyQueue::LossyQueue(const std::string& n, const QueueSettings& s, MessageStore* const ms, management::Manageable* p, Broker* b) - : Queue(n, s, ms, p, b) {} - -bool LossyQueue::checkDepth(const QueueDepth& increment, const Message& message) -{ - if (settings.maxDepth.hasSize() && increment.getSize() > settings.maxDepth.getSize()) { - if (mgmtObject) { - mgmtObject->inc_discardsOverflow(); - if (brokerMgmtObject) - brokerMgmtObject->inc_discardsOverflow(); - } - throw qpid::framing::ResourceLimitExceededException(QPID_MSG("Message larger than configured maximum depth on " - << name << ": size=" << increment.getSize() << ", max-size=" << settings.maxDepth.getSize())); - } - - while (settings.maxDepth && (settings.maxDepth - current < increment)) { - 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 - - // Note: in the case of a priority queue we are only comparing the new mesage - // with single lowest-priority message, hence the final parameter maxTests - // is 1 in this case, so we only test one message for removal. - if (remove(1, - settings.priorities ? - boost::bind(&isLowerPriorityThan, message.getPriority(), _1) : - MessagePredicate(), boost::bind(&reroute, alternateExchange, _1), - PURGE, false, - settings.priorities ? 1 : 0)) - { - if (mgmtObject) { - mgmtObject->inc_discardsRing(1); - if (brokerMgmtObject) - brokerMgmtObject->inc_discardsRing(1); - } - } else { - //should only be the case for a non-empty queue if we are - //testing priority and there was no lower (or equal) - //priority message available to purge - break; - } - } - if (settings.maxDepth && (settings.maxDepth - current < increment)) { - //will only be the case where we were unable to purge another - //message, which should only be the case if we are purging - //based on priority and there was no message with a lower (or - //equal) priority than this one, meaning that we drop this - //current message - if (mgmtObject) { - mgmtObject->inc_discardsRing(1); - if (brokerMgmtObject) - brokerMgmtObject->inc_discardsRing(1); - } - return false; - } else { - //have sufficient space for this message - current += increment; - return true; - } -} -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/LossyQueue.h b/qpid/cpp/src/qpid/broker/LossyQueue.h deleted file mode 100644 index 705865f449..0000000000 --- a/qpid/cpp/src/qpid/broker/LossyQueue.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef QPID_BROKER_LOSSYQUEUE_H -#define QPID_BROKER_LOSSYQUEUE_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/Queue.h" - -namespace qpid { -namespace broker { - -/** - * Drops messages to prevent a breach of any configured maximum depth. - */ -class LossyQueue : public virtual Queue -{ - public: - LossyQueue(const std::string&, const QueueSettings&, MessageStore* const, management::Manageable*, Broker*); - bool checkDepth(const QueueDepth& increment, const Message&); - private: -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_LOSSYQUEUE_H*/ diff --git a/qpid/cpp/src/qpid/broker/Lvq.cpp b/qpid/cpp/src/qpid/broker/Lvq.cpp deleted file mode 100644 index 34f080c57f..0000000000 --- a/qpid/cpp/src/qpid/broker/Lvq.cpp +++ /dev/null @@ -1,64 +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 "Lvq.h" -#include "MessageMap.h" -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace broker { -Lvq::Lvq(const std::string& n, std::auto_ptr m, const QueueSettings& s, MessageStore* const ms, management::Manageable* p, Broker* b) - : Queue(n, s, ms, p, b), messageMap(*m) -{ - messages = m; -} - -void Lvq::push(Message& message, bool isRecovery) -{ - QueueListeners::NotificationSet copy; - Message old; - bool removed; - { - qpid::sys::Mutex::ScopedLock locker(messageLock); - message.setSequence(++sequence); - interceptors.publish(message); - removed = messageMap.update(message, old); - listeners.populate(copy); - observeEnqueue(message, locker); - if (removed) { - if (mgmtObject) { - mgmtObject->inc_acquires(); - mgmtObject->inc_discardsLvq(); - if (brokerMgmtObject) { - brokerMgmtObject->inc_acquires(); - brokerMgmtObject->inc_discardsLvq(); - } - } - observeDequeue(old, locker, 0/*can't be empty, so no need to check autodelete*/); - } - } - copy.notify(); - if (removed) { - if (isRecovery) pendingDequeues.push_back(old); - else if (old.isPersistent()) - dequeueFromStore(old.getPersistentContext());//do outside of lock - } -} -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/Lvq.h b/qpid/cpp/src/qpid/broker/Lvq.h deleted file mode 100644 index 26ba2b4914..0000000000 --- a/qpid/cpp/src/qpid/broker/Lvq.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_BROKER_LVQ_H -#define QPID_BROKER_LVQ_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/Queue.h" - -namespace qpid { -namespace broker { -class MessageMap; - -/** - * Subclass of queue that handles last-value-queue semantics in - * conjunction with the MessageMap class. This requires an existing - * message to be 'replaced' by a newer message with the same key. - */ -class Lvq : public virtual Queue -{ - public: - Lvq(const std::string&, std::auto_ptr, const QueueSettings&, MessageStore* const, management::Manageable*, Broker*); - void push(Message& msg, bool isRecovery=false); - private: - MessageMap& messageMap; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_LVQ_H*/ diff --git a/qpid/cpp/src/qpid/broker/Message.cpp b/qpid/cpp/src/qpid/broker/Message.cpp deleted file mode 100644 index 76be9742c6..0000000000 --- a/qpid/cpp/src/qpid/broker/Message.cpp +++ /dev/null @@ -1,386 +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/broker/Message.h" - -#include "qpid/amqp/CharSequence.h" -#include "qpid/amqp/MapHandler.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/management/Manageable.h" -#include "qpid/StringUtils.h" -#include "qpid/log/Statement.h" -#include "qpid/assert.h" - -#include -#include -#include - -using boost::intrusive_ptr; -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::sys::TIME_MSEC; -using qpid::sys::FAR_FUTURE; -using qpid::amqp::CharSequence; -using qpid::amqp::MapHandler; -using std::string; - -namespace qpid { -namespace broker { - -Message::Message() : deliveryCount(-1), alreadyAcquired(false), replicationId(0), isReplicationIdSet(false) -{} - -Message::Message(boost::intrusive_ptr e, boost::intrusive_ptr p) - : sharedState(e), persistentContext(p), deliveryCount(-1), alreadyAcquired(false), replicationId(0), isReplicationIdSet(false) -{ - if (persistentContext) persistentContext->setIngressCompletion(e); -} - -Message::~Message() {} - - -std::string Message::getRoutingKey() const -{ - return getEncoding().getRoutingKey(); -} - -std::string Message::getTo() const -{ - return getEncoding().getTo(); -} -std::string Message::getSubject() const -{ - return getEncoding().getSubject(); -} -std::string Message::getReplyTo() const -{ - return getEncoding().getReplyTo(); -} - -bool Message::isPersistent() const -{ - return getEncoding().isPersistent(); -} - -uint64_t Message::getMessageSize() const -{ - return getEncoding().getMessageSize(); -} - -boost::intrusive_ptr Message::getIngressCompletion() const -{ - return sharedState; -} - -namespace -{ -const std::string X_QPID_TRACE("x-qpid.trace"); -} - -bool Message::isExcluded(const std::vector& excludes) const -{ - std::string traceStr = getEncoding().getAnnotationAsString(X_QPID_TRACE); - if (traceStr.size()) { - std::vector trace = split(traceStr, ", "); - for (std::vector::const_iterator i = excludes.begin(); i != excludes.end(); i++) { - for (std::vector::const_iterator j = trace.begin(); j != trace.end(); j++) { - if (*i == *j) { - return true; - } - } - } - } - return false; -} - -void Message::addTraceId(const std::string& id) -{ - std::string trace = getEncoding().getAnnotationAsString(X_QPID_TRACE); - if (trace.empty()) { - addAnnotation(X_QPID_TRACE, id); - } else if (trace.find(id) == std::string::npos) { - trace += ","; - trace += id; - addAnnotation(X_QPID_TRACE, trace); - } -} - -void Message::clearTrace() -{ - addAnnotation(X_QPID_TRACE, std::string()); -} - -uint64_t Message::getTimestamp() const -{ - return sharedState ? sharedState->getTimestamp() : 0; -} - -uint64_t Message::getTtl() const -{ - uint64_t ttl; - if (getTtl(ttl, 1)/*set to 1 if expired*/) { - return ttl; - } else { - return 0; - } -} - -bool Message::getTtl(uint64_t& ttl) const -{ - return getTtl(ttl, 0); //set to 0 if expired -} - -bool Message::getTtl(uint64_t& ttl, uint64_t expiredValue) const -{ - if (sharedState->getTtl(ttl) && sharedState->getExpiration() < FAR_FUTURE) { - sys::Duration remaining = sharedState->getTimeToExpiration(); - // convert from ns to ms - ttl = (int64_t(remaining) >= 1000000 ? int64_t(remaining)/1000000 : expiredValue); - return true; - } else { - return false; - } -} - -void Message::addAnnotation(const std::string& key, const qpid::types::Variant& value) -{ - annotations.get()[key] = value; - annotationsChanged(); -} - -void Message::annotationsChanged() -{ - if (persistentContext) { - uint64_t id = persistentContext->getPersistenceId(); - persistentContext = persistentContext->merge(getAnnotations()); - persistentContext->setIngressCompletion(sharedState); - persistentContext->setPersistenceId(id); - } -} - -uint8_t Message::getPriority() const -{ - return getEncoding().getPriority(); -} - -bool Message::getIsManagementMessage() const { return sharedState->getIsManagementMessage(); } - -const Connection* Message::getPublisher() const { return sharedState->getPublisher(); } -bool Message::isLocalTo(const OwnershipToken* token) const { - return token && sharedState->getPublisher() && token->isLocal(sharedState->getPublisher()); -} - - -qpid::framing::SequenceNumber Message::getSequence() const -{ - return sequence; -} -void Message::setSequence(const qpid::framing::SequenceNumber& s) -{ - sequence = s; -} - -MessageState Message::getState() const -{ - return state; -} -void Message::setState(MessageState s) -{ - state = s; -} -namespace { -const qpid::types::Variant::Map EMPTY_MAP; -} - -const qpid::types::Variant::Map& Message::getAnnotations() const -{ - return annotations ? *annotations : EMPTY_MAP; -} - -qpid::types::Variant Message::getAnnotation(const std::string& key) const -{ - const qpid::types::Variant::Map& a = getAnnotations(); - qpid::types::Variant::Map::const_iterator i = a.find(key); - if (i != a.end()) return i->second; - //FIXME: modify Encoding interface to allow retrieval of - //annotations of different types from the message data as received - //off the wire - return qpid::types::Variant(getEncoding().getAnnotationAsString(key)); -} - -std::string Message::getUserId() const -{ - return sharedState->getUserId(); -} - -Message::SharedState& Message::getSharedState() -{ - return *sharedState; -} -const Message::Encoding& Message::getEncoding() const -{ - return *sharedState; -} -Message::operator bool() const -{ - return !!sharedState; -} - -std::string Message::getContent() const -{ - return sharedState->getContent(); -} - -std::string Message::getPropertyAsString(const std::string& key) const -{ - return sharedState->getPropertyAsString(key); -} -namespace { -class PropertyRetriever : public MapHandler -{ - public: - PropertyRetriever(const std::string& key) : name(key) {} - void handleVoid(const CharSequence&) {} - void handleBool(const CharSequence& key, bool value) { handle(key, value); } - void handleUint8(const CharSequence& key, uint8_t value) { handle(key, value); } - void handleUint16(const CharSequence& key, uint16_t value) { handle(key, value); } - void handleUint32(const CharSequence& key, uint32_t value) { handle(key, value); } - void handleUint64(const CharSequence& key, uint64_t value) { handle(key, value); } - void handleInt8(const CharSequence& key, int8_t value) { handle(key, value); } - void handleInt16(const CharSequence& key, int16_t value) { handle(key, value); } - void handleInt32(const CharSequence& key, int32_t value) { handle(key, value); } - void handleInt64(const CharSequence& key, int64_t value) { handle(key, value); } - void handleFloat(const CharSequence& key, float value) { handle(key, value); } - void handleDouble(const CharSequence& key, double value) { handle(key, value); } - void handleString(const CharSequence& key, const CharSequence& value, const CharSequence& /*encoding*/) - { - if (matches(key)) result = std::string(value.data, value.size); - } - qpid::types::Variant getResult() { return result; } - - private: - std::string name; - qpid::types::Variant result; - - bool matches(const CharSequence& key) - { - return name.size()==key.size && - ::strncmp(key.data, name.data(), key.size) == 0; - } - - template void handle(const CharSequence& key, T value) - { - if (matches(key)) result = value; - } -}; -} -qpid::types::Variant Message::getProperty(const std::string& key) const -{ - PropertyRetriever r(key); - sharedState->processProperties(r); - return r.getResult(); -} - -std::string Message::printProperties() const -{ - return sharedState->printProperties(); -} - -boost::intrusive_ptr Message::getPersistentContext() const -{ - return persistentContext; -} - -void Message::processProperties(MapHandler& handler) const -{ - sharedState->processProperties(handler); -} - -bool Message::hasReplicationId() const { - return isReplicationIdSet; -} - -uint64_t Message::getReplicationId() const { - return replicationId; -} - -void Message::setReplicationId(framing::SequenceNumber id) { - replicationId = id; - isReplicationIdSet = true; -} - -sys::AbsTime Message::getExpiration() const -{ - return sharedState->getExpiration(); -} - -Message::SharedStateImpl::SharedStateImpl() : publisher(0), expiration(qpid::sys::FAR_FUTURE), isManagementMessage(false) {} - -const Connection* Message::SharedStateImpl::getPublisher() const -{ - return publisher; -} - -void Message::SharedStateImpl::setPublisher(const Connection* p) -{ - publisher = p; -} - -sys::AbsTime Message::SharedStateImpl::getExpiration() const -{ - return expiration; -} - -void Message::SharedStateImpl::setExpiration(sys::AbsTime e) -{ - expiration = e; -} - -sys::Duration Message::SharedStateImpl::getTimeToExpiration() const -{ - return sys::Duration(sys::AbsTime::now(), expiration); -} - -void Message::SharedStateImpl::computeExpiration() -{ - //TODO: this is still quite 0-10 specific... - uint64_t ttl; - if (getTtl(ttl)) { - // Use higher resolution time for the internal expiry calculation. - // Prevent overflow as a signed int64_t - Duration duration(std::min(ttl * TIME_MSEC, - (uint64_t) std::numeric_limits::max())); - expiration = AbsTime(sys::AbsTime::now(), duration); - } -} - -bool Message::SharedStateImpl::getIsManagementMessage() const -{ - return isManagementMessage; -} -void Message::SharedStateImpl::setIsManagementMessage(bool b) -{ - isManagementMessage = b; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/Message.h b/qpid/cpp/src/qpid/broker/Message.h deleted file mode 100644 index f704c7a876..0000000000 --- a/qpid/cpp/src/qpid/broker/Message.h +++ /dev/null @@ -1,237 +0,0 @@ -#ifndef _broker_Message_h -#define _broker_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/RefCounted.h" -#include "qpid/broker/PersistableMessage.h" -//TODO: move the following out of framing or replace it -#include "qpid/framing/SequenceNumber.h" -#include "qpid/sys/Time.h" -#include "qpid/types/Variant.h" - -#include "qpid/broker/BrokerImportExport.h" - -#include -#include -#include -#include - -namespace qpid { -namespace amqp { -class MapHandler; -struct MessageId; -} - -namespace management { -class ObjectId; -class Manageable; -} - -namespace broker { -class OwnershipToken; -class Connection; - -enum MessageState -{ - AVAILABLE=1, - ACQUIRED=2, - DELETED=4, - UNAVAILABLE=8 -}; - -class Message { -public: - class Encoding : public IngressCompletion - { - public: - virtual ~Encoding() {} - virtual std::string getRoutingKey() const = 0; - virtual bool isPersistent() const = 0; - virtual uint8_t getPriority() const = 0; - virtual uint64_t getMessageSize() const = 0; - virtual qpid::amqp::MessageId getMessageId() const = 0; - virtual qpid::amqp::MessageId getCorrelationId() const = 0; - virtual std::string getPropertyAsString(const std::string& key) const = 0; - virtual std::string getAnnotationAsString(const std::string& key) const = 0; - virtual bool getTtl(uint64_t&) const = 0; - virtual std::string getContent() const = 0; - virtual void processProperties(qpid::amqp::MapHandler&) const = 0; - virtual std::string getUserId() const = 0; - virtual uint64_t getTimestamp() const = 0; - virtual std::string getTo() const = 0; - virtual std::string getSubject() const = 0; - virtual std::string getReplyTo() const = 0; - virtual std::string printProperties() const = 0; - }; - - class SharedState : public Encoding - { - public: - virtual ~SharedState() {} - virtual const Connection* getPublisher() const = 0; - virtual void setPublisher(const Connection* p) = 0; - - virtual void setExpiration(sys::AbsTime e) = 0; - virtual sys::AbsTime getExpiration() const = 0; - virtual sys::Duration getTimeToExpiration() const = 0; - virtual void computeExpiration() = 0; - - virtual bool getIsManagementMessage() const = 0; - virtual void setIsManagementMessage(bool b) = 0; - }; - - class SharedStateImpl : public SharedState - { - const Connection* publisher; - qpid::sys::AbsTime expiration; - bool isManagementMessage; - public: - QPID_BROKER_EXTERN SharedStateImpl(); - virtual ~SharedStateImpl() {} - QPID_BROKER_EXTERN const Connection* getPublisher() const; - QPID_BROKER_EXTERN void setPublisher(const Connection* p); - QPID_BROKER_EXTERN void setExpiration(sys::AbsTime e); - QPID_BROKER_EXTERN sys::AbsTime getExpiration() const; - QPID_BROKER_EXTERN sys::Duration getTimeToExpiration() const; - QPID_BROKER_EXTERN void computeExpiration(); - QPID_BROKER_EXTERN bool getIsManagementMessage() const; - QPID_BROKER_EXTERN void setIsManagementMessage(bool b); - }; - - QPID_BROKER_EXTERN Message(boost::intrusive_ptr, boost::intrusive_ptr); - QPID_BROKER_EXTERN Message(); - QPID_BROKER_EXTERN ~Message(); - - bool isRedelivered() const { return deliveryCount > 0; } - bool hasBeenAcquired() const { return alreadyAcquired; } - void deliver() { ++deliveryCount; alreadyAcquired |= (deliveryCount>0); } - void undeliver() { --deliveryCount; } - int getDeliveryCount() const { return deliveryCount; } - void resetDeliveryCount() { deliveryCount = -1; alreadyAcquired = false; } - - const Connection* getPublisher() const; - bool isLocalTo(const OwnershipToken*) const; - - QPID_BROKER_EXTERN std::string getRoutingKey() const; - QPID_BROKER_EXTERN bool isPersistent() const; - - QPID_BROKER_EXTERN sys::AbsTime getExpiration() const; - uint64_t getTtl() const; - QPID_BROKER_EXTERN bool getTtl(uint64_t&) const; - - QPID_BROKER_EXTERN uint64_t getTimestamp() const; - - //required for selectors: - QPID_BROKER_EXTERN std::string getTo() const; - QPID_BROKER_EXTERN std::string getSubject() const; - QPID_BROKER_EXTERN std::string getReplyTo() const; - - QPID_BROKER_EXTERN void addAnnotation(const std::string& key, const qpid::types::Variant& value); - QPID_BROKER_EXTERN bool isExcluded(const std::vector& excludes) const; - QPID_BROKER_EXTERN void addTraceId(const std::string& id); - QPID_BROKER_EXTERN void clearTrace(); - QPID_BROKER_EXTERN uint8_t getPriority() const; - QPID_BROKER_EXTERN std::string getPropertyAsString(const std::string& key) const; - QPID_BROKER_EXTERN qpid::types::Variant getProperty(const std::string& key) const; - void processProperties(qpid::amqp::MapHandler&) const; - std::string printProperties() const; - - QPID_BROKER_EXTERN uint64_t getMessageSize() const; - - QPID_BROKER_EXTERN const Encoding& getEncoding() const; - QPID_BROKER_EXTERN operator bool() const; - QPID_BROKER_EXTERN SharedState& getSharedState(); - - bool getIsManagementMessage() const; - - QPID_BROKER_EXTERN qpid::framing::SequenceNumber getSequence() const; - QPID_BROKER_EXTERN void setSequence(const qpid::framing::SequenceNumber&); - - MessageState getState() const; - void setState(MessageState); - - QPID_BROKER_EXTERN qpid::types::Variant getAnnotation(const std::string& key) const; - QPID_BROKER_EXTERN const qpid::types::Variant::Map& getAnnotations() 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 - - QPID_BROKER_EXTERN boost::intrusive_ptr getIngressCompletion() const; - QPID_BROKER_EXTERN boost::intrusive_ptr getPersistentContext() const; - QPID_BROKER_EXTERN bool hasReplicationId() const; - QPID_BROKER_EXTERN uint64_t getReplicationId() const; - QPID_BROKER_EXTERN void setReplicationId(framing::SequenceNumber id); - - private: - /** - * Template for optional members that are only constructed when - * if/when needed, to conserve memory. (Boost::optional doesn't - * help here). - */ - template class Optional - { - boost::scoped_ptr value; - public: - Optional() : value(0) {} - Optional(const Optional& o) : value(o.value ? new T(*o.value) : 0) {} - T& get() - { - if (!value) value.reset(new T); - return *value; - } - const T& operator*() const - { - return *value; - } - Optional& operator=(const Optional& o) - { - if (o.value) { - if (!value) value.reset(new T(*o.value)); - } - return *this; - } - operator bool() const - { - return !!value; - } - }; - - - boost::intrusive_ptr sharedState; - boost::intrusive_ptr persistentContext; - int deliveryCount; - bool alreadyAcquired; - Optional annotations; - MessageState state; - qpid::framing::SequenceNumber sequence; - framing::SequenceNumber replicationId; - bool isReplicationIdSet:1; - - void annotationsChanged(); - bool getTtl(uint64_t&, uint64_t expiredValue) const; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/MessageAdapter.cpp b/qpid/cpp/src/qpid/broker/MessageAdapter.cpp deleted file mode 100644 index 489386f82e..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageAdapter.cpp +++ /dev/null @@ -1,81 +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/broker/MessageAdapter.h" - -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/MessageTransferBody.h" - -namespace { - const std::string EMPTY; -} - -namespace qpid { -namespace broker{ - - std::string TransferAdapter::getRoutingKey(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get(); - return p ? p->getRoutingKey() : EMPTY; - } - - std::string TransferAdapter::getExchange(const framing::FrameSet& f) - { - return f.as()->getDestination(); - } - - bool TransferAdapter::isImmediate(const framing::FrameSet&) - { - //TODO: delete this, immediate is no longer part of the spec - return false; - } - - const framing::FieldTable* TransferAdapter::getApplicationHeaders(const framing::FrameSet& f) - { - const framing::MessageProperties* p = f.getHeaders()->get(); - return p ? &(p->getApplicationHeaders()) : 0; - } - - bool TransferAdapter::isPersistent(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get(); - return p && p->getDeliveryMode() == 2; - } - - bool TransferAdapter::requiresAccept(const framing::FrameSet& f) - { - const framing::MessageTransferBody* b = f.as(); - return b && b->getAcceptMode() == 0/*EXPLICIT == 0*/; - } - - uint8_t TransferAdapter::getPriority(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get(); - return p ? p->getPriority() : 0; - } - - std::string TransferAdapter::getAppId(const framing::FrameSet& f) - { - const framing::MessageProperties* p = f.getHeaders()->get(); - return p ? p->getAppId() : EMPTY; - } -}} diff --git a/qpid/cpp/src/qpid/broker/MessageAdapter.h b/qpid/cpp/src/qpid/broker/MessageAdapter.h deleted file mode 100644 index df50db4063..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageAdapter.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _broker_MessageAdapter_h -#define _broker_MessageAdapter_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 -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FrameSet.h" - -namespace qpid { -namespace broker { - -// TODO aconway 2007-11-09: No longer needed, we only have one type of message. -struct MessageAdapter -{ - virtual ~MessageAdapter() {} - - virtual std::string getRoutingKey(const framing::FrameSet& f) = 0; - virtual std::string getExchange(const framing::FrameSet& f) = 0; - virtual bool isImmediate(const framing::FrameSet& f) = 0; - virtual const framing::FieldTable* getApplicationHeaders(const framing::FrameSet& f) = 0; - virtual bool isPersistent(const framing::FrameSet& f) = 0; - virtual bool requiresAccept(const framing::FrameSet& f) = 0; - virtual uint8_t getPriority(const framing::FrameSet& f) = 0; - virtual std::string getAppId(const framing::FrameSet& f) = 0; -}; - -struct TransferAdapter : MessageAdapter -{ - virtual std::string getRoutingKey(const framing::FrameSet& f); - virtual std::string getExchange(const framing::FrameSet& f); - virtual const framing::FieldTable* getApplicationHeaders(const framing::FrameSet& f); - virtual bool isPersistent(const framing::FrameSet& f); - bool isImmediate(const framing::FrameSet&); - bool requiresAccept(const framing::FrameSet& f); - uint8_t getPriority(const framing::FrameSet& f); - virtual std::string getAppId(const framing::FrameSet& f); -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/MessageBuilder.cpp b/qpid/cpp/src/qpid/broker/MessageBuilder.cpp deleted file mode 100644 index 109c9b8757..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageBuilder.cpp +++ /dev/null @@ -1,125 +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/broker/MessageBuilder.h" - -#include "qpid/broker/Message.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; -using namespace qpid::framing; - -namespace -{ - std::string type_str(uint8_t type); - const std::string QPID_MANAGEMENT("qpid.management"); -} - -MessageBuilder::MessageBuilder() : state(DORMANT), copyExchange(true) {} - -void MessageBuilder::handle(AMQFrame& frame) -{ - uint8_t type = frame.getBody()->type(); - switch(state) { - case METHOD: - checkType(METHOD_BODY, type); - if (!frame.getMethod()->isA()) - throw NotImplementedException(QPID_MSG("Unexpected method: " << *(frame.getMethod()))); - - exchange = frame.castBody()->getDestination(); - state = HEADER; - break; - case HEADER: - if (type == CONTENT_BODY) { - //TODO: rethink how to handle non-existent headers(?)... - //didn't get a header: add in a dummy - AMQFrame header((AMQHeaderBody())); - header.setBof(false); - header.setEof(false); - message->getFrames().append(header); - } else if (type == HEADER_BODY) { - if (copyExchange) { - frame.castBody()->get(true)-> - setExchange(exchange); - } - } else { - throw CommandInvalidException( - QPID_MSG("Invalid frame sequence for message, expected header or content got " - << type_str(type) << ")")); - } - state = CONTENT; - break; - case CONTENT: - checkType(CONTENT_BODY, type); - break; - default: - throw CommandInvalidException(QPID_MSG("Invalid frame sequence for message (state=" << state << ")")); - } - message->getFrames().append(frame); -} - -void MessageBuilder::end() -{ - message->computeRequiredCredit(); - message = 0; - state = DORMANT; -} - -void MessageBuilder::start(const SequenceNumber& id) -{ - message = intrusive_ptr(new qpid::broker::amqp_0_10::MessageTransfer(id)); - state = METHOD; -} - -namespace { - -const std::string HEADER_BODY_S = "HEADER"; -const std::string METHOD_BODY_S = "METHOD"; -const std::string CONTENT_BODY_S = "CONTENT"; -const std::string HEARTBEAT_BODY_S = "HEARTBEAT"; -const std::string UNKNOWN = "unknown"; - -std::string type_str(uint8_t type) -{ - switch(type) { - case METHOD_BODY: return METHOD_BODY_S; - case HEADER_BODY: return HEADER_BODY_S; - case CONTENT_BODY: return CONTENT_BODY_S; - case HEARTBEAT_BODY: return HEARTBEAT_BODY_S; - } - return UNKNOWN; -} - -} - -void MessageBuilder::checkType(uint8_t expected, uint8_t actual) -{ - if (expected != actual) { - throw CommandInvalidException(QPID_MSG("Invalid frame sequence for message (expected " - << type_str(expected) << " got " << type_str(actual) << ")")); - } -} - -boost::intrusive_ptr MessageBuilder::getMessage() { return message; } diff --git a/qpid/cpp/src/qpid/broker/MessageBuilder.h b/qpid/cpp/src/qpid/broker/MessageBuilder.h deleted file mode 100644 index e7a668e18d..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageBuilder.h +++ /dev/null @@ -1,62 +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. - * - */ -#ifndef _MessageBuilder_ -#define _MessageBuilder_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/RefCounted.h" - -#include - -#include - -namespace qpid { - namespace broker { - namespace amqp_0_10 { - class MessageTransfer; - } - - class QPID_BROKER_CLASS_EXTERN MessageBuilder : public framing::FrameHandler{ - public: - QPID_BROKER_EXTERN MessageBuilder(); - QPID_BROKER_EXTERN void handle(framing::AMQFrame& frame); - boost::intrusive_ptr getMessage(); - QPID_BROKER_EXTERN void start(const framing::SequenceNumber& id); - void end(); - void setCopyExchange(bool value) { copyExchange = value; } - - private: - enum State {DORMANT, METHOD, HEADER, CONTENT}; - State state; - boost::intrusive_ptr message; - std::string exchange; - bool copyExchange; - - void checkType(uint8_t expected, uint8_t actual); - }; - } -} - - -#endif - diff --git a/qpid/cpp/src/qpid/broker/MessageDeque.cpp b/qpid/cpp/src/qpid/broker/MessageDeque.cpp deleted file mode 100644 index 1529d4ac94..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageDeque.cpp +++ /dev/null @@ -1,89 +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/broker/MessageDeque.h" -#include "assert.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/QueueCursor.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { -namespace { -Message padding(qpid::framing::SequenceNumber id) { - Message m; - m.setState(DELETED); - m.setSequence(id); - return m; -} -} - -using qpid::framing::SequenceNumber; - -MessageDeque::MessageDeque() : messages(&padding) {} - - -bool MessageDeque::deleted(const QueueCursor& cursor) -{ - return messages.deleted(cursor); -} - -void MessageDeque::publish(const Message& added) -{ - messages.publish(added); -} - -Message* MessageDeque::release(const QueueCursor& cursor) -{ - return messages.release(cursor); -} - -Message* MessageDeque::next(QueueCursor& cursor) -{ - return messages.next(cursor); -} - -size_t MessageDeque::size() -{ - return messages.size(); -} - -Message* MessageDeque::find(const framing::SequenceNumber& position, QueueCursor* cursor) -{ - return messages.find(position, cursor); -} - -Message* MessageDeque::find(const QueueCursor& cursor) -{ - return messages.find(cursor); -} - -void MessageDeque::foreach(Functor f) -{ - messages.foreach(f); -} - -void MessageDeque::resetCursors() -{ - messages.resetCursors(); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/MessageDeque.h b/qpid/cpp/src/qpid/broker/MessageDeque.h deleted file mode 100644 index ec67476926..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageDeque.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef QPID_BROKER_MESSAGEDEQUE_H -#define QPID_BROKER_MESSAGEDEQUE_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/Messages.h" -#include "qpid/broker/IndexedDeque.h" - -namespace qpid { -namespace broker { - -/** - * Provides the standard FIFO queue behaviour. - */ -class MessageDeque : public Messages -{ - public: - MessageDeque(); - size_t size(); - bool deleted(const QueueCursor&); - void publish(const Message& added); - Message* next(QueueCursor&); - Message* release(const QueueCursor& cursor); - Message* find(const QueueCursor&); - Message* find(const framing::SequenceNumber&, QueueCursor*); - - void foreach(Functor); - - void resetCursors(); - - private: - typedef IndexedDeque Deque; - Deque messages; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGEDEQUE_H*/ diff --git a/qpid/cpp/src/qpid/broker/MessageDistributor.h b/qpid/cpp/src/qpid/broker/MessageDistributor.h deleted file mode 100644 index c11e4495a1..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageDistributor.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _broker_MessageDistributor_h -#define _broker_MessageDistributor_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/types/Variant.h" -/** Abstraction used by Queue to determine the next "most desirable" message to provide to - * a particular consuming client - */ - -namespace qpid { -namespace broker { - -class Message; - -class MessageDistributor -{ - public: - virtual ~MessageDistributor() {}; - - /** - * Determine whether the named consumer can take ownership of the specified message. - * @param consumer the name of the consumer that is attempting to acquire the message - * @param target the message to be acquired - * @return true if ownership is permitted, false if ownership cannot be assigned. - */ - virtual bool acquire(const std::string& consumer, Message& target) = 0; - - /** hook to add any interesting management state to the status map */ - virtual void query(qpid::types::Variant::Map&) const = 0; -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/MessageGroupManager.cpp b/qpid/cpp/src/qpid/broker/MessageGroupManager.cpp deleted file mode 100644 index c083e4ee0f..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageGroupManager.cpp +++ /dev/null @@ -1,313 +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/broker/MessageGroupManager.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Messages.h" -#include "qpid/broker/MessageDeque.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/TypeCode.h" -#include "qpid/types/Variant.h" -#include "qpid/log/Statement.h" -#include "qpid/types/Variant.h" - -using namespace qpid::broker; - -namespace { - const std::string GROUP_QUERY_KEY("qpid.message_group_queue"); - const std::string GROUP_HEADER_KEY("group_header_key"); - const std::string GROUP_STATE_KEY("group_state"); - const std::string GROUP_ID_KEY("group_id"); - const std::string GROUP_MSG_COUNT("msg_count"); - const std::string GROUP_TIMESTAMP("timestamp"); - const std::string GROUP_CONSUMER("consumer"); -} - - -const std::string MessageGroupManager::qpidMessageGroupKey("qpid.group_header_key"); -const std::string MessageGroupManager::qpidSharedGroup("qpid.shared_msg_group"); -const std::string MessageGroupManager::qpidMessageGroupTimestamp("qpid.group_timestamp"); - - -/** return an iterator to the message at position, or members.end() if not found */ -MessageGroupManager::GroupState::MessageFifo::iterator -MessageGroupManager::GroupState::findMsg(const qpid::framing::SequenceNumber &position) -{ - MessageState mState(position); - MessageFifo::iterator found = std::lower_bound(members.begin(), members.end(), mState); - return (found->position == position) ? found : members.end(); -} - -void MessageGroupManager::unFree( const GroupState& state ) -{ - GroupFifo::iterator pos = freeGroups.find( state.members.front().position ); - assert( pos != freeGroups.end() && pos->second == &state ); - freeGroups.erase( pos ); -} - -void MessageGroupManager::own( GroupState& state, const std::string& owner ) -{ - state.owner = owner; - unFree( state ); -} - -void MessageGroupManager::disown( GroupState& state ) -{ - state.owner.clear(); - assert(state.members.size()); - assert(freeGroups.find(state.members.front().position) == freeGroups.end()); - freeGroups[state.members.front().position] = &state; -} - -MessageGroupManager::GroupState& MessageGroupManager::findGroup( const Message& m ) -{ - uint32_t thisMsg = m.getSequence().getValue(); - if (cachedGroup && lastMsg == thisMsg) { - hits++; - return *cachedGroup; - } - - std::string group = m.getPropertyAsString(groupIdHeader); - if (group.empty()) group = defaultGroupId; //empty group is reserved - - if (cachedGroup && group == lastGroup) { - hits++; - lastMsg = thisMsg; - return *cachedGroup; - } - - misses++; - - GroupState& found = messageGroups[group]; - if (found.group.empty()) - found.group = group; // new group, assign name - lastMsg = thisMsg; - lastGroup = group; - cachedGroup = &found; - return found; -} - - -void MessageGroupManager::enqueued( const Message& m ) -{ - // @todo KAG optimization - store reference to group state in QueuedMessage - // issue: const-ness?? - GroupState& state = findGroup(m); - GroupState::MessageState mState(m.getSequence()); - state.members.push_back(mState); - uint32_t total = state.members.size(); - QPID_LOG( trace, "group queue " << qName << - ": added message to group id=" << state.group << " total=" << total ); - if (total == 1) { - // newly created group, no owner - assert(freeGroups.find(m.getSequence()) == freeGroups.end()); - freeGroups[m.getSequence()] = &state; - } -} - - -void MessageGroupManager::acquired( const Message& m ) -{ - // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage - // issue: const-ness?? - GroupState& state = findGroup(m); - GroupState::MessageFifo::iterator gm = state.findMsg(m.getSequence()); - assert(gm != state.members.end()); - gm->acquired = true; - state.acquired += 1; - QPID_LOG( trace, "group queue " << qName << - ": acquired message in group id=" << state.group << " acquired=" << state.acquired ); -} - - -void MessageGroupManager::requeued( const Message& m ) -{ - // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage - // issue: const-ness?? - GroupState& state = findGroup(m); - assert( state.acquired != 0 ); - state.acquired -= 1; - GroupState::MessageFifo::iterator i = state.findMsg(m.getSequence()); - assert(i != state.members.end()); - i->acquired = false; - if (state.acquired == 0 && state.owned()) { - QPID_LOG( trace, "group queue " << qName << - ": consumer name=" << state.owner << " released group id=" << state.group); - disown(state); - } - QPID_LOG( trace, "group queue " << qName << - ": requeued message to group id=" << state.group << " acquired=" << state.acquired ); -} - - -void MessageGroupManager::dequeued( const Message& m ) -{ - // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage - // issue: const-ness?? - GroupState& state = findGroup(m); - GroupState::MessageFifo::iterator i = state.findMsg(m.getSequence()); - assert(i != state.members.end()); - if (i->acquired) { - assert( state.acquired != 0 ); - state.acquired -= 1; - } - - // special case if qm is first (oldest) message in the group: - // may need to re-insert it back on the freeGroups list, as the index will change - bool reFreeNeeded = false; - if (i == state.members.begin()) { - if (!state.owned()) { - // will be on the freeGroups list if mgmt is dequeueing rather than a consumer! - // if on freelist, it is indexed by first member, which is about to be removed! - unFree(state); - reFreeNeeded = true; - } - state.members.pop_front(); - } else { - state.members.erase(i); - } - - uint32_t total = state.members.size(); - QPID_LOG( trace, "group queue " << qName << - ": dequeued message from group id=" << state.group << " total=" << total ); - - if (total == 0) { - QPID_LOG( trace, "group queue " << qName << ": deleting group id=" << state.group); - if (cachedGroup == &state) { - cachedGroup = 0; - } - std::string key(state.group); - messageGroups.erase( key ); - } else if (state.acquired == 0 && state.owned()) { - QPID_LOG( trace, "group queue " << qName << - ": consumer name=" << state.owner << " released group id=" << state.group); - disown(state); - MessageDeque* md = dynamic_cast(&messages); - if (md) { - md->resetCursors(); - } else { - QPID_LOG(warning, "Could not reset cursors for message group, unexpected container type"); - } - } else if (reFreeNeeded) { - disown(state); - } -} - -MessageGroupManager::~MessageGroupManager() -{ - QPID_LOG( debug, "group queue " << qName << " cache results: hits=" << hits << " misses=" << misses ); -} - -bool MessageGroupManager::acquire(const std::string& consumer, Message& m) -{ - if (m.getState() == AVAILABLE) { - // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage - GroupState& state = findGroup(m); - - if (!state.owned()) { - own( state, consumer ); - QPID_LOG( trace, "group queue " << qName << - ": consumer name=" << consumer << " has acquired group id=" << state.group); - } - if (state.owner == consumer) { - m.setState(ACQUIRED); - return true; - } else { - return false; - } - } else { - return false; - } -} - -void MessageGroupManager::query(qpid::types::Variant::Map& status) const -{ - /** Add a description of the current state of the message groups for this queue. - FORMAT: - { "qpid.message_group_queue": - { "group_header_key" : "", - "group_state" : - [ { "group_id" : "", - "msg_count" : , - "timestamp" : , - "consumer" : }, - {...} // one for each known group - ] - } - } - **/ - - assert(status.find(GROUP_QUERY_KEY) == status.end()); - qpid::types::Variant::Map state; - qpid::types::Variant::List groups; - - state[GROUP_HEADER_KEY] = groupIdHeader; - for (GroupMap::const_iterator g = messageGroups.begin(); - g != messageGroups.end(); ++g) { - qpid::types::Variant::Map info; - info[GROUP_ID_KEY] = g->first; - info[GROUP_MSG_COUNT] = (uint64_t) g->second.members.size(); - // set the timestamp to the arrival timestamp of the oldest (HEAD) message, if present - info[GROUP_TIMESTAMP] = 0; - if (g->second.members.size() != 0) { - Message* m = messages.find(g->second.members.front().position, 0); - if (m && m->getTimestamp()) { - info[GROUP_TIMESTAMP] = m->getTimestamp(); - } - } - info[GROUP_CONSUMER] = g->second.owner; - groups.push_back(info); - } - state[GROUP_STATE_KEY] = groups; - status[GROUP_QUERY_KEY] = state; -} - - -boost::shared_ptr MessageGroupManager::create( const std::string& qName, - Messages& messages, - const QueueSettings& settings ) -{ - boost::shared_ptr manager( new MessageGroupManager( settings.groupKey, qName, messages, settings.addTimestamp ) ); - QPID_LOG( debug, "Configured Queue '" << qName << - "' for message grouping using header key '" << settings.groupKey << "'" << - " (timestamp=" << settings.addTimestamp << ")"); - return manager; -} - -std::string MessageGroupManager::defaultGroupId; -void MessageGroupManager::setDefaults(const std::string& groupId) // static -{ - defaultGroupId = groupId; -} - -namespace { - const std::string GROUP_NAME("name"); - const std::string GROUP_OWNER("owner"); - const std::string GROUP_ACQUIRED_CT("acquired-ct"); - const std::string GROUP_POSITIONS("positions"); - const std::string GROUP_ACQUIRED_MSGS("acquired-msgs"); - const std::string GROUP_STATE("group-state"); -} - diff --git a/qpid/cpp/src/qpid/broker/MessageGroupManager.h b/qpid/cpp/src/qpid/broker/MessageGroupManager.h deleted file mode 100644 index bf45e776c8..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageGroupManager.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef _broker_MessageGroupManager_h -#define _broker_MessageGroupManager_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. - * - */ - -/* for managing message grouping on Queues */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/broker/MessageDistributor.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/sys/unordered_map.h" - -#include "boost/shared_ptr.hpp" -#include - -namespace qpid { -namespace broker { - -class QueueObserver; -struct QueueSettings; -class MessageDistributor; -class Messages; -class Consumer; - -class MessageGroupManager : public QueueObserver, public MessageDistributor -{ - static std::string defaultGroupId; // assigned if no group id header present - - const std::string groupIdHeader; // msg header holding group identifier - const unsigned int timestamp; // mark messages with timestamp if set - Messages& messages; // parent Queue's in memory message container - const std::string qName; // name of parent queue (for logs) - - struct GroupState { - // note: update getState()/setState() when changing this object's state implementation - - // track which messages are in this group, and if they have been acquired - struct MessageState { - qpid::framing::SequenceNumber position; - bool acquired; - MessageState() : acquired(false) {} - MessageState(const qpid::framing::SequenceNumber& p) : position(p), acquired(false) {} - bool operator<(const MessageState& b) const { return position < b.position; } - }; - typedef std::deque MessageFifo; - - std::string group; // group identifier - std::string owner; // consumer with outstanding acquired messages - uint32_t acquired; // count of outstanding acquired messages - MessageFifo members; // msgs belonging to this group, in enqueue order - - GroupState() : acquired(0) {} - bool owned() const {return !owner.empty();} - MessageFifo::iterator findMsg(const qpid::framing::SequenceNumber &); - }; - - typedef sys::unordered_map GroupMap; - typedef std::map GroupFifo; - - GroupMap messageGroups; // index: group name - GroupFifo freeGroups; // ordered by oldest free msg - //Consumers consumers; // index: consumer name - - GroupState& findGroup( const Message& m ); - unsigned long hits, misses; // for debug - uint32_t lastMsg; - std::string lastGroup; - GroupState *cachedGroup; - - void unFree( const GroupState& state ); - void own( GroupState& state, const std::string& owner ); - void disown( GroupState& state ); - - public: - static const std::string qpidMessageGroupKey; - static const std::string qpidSharedGroup; // if specified, one group can be consumed by multiple receivers - static const std::string qpidMessageGroupTimestamp; - - static QPID_BROKER_EXTERN void setDefaults(const std::string& groupId); - static boost::shared_ptr create( const std::string& qName, - Messages& messages, - const QueueSettings& settings ); - - MessageGroupManager(const std::string& header, const std::string& _qName, - Messages& container, unsigned int _timestamp=0 ) - : groupIdHeader( header ), timestamp(_timestamp), messages(container), - qName(_qName), - hits(0), misses(0), - lastMsg(0), cachedGroup(0) {} - virtual ~MessageGroupManager(); - - // QueueObserver iface - void enqueued( const Message& qm ); - void acquired( const Message& qm ); - void requeued( const Message& qm ); - void dequeued( const Message& qm ); - void consumerAdded( const Consumer& ) {}; - void consumerRemoved( const Consumer& ) {}; - - // MessageDistributor iface - bool acquire(const std::string& c, Message& ); - void query(qpid::types::Variant::Map&) const; - - bool match(const qpid::types::Variant::Map*, const Message&) const; -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/MessageInterceptor.h b/qpid/cpp/src/qpid/broker/MessageInterceptor.h deleted file mode 100644 index 3ada86b6f7..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageInterceptor.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef QPID_BROKER_MESSAGEINTERCEPTOR_H -#define QPID_BROKER_MESSAGEINTERCEPTOR_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 "Observers.h" - -namespace qpid { -namespace broker { - -class Message; - -/** - * Interface for classes that want to modify a message as it is processed by the queue. - */ -class MessageInterceptor -{ - public: - virtual ~MessageInterceptor() {} - - /** Modify a message before it is recorded in durable store */ - virtual void record(Message&) {} - /** Modify a message as it is being published onto the queue. */ - virtual void publish(Message&) {} -}; - -class MessageInterceptors : public Observers { - public: - void record(Message& m) { - each(boost::bind(&MessageInterceptor::record, _1, boost::ref(m))); - } - void publish(Message& m) { - each(boost::bind(&MessageInterceptor::publish, _1, boost::ref(m))); - } -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGEINTERCEPTOR_H*/ diff --git a/qpid/cpp/src/qpid/broker/MessageMap.cpp b/qpid/cpp/src/qpid/broker/MessageMap.cpp deleted file mode 100644 index 4cdd83c9aa..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageMap.cpp +++ /dev/null @@ -1,161 +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/broker/MessageMap.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/QueueCursor.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { -namespace broker { -namespace { -const std::string EMPTY; -} - - -std::string MessageMap::getKey(const Message& message) -{ - return message.getPropertyAsString(key); -} - -size_t MessageMap::size() -{ - size_t count(0); - for (Ordering::iterator i = messages.begin(); i != messages.end(); ++i) { - if (i->second.getState() == AVAILABLE) ++count; - } - return count; -} - -bool MessageMap::empty() -{ - return size() == 0;//TODO: more efficient implementation -} - -bool MessageMap::deleted(const QueueCursor& cursor) -{ - Ordering::iterator i = messages.find(cursor.position); - if (i != messages.end()) { - erase(i); - return true; - } else { - return false; - } -} - -Message* MessageMap::find(const QueueCursor& cursor) -{ - if (cursor.valid) return find(cursor.position, 0); - else return 0; -} - -Message* MessageMap::find(const framing::SequenceNumber& position, QueueCursor* cursor) -{ - Ordering::iterator i = messages.lower_bound(position); - if (i != messages.end()) { - if (cursor) cursor->setPosition(i->first, version); - if (i->first == position) return &(i->second); - else return 0; - } else { - //there is no message whose sequence is greater than position, - //i.e. haven't got there yet - if (cursor) cursor->setPosition(position, version); - return 0; - } -} - -Message* MessageMap::next(QueueCursor& cursor) -{ - Ordering::iterator i; - if (!cursor.valid) i = messages.begin(); //start with oldest message - else i = messages.upper_bound(cursor.position); //get first message that is greater than position - - while (i != messages.end()) { - Message& m = i->second; - cursor.setPosition(m.getSequence(), version); - if (cursor.check(m)) { - return &m; - } else { - ++i; - } - } - return 0; -} - -const Message& MessageMap::replace(const Message& original, const Message& update) -{ - messages.erase(original.getSequence()); - std::pair i = messages.insert(Ordering::value_type(update.getSequence(), update)); - i.first->second.setState(AVAILABLE); - return i.first->second; -} - -void MessageMap::publish(const Message& added) -{ - Message dummy; - update(added, dummy); -} - -bool MessageMap::update(const Message& added, Message& removed) -{ - std::pair result = index.insert(Index::value_type(getKey(added), added)); - if (result.second) { - //there was no previous message for this key; nothing needs to - //be removed, just add the message into its correct position - messages.insert(Ordering::value_type(added.getSequence(), added)).first->second.setState(AVAILABLE); - return false; - } else { - //there is already a message with that key which needs to be replaced - removed = result.first->second; - result.first->second = replace(result.first->second, added); - result.first->second.setState(AVAILABLE); - QPID_LOG(debug, "Displaced message at " << removed.getSequence() << " with " << result.first->second.getSequence() << ": " << result.first->first); - return true; - } -} - -Message* MessageMap::release(const QueueCursor& cursor) -{ - Ordering::iterator i = messages.find(cursor.position); - if (i != messages.end()) { - i->second.setState(AVAILABLE); - return &i->second; - } else { - return 0; - } -} - -void MessageMap::foreach(Functor f) -{ - for (Ordering::iterator i = messages.begin(); i != messages.end(); ++i) { - if (i->second.getState() == AVAILABLE) f(i->second); - } -} - -void MessageMap::erase(Ordering::iterator i) -{ - index.erase(getKey(i->second)); - messages.erase(i); -} - -MessageMap::MessageMap(const std::string& k) : key(k), version(0) {} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/MessageMap.h b/qpid/cpp/src/qpid/broker/MessageMap.h deleted file mode 100644 index c30606d0ff..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageMap.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef QPID_BROKER_MESSAGEMAP_H -#define QPID_BROKER_MESSAGEMAP_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/Messages.h" -#include "qpid/broker/Message.h" -#include "qpid/framing/SequenceNumber.h" -#include -#include - -namespace qpid { -namespace broker { - -/** - * Provides a last value queue behaviour, whereby a messages replace - * any previous message with the same value for a defined property - * (i.e. the key). - */ -class MessageMap : public Messages -{ - public: - MessageMap(const std::string& key); - - size_t size(); - bool empty(); - - bool deleted(const QueueCursor&); - void publish(const Message& added);//use update instead to get replaced message - Message* next(QueueCursor&); - Message* release(const QueueCursor& cursor); - Message* find(const QueueCursor&); - Message* find(const framing::SequenceNumber&, QueueCursor*); - - void foreach(Functor); - - bool update(const Message& added, Message& removed); - - protected: - typedef std::map Index; - typedef std::map Ordering; - const std::string key; - Index index; - Ordering messages; - int32_t version; - - std::string getKey(const Message&); - virtual const Message& replace(const Message&, const Message&); - void erase(Ordering::iterator); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGEMAP_H*/ diff --git a/qpid/cpp/src/qpid/broker/MessageStore.h b/qpid/cpp/src/qpid/broker/MessageStore.h deleted file mode 100644 index 4f7e9f3d5f..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageStore.h +++ /dev/null @@ -1,189 +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. - * - */ -#ifndef _MessageStore_ -#define _MessageStore_ - -#include "qpid/broker/PersistableExchange.h" -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/PersistableConfig.h" -#include "qpid/broker/RecoveryManager.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/FieldTable.h" - -#include -#include - -namespace qpid { -namespace broker { - -/** - * An abstraction of the persistent storage for messages. (In - * all methods, any pointers/references to queues or messages - * are valid only for the duration of the call). - */ -class MessageStore : public TransactionalStore, public Recoverable { - public: - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const framing::FieldTable& args) = 0; - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue) = 0; - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const framing::FieldTable& args) = 0; - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange) = 0; - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args) = 0; - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args) = 0; - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config) = 0; - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config) = 0; - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr& msg) = 0; - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg) = 0; - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr& msg, - const std::string& data) = 0; - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, uint64_t offset, uint32_t length) = 0; - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) = 0; - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) = 0; - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const qpid::broker::PersistableQueue& queue)=0; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) = 0; - - - virtual ~MessageStore(){} -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp b/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp deleted file mode 100644 index 556ecc3084..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp +++ /dev/null @@ -1,173 +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/broker/MessageStoreModule.h" -#include "qpid/broker/NullMessageStore.h" -#include - -// This transfer protects against the unloading of the store lib prior to the handling of the exception -#define TRANSFER_EXCEPTION(fn) try { fn; } catch (std::exception& e) { throw Exception(e.what()); } - -using boost::intrusive_ptr; -using qpid::framing::FieldTable; -using std::string; - -namespace qpid { -namespace broker { - -MessageStoreModule::MessageStoreModule(const boost::shared_ptr& _store) - : store(_store) {} - -MessageStoreModule::~MessageStoreModule() -{ -} - -void MessageStoreModule::create(PersistableQueue& queue, const FieldTable& args) -{ - TRANSFER_EXCEPTION(store->create(queue, args)); -} - -void MessageStoreModule::destroy(PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->destroy(queue)); -} - -void MessageStoreModule::create(const PersistableExchange& exchange, const FieldTable& args) -{ - TRANSFER_EXCEPTION(store->create(exchange, args)); -} - -void MessageStoreModule::destroy(const PersistableExchange& exchange) -{ - TRANSFER_EXCEPTION(store->destroy(exchange)); -} - -void MessageStoreModule::bind(const PersistableExchange& e, const PersistableQueue& q, - const std::string& k, const framing::FieldTable& a) -{ - TRANSFER_EXCEPTION(store->bind(e, q, k, a)); -} - -void MessageStoreModule::unbind(const PersistableExchange& e, const PersistableQueue& q, - const std::string& k, const framing::FieldTable& a) -{ - TRANSFER_EXCEPTION(store->unbind(e, q, k, a)); -} - -void MessageStoreModule::create(const PersistableConfig& config) -{ - TRANSFER_EXCEPTION(store->create(config)); -} - -void MessageStoreModule::destroy(const PersistableConfig& config) -{ - TRANSFER_EXCEPTION(store->destroy(config)); -} - -void MessageStoreModule::recover(RecoveryManager& registry) -{ - TRANSFER_EXCEPTION(store->recover(registry)); -} - -void MessageStoreModule::stage(const intrusive_ptr& msg) -{ - TRANSFER_EXCEPTION(store->stage(msg)); -} - -void MessageStoreModule::destroy(PersistableMessage& msg) -{ - TRANSFER_EXCEPTION(store->destroy(msg)); -} - -void MessageStoreModule::appendContent(const intrusive_ptr& msg, - const std::string& data) -{ - TRANSFER_EXCEPTION(store->appendContent(msg, data)); -} - -void MessageStoreModule::loadContent( - const qpid::broker::PersistableQueue& queue, - const intrusive_ptr& msg, - string& data, uint64_t offset, uint32_t length) -{ - TRANSFER_EXCEPTION(store->loadContent(queue, msg, data, offset, length)); -} - -void MessageStoreModule::enqueue(TransactionContext* ctxt, - const intrusive_ptr& msg, - const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->enqueue(ctxt, msg, queue)); -} - -void MessageStoreModule::dequeue(TransactionContext* ctxt, - const intrusive_ptr& msg, - const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->dequeue(ctxt, msg, queue)); -} - -void MessageStoreModule::flush(const qpid::broker::PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->flush(queue)); -} - -uint32_t MessageStoreModule::outstandingQueueAIO(const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(return store->outstandingQueueAIO(queue)); -} - -std::auto_ptr MessageStoreModule::begin() -{ - TRANSFER_EXCEPTION(return store->begin()); -} - -std::auto_ptr MessageStoreModule::begin(const std::string& xid) -{ - TRANSFER_EXCEPTION(return store->begin(xid)); -} - -void MessageStoreModule::prepare(TPCTransactionContext& txn) -{ - TRANSFER_EXCEPTION(store->prepare(txn)); -} - -void MessageStoreModule::commit(TransactionContext& ctxt) -{ - TRANSFER_EXCEPTION(store->commit(ctxt)); -} - -void MessageStoreModule::abort(TransactionContext& ctxt) -{ - TRANSFER_EXCEPTION(store->abort(ctxt)); -} - -void MessageStoreModule::collectPreparedXids(std::set& xids) -{ - TRANSFER_EXCEPTION(store->collectPreparedXids(xids)); -} - -bool MessageStoreModule::isNull() const -{ - return NullMessageStore::isNullStore(store.get()); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/MessageStoreModule.h b/qpid/cpp/src/qpid/broker/MessageStoreModule.h deleted file mode 100644 index ca7de3d318..0000000000 --- a/qpid/cpp/src/qpid/broker/MessageStoreModule.h +++ /dev/null @@ -1,85 +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. - * - */ -#ifndef _MessageStoreModule_ -#define _MessageStoreModule_ - -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveryManager.h" - -#include -#include - -namespace qpid { -namespace broker { - -/** - * A null implementation of the MessageStore interface - */ -class MessageStoreModule : public MessageStore -{ - boost::shared_ptr store; - public: - MessageStoreModule(const boost::shared_ptr& store); - - std::auto_ptr begin(); - std::auto_ptr begin(const std::string& xid); - void prepare(TPCTransactionContext& txn); - void commit(TransactionContext& txn); - void abort(TransactionContext& txn); - void collectPreparedXids(std::set& xids); - - void create(PersistableQueue& queue, const framing::FieldTable& args); - void destroy(PersistableQueue& queue); - void create(const PersistableExchange& exchange, const framing::FieldTable& args); - void destroy(const PersistableExchange& exchange); - void bind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args); - void unbind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args); - void create(const PersistableConfig& config); - void destroy(const PersistableConfig& config); - void recover(RecoveryManager& queues); - void stage(const boost::intrusive_ptr& msg); - void destroy(PersistableMessage& msg); - void appendContent(const boost::intrusive_ptr& msg, const std::string& data); - void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, std::string& data, - uint64_t offset, uint32_t length); - - void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue); - void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue); - uint32_t outstandingQueueAIO(const PersistableQueue& queue); - void flush(const qpid::broker::PersistableQueue& queue); - bool isNull() const; - - ~MessageStoreModule(); -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/Messages.h b/qpid/cpp/src/qpid/broker/Messages.h deleted file mode 100644 index 5f51e69c11..0000000000 --- a/qpid/cpp/src/qpid/broker/Messages.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef QPID_BROKER_MESSAGES_H -#define QPID_BROKER_MESSAGES_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/SequenceNumber.h" -#include - -namespace qpid { -namespace framing { -class SequenceNumber; -} -namespace broker { -class Message; -class QueueCursor; - -/** - * This interface abstracts out the access to the messages held for - * delivery by a Queue instance. Note the the assumption at present is - * that all locking is done in the Queue itself. - */ -class Messages -{ - public: - typedef boost::function1 Functor; - - virtual ~Messages() {} - /** - * @return the number of messages available for delivery. - */ - virtual size_t size() = 0; - - /** - * Called when a message is deleted from the queue. - */ - virtual bool deleted(const QueueCursor&) = 0; - /** - * Makes a message available. - */ - virtual void publish(const Message& added) = 0; - /** - * Retrieve the next message for the given cursor. A reference to - * the message is passed back via the second parameter. - * - * @return a pointer to the message if there is one, in which case - * the cursor that points to it is assigned to cursor; null - * otherwise. - */ - virtual Message* next(QueueCursor& cursor) = 0; - - /** - * Release the message i.e. return it to the available state - * unless it has already been deleted. - * - * @return a pointer to the Message if it is still in acquired state and - * hence can be released; null if it has already been deleted - */ - virtual Message* release(const QueueCursor& cursor) = 0; - /** - * Find the message with the specified sequence number, returning - * a pointer if found, null otherwise. A cursor to the matched - * message can be passed back via the second parameter, regardless - * of whether the message is found, using this cursor to call - * next() will give the next message greater than position if one - * exists. - */ - virtual Message* find(const framing::SequenceNumber&, QueueCursor*) = 0; - - /** - * Find the message at the specified position, returning a pointer if - * found, null otherwise. - */ - virtual Message* find(const QueueCursor&) = 0; - - /** - * Apply, the functor to each message held - */ - virtual void foreach(Functor) = 0; - - /** - * Allows implementation to perform optional checks before message - * is stored. - */ - virtual void check(const Message&) {}; - - private: -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGES_H*/ diff --git a/qpid/cpp/src/qpid/broker/NameGenerator.cpp b/qpid/cpp/src/qpid/broker/NameGenerator.cpp deleted file mode 100644 index e7f193d546..0000000000 --- a/qpid/cpp/src/qpid/broker/NameGenerator.cpp +++ /dev/null @@ -1,32 +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/broker/NameGenerator.h" -#include - -using namespace qpid::broker; - -NameGenerator::NameGenerator(const std::string& _base) : base(_base), counter(1) {} - -std::string NameGenerator::generate(){ - std::stringstream ss; - ss << base << counter++; - return ss.str(); -} diff --git a/qpid/cpp/src/qpid/broker/NameGenerator.h b/qpid/cpp/src/qpid/broker/NameGenerator.h deleted file mode 100644 index 2e9f7febe2..0000000000 --- a/qpid/cpp/src/qpid/broker/NameGenerator.h +++ /dev/null @@ -1,40 +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. - * - */ -#ifndef _NameGenerator_ -#define _NameGenerator_ - -#include - -namespace qpid { - namespace broker { - class NameGenerator{ - const std::string base; - unsigned int counter; - public: - NameGenerator(const std::string& base); - std::string generate(); - }; - const std::string QPID_NAME_PREFIX("qpid."); // reserved for private names - } -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/NullMessageStore.cpp b/qpid/cpp/src/qpid/broker/NullMessageStore.cpp deleted file mode 100644 index f2ff7d0e6e..0000000000 --- a/qpid/cpp/src/qpid/broker/NullMessageStore.cpp +++ /dev/null @@ -1,163 +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/broker/NullMessageStore.h" -#include "qpid/broker/MessageStoreModule.h" -#include "qpid/broker/RecoveryManager.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" - -#include - -using boost::intrusive_ptr; - -namespace qpid{ -namespace broker{ - -const std::string nullxid = ""; - -class SimpleDummyCtxt : public TransactionContext {}; - -class DummyCtxt : public TPCTransactionContext -{ - const std::string xid; -public: - DummyCtxt(const std::string& _xid) : xid(_xid) {} - static std::string getXid(TransactionContext& ctxt) - { - DummyCtxt* c(dynamic_cast(&ctxt)); - return c ? c->xid : nullxid; - } -}; - -NullMessageStore::NullMessageStore() : nextPersistenceId(1) {} - -void NullMessageStore::create(PersistableQueue& queue, const framing::FieldTable& /*args*/) -{ - queue.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(PersistableQueue&) {} - -void NullMessageStore::create(const PersistableExchange& exchange, const framing::FieldTable& /*args*/) -{ - exchange.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(const PersistableExchange& ) {} - -void NullMessageStore::bind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&){} - -void NullMessageStore::unbind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&){} - -void NullMessageStore::create(const PersistableConfig& config) -{ - config.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(const PersistableConfig&) {} - -void NullMessageStore::recover(RecoveryManager&) {} - -void NullMessageStore::stage(const intrusive_ptr&) {} - -void NullMessageStore::destroy(PersistableMessage&) {} - -void NullMessageStore::appendContent(const intrusive_ptr&, const std::string&) {} - -void NullMessageStore::loadContent(const qpid::broker::PersistableQueue&, - const intrusive_ptr&, - std::string&, uint64_t, uint32_t) -{ - throw qpid::framing::InternalErrorException("Can't load content; persistence not enabled"); -} - -void NullMessageStore::enqueue(TransactionContext*, - const intrusive_ptr& msg, - const PersistableQueue&) -{ - msg->enqueueComplete(); -} - -void NullMessageStore::dequeue(TransactionContext*, - const intrusive_ptr& msg, - const PersistableQueue&) -{ - msg->dequeueComplete(); -} - -void NullMessageStore::flush(const qpid::broker::PersistableQueue&) {} - -uint32_t NullMessageStore::outstandingQueueAIO(const PersistableQueue& ) { - return 0; -} - -std::auto_ptr NullMessageStore::begin() -{ - return std::auto_ptr(new SimpleDummyCtxt()); -} - -std::auto_ptr NullMessageStore::begin(const std::string& xid) -{ - return std::auto_ptr(new DummyCtxt(xid)); -} - -void NullMessageStore::prepare(TPCTransactionContext& ctxt) -{ - qpid::sys::ScopedLock l(lock); - prepared.insert(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::commit(TransactionContext& ctxt) -{ - qpid::sys::ScopedLock l(lock); - prepared.erase(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::abort(TransactionContext& ctxt) -{ - qpid::sys::ScopedLock l(lock); - prepared.erase(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::collectPreparedXids(std::set& out) -{ - qpid::sys::ScopedLock l(lock); - out.insert(prepared.begin(), prepared.end()); -} - -bool NullMessageStore::isNull() const -{ - return true; -} - -bool NullMessageStore::isNullStore(const MessageStore* store) -{ - const MessageStoreModule* wrapper = dynamic_cast(store); - if (wrapper) { - return wrapper->isNull(); - } else { - const NullMessageStore* test = dynamic_cast(store); - return test && test->isNull(); - } -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/NullMessageStore.h b/qpid/cpp/src/qpid/broker/NullMessageStore.h deleted file mode 100644 index 9f394d1fde..0000000000 --- a/qpid/cpp/src/qpid/broker/NullMessageStore.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _NullMessageStore_ -#define _NullMessageStore_ - -#include -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/Queue.h" -#include "qpid/sys/Mutex.h" - -#include - -namespace qpid { -namespace broker { - -/** - * A null implementation of the MessageStore interface - */ -class QPID_BROKER_CLASS_EXTERN NullMessageStore : public MessageStore -{ - std::set prepared; - uint64_t nextPersistenceId; - qpid::sys::Mutex lock; - public: - QPID_BROKER_EXTERN NullMessageStore(); - - QPID_BROKER_EXTERN virtual std::auto_ptr begin(); - QPID_BROKER_EXTERN virtual std::auto_ptr begin(const std::string& xid); - QPID_BROKER_EXTERN virtual void prepare(TPCTransactionContext& txn); - QPID_BROKER_EXTERN virtual void commit(TransactionContext& txn); - QPID_BROKER_EXTERN virtual void abort(TransactionContext& txn); - QPID_BROKER_EXTERN virtual void collectPreparedXids(std::set& xids); - - QPID_BROKER_EXTERN virtual void create(PersistableQueue& queue, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void destroy(PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void create(const PersistableExchange& exchange, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void destroy(const PersistableExchange& exchange); - - QPID_BROKER_EXTERN virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void create(const PersistableConfig& config); - QPID_BROKER_EXTERN virtual void destroy(const PersistableConfig& config); - QPID_BROKER_EXTERN virtual void recover(RecoveryManager& queues); - QPID_BROKER_EXTERN virtual void stage(const boost::intrusive_ptr& msg); - QPID_BROKER_EXTERN virtual void destroy(PersistableMessage& msg); - QPID_BROKER_EXTERN virtual void appendContent(const boost::intrusive_ptr& msg, - const std::string& data); - QPID_BROKER_EXTERN virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length); - QPID_BROKER_EXTERN virtual void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void flush(const qpid::broker::PersistableQueue& queue); - ~NullMessageStore(){} - - QPID_BROKER_EXTERN virtual bool isNull() const; - static bool isNullStore(const MessageStore*); -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/ObjectFactory.cpp b/qpid/cpp/src/qpid/broker/ObjectFactory.cpp deleted file mode 100644 index 39edaa9fab..0000000000 --- a/qpid/cpp/src/qpid/broker/ObjectFactory.cpp +++ /dev/null @@ -1,75 +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 "ObjectFactory.h" -#include "Broker.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -bool ObjectFactoryRegistry::createObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId) -{ - for (Factories::iterator i = factories.begin(); i != factories.end(); ++i) - { - if ((*i)->createObject(broker, type, name, properties, userId, connectionId)) return true; - } - return false; -} - -bool ObjectFactoryRegistry::deleteObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId) -{ - for (Factories::iterator i = factories.begin(); i != factories.end(); ++i) - { - if ((*i)->deleteObject(broker, type, name, properties, userId, connectionId)) return true; - } - return false; -} - -bool ObjectFactoryRegistry::recoverObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - uint64_t persistenceId) -{ - for (Factories::iterator i = factories.begin(); i != factories.end(); ++i) - { - try { - if ((*i)->recoverObject(broker, type, name, properties, persistenceId)) return true; - } catch (const std::exception& e) { - QPID_LOG(warning, "Error while recovering object " << name << " of type " << type << ": " << e.what()); - } - } - return false; -} - -ObjectFactoryRegistry::~ObjectFactoryRegistry() -{ - for (Factories::iterator i = factories.begin(); i != factories.end(); ++i) - { - delete *i; - } - factories.clear(); -} -void ObjectFactoryRegistry::add(ObjectFactory* factory) -{ - factories.push_back(factory); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/ObjectFactory.h b/qpid/cpp/src/qpid/broker/ObjectFactory.h deleted file mode 100644 index d1b570da2f..0000000000 --- a/qpid/cpp/src/qpid/broker/ObjectFactory.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_BROKER_OBJECTFACTORY_H -#define QPID_BROKER_OBJECTFACTORY_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/BrokerImportExport.h" -#include "qpid/types/Variant.h" -#include - -namespace qpid { -namespace broker { - -class Broker; - -/** - * An extension point through which plugins can register functionality - * for creating (and deleting) particular types of objects via the - * Broker::createObject() method (or deleteObject()), invoked via management. - */ -class ObjectFactory -{ - public: - virtual bool createObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId) = 0; - virtual bool deleteObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId) = 0; - virtual bool recoverObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, uint64_t persistenceId) = 0; - virtual ~ObjectFactory() {} - private: -}; - -class ObjectFactoryRegistry : public ObjectFactory -{ - public: - bool createObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId); - bool deleteObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId); - bool recoverObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, uint64_t persistenceId); - - ~ObjectFactoryRegistry(); - QPID_BROKER_EXTERN void add(ObjectFactory*); - private: - typedef std::vector Factories; - Factories factories; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_OBJECTFACTORY_H*/ diff --git a/qpid/cpp/src/qpid/broker/Observers.h b/qpid/cpp/src/qpid/broker/Observers.h deleted file mode 100644 index 72600329e6..0000000000 --- a/qpid/cpp/src/qpid/broker/Observers.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef QPID_BROKER_OBSERVERS_H -#define QPID_BROKER_OBSERVERS_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 -#include -#include - -namespace qpid { -namespace broker { - -/** - * Base class for collections of observers with thread-safe add/remove and traversal. - */ -template -class Observers -{ - public: - typedef boost::shared_ptr ObserverPtr; - - void add(const ObserverPtr& observer) { - sys::Mutex::ScopedLock l(lock); - observers.insert(observer); - } - - void remove(const ObserverPtr& observer) { - sys::Mutex::ScopedLock l(lock); - observers.erase(observer) ; - } - - /** Iterate over the observers. */ - template void each(F f) { - Set copy; // Make a copy and iterate outside the lock. - { - sys::Mutex::ScopedLock l(lock); - copy = observers; - } - std::for_each(copy.begin(), copy.end(), f); - } - - template boost::shared_ptr findType() const { - sys::Mutex::ScopedLock l(lock); - typename Set::const_iterator i = - std::find_if(observers.begin(), observers.end(), &isA); - return i == observers.end() ? - boost::shared_ptr() : boost::dynamic_pointer_cast(*i); - } - virtual ~Observers() {} - - protected: - typedef std::set Set; - Observers() : lock(myLock) {} - - /** Specify a lock for the Observers to use */ - Observers(sys::Mutex& l) : lock(l) {} - - /** Iterate over the observers without taking the lock, caller must hold the lock */ - template void each(F f, const sys::Mutex::ScopedLock&) { - std::for_each(observers.begin(), observers.end(), f); - } - - template static bool isA(const ObserverPtr&o) { - return !!boost::dynamic_pointer_cast(o); - } - - mutable sys::Mutex myLock; - sys::Mutex& lock; - Set observers; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_OBSERVERS_H*/ diff --git a/qpid/cpp/src/qpid/broker/OwnershipToken.h b/qpid/cpp/src/qpid/broker/OwnershipToken.h deleted file mode 100644 index 2fc51408b6..0000000000 --- a/qpid/cpp/src/qpid/broker/OwnershipToken.h +++ /dev/null @@ -1,36 +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. - * - */ -#ifndef _OwnershipToken_ -#define _OwnershipToken_ - -namespace qpid { -namespace broker { - -class OwnershipToken{ -public: - virtual bool isLocal(const OwnershipToken* t) const { return this==t; }; - virtual ~OwnershipToken(){} -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/PagedQueue.cpp b/qpid/cpp/src/qpid/broker/PagedQueue.cpp deleted file mode 100644 index b3b7f6a2d4..0000000000 --- a/qpid/cpp/src/qpid/broker/PagedQueue.cpp +++ /dev/null @@ -1,465 +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/broker/PagedQueue.h" -#include "qpid/broker/Protocol.h" -#include "qpid/broker/QueueCursor.h" -#include "qpid/broker/Message.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/Time.h" -#include - -namespace qpid { -namespace broker { -namespace { -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::sys::ZERO; -using qpid::sys::FAR_FUTURE; -using qpid::sys::MemoryMappedFile; -const uint32_t OVERHEAD(4/*content-size*/ + 4/*sequence-number*/ + 8/*persistence-id*/ + 8/*expiration*/); - -size_t encodedSize(const Message& msg) -{ - return msg.getPersistentContext()->encodedSize() + OVERHEAD; -} - -size_t encode(const Message& msg, char* data, size_t size) -{ - uint32_t encoded = msg.getPersistentContext()->encodedSize(); - uint32_t required = encoded + OVERHEAD; - if (required > size) return 0; - qpid::framing::Buffer buffer(data, required); - buffer.putLong(encoded); - buffer.putLong(msg.getSequence()); - buffer.putLongLong(msg.getPersistentContext()->getPersistenceId()); - sys::AbsTime expiration = msg.getExpiration(); - int64_t t(0); - if (expiration < FAR_FUTURE) { - // Just need an integer that will round trip - t = Duration(ZERO, expiration); - } - buffer.putLongLong(t); - msg.getPersistentContext()->encode(buffer); - assert(buffer.getPosition() == required); - return required; -} - -size_t decode(ProtocolRegistry& protocols, Message& msg, const char* data, size_t size) -{ - qpid::framing::Buffer metadata(const_cast(data), size); - uint32_t encoded = metadata.getLong(); - uint32_t sequence = metadata.getLong(); - uint64_t persistenceId = metadata.getLongLong(); - int64_t t = metadata.getLongLong(); - assert(metadata.available() >= encoded); - qpid::framing::Buffer buffer(const_cast(data) + metadata.getPosition(), encoded); - msg = protocols.decode(buffer); - assert(buffer.getPosition() == encoded); - msg.setSequence(qpid::framing::SequenceNumber(sequence)); - msg.getPersistentContext()->setPersistenceId(persistenceId); - if (t) { - sys::AbsTime expiration(ZERO, t); - msg.getSharedState().setExpiration(expiration); - } - return encoded + metadata.getPosition(); -} - -} - -PagedQueue::PagedQueue(const std::string& name_, const std::string& directory, uint m, uint factor, ProtocolRegistry& p) - : name(name_), pageSize(file.getPageSize()*factor), maxLoaded(m), protocols(p), offset(0), loaded(0), version(0) -{ - if (directory.empty()) { - throw qpid::Exception(QPID_MSG("Cannot create paged queue: No paged queue directory specified")); - } - file.open(name, directory); - QPID_LOG(debug, "PagedQueue[" << name << "]"); -} - -PagedQueue::~PagedQueue() -{ - file.close(); -} - -size_t PagedQueue::size() -{ - size_t total(0); - for (Used::const_iterator i = used.begin(); i != used.end(); ++i) { - total += i->second.available(); - } - return total; -} - -bool PagedQueue::deleted(const QueueCursor& cursor) -{ - if (cursor.valid) { - Used::iterator page = findPage(cursor.position, false); - if (page == used.end()) { - return false; - } - page->second.deleted(cursor.position); - if (page->second.empty()) { - //move page to free list - --loaded; - page->second.clear(file); - free.push_back(page->second); - used.erase(page); - } - return true; - } else { - return false; - } -} - -void PagedQueue::check(const Message& added) -{ - if (encodedSize(added) > pageSize) { - QPID_LOG(error, "Message is larger than page size for queue " << name); - throw qpid::framing::PreconditionFailedException(QPID_MSG("Message is larger than page size for queue " << name)); - } -} - -void PagedQueue::publish(const Message& added) -{ - check(added); - Used::reverse_iterator i = used.rbegin(); - if (i != used.rend()) { - if (!i->second.isLoaded()) load(i->second); - if (i->second.add(added)) return; - } - //used is empty or last page is full, need to add a new page - if (!newPage(added.getSequence()).add(added)) { - QPID_LOG(error, "Could not add message to paged queue " << name); - throw qpid::Exception(QPID_MSG("Could not add message to paged queue " << name)); - } -} - -Message* PagedQueue::next(QueueCursor& cursor) -{ - Used::iterator i = used.begin(); - if (cursor.valid) { - qpid::framing::SequenceNumber position(cursor.position); - ++position; - i = findPage(position, true); - if (i == used.end() && !used.empty() && used.begin()->first > position) i = used.begin(); - } - while (i != used.end()) { - if (!i->second.isLoaded()) load(i->second); - Message* m = i->second.next(version, cursor); - QPID_LOG(debug, "PagedQueue::next(" << cursor.valid << ":" << cursor.position << "): " << m); - if (m) return m; - ++i; - } - QPID_LOG(debug, "PagedQueue::next(" << cursor.valid << ":" << cursor.position << ") returning 0 "); - return 0; -} - -Message* PagedQueue::release(const QueueCursor& cursor) -{ - if (cursor.valid) { - Used::iterator i = findPage(cursor.position, true); - if (i == used.end()) return 0; - return i->second.release(cursor.position); - } else { - return 0; - } -} - -Message* PagedQueue::find(const framing::SequenceNumber& position, QueueCursor* cursor) -{ - Used::iterator i = findPage(position, true); - if (i != used.end()) { - Message* m = i->second.find(position); - if (cursor) { - cursor->setPosition(version, m ? m->getSequence() : position); - } - return m; - } else { - return 0; - } -} - -void PagedQueue::foreach(Functor) -{ - //TODO: -} - -Message* PagedQueue::find(const QueueCursor& cursor) -{ - if (cursor.valid) return find(cursor.position, 0); - else return 0; -} - -PagedQueue::Page::Page(size_t s, size_t o) : size(s), offset(o), region(0), used(0) -{ - QPID_LOG(debug, "Created Page[" << offset << "], size=" << size); -} - -void PagedQueue::Page::deleted(qpid::framing::SequenceNumber s) -{ - if (isLoaded()) { - Message* message = find(s); - assert(message);//could this ever legitimately be 0? - message->setState(DELETED); - } - contents.remove(s); - acquired.remove(s); -} - -Message* PagedQueue::Page::release(qpid::framing::SequenceNumber s) -{ - Message* m = find(s); - if (m) { - m->setState(AVAILABLE); - } - acquired.remove(s); - return m; -} - -bool PagedQueue::Page::add(const Message& message) -{ - assert(region); - assert (size >= used); - size_t encoded = encode(message, region + used, size - used); - QPID_LOG(debug, "Calling Page[" << offset << "]::add() used=" << used << ", size=" << size << ", encoded=" << encoded << ")"); - if (encoded) { - used += encoded; - messages.push_back(message); - messages.back().setState(AVAILABLE); - contents.add(message.getSequence()); - return true; - } else { - return false; - } -} - -bool PagedQueue::Page::empty() const -{ - return contents.empty(); -} - -bool PagedQueue::Page::isLoaded() const -{ - return region; -} - -Message* PagedQueue::Page::next(uint32_t version, QueueCursor& cursor) -{ - if (messages.empty()) return 0; - - qpid::framing::SequenceNumber position; - if (cursor.valid) { - position = cursor.position + 1; - if (position < messages.front().getSequence()) { - position = messages.front().getSequence(); - cursor.setPosition(position, version); - } - } else { - position = messages.front().getSequence(); - cursor.setPosition(position, version); - } - - Message* m; - do { - m = find(position); - if (m) cursor.setPosition(position, version); - ++position; - } while (m != 0 && !cursor.check(*m)); - return m; - //if it is the first in the page, increment the hint count of the page - //if it is the last in the page, decrement the hint count of the page -} - -/** - * Called before adding to the free list - */ -void PagedQueue::Page::clear(MemoryMappedFile& file) -{ - if (region) file.unmap(region, size); - region = 0; - used = 0; - contents.clear(); - messages.clear(); -} - -size_t PagedQueue::Page::available() const -{ - return contents.size() - acquired.size(); -} - -Message* PagedQueue::Page::find(qpid::framing::SequenceNumber position) -{ - if (messages.size()) { - assert(position >= messages.front().getSequence()); - - size_t index = position - messages.front().getSequence(); - if (index < messages.size()) return &(messages[index]); - else return 0; - } else { - //page is empty, is this an error? - QPID_LOG(warning, "Could not find message at " << position << "; empty page."); - return 0; - } - - //if it is the first in the page, increment the hint count of the page - //if it is the last in the page, decrement the hint count of the page -} - -void PagedQueue::Page::load(MemoryMappedFile& file, ProtocolRegistry& protocols) -{ - QPID_LOG(debug, "Page[" << offset << "]::load" << " used=" << used << ", size=" << size); - assert(region == 0); - region = file.map(offset, size); - assert(region != 0); - bool haveData = used > 0; - used = 4;//first 4 bytes are the count - if (haveData) { - 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; - used += decode(protocols, message, region + used, size - used); - if (!contents.contains(message.getSequence())) { - message.setState(DELETED); - QPID_LOG(debug, "Setting state to deleted for message loaded at " << message.getSequence()); - } else if (acquired.contains(message.getSequence())) { - message.setState(ACQUIRED); - } else { - message.setState(AVAILABLE); - } - messages.push_back(message); - } - if (messages.size()) { - QPID_LOG(debug, "Page[" << offset << "]::load " << messages.size() << " messages loaded from " - << messages.front().getSequence() << " to " << messages.back().getSequence()); - } else { - QPID_LOG(debug, "Page[" << offset << "]::load no messages loaded"); - } - }//else there is nothing we need to explicitly load, just needed to map region -} - -void PagedQueue::Page::unload(MemoryMappedFile& file) -{ - if (messages.size()) { - QPID_LOG(debug, "Page[" << offset << "]::unload " << messages.size() << " messages to unload from " - << messages.front().getSequence() << " to " << messages.back().getSequence()); - } else { - QPID_LOG(debug, "Page[" << offset << "]::unload no messages to unload"); - } - for (std::deque::iterator i = messages.begin(); i != messages.end(); ++i) { - if (i->getState() == ACQUIRED) acquired.add(i->getSequence()); - } - uint32_t count = messages.size(); - qpid::framing::Buffer buffer(region, sizeof(uint32_t)); - buffer.putLong(count); - file.flush(region, size); - file.unmap(region, size); - //remove messages from memory - messages.clear(); - region = 0; -} - -void PagedQueue::load(Page& page) -{ - //if needed, release another page - if (loaded == maxLoaded) { - //which page to select? - Used::reverse_iterator i = used.rbegin(); - while (i != used.rend() && !i->second.isLoaded()) { - ++i; - } - assert(i != used.rend()); - unload(i->second); - } - page.load(file, protocols); - ++loaded; - QPID_LOG(debug, "PagedQueue[" << name << "] loaded page, " << loaded << " pages now loaded"); -} - -void PagedQueue::unload(Page& page) -{ - page.unload(file); - --loaded; - QPID_LOG(debug, "PagedQueue[" << name << "] unloaded page, " << loaded << " pages now loaded"); -} - - -PagedQueue::Page& PagedQueue::newPage(qpid::framing::SequenceNumber id) -{ - if (loaded == maxLoaded) { - //need to release a page from memory to make way for a new one - - //choose last one? - Used::reverse_iterator i = used.rbegin(); - while (!i->second.isLoaded() && i != used.rend()) { - ++i; - } - assert(i != used.rend()); - unload(i->second); - } - if (free.empty()) { - //need to extend file and add some pages to the free list - addPages(4/*arbitrary number, should this be config item?*/); - } - std::pair result = used.insert(Used::value_type(id, free.front())); - QPID_LOG(debug, "Added page for sequence starting from " << id); - assert(result.second); - free.pop_front(); - load(result.first->second); - return result.first->second; -} - -void PagedQueue::addPages(size_t count) -{ - for (size_t i = 0; i < count; ++i) { - free.push_back(Page(pageSize, offset)); - offset += pageSize; - file.expand(offset); - } - QPID_LOG(debug, "Added " << count << " pages to free list; now have " << used.size() << " used, and " << free.size() << " free"); -} - -PagedQueue::Used::iterator PagedQueue::findPage(const QueueCursor& cursor) -{ - Used::iterator i = used.begin(); - if (cursor.valid) { - i = findPage(cursor.position, true); - } else if (i != used.end() && !i->second.isLoaded()) { - load(i->second); - } - return i; -} - -PagedQueue::Used::iterator PagedQueue::findPage(qpid::framing::SequenceNumber n, bool loadIfRequired) -{ - Used::iterator i = used.end(); - for (Used::iterator j = used.begin(); j != used.end() && j->first <= n; ++j) { - i = j; - } - if (loadIfRequired && i != used.end() && !i->second.isLoaded()) { - load(i->second); - } - return i; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/PagedQueue.h b/qpid/cpp/src/qpid/broker/PagedQueue.h deleted file mode 100644 index a53fd8b469..0000000000 --- a/qpid/cpp/src/qpid/broker/PagedQueue.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef QPID_BROKER_PAGEDQUEUE_H -#define QPID_BROKER_PAGEDQUEUE_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/Messages.h" -#include "qpid/broker/Message.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/MemoryMappedFile.h" -#include -#include -#include - -namespace qpid { -namespace broker { -class ProtocolRegistry; - - -/** - * - */ -class PagedQueue : public Messages { - public: - PagedQueue(const std::string& name, const std::string& directory, uint maxLoaded, uint pageFactor, ProtocolRegistry& protocols); - ~PagedQueue(); - size_t size(); - bool deleted(const QueueCursor&); - void publish(const Message& added); - Message* next(QueueCursor& cursor); - Message* release(const QueueCursor& cursor); - Message* find(const framing::SequenceNumber&, QueueCursor*); - Message* find(const QueueCursor&); - void foreach(Functor); - void check(const Message& added); - private: - class Page { - public: - Page(size_t size, size_t offset); - void read();//decode messages from memory mapped file - void write();//encode messages into memory mapped file - bool isLoaded() const; - bool empty() const; - void deleted(qpid::framing::SequenceNumber); - Message* release(qpid::framing::SequenceNumber); - bool add(const Message&); - Message* next(uint32_t version, QueueCursor&); - Message* find(qpid::framing::SequenceNumber); - void load(qpid::sys::MemoryMappedFile&,ProtocolRegistry&); - void unload(qpid::sys::MemoryMappedFile&); - void clear(qpid::sys::MemoryMappedFile&); - size_t available() const; - private: - size_t size; - size_t offset; - - char* region;//0 implies not mapped - qpid::framing::SequenceSet contents; - qpid::framing::SequenceSet acquired; - std::deque messages;//decoded representation - size_t used;//amount of data used to encode current set of messages held - }; - - qpid::sys::MemoryMappedFile file; - std::string name; - const size_t pageSize; - const uint maxLoaded; - ProtocolRegistry& protocols; - size_t offset; - typedef std::map Used; - Used used; - std::list free; - uint loaded; - uint32_t version; - - void addPages(size_t count); - Page& newPage(qpid::framing::SequenceNumber); - Used::iterator findPage(const QueueCursor& cursor); - Used::iterator findPage(qpid::framing::SequenceNumber n, bool loadIfRequired); - void load(Page&); - void unload(Page&); - bool deleted(qpid::framing::SequenceNumber); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_PAGEDQUEUE_H*/ diff --git a/qpid/cpp/src/qpid/broker/Persistable.h b/qpid/cpp/src/qpid/broker/Persistable.h deleted file mode 100644 index 444aca3295..0000000000 --- a/qpid/cpp/src/qpid/broker/Persistable.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _broker_Persistable_h -#define _broker_Persistable_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/Buffer.h" -#include "qpid/RefCounted.h" - -namespace qpid { -namespace broker { - -/** - * Base class for all persistable objects - */ -class Persistable : public virtual RefCounted -{ -public: - /** - * Allows the store to attach its own identifier to this object - */ - virtual void setPersistenceId(uint64_t id) const = 0; - /** - * Returns any identifier the store may have attached to this - * object - */ - virtual uint64_t getPersistenceId() const = 0; - /** - * Encodes the persistable state of this object into the supplied - * buffer - */ - virtual void encode(framing::Buffer& buffer) const = 0; - /** - * @returns the size of the buffer needed to encode this object - */ - virtual uint32_t encodedSize() const = 0; - - virtual ~Persistable() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/PersistableConfig.h b/qpid/cpp/src/qpid/broker/PersistableConfig.h deleted file mode 100644 index 8ddb84d129..0000000000 --- a/qpid/cpp/src/qpid/broker/PersistableConfig.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_PersistableConfig_h -#define _broker_PersistableConfig_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 -#include "qpid/broker/Persistable.h" - -namespace qpid { -namespace broker { - -/** - * The interface used by general-purpose persistable configuration for - * the message store. - */ -class PersistableConfig : public Persistable -{ -public: - virtual const std::string& getName() const = 0; - virtual ~PersistableConfig() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/PersistableExchange.h b/qpid/cpp/src/qpid/broker/PersistableExchange.h deleted file mode 100644 index e1a0853247..0000000000 --- a/qpid/cpp/src/qpid/broker/PersistableExchange.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_PersistableExchange_h -#define _broker_PersistableExchange_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 -#include "qpid/broker/Persistable.h" - -namespace qpid { -namespace broker { - -/** - * The interface exchanges must expose to the MessageStore in order to be - * persistable. - */ -class PersistableExchange : public Persistable -{ -public: - virtual const std::string& getName() const = 0; - virtual ~PersistableExchange() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/PersistableMessage.cpp b/qpid/cpp/src/qpid/broker/PersistableMessage.cpp deleted file mode 100644 index afc0976d61..0000000000 --- a/qpid/cpp/src/qpid/broker/PersistableMessage.cpp +++ /dev/null @@ -1,71 +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/broker/PersistableMessage.h" -#include "qpid/broker/Queue.h" -#include - -using namespace qpid::broker; - -namespace qpid { -namespace broker { - -PersistableMessage::~PersistableMessage() {} -PersistableMessage::PersistableMessage() : ingressCompletion(0), persistenceId(0) {} - -void PersistableMessage::setIngressCompletion(boost::intrusive_ptr i) -{ - ingressCompletion = i.get(); - /** - * What follows is a hack to account for the fact that the - * AsyncCompletion to use may be, but is not always, this same - * object. - * - * This is hopefully temporary, and allows the store interface to - * remain unchanged without requiring another object to be allocated - * for every message. - * - * The case in question is where a message previously passed to - * the store is modified by some other queue onto which it is - * pushed, and then again persisted to the store. These will be - * two separate PersistableMessage instances (since the latter now - * has different content), but need to share the same - * AsyncCompletion (since they refer to the same incoming transfer - * command). - */ - if (static_cast(ingressCompletion) != static_cast(this)) { - holder = i; - } -} - -void PersistableMessage::enqueueAsync(boost::shared_ptr q) -{ - enqueueStart(); - ingressCompletion->enqueueAsync(q); -} - -void PersistableMessage::dequeueComplete() {} - -}} - - diff --git a/qpid/cpp/src/qpid/broker/PersistableMessage.h b/qpid/cpp/src/qpid/broker/PersistableMessage.h deleted file mode 100644 index cfcf8f0afc..0000000000 --- a/qpid/cpp/src/qpid/broker/PersistableMessage.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _broker_PersistableMessage_h -#define _broker_PersistableMessage_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 -#include -#include -#include -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Persistable.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/amqp_framing.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/IngressCompletion.h" -#include - -namespace qpid { -namespace types { -class Variant; -} -namespace broker { - -class MessageStore; -class Queue; - -/** - * Base class for persistable messages. - */ -class PersistableMessage : public Persistable -{ - /** - * "Ingress" messages == messages sent _to_ the broker. - * Tracks the number of outstanding asynchronous operations that must - * complete before an inbound message can be considered fully received by the - * broker. E.g. all enqueues have completed, the message has been written - * to store, credit has been replenished, etc. Once all outstanding - * operations have completed, the transfer of this message from the client - * may be considered complete. - */ - IngressCompletion* ingressCompletion; - boost::intrusive_ptr holder; - mutable uint64_t persistenceId; - - public: - QPID_BROKER_EXTERN virtual ~PersistableMessage(); - QPID_BROKER_EXTERN PersistableMessage(); - - virtual QPID_BROKER_EXTERN bool isPersistent() const = 0; - - /** track the progress of a message received by the broker - see ingressCompletion above */ - QPID_BROKER_INLINE_EXTERN bool isIngressComplete() { return ingressCompletion->isDone(); } - QPID_BROKER_INLINE_EXTERN IngressCompletion& getIngressCompletion() { return *ingressCompletion; } - QPID_BROKER_EXTERN void setIngressCompletion(boost::intrusive_ptr i); - - QPID_BROKER_INLINE_EXTERN void enqueueStart() { ingressCompletion->startCompleter(); } - QPID_BROKER_INLINE_EXTERN void enqueueComplete() { ingressCompletion->finishCompleter(); } - - QPID_BROKER_EXTERN void enqueueAsync(boost::shared_ptr queue); - - QPID_BROKER_EXTERN void dequeueComplete(); - - uint64_t getPersistenceId() const { return persistenceId; } - void setPersistenceId(uint64_t _persistenceId) const { persistenceId = _persistenceId; } - - - virtual void decodeHeader(framing::Buffer& buffer) = 0; - virtual void decodeContent(framing::Buffer& buffer) = 0; - virtual uint32_t encodedHeaderSize() const = 0; - virtual boost::intrusive_ptr merge(const std::map& annotations) const = 0; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/PersistableObject.cpp b/qpid/cpp/src/qpid/broker/PersistableObject.cpp deleted file mode 100644 index 575ef09270..0000000000 --- a/qpid/cpp/src/qpid/broker/PersistableObject.cpp +++ /dev/null @@ -1,89 +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 "PersistableObject.h" -#include "Broker.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/amqp_0_10/CodecsInternal.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { -namespace { -const std::string UTF8("utf8"); -} -PersistableObject::PersistableObject(const std::string& n, const std::string& t, const qpid::types::Variant::Map p) : name(n), type(t), properties(p), id(0) {} -PersistableObject::PersistableObject() : id(0) {} -PersistableObject::~PersistableObject() {} -const std::string& PersistableObject::getName() const { return name; } -const std::string& PersistableObject::getType() const { return type; } -void PersistableObject::setPersistenceId(uint64_t i) const { id = i; } -uint64_t PersistableObject::getPersistenceId() const { return id; } -void PersistableObject::encode(framing::Buffer& buffer) const -{ - buffer.putShortString(type); - buffer.putMediumString(name); - qpid::amqp_0_10::encode(properties, qpid::amqp_0_10::encodedSize(properties), buffer); -} -uint32_t PersistableObject::encodedSize() const -{ - return type.size()+1 + name.size()+2 + qpid::amqp_0_10::encodedSize(properties); -} -void PersistableObject::decode(framing::Buffer& buffer) -{ - buffer.getShortString(type); - buffer.getMediumString(name); - qpid::framing::FieldTable ft; - buffer.get(ft); - qpid::amqp_0_10::translate(ft, properties); -} -bool PersistableObject::recover(Broker& broker) -{ - return broker.getObjectFactoryRegistry().recoverObject(broker, type, name, properties, id); -} - -namespace { -class RecoverableObject : public RecoverableConfig -{ - public: - RecoverableObject(boost::shared_ptr o) : object(o) {} - void setPersistenceId(uint64_t id) { object->setPersistenceId(id); } - private: - boost::shared_ptr object; -}; -} -boost::shared_ptr RecoveredObjects::recover(framing::Buffer& buffer) -{ - boost::shared_ptr object(new PersistableObject()); - object->decode(buffer); - objects.push_back(object); - return boost::shared_ptr(new RecoverableObject(object)); -} -void RecoveredObjects::restore(Broker& broker) -{ - //recover objects created through ObjectFactory - for (Objects::iterator i = objects.begin(); i != objects.end(); ++i) { - if (!(*i)->recover(broker)) { - QPID_LOG(warning, "Failed to recover object " << (*i)->name << " of type " << (*i)->type); - } - } -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/PersistableObject.h b/qpid/cpp/src/qpid/broker/PersistableObject.h deleted file mode 100644 index da4bd44601..0000000000 --- a/qpid/cpp/src/qpid/broker/PersistableObject.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef QPID_BROKER_PERSISTABLEOBJECT_H -#define QPID_BROKER_PERSISTABLEOBJECT_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/BrokerImportExport.h" -#include "PersistableConfig.h" -#include "qpid/types/Variant.h" -#include -#include - -namespace qpid { -namespace broker { -class Broker; -class RecoverableConfig; -/** - * Generic persistence support for objects created through the brokers - * create method. - */ -class PersistableObject : public PersistableConfig -{ - public: - 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 const std::string& getType() 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; - std::string type; - qpid::types::Variant::Map properties; - mutable uint64_t id; - - PersistableObject(); - void decode(framing::Buffer& buffer); - bool recover(Broker&); -}; - -class RecoveredObjects -{ - public: - boost::shared_ptr recover(framing::Buffer&); - void restore(Broker&); - private: - typedef std::vector > Objects; - Objects objects; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_PERSISTABLEOBJECT_H*/ diff --git a/qpid/cpp/src/qpid/broker/PersistableQueue.h b/qpid/cpp/src/qpid/broker/PersistableQueue.h deleted file mode 100644 index 6733163084..0000000000 --- a/qpid/cpp/src/qpid/broker/PersistableQueue.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _broker_PersistableQueue_h -#define _broker_PersistableQueue_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 -#include "qpid/broker/Persistable.h" -#include "qpid/management/Manageable.h" - -namespace qpid { -namespace broker { - - -/** -* Empty class to be used by any module that wanted to set an external per queue store into -* persistableQueue -*/ - -class ExternalQueueStore : public management::Manageable -{ -public: - virtual ~ExternalQueueStore() {}; - -}; - - -/** - * The interface queues must expose to the MessageStore in order to be - * persistable. - */ -class PersistableQueue : public Persistable -{ -public: - virtual const std::string& getName() const = 0; - virtual ~PersistableQueue() { - if (externalQueueStore) { - delete externalQueueStore; - externalQueueStore = 0; - } - }; - - virtual void setExternalQueueStore(ExternalQueueStore* inst) = 0; - virtual void flush() = 0; - - inline ExternalQueueStore* getExternalQueueStore() const {return externalQueueStore;}; - - PersistableQueue():externalQueueStore(NULL){ - }; - -protected: - ExternalQueueStore* externalQueueStore; - -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/PriorityQueue.cpp b/qpid/cpp/src/qpid/broker/PriorityQueue.cpp deleted file mode 100644 index 58764637b1..0000000000 --- a/qpid/cpp/src/qpid/broker/PriorityQueue.cpp +++ /dev/null @@ -1,234 +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 ownersip. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/PriorityQueue.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueCursor.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include -#include -#include - -namespace qpid { -namespace broker { -namespace { -class PriorityContext : public CursorContext { - public: - std::vector position; - PriorityContext(size_t levels, SubscriptionType type) : position(levels, QueueCursor(type)) {} -}; -} - - -PriorityQueue::PriorityQueue(int l) : - levels(l), - messages(levels, Deque(boost::bind(&PriorityQueue::priorityPadding, this, _1))), - counters(levels, framing::SequenceNumber()), - fifo(boost::bind(&PriorityQueue::fifoPadding, this, _1)), - frontLevel(0), haveFront(false), cached(false) -{ -} - -bool PriorityQueue::deleted(const QueueCursor& c) -{ - MessagePointer* ptr = fifo.find(c); - if (ptr && ptr->holder) { - //mark the message as deleted - ptr->holder->message.setState(DELETED); - //clean the deque for the relevant priority level - boost::shared_ptr ctxt = boost::dynamic_pointer_cast(c.context); - messages[ptr->holder->priority].clean(); - //stop referencing that message holder (it may now have been - //deleted) - ptr->holder = 0; - //clean fifo index - fifo.clean(); - return true; - } else { - return false; - } -} - -size_t PriorityQueue::size() -{ - return fifo.size(); -} - -Message* PriorityQueue::next(QueueCursor& cursor) -{ - boost::shared_ptr ctxt = boost::dynamic_pointer_cast(cursor.context); - if (!ctxt) { - ctxt = boost::shared_ptr(new PriorityContext(levels, cursor.type)); - cursor.context = ctxt; - } - if (cursor.type == REPLICATOR) { - //browse in fifo order - MessagePointer* ptr = fifo.next(cursor); - return ptr ? &(ptr->holder->message) : 0; - } else if (cursor.type == PURGE) { - //iterate over message in reverse priority order (i.e. purge lowest priority message first) - //ignore any fairshare configuration here as well - for (int p = 0; p < levels; ++p) { - MessageHolder* holder = messages[p].next(ctxt->position[p]); - if (holder) { - cursor.setPosition(holder->message.getSequence(), 0); - return &(holder->message); - } - } - return 0; - } else { - //check each level in turn, in priority order, for any more messages - Priority p = firstLevel(); - do { - MessageHolder* holder = messages[p.current].next(ctxt->position[p.current]); - if (holder) { - cursor.setPosition(holder->message.getSequence(), 0); - return &(holder->message); - } - } while (nextLevel(p)); - return 0; - } -} - -Message* PriorityQueue::find(const QueueCursor& cursor) -{ - return find(cursor.position, 0); -} - -Message* PriorityQueue::find(const framing::SequenceNumber& position, QueueCursor* cursor) -{ - MessagePointer* ptr = fifo.find(position, cursor); - return ptr ? &(ptr->holder->message) : 0; -} - -void PriorityQueue::publish(const Message& published) -{ - MessageHolder holder; - holder.message = published; - holder.priority = getPriorityLevel(published); - holder.id = ++(counters[holder.priority]); - MessagePointer pointer; - pointer.holder = &(messages[holder.priority].publish(holder)); - pointer.id = published.getSequence(); - fifo.publish(pointer); -} - -Message* PriorityQueue::release(const QueueCursor& cursor) -{ - MessagePointer* ptr = fifo.release(cursor); - if (ptr) { - messages[ptr->holder->priority].resetCursors(); - return &(ptr->holder->message); - } else { - return 0; - } -} - -void PriorityQueue::foreach(Functor f) -{ - fifo.foreach(f); -} - -uint PriorityQueue::getPriorityLevel(const Message& m) const -{ - uint priority = m.getPriority(); - //Use AMQP 0-10 approach to mapping priorities to a fixed level - //(see rule priority-level-implementation) - const uint firstLevel = 5 - uint(std::min(5.0, std::ceil((double) levels/2.0))); - if (priority <= firstLevel) return 0; - return std::min(priority - firstLevel, (uint)levels-1); -} -PriorityQueue::MessagePointer PriorityQueue::fifoPadding(qpid::framing::SequenceNumber id) -{ - PriorityQueue::MessagePointer pointer; - pointer.holder = 0; - pointer.id = id; - return pointer; -} - -PriorityQueue::MessageHolder PriorityQueue::priorityPadding(qpid::framing::SequenceNumber id) -{ - PriorityQueue::MessageHolder holder; - holder.id = id; - holder.message.setState(DELETED); - return holder; -} - -PriorityQueue::Priority PriorityQueue::firstLevel() -{ - return Priority(levels - 1); -} -bool PriorityQueue::nextLevel(Priority& p) -{ - if (p.current > 0) { - --(p.current); - return true; - } else { - return false; - } -} - -framing::SequenceNumber PriorityQueue::MessageHolder::getSequence() const -{ - return id; -} -void PriorityQueue::MessageHolder::setState(MessageState s) -{ - message.setState(s); -} -MessageState PriorityQueue::MessageHolder::getState() const -{ - return message.getState(); -} -PriorityQueue::MessageHolder::operator Message&() -{ - return message; -} -framing::SequenceNumber PriorityQueue::MessagePointer::getSequence() const -{ - if (holder) { - return holder->message.getSequence(); - } else { - //this is used when the instance is merely acting as padding - return id; - } -} -void PriorityQueue::MessagePointer::setState(MessageState s) -{ - if (holder) { - holder->message.setState(s); - } -} -MessageState PriorityQueue::MessagePointer::getState() const -{ - if (holder) { - return holder->message.getState(); - } else { - return DELETED; - } -} -PriorityQueue::MessagePointer::operator Message&() -{ - assert(holder); - return holder->message; -} -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/PriorityQueue.h b/qpid/cpp/src/qpid/broker/PriorityQueue.h deleted file mode 100644 index 16432bfb54..0000000000 --- a/qpid/cpp/src/qpid/broker/PriorityQueue.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef QPID_BROKER_PRIORITYQUEUE_H -#define QPID_BROKER_PRIORITYQUEUE_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/MessageDeque.h" -#include "qpid/broker/IndexedDeque.h" -#include "qpid/sys/IntegerTypes.h" -#include -#include - -namespace qpid { -namespace broker { - -/** - * Basic priority queue with a configurable number of recognised - * priority levels. This is implemented as a separate deque per - * priority level. - * - * Browsing is FIFO not priority order. There is a MessageDeque - * for fast browsing. - */ -class PriorityQueue : public Messages -{ - public: - PriorityQueue(int levels); - virtual ~PriorityQueue() {} - size_t size(); - - bool deleted(const QueueCursor&); - void publish(const Message& added); - Message* next(QueueCursor&); - Message* release(const QueueCursor& cursor); - Message* find(const QueueCursor&); - Message* find(const framing::SequenceNumber&, QueueCursor*); - - void foreach(Functor); - static uint getPriority(const Message&); - protected: - const int levels; - struct Priority - { - const int start; - int current; - Priority(int s) : start(s), current(start) {} - }; - virtual Priority firstLevel(); - virtual bool nextLevel(Priority& ); - - private: - struct MessageHolder - { - Message message; - int priority; - framing::SequenceNumber id; - framing::SequenceNumber getSequence() const; - void setState(MessageState); - MessageState getState() const; - operator Message&(); - }; - struct MessagePointer - { - MessageHolder* holder; - framing::SequenceNumber id;//used only for padding - framing::SequenceNumber getSequence() const; - void setState(MessageState); - MessageState getState() const; - operator Message&(); - }; - typedef IndexedDeque Deque; - typedef std::vector PriorityLevels; - typedef std::vector Counters; - - /** Holds pointers to messages (stored in the fifo index) separated by priority. - */ - PriorityLevels messages; - Counters counters; - /** FIFO index of messages for fast browsing and indexing */ - IndexedDeque fifo; - uint frontLevel; - bool haveFront; - bool cached; - - uint getPriorityLevel(const Message&) const; - MessageHolder priorityPadding(qpid::framing::SequenceNumber); - MessagePointer fifoPadding(qpid::framing::SequenceNumber); -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_PRIORITYQUEUE_H*/ diff --git a/qpid/cpp/src/qpid/broker/Protocol.cpp b/qpid/cpp/src/qpid/broker/Protocol.cpp deleted file mode 100644 index e9e7892499..0000000000 --- a/qpid/cpp/src/qpid/broker/Protocol.cpp +++ /dev/null @@ -1,141 +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 "Protocol.h" -#include "qpid/broker/RecoverableMessageImpl.h" -#include "qpid/amqp_0_10/Connection.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/broker/SecureConnection.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { -namespace { -const std::string AMQP_0_10("amqp0-10"); -} -ProtocolRegistry::ProtocolRegistry(const std::set& e, Broker* b) : enabled(e), broker(b) {} - -qpid::sys::ConnectionCodec* ProtocolRegistry::create(const qpid::framing::ProtocolVersion& v, qpid::sys::OutputControl& o, const std::string& id, const qpid::sys::SecuritySettings& s) -{ - if (v == qpid::framing::ProtocolVersion(0, 10)) { - if (isEnabled(AMQP_0_10)) { - return create_0_10(o, id, s, false); - } - } - qpid::sys::ConnectionCodec* codec = 0; - for (Protocols::const_iterator i = protocols.begin(); !codec && i != protocols.end(); ++i) { - if (isEnabled(i->first)) { - codec = i->second->create(v, o, id, s); - } - } - return codec; -} -qpid::sys::ConnectionCodec* ProtocolRegistry::create(qpid::sys::OutputControl& o, const std::string& id, const qpid::sys::SecuritySettings& s) -{ - return create_0_10(o, id, s, true); -} - -qpid::framing::ProtocolVersion ProtocolRegistry::supportedVersion() const -{ - if (isEnabled(AMQP_0_10)) { - return qpid::framing::ProtocolVersion(0,10); - } else { - for (Protocols::const_iterator i = protocols.begin(); i != protocols.end(); ++i) { - if (isEnabled(i->first)) { - return i->second->supportedVersion(); - } - } - } - QPID_LOG(error, "No enabled protocols!"); - return qpid::framing::ProtocolVersion(0,0); -} - -bool ProtocolRegistry::isEnabled(const std::string& name) const -{ - return enabled.empty()/*if nothing is explicitly enabled, assume everything is*/ || enabled.find(name) != enabled.end(); -} - - -typedef std::auto_ptr CodecPtr; -typedef std::auto_ptr SecureConnectionPtr; -typedef std::auto_ptr ConnectionPtr; -typedef std::auto_ptr InputPtr; - -sys::ConnectionCodec* -ProtocolRegistry::create_0_10(qpid::sys::OutputControl& out, const std::string& id, - const qpid::sys::SecuritySettings& external, bool brokerActsAsClient) -{ - assert(broker); - SecureConnectionPtr sc(new SecureConnection()); - CodecPtr c(new qpid::amqp_0_10::Connection(out, id, brokerActsAsClient)); - ConnectionPtr i(new broker::amqp_0_10::Connection(c.get(), *broker, id, external, brokerActsAsClient)); - i->setSecureConnection(sc.get()); - c->setInputHandler(InputPtr(i.release())); - sc->setCodec(std::auto_ptr(c)); - return sc.release(); -} - -boost::intrusive_ptr ProtocolRegistry::translate(const Message& m) -{ - boost::intrusive_ptr transfer; - const qpid::broker::amqp_0_10::MessageTransfer* ptr = dynamic_cast(&m.getEncoding()); - if (ptr) transfer = boost::intrusive_ptr(ptr); - for (Protocols::const_iterator i = protocols.begin(); !transfer && i != protocols.end(); ++i) { - transfer = i->second->translate(m); - } - if (!transfer) throw new Exception("Could not convert message into 0-10"); - return transfer; -} -boost::shared_ptr ProtocolRegistry::recover(qpid::framing::Buffer& b) -{ - uint32_t position = b.getPosition(); - for (Protocols::const_iterator i = protocols.begin(); i != protocols.end(); ++i) { - boost::shared_ptr msg = i->second->recover(b); - if (msg) return msg; - else b.setPosition(position); - } - boost::intrusive_ptr transfer(new qpid::broker::amqp_0_10::MessageTransfer()); - transfer->decodeHeader(b); - boost::shared_ptr msg(new RecoverableMessageImpl(Message(transfer, transfer))); - return msg; -} - -Message ProtocolRegistry::decode(qpid::framing::Buffer& buffer) -{ - boost::shared_ptr r = recover(buffer); - r->decodeContent(buffer); - return r->getMessage(); -} - -ProtocolRegistry::~ProtocolRegistry() -{ - for (Protocols::const_iterator i = protocols.begin(); i != protocols.end(); ++i) { - delete i->second; - } - protocols.clear(); -} -void ProtocolRegistry::add(const std::string& key, Protocol* protocol) -{ - protocols[key] = protocol; - QPID_LOG(info, "Loaded protocol " << key); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/Protocol.h b/qpid/cpp/src/qpid/broker/Protocol.h deleted file mode 100644 index a7dbc98fff..0000000000 --- a/qpid/cpp/src/qpid/broker/Protocol.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef QPID_BROKER_PROTOCOL_H -#define QPID_BROKER_PROTOCOL_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 -#include -#include -#include -#include -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/broker/BrokerImportExport.h" - -namespace qpid { -namespace sys { -class OutputControl; -struct SecuritySettings; -} -namespace framing { -class Buffer; -class ProtocolVersion; -} -namespace broker { -class Broker; -class Message; -class RecoverableMessage; -namespace amqp_0_10 { -class MessageTransfer; -} - -/** - * A simple abstraction allowing pluggable protocol(s) - * (versions). AMQP 0-10 is considered the default. Alternatives must - * provide a ConnectionCodec for encoding/decoding the protocol in - * full, a means of translating the native message format of that - * protocol into AMQP 0-10 and a means of recovering durable messages - * from disk. - */ -class Protocol -{ - public: - virtual ~Protocol() {} - virtual qpid::sys::ConnectionCodec* create(const qpid::framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&) = 0; - virtual boost::intrusive_ptr translate(const Message&) = 0; - virtual boost::shared_ptr recover(qpid::framing::Buffer&) = 0; - virtual qpid::framing::ProtocolVersion supportedVersion() const = 0; - - private: -}; - -class ProtocolRegistry : public Protocol, public qpid::sys::ConnectionCodec::Factory -{ - public: - QPID_BROKER_EXTERN qpid::sys::ConnectionCodec* create(const qpid::framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&); - QPID_BROKER_EXTERN qpid::sys::ConnectionCodec* create(qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&); - QPID_BROKER_EXTERN qpid::framing::ProtocolVersion supportedVersion() const; - QPID_BROKER_EXTERN boost::intrusive_ptr translate(const Message&); - QPID_BROKER_EXTERN boost::shared_ptr recover(qpid::framing::Buffer&); - QPID_BROKER_EXTERN Message decode(qpid::framing::Buffer&); - - QPID_BROKER_EXTERN ProtocolRegistry(const std::set& enabled, Broker* b); - QPID_BROKER_EXTERN ~ProtocolRegistry(); - 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 - typedef std::map Protocols; - Protocols protocols; - const std::set enabled; - Broker* broker; - - qpid::sys::ConnectionCodec* create_0_10(qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&, bool); - bool isEnabled(const std::string&) const; - -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_PROTOCOL_H*/ diff --git a/qpid/cpp/src/qpid/broker/Queue.cpp b/qpid/cpp/src/qpid/broker/Queue.cpp deleted file mode 100644 index 858e8748c4..0000000000 --- a/qpid/cpp/src/qpid/broker/Queue.cpp +++ /dev/null @@ -1,1793 +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/broker/Queue.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/AclModule.h" -#include "qpid/broker/QueueCursor.h" -#include "qpid/broker/QueueDepth.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/MessageDeque.h" -#include "qpid/broker/MessageDistributor.h" -#include "qpid/broker/FifoDistributor.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/Selector.h" -#include "qpid/broker/TransactionObserver.h" -#include "qpid/broker/TxDequeue.h" - -//TODO: get rid of this -#include "qpid/broker/amqp_0_10/MessageTransfer.h" - -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/StringUtils.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Timer.h" -#include "qpid/types/Variant.h" -#include "qmf/org/apache/qpid/broker/ArgsQueuePurge.h" -#include "qmf/org/apache/qpid/broker/ArgsQueueReroute.h" -#include "qmf/org/apache/qpid/broker/EventQueueDelete.h" -#include "qmf/org/apache/qpid/broker/EventSubscribe.h" -#include "qmf/org/apache/qpid/broker/EventUnsubscribe.h" - -#include -#include -#include - -#include -#include - - -namespace qpid { -namespace broker { - -using namespace qpid::sys; -using namespace qpid::framing; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::management::getCurrentPublisher; -using std::string; -using std::for_each; -using std::mem_fun; -namespace _qmf = qmf::org::apache::qpid::broker; - - -namespace -{ - -inline void mgntEnqStats(const Message& msg, - _qmf::Queue::shared_ptr mgmtObject, - _qmf::Broker::shared_ptr brokerMgmtObject) -{ - if (mgmtObject != 0) { - _qmf::Queue::PerThreadStats *qStats = mgmtObject->getStatistics(); - _qmf::Broker::PerThreadStats *bStats = brokerMgmtObject->getStatistics(); - - uint64_t contentSize = msg.getMessageSize(); - qStats->msgTotalEnqueues +=1; - bStats->msgTotalEnqueues += 1; - qStats->byteTotalEnqueues += contentSize; - bStats->byteTotalEnqueues += contentSize; - if (msg.isPersistent ()) { - qStats->msgPersistEnqueues += 1; - bStats->msgPersistEnqueues += 1; - qStats->bytePersistEnqueues += contentSize; - bStats->bytePersistEnqueues += contentSize; - } - mgmtObject->statisticsUpdated(); - brokerMgmtObject->statisticsUpdated(); - } -} - -inline void mgntDeqStats(const Message& msg, - _qmf::Queue::shared_ptr mgmtObject, - _qmf::Broker::shared_ptr brokerMgmtObject) -{ - if (mgmtObject != 0){ - _qmf::Queue::PerThreadStats *qStats = mgmtObject->getStatistics(); - _qmf::Broker::PerThreadStats *bStats = brokerMgmtObject->getStatistics(); - uint64_t contentSize = msg.getMessageSize(); - - qStats->msgTotalDequeues += 1; - bStats->msgTotalDequeues += 1; - qStats->byteTotalDequeues += contentSize; - bStats->byteTotalDequeues += contentSize; - if (msg.isPersistent ()){ - qStats->msgPersistDequeues += 1; - bStats->msgPersistDequeues += 1; - qStats->bytePersistDequeues += contentSize; - bStats->bytePersistDequeues += contentSize; - } - mgmtObject->statisticsUpdated(); - brokerMgmtObject->statisticsUpdated(); - } -} - -QueueSettings merge(const QueueSettings& inputs, const Broker& broker) -{ - QueueSettings settings(inputs); - settings.maxDepth = QueueDepth(); - if (inputs.maxDepth.hasCount() && inputs.maxDepth.getCount()) { - settings.maxDepth.setCount(inputs.maxDepth.getCount()); - } - if (inputs.maxDepth.hasSize()) { - if (inputs.maxDepth.getSize()) { - settings.maxDepth.setSize(inputs.maxDepth.getSize()); - } - } else if (broker.getQueueLimit()) { - settings.maxDepth.setSize(broker.getQueueLimit()); - } - return settings; -} - -} - - -Queue::TxPublish::TxPublish(const Message& m, boost::shared_ptr q) : message(m), queue(q), prepared(false) {} -bool Queue::TxPublish::prepare(TransactionContext* ctxt) throw() -{ - try { - prepared = queue->enqueue(ctxt, message); - return true; - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to prepare: " << e.what()); - return false; - } -} -void Queue::TxPublish::commit() throw() -{ - try { - if (prepared) queue->process(message); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } -} -void Queue::TxPublish::rollback() throw() -{ - try { - if (prepared) queue->enqueueAborted(message); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to rollback: " << e.what()); - } -} - -void Queue::TxPublish::callObserver( - const boost::shared_ptr& observer) -{ - observer->enqueue(queue, message); -} - -Queue::Queue(const string& _name, const QueueSettings& _settings, - MessageStore* const _store, - Manageable* parent, - Broker* b) : - - name(_name), - store(_store), - owner(0), - exclusive(0), - messages(new MessageDeque()), - persistenceId(0), - settings(b ? merge(_settings, *b) : _settings), - eventMode(0), - observers(name, messageLock), - broker(b), - deleted(false), - barrier(*this), - allocator(new FifoDistributor( *messages )), - redirectSource(false) -{ - current.setCount(0);//always track depth in messages - if (settings.maxDepth.getSize()) current.setSize(0);//track depth in bytes only if policy requires it - if (settings.traceExcludes.size()) { - split(traceExclude, settings.traceExcludes, ", "); - } - qpid::amqp_0_10::translate(settings.asMap(), encodableSettings); - if (parent != 0 && broker != 0) { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) { - mgmtObject = _qmf::Queue::shared_ptr( - new _qmf::Queue(agent, this, parent, _name, _store != 0, settings.autodelete)); - mgmtObject->set_arguments(settings.asMap()); - agent->addObject(mgmtObject, 0, store != 0); - brokerMgmtObject = boost::dynamic_pointer_cast<_qmf::Broker>(broker->GetManagementObject()); - if (brokerMgmtObject) - brokerMgmtObject->inc_queueCount(); - } - } - - if ( settings.isBrowseOnly ) { - QPID_LOG ( info, "Queue " << name << " is browse-only." ); - } - if (settings.filter.size()) { - selector.reset(new Selector(settings.filter)); - QPID_LOG (info, "Queue " << name << " using filter: " << settings.filter); - } -} - -Queue::~Queue() -{ - if (mgmtObject != 0) { - mgmtObject->debugStats("destroying"); - mgmtObject->resourceDestroy(); - } -} - -bool Queue::isLocal(const Message& msg) -{ - //message is considered local if it was published on the same - //connection as that of the session which declared this queue - //exclusive (owner) or which has an exclusive subscription - //(exclusive) - return settings.noLocal && (msg.isLocalTo(owner) || msg.isLocalTo(exclusive)); -} - -bool Queue::isExcluded(const Message& msg) -{ - return traceExclude.size() && msg.isExcluded(traceExclude); -} - -bool Queue::accept(const Message& msg) -{ - //TODO: move some of this out of the queue and into the publishing - //'link' for whatever protocol is used; that would let protocol - //specific stuff be kept out the queue - if (broker::amqp_0_10::MessageTransfer::isImmediateDeliveryRequired(msg) && getConsumerCount() == 0) { - if (alternateExchange) { - DeliverableMessage deliverable(msg, 0); - alternateExchange->route(deliverable); - } - return false; - } else if (isLocal(msg)) { - //drop message - QPID_LOG(info, "Dropping 'local' message from " << getName()); - return false; - } else if (isExcluded(msg)) { - //drop message - QPID_LOG(info, "Dropping excluded message from " << getName()); - return false; - } else { - messages->check(msg); - if (selector) { - return selector->filter(msg); - } else { - return true; - } - } -} - -void Queue::deliver(Message msg, TxBuffer* txn) -{ - if (redirectPeer) { - redirectPeer->deliverTo(msg, txn); - } else { - deliverTo(msg, 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); - QPID_LOG(debug, "Message " << msg.getSequence() << " enqueue on " << name - << " enlisted in " << txn); - } else { - if (enqueue(0, msg)) { - push(msg); - QPID_LOG(debug, "Message " << msg.getSequence() << " enqueued on " << name); - } else { - QPID_LOG(debug, "Message " << msg.getSequence() << " dropped from " << name); - } - } - } -} - -void Queue::recoverPrepared(const Message& msg) -{ - Mutex::ScopedLock locker(messageLock); - current += QueueDepth(1, msg.getMessageSize()); -} - -void Queue::recover(Message& msg) -{ - recoverPrepared(msg); - push(msg, true); -} - -void Queue::process(Message& msg) -{ - push(msg); - if (mgmtObject != 0){ - _qmf::Queue::PerThreadStats *qStats = mgmtObject->getStatistics(); - const uint64_t contentSize = msg.getMessageSize(); - qStats->msgTxnEnqueues += 1; - qStats->byteTxnEnqueues += contentSize; - mgmtObject->statisticsUpdated(); - if (brokerMgmtObject) { - _qmf::Broker::PerThreadStats *bStats = brokerMgmtObject->getStatistics(); - bStats->msgTxnEnqueues += 1; - bStats->byteTxnEnqueues += contentSize; - brokerMgmtObject->statisticsUpdated(); - } - } -} - -void Queue::mergeMessageAnnotations(const QueueCursor& position, - const qpid::types::Variant::Map& messageAnnotations) -{ - Mutex::ScopedLock locker(messageLock); - Message *message = messages->find(position); - if (!message) return; - - qpid::types::Variant::Map::const_iterator it; - for (it = messageAnnotations.begin(); it != messageAnnotations.end(); ++it) { - message->addAnnotation(it->first, it->second); - } -} - -void Queue::release(const QueueCursor& position, bool markRedelivered) -{ - QueueListeners::NotificationSet copy; - { - Mutex::ScopedLock locker(messageLock); - if (!deleted) { - Message* message = messages->release(position); - if (message) { - if (!markRedelivered) message->undeliver(); - listeners.populate(copy); - observeRequeue(*message, locker); - if (mgmtObject) { - mgmtObject->inc_releases(); - if (brokerMgmtObject) - brokerMgmtObject->inc_releases(); - } - } - } - } - copy.notify(); -} - -bool Queue::dequeueMessageAt(const SequenceNumber& position) -{ - ScopedAutoDelete autodelete(*this); - boost::intrusive_ptr pmsg; - { - Mutex::ScopedLock locker(messageLock); - QPID_LOG(debug, "Attempting to dequeue message at " << position); - QueueCursor cursor; - Message* msg = messages->find(position, &cursor); - if (msg) { - if (msg->isPersistent()) pmsg = msg->getPersistentContext(); - observeDequeue(*msg, locker, settings.autodelete ? &autodelete : 0); - messages->deleted(cursor); - } else { - QPID_LOG(debug, "Could not dequeue message at " << position << "; no such message"); - return false; - } - } - dequeueFromStore(pmsg); - return true; -} - -bool Queue::acquire(const QueueCursor& position, const std::string& consumer) -{ - Mutex::ScopedLock locker(messageLock); - Message* msg; - - msg = messages->find(position); - if (msg) { - QPID_LOG(debug, consumer << " attempting to acquire message at " << msg->getSequence()); - if (!allocator->acquire(consumer, *msg)) { - QPID_LOG(debug, "Not permitted to acquire msg at " << msg->getSequence() << " from '" << name); - return false; - } else { - observeAcquire(*msg, locker); - QPID_LOG(debug, "Acquired message at " << msg->getSequence() << " from " << name); - return true; - } - } else { - QPID_LOG(debug, "Failed to acquire message which no longer exists on " << name); - return false; - } -} - -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); - QueueCursor cursor = c->getCursor(); // Save current position. - Message* msg = messages->next(*c); // Advances c. - if (msg) { - if (isExpired(name, *msg, sys::AbsTime::now())) { - QPID_LOG(debug, "Message expired from queue '" << name << "'"); - observeDequeue(*msg, locker, settings.autodelete ? &autodelete : 0); - //ERROR: don't hold lock across call to store!! - if (msg->isPersistent()) dequeueFromStore(msg->getPersistentContext()); - if (mgmtObject) { - mgmtObject->inc_discardsTtl(); - if (brokerMgmtObject) - brokerMgmtObject->inc_discardsTtl(); - } - messages->deleted(*c); - continue; - } - - if (c->filter(*msg)) { - if (c->accept(*msg)) { - if (c->preAcquires()) { - QPID_LOG(debug, "Attempting to acquire message " << msg->getSequence() - << " from '" << name << "' with state " << msg->getState()); - if (allocator->acquire(c->getName(), *msg)) { - if (mgmtObject) { - mgmtObject->inc_acquires(); - if (brokerMgmtObject) - brokerMgmtObject->inc_acquires(); - } - observeAcquire(*msg, locker); - msg->deliver(); - } else { - QPID_LOG(debug, "Could not acquire message from '" << name << "'"); - continue; //try another message - } - } - QPID_LOG(debug, "Message " << msg->getSequence() << " retrieved from '" - << name << "'"); - m = *msg; - 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 << "'"); - c->setCursor(cursor); // Restore cursor, will try again with credit - if (c->preAcquires()) { - //let someone else try - listeners.populate(set); - } - break; - } - } else { - //consumer will never want this message, try another one - QPID_LOG(debug, "Consumer doesn't want message from '" << name << "'"); - if (c->preAcquires()) { - //let someone else try to take this one - listeners.populate(set); - } - } - } else { - QPID_LOG(debug, "No messages to dispatch on queue '" << name << "'"); - c->stopped(); - listeners.addListener(c); - break; - } - - } - set.notify(); - return messageFound; -} - -void Queue::removeListener(Consumer::shared_ptr c) -{ - QueueListeners::NotificationSet set; - { - Mutex::ScopedLock locker(messageLock); - listeners.removeListener(c); - if (messages->size()) { - listeners.populate(set); - } - } - set.notify(); -} - -bool Queue::dispatch(Consumer::shared_ptr c) -{ - Message msg; - if (getNextMessage(msg, c)) { - c->deliver(*c, msg); - return true; - } else { - return false; - } -} - -bool Queue::find(SequenceNumber pos, Message& msg) const -{ - Mutex::ScopedLock locker(messageLock); - Message* ptr = messages->find(pos, 0); - if (ptr) { - msg = *ptr; - return true; - } - return false; -} - -void Queue::markInUse(bool controlling) -{ - Mutex::ScopedLock locker(messageLock); - if (controlling) users.addLifecycleController(); - else users.addOther(); -} - -void Queue::releaseFromUse(bool controlling, bool doDelete) -{ - bool trydelete; - if (controlling) { - Mutex::ScopedLock locker(messageLock); - users.removeLifecycleController(); - trydelete = true; - } else { - Mutex::ScopedLock locker(messageLock); - users.removeOther(); - trydelete = isUnused(locker); - } - if (trydelete && doDelete) scheduleAutoDelete(); -} - -void Queue::consume(Consumer::shared_ptr c, bool requestExclusive, - const framing::FieldTable& arguments, - const std::string& connectionId, const std::string& userId) -{ - boost::intrusive_ptr t; - { - Mutex::ScopedLock locker(messageLock); - if (c->preAcquires()) { - if(settings.isBrowseOnly) { - throw NotAllowedException( - QPID_MSG("Queue " << name << " is browse only. Refusing acquiring consumer.")); - } - - if(exclusive) { - throw ResourceLockedException( - QPID_MSG("Queue " << getName() - << " has an exclusive consumer. No more consumers allowed.")); - } else if(requestExclusive) { - if(users.hasConsumers()) { - throw ResourceLockedException( - QPID_MSG("Queue " << getName() - << " already has consumers. Exclusive access denied.")); - } else { - exclusive = c->getSession(); - } - } - users.addConsumer(); - } else if(c->isCounted()) { - users.addBrowser(); - } - if(c->isCounted()) { - //reset auto deletion timer if necessary - if (settings.autoDeleteDelay && autoDeleteTask) { - t = autoDeleteTask; - } - - observeConsumerAdd(*c, locker); - } - } - if (t) t->cancel(); - if (mgmtObject != 0 && c->isCounted()) { - mgmtObject->inc_consumerCount(); - } - if (broker) { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent) { - agent->raiseEvent( - _qmf::EventSubscribe(connectionId, userId, name, - c->getTag(), requestExclusive, ManagementAgent::toMap(arguments))); - } - } -} - -void Queue::cancel(Consumer::shared_ptr c, const std::string& connectionId, const std::string& userId) -{ - removeListener(c); - if(c->isCounted()) - - { - bool unused; - { - Mutex::ScopedLock locker(messageLock); - if (c->preAcquires()) { - users.removeConsumer(); - if (exclusive) exclusive = 0; - } else { - users.removeBrowser(); - } - observeConsumerRemove(*c, locker); - unused = !users.isUsed(); - } - if (mgmtObject != 0) { - mgmtObject->dec_consumerCount(); - } - if (unused && settings.autodelete) scheduleAutoDelete(); - } - if (broker) { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent) agent->raiseEvent(_qmf::EventUnsubscribe(connectionId, userId, c->getTag())); - } -} - -bool Queue::isExpired(const std::string& name, const Message& m, AbsTime now) -{ - if (m.getExpiration() < now) { - QPID_LOG(debug, "Message expired from queue '" << name << "': " << m.printProperties()); - return true; - } else { - return false; - } -} - -/** - *@param lapse: time since the last purgeExpired - */ -void Queue::purgeExpired(sys::Duration lapse) { - //As expired messages are discarded during dequeue also, only - //bother explicitly expiring if the rate of dequeues since last - //attempt is less than one per second. - int count = dequeueSincePurge.get(); - dequeueSincePurge -= count; - int seconds = int64_t(lapse)/qpid::sys::TIME_SEC; - if (seconds == 0 || count / seconds < 1) { - sys::AbsTime time = sys::AbsTime::now(); - uint32_t count = remove(0, boost::bind(&isExpired, name, _1, time), 0, CONSUMER, settings.autodelete); - QPID_LOG(debug, "Purged " << count << " expired messages from " << getName()); - // - // Report the count of discarded-by-ttl messages - // - if (mgmtObject && count) { - mgmtObject->inc_discardsTtl(count); - if (brokerMgmtObject) { - brokerMgmtObject->inc_discardsTtl(count); - } - } - } -} - -namespace { - // for use with purge/move below - collect messages that match a given filter - // - class MessageFilter - { - public: - static const std::string typeKey; - static const std::string paramsKey; - static MessageFilter *create( const ::qpid::types::Variant::Map *filter ); - virtual bool match( const Message& ) const { return true; } - virtual ~MessageFilter() {} - protected: - MessageFilter() {}; - }; - const std::string MessageFilter::typeKey("filter_type"); - const std::string MessageFilter::paramsKey("filter_params"); - - // filter by message header string value exact match - class HeaderMatchFilter : public MessageFilter - { - public: - /* Config: - { 'filter_type' : 'header_match_str', - 'filter_params' : { 'header_key' : "
", - 'header_value' : "" - } - } - */ - static const std::string typeKey; - static const std::string headerKey; - static const std::string valueKey; - HeaderMatchFilter( const std::string& _header, const std::string& _value ) - : MessageFilter (), header(_header), value(_value) {} - bool match( const Message& msg ) const - { - return msg.getPropertyAsString(header) == value; - } - private: - const std::string header; - const std::string value; - }; - const std::string HeaderMatchFilter::typeKey("header_match_str"); - const std::string HeaderMatchFilter::headerKey("header_key"); - const std::string HeaderMatchFilter::valueKey("header_value"); - - // factory to create correct filter based on map - MessageFilter* MessageFilter::create( const ::qpid::types::Variant::Map *filter ) - { - using namespace qpid::types; - if (filter && !filter->empty()) { - Variant::Map::const_iterator i = filter->find(MessageFilter::typeKey); - if (i != filter->end()) { - - if (i->second.asString() == HeaderMatchFilter::typeKey) { - Variant::Map::const_iterator p = filter->find(MessageFilter::paramsKey); - if (p != filter->end() && p->second.getType() == VAR_MAP) { - Variant::Map::const_iterator k = p->second.asMap().find(HeaderMatchFilter::headerKey); - Variant::Map::const_iterator v = p->second.asMap().find(HeaderMatchFilter::valueKey); - if (k != p->second.asMap().end() && v != p->second.asMap().end()) { - std::string headerKey(k->second.asString()); - std::string value(v->second.asString()); - QPID_LOG(debug, "Message filtering by header value configured. key: " << headerKey << " value: " << value ); - return new HeaderMatchFilter( headerKey, value ); - } - } - } - } - QPID_LOG(error, "Unrecognized message filter: '" << *filter << "'"); - throw qpid::Exception(QPID_MSG("Unrecognized message filter: '" << *filter << "'")); - } - return new MessageFilter(); - } - - void moveTo(boost::shared_ptr q, Message& m) - { - if (q) { - q->deliver(m); - } - } -} // end namespace - -uint32_t Queue::remove(const uint32_t maxCount, MessagePredicate p, MessageFunctor f, - SubscriptionType type, bool triggerAutoDelete, uint32_t maxTests) -{ - ScopedAutoDelete autodelete(*this); - std::deque removed; - { - QueueCursor c(type); - uint32_t count(0), tests(0); - Mutex::ScopedLock locker(messageLock); - Message* m = messages->next(c); - while (m){ - if (maxTests && tests++ >= maxTests) break; - if (!p || p(*m)) { - if (maxCount && count++ >= maxCount) break; - if (m->getState() == AVAILABLE) { - //don't actually acquire, just act as if we did - observeAcquire(*m, locker); - } - observeDequeue(*m, locker, triggerAutoDelete ? &autodelete : 0); - removed.push_back(*m);//takes a copy of the message - if (!messages->deleted(c)) { - QPID_LOG(warning, "Failed to correctly remove message from " << name << "; state is not consistent!"); - assert(false); - } - } - m = messages->next(c); - } - } - for (std::deque::iterator i = removed.begin(); i != removed.end(); ++i) { - if (f) f(*i);//ERROR? need to clear old persistent context? - if (i->isPersistent()) dequeueFromStore(i->getPersistentContext());//do this outside of lock and after any re-routing - } - return removed.size(); -} - - -/** - * purge - for purging all or some messages on a queue - * depending on the purge_request - * - * qty == 0 then purge all messages - * == N then purge N messages from queue - * Sometimes qty == 1 to unblock the top of queue - * - * The dest exchange may be supplied to re-route messages through the exchange. - * It is safe to re-route messages such that they arrive back on the same queue, - * even if the queue is ordered by priority. - * - * An optional filter can be supplied that will be applied against each message. The - * message is purged only if the filter matches. See MessageDistributor for more detail. - */ -uint32_t Queue::purge(const uint32_t qty, boost::shared_ptr dest, - const qpid::types::Variant::Map *filter) -{ - std::auto_ptr mf(MessageFilter::create(filter)); - uint32_t count = remove(qty, boost::bind(&MessageFilter::match, mf.get(), _1), boost::bind(&reroute, dest, _1), CONSUMER/*?*/, settings.autodelete); - - if (mgmtObject && count) { - mgmtObject->inc_acquires(count); - if (dest.get()) { - mgmtObject->inc_reroutes(count); - if (brokerMgmtObject) { - brokerMgmtObject->inc_acquires(count); - brokerMgmtObject->inc_reroutes(count); - } - } else { - mgmtObject->inc_discardsPurge(count); - if (brokerMgmtObject) { - brokerMgmtObject->inc_acquires(count); - brokerMgmtObject->inc_discardsPurge(count); - } - } - } - - return count; -} - -uint32_t Queue::move(const Queue::shared_ptr destq, uint32_t qty, - const qpid::types::Variant::Map *filter) -{ - std::auto_ptr mf(MessageFilter::create(filter)); - return remove(qty, boost::bind(&MessageFilter::match, mf.get(), _1), boost::bind(&moveTo, destq, _1), CONSUMER/*?*/, settings.autodelete); -} - -void Queue::push(Message& message, bool /*isRecovery*/) -{ - QueueListeners::NotificationSet copy; - { - Mutex::ScopedLock locker(messageLock); - message.setSequence(++sequence); - if (settings.sequencing) message.addAnnotation(settings.sequenceKey, (uint32_t)sequence); - interceptors.publish(message); - messages->publish(message); - listeners.populate(copy); - observeEnqueue(message, locker); - } - copy.notify(); -} - -uint32_t Queue::getMessageCount() const -{ - Mutex::ScopedLock locker(messageLock); - return messages->size(); -} - -uint32_t Queue::getConsumerCount() const -{ - Mutex::ScopedLock locker(messageLock); - return users.getSubscriberCount(); -} - -bool Queue::canAutoDelete() const -{ - Mutex::ScopedLock locker(messageLock); - return !deleted && checkAutoDelete(locker); -} - -bool Queue::checkAutoDelete(const Mutex::ScopedLock& lock) const -{ - if (settings.autodelete) { - switch (settings.lifetime) { - case QueueSettings::DELETE_IF_UNUSED: - return isUnused(lock); - case QueueSettings::DELETE_IF_EMPTY: - return !users.isInUseByController() && isEmpty(lock); - case QueueSettings::DELETE_IF_UNUSED_AND_EMPTY: - return isUnused(lock) && isEmpty(lock); - case QueueSettings::DELETE_ON_CLOSE: - return !users.isInUseByController(); - } - } - return false; -} - -bool Queue::isUnused(const Mutex::ScopedLock&) const -{ - return !owner && !users.isUsed();; -} - -bool Queue::isEmpty(const Mutex::ScopedLock&) const -{ - return current.getCount() == 0; -} -/* - * return true if enqueue succeeded and message should be made - * available; returning false will result in the message being dropped - */ -bool Queue::enqueue(TransactionContext* ctxt, Message& msg) -{ - ScopedUse u(barrier); - if (!u.acquired) return false; - - { - Mutex::ScopedLock locker(messageLock); - if (!checkDepth(QueueDepth(1, msg.getMessageSize()), msg)) { - return false; - } - } - - if (settings.traceId.size()) { - msg.addTraceId(settings.traceId); - } - - if (msg.isPersistent() && store) { - // mark the message as being enqueued - the store MUST CALL msg->enqueueComplete() - // when it considers the message stored. - boost::intrusive_ptr pmsg = msg.getPersistentContext(); - assert(pmsg); - pmsg->enqueueAsync(shared_from_this()); - try { - store->enqueue(ctxt, pmsg, *this); - } catch (...) { - enqueueAborted(msg); - throw; - } - } - return true; -} - -void Queue::enqueueAborted(const Message& msg) -{ - //Called when any transactional enqueue is aborted (including but - //not limited to a recovered dtx transaction) - Mutex::ScopedLock locker(messageLock); - current -= QueueDepth(1, msg.getMessageSize()); -} - -void Queue::enqueueCommited(Message& msg) -{ - //called when a recovered dtx enqueue operation is committed; the - //message is already on disk and space has been reserved in policy - //but it should now be made available - process(msg); -} -void Queue::dequeueAborted(Message& msg) -{ - //called when a recovered dtx dequeue operation is aborted; the - //message should be added back to the queue - push(msg); -} -void Queue::dequeueCommited(const Message& msg) -{ - //called when a recovered dtx dequeue operation is committed; the - //message will at this point have already been removed from the - //store and will not be available for delivery. The only action - //required is to ensure the observers are notified and the - //management stats are correctly decremented - ScopedAutoDelete autodelete(*this); - Mutex::ScopedLock locker(messageLock); - observeDequeue(msg, locker, settings.autodelete ? &autodelete : 0); - if (mgmtObject != 0) { - mgmtObject->inc_msgTxnDequeues(); - mgmtObject->inc_byteTxnDequeues(msg.getMessageSize()); - } -} - - -void Queue::dequeueFromStore(boost::intrusive_ptr msg) -{ - ScopedUse u(barrier); - if (u.acquired && msg && store) { - store->dequeue(0, msg, *this); - } -} - -void Queue::dequeue(const QueueCursor& cursor, TxBuffer* txn) -{ - if (txn) { - TxOp::shared_ptr op; - { - Mutex::ScopedLock locker(messageLock); - Message* msg = messages->find(cursor); - if (msg) { - op = TxOp::shared_ptr(new TxDequeue(cursor, shared_from_this(), msg->getSequence(), msg->getReplicationId())); - } - } - if (op) txn->enlist(op); - } else { - dequeue(0, cursor); - } -} - - -void Queue::dequeue(TransactionContext* ctxt, const QueueCursor& cursor) -{ - ScopedUse u(barrier); - if (!u.acquired) return; - ScopedAutoDelete autodelete(*this); - boost::intrusive_ptr pmsg; - { - Mutex::ScopedLock locker(messageLock); - Message* msg = messages->find(cursor); - if (msg) { - if (msg->isPersistent()) pmsg = msg->getPersistentContext(); - if (!ctxt) { - observeDequeue(*msg, locker, settings.autodelete ? &autodelete : 0); - messages->deleted(cursor);//message pointer not valid after this - } - } else { - return; - } - } - if (store && pmsg) { - store->dequeue(ctxt, pmsg, *this); - } -} - -void Queue::dequeueCommitted(const QueueCursor& cursor) -{ - ScopedAutoDelete autodelete(*this); - Mutex::ScopedLock locker(messageLock); - Message* msg = messages->find(cursor); - if (msg) { - const uint64_t contentSize = msg->getMessageSize(); - observeDequeue(*msg, locker, settings.autodelete ? &autodelete : 0); - if (mgmtObject != 0) { - mgmtObject->inc_msgTxnDequeues(); - mgmtObject->inc_byteTxnDequeues(contentSize); - } - if (brokerMgmtObject) { - _qmf::Broker::PerThreadStats *bStats = brokerMgmtObject->getStatistics(); - bStats->msgTxnDequeues += 1; - bStats->byteTxnDequeues += contentSize; - brokerMgmtObject->statisticsUpdated(); - } - messages->deleted(cursor); - } else { - QPID_LOG(error, "Could not find dequeued message on commit"); - } -} - -/** - * Updates policy and management when a message has been dequeued, - * Requires messageLock be held by caller. - */ -void Queue::observeDequeue(const Message& msg, const Mutex::ScopedLock& lock, ScopedAutoDelete* autodelete) -{ - current -= QueueDepth(1, msg.getMessageSize()); - mgntDeqStats(msg, mgmtObject, brokerMgmtObject); - observers.dequeued(msg, lock); - if (autodelete && isEmpty(lock)) autodelete->check(lock); -} - -/** updates queue observers when a message has become unavailable for transfer. - * Requires messageLock be held by caller. - */ -void Queue::observeAcquire(const Message& msg, const Mutex::ScopedLock& l) -{ - observers.acquired(msg, l); -} - -/** updates queue observers when a message has become re-available for transfer - * Requires messageLock be held by caller. - */ -void Queue::observeRequeue(const Message& msg, const Mutex::ScopedLock& l) -{ - observers.requeued(msg, l); -} - -/** updates queue observers when a new consumer has subscribed to this queue. - */ -void Queue::observeConsumerAdd( const Consumer& c, const qpid::sys::Mutex::ScopedLock& l) -{ - observers.consumerAdded(c, l); -} - -/** updates queue observers when a consumer has unsubscribed from this queue. - */ -void Queue::observeConsumerRemove( const Consumer& c, const qpid::sys::Mutex::ScopedLock& l) -{ - observers.consumerRemoved(c, l); -} - - -void Queue::create() -{ - if (store) { - store->create(*this, settings.storeSettings); - } -} - - -int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::string& key) -{ - qpid::framing::FieldTable::ValuePtr v = settings.get(key); - if (!v) { - return 0; - } else if (v->convertsTo()) { - return v->get(); - } else if (v->convertsTo()){ - std::string s = v->get(); - try { - return boost::lexical_cast(s); - } catch(const boost::bad_lexical_cast&) { - QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << s); - return 0; - } - } else { - QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << *v); - return 0; - } -} - -bool getBoolSetting(const qpid::framing::FieldTable& settings, const std::string& key) -{ - qpid::framing::FieldTable::ValuePtr v = settings.get(key); - if (!v) { - return false; - } else if (v->convertsTo()) { - return v->get() != 0; - } else if (v->convertsTo()){ - std::string s = v->get(); - if (s == "True") return true; - if (s == "true") return true; - if (s == "False") return false; - if (s == "false") return false; - try { - return boost::lexical_cast(s); - } catch(const boost::bad_lexical_cast&) { - QPID_LOG(warning, "Ignoring invalid boolean value for " << key << ": " << s); - return false; - } - } else { - QPID_LOG(warning, "Ignoring invalid boolean value for " << key << ": " << *v); - return false; - } -} - -void Queue::abandoned(const Message& message) -{ - if (reroute(alternateExchange, message) && brokerMgmtObject) - brokerMgmtObject->inc_abandonedViaAlt(); - else if (brokerMgmtObject) - brokerMgmtObject->inc_abandoned(); -} - -void Queue::destroyed() -{ - if (mgmtObject != 0) - mgmtObject->debugStats("destroying"); - unbind(broker->getExchanges()); - remove(0, 0, boost::bind(&Queue::abandoned, this, _1), REPLICATOR/*even acquired message are treated as abandoned*/, false); - if (alternateExchange.get()) { - alternateExchange->decAlternateUsers(); - alternateExchange.reset(); - } - - if (store) { - barrier.destroy(); - store->flush(*this); - store->destroy(*this); - store = 0;//ensure we make no more calls to the store for this queue - } - notifyDeleted(); - { - Mutex::ScopedLock l(messageLock); - if (autoDeleteTask) autoDeleteTask = boost::intrusive_ptr(); - observers.destroy(l); - } - if (mgmtObject != 0) { - mgmtObject->resourceDestroy(); - if (brokerMgmtObject) - brokerMgmtObject->dec_queueCount(); - mgmtObject = _qmf::Queue::shared_ptr(); // dont print debugStats in Queue::~Queue - } -} - -void Queue::notifyDeleted() -{ - QueueListeners::ListenerSet set; - { - Mutex::ScopedLock locker(messageLock); - deleted = true; - listeners.snapshot(set); - } - set.notifyAll(); -} - -void Queue::bound(const string& exchange, const string& key, - const FieldTable& args) -{ - bindings.add(exchange, key, args); -} - -void Queue::unbind(ExchangeRegistry& exchanges) -{ - bindings.unbind(exchanges, shared_from_this()); -} - - -uint64_t Queue::getPersistenceId() const -{ - return persistenceId; -} - -void Queue::setPersistenceId(uint64_t _persistenceId) const -{ - if (mgmtObject != 0 && persistenceId == 0 && externalQueueStore) - { - ManagementObject::shared_ptr childObj = externalQueueStore->GetManagementObject(); - if (childObj != 0) - childObj->setReference(mgmtObject->getObjectId()); - } - persistenceId = _persistenceId; -} - -void Queue::encode(Buffer& buffer) const -{ - buffer.putShortString(name); - buffer.put(encodableSettings); - buffer.putShortString(alternateExchange.get() ? alternateExchange->getName() : std::string("")); - buffer.putShortString(userId); - buffer.putInt8(isAutoDelete()); -} - -uint32_t Queue::encodedSize() const -{ - return name.size() + 1/*short string size octet*/ - + (alternateExchange.get() ? alternateExchange->getName().size() : 0) + 1 /* short string */ - + userId.size() + 1 /* short string */ - + 1 /* autodelete flag */ - + encodableSettings.encodedSize(); -} - -void Queue::updateAclUserQueueCount() -{ - if (broker->getAcl()) - broker->getAcl()->approveCreateQueue(userId, name); -} - -Queue::shared_ptr Queue::restore( QueueRegistry& queues, Buffer& buffer ) -{ - string name; - string _userId; - FieldTable ft; - boost::shared_ptr alternate; - QueueSettings settings(true, false); // settings.autodelete might be overwritten - string altExch; - bool has_userId = false; - bool has_altExch = false; - - buffer.getShortString(name); - buffer.get(ft); - settings.populate(ft, settings.storeSettings); - //get alternate exchange - if (buffer.available()) { - buffer.getShortString(altExch); - has_altExch = true; - } - //get userId of queue's creator; ACL counters for userId are done after ACL plugin is initialized - if (buffer.available()) { - buffer.getShortString(_userId); - has_userId = true; - } - //get autodelete flag - if (buffer.available()) { - settings.autodelete = buffer.getInt8(); - } - - std::pair result = queues.declare(name, settings, alternate, true); - if (has_altExch) - result.first->alternateExchangeName.assign(altExch); - if (has_userId) - result.first->setOwningUser(_userId); - - if (result.first->getSettings().autoDeleteDelay) { - result.first->scheduleAutoDelete(); - } - - return result.first; -} - - -void Queue::setAlternateExchange(boost::shared_ptr exchange) -{ - alternateExchange = exchange; - alternateExchange->incAlternateUsers(); - if (mgmtObject) { - if (exchange.get() != 0) - mgmtObject->set_altExchange(exchange->GetManagementObject()->getObjectId()); - else - mgmtObject->clr_altExchange(); - } -} - -boost::shared_ptr Queue::getAlternateExchange() -{ - return alternateExchange; -} - -struct AutoDeleteTask : qpid::sys::TimerTask -{ - Queue::shared_ptr queue; - long expectedVersion; - - AutoDeleteTask(Queue::shared_ptr q, AbsTime fireTime) - : qpid::sys::TimerTask(fireTime, "DelayedAutoDeletion:"+q->getName()), queue(q), expectedVersion(q->version) {} - - void fire() - { - //need to detect case where queue was used after the task was - //created, but then became unused again before the task fired; - //in this case ignore this request as there will have already - //been a later task added - queue->tryAutoDelete(expectedVersion); - } -}; - -void Queue::scheduleAutoDelete(bool immediate) -{ - if (canAutoDelete()) { - if (!immediate && settings.autoDeleteDelay) { - AbsTime time(now(), Duration(settings.autoDeleteDelay * TIME_SEC)); - autoDeleteTask = boost::intrusive_ptr(new AutoDeleteTask(shared_from_this(), time)); - broker->getTimer().add(autoDeleteTask); - QPID_LOG(debug, "Timed auto-delete for " << getName() << " initiated"); - } else { - tryAutoDelete(version); - } - } -} - -void Queue::tryAutoDelete(long expectedVersion) -{ - bool proceed(false); - { - Mutex::ScopedLock locker(messageLock); - if (!deleted && checkAutoDelete(locker)) { - proceed = true; - } - } - - if (proceed) { - if (broker->getQueues().destroyIfUntouched(name, expectedVersion)) { - { - Mutex::ScopedLock locker(messageLock); - deleted = true; - } - if (broker->getAcl()) - broker->getAcl()->recordDestroyQueue(name); - - QPID_LOG_CAT(debug, model, "Auto-delete queue deleted: " << name << " (" << deleted << ")"); - } else { - //queue was accessed since the delayed auto-delete was scheduled, so try again - QPID_LOG_CAT(debug, model, "Auto-delete interrupted for queue: " << name); - scheduleAutoDelete(); - } - } else { - QPID_LOG_CAT(debug, model, "Auto-delete queue could not be deleted: " << name); - } -} - -bool Queue::isExclusiveOwner(const OwnershipToken* const o) const -{ - Mutex::ScopedLock locker(messageLock); - return o == owner; -} - -void Queue::releaseExclusiveOwnership(bool immediateExpiry) -{ - bool unused; - { - Mutex::ScopedLock locker(messageLock); - owner = 0; - if (mgmtObject) { - mgmtObject->set_exclusive(false); - } - unused = !users.isUsed(); - } - if (unused && settings.autodelete) { - scheduleAutoDelete(immediateExpiry); - } -} - -bool Queue::setExclusiveOwner(const OwnershipToken* const o) -{ - //reset auto deletion timer if necessary - if (settings.autoDeleteDelay && autoDeleteTask) { - autoDeleteTask->cancel(); - } - Mutex::ScopedLock locker(messageLock); - if (owner || users.hasConsumers()) { - return false; - } else { - owner = o; - if (mgmtObject) { - mgmtObject->set_exclusive(true); - } - return true; - } -} - -bool Queue::hasExclusiveOwner() const -{ - Mutex::ScopedLock locker(messageLock); - return owner != 0; -} - -bool Queue::hasExclusiveConsumer() const -{ - return exclusive; -} - -void Queue::setExternalQueueStore(ExternalQueueStore* inst) { - if (externalQueueStore!=inst && externalQueueStore) - delete externalQueueStore; - externalQueueStore = inst; - - if (inst) { - ManagementObject::shared_ptr childObj = inst->GetManagementObject(); - if (childObj != 0 && mgmtObject != 0) - childObj->setReference(mgmtObject->getObjectId()); - } -} - -void Queue::countRejected() const -{ - if (mgmtObject) { - mgmtObject->inc_discardsSubscriber(); - if (brokerMgmtObject) - brokerMgmtObject->inc_discardsSubscriber(); - } -} - -ManagementObject::shared_ptr Queue::GetManagementObject(void) const -{ - return mgmtObject; -} - -Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, string& etext) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - AclModule* acl = broker->getAcl(); - std::string _userId = (getCurrentPublisher()?getCurrentPublisher()->getUserId():""); - - QPID_LOG (debug, "Queue::ManagementMethod [id=" << methodId << "]"); - - switch (methodId) { - case _qmf::Queue::METHOD_PURGE : - { - if ((acl)&&(!(acl->authorise(_userId, acl::ACT_PURGE, acl::OBJ_QUEUE, name, NULL)))) { - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied purge request from " << _userId)); - } - _qmf::ArgsQueuePurge& purgeArgs = (_qmf::ArgsQueuePurge&) args; - purge(purgeArgs.i_request, boost::shared_ptr(), &purgeArgs.i_filter); - status = Manageable::STATUS_OK; - } - break; - - case _qmf::Queue::METHOD_REROUTE : - { - _qmf::ArgsQueueReroute& rerouteArgs = (_qmf::ArgsQueueReroute&) args; - boost::shared_ptr dest; - if (rerouteArgs.i_useAltExchange) { - if (!alternateExchange) { - status = Manageable::STATUS_PARAMETER_INVALID; - etext = "No alternate-exchange defined"; - break; - } - dest = alternateExchange; - } else { - try { - dest = broker->getExchanges().get(rerouteArgs.i_exchange); - } catch(const std::exception&) { - status = Manageable::STATUS_PARAMETER_INVALID; - etext = "Exchange not found"; - break; - } - } - - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_EXCHANGENAME, dest->getName())); - if (!acl->authorise(_userId, acl::ACT_REROUTE, acl::OBJ_QUEUE, name, ¶ms)) { - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied reroute request from " << _userId)); - } - } - - purge(rerouteArgs.i_request, dest, &rerouteArgs.i_filter); - status = Manageable::STATUS_OK; - } - break; - } - - return status; -} - - -void Queue::query(qpid::types::Variant::Map& results) const -{ - Mutex::ScopedLock locker(messageLock); - /** @todo add any interesting queue state into results */ - if (allocator) allocator->query(results); -} - -namespace { -struct After { - framing::SequenceNumber seq; - After(framing::SequenceNumber s) : seq(s) {} - bool operator()(const Message& m) { return m.getSequence() > seq; } -}; -} // namespace - - -void Queue::setPosition(SequenceNumber n) { - Mutex::ScopedLock locker(messageLock); - if (n < sequence) { - remove(0, After(n), MessagePredicate(), BROWSER, false); - } - sequence = n; - QPID_LOG(debug, "Set position to " << sequence << " on " << getName()); -} - -SequenceNumber Queue::getPosition() { - Mutex::ScopedLock locker(messageLock); - return sequence; -} - -void Queue::getRange(framing::SequenceNumber& front, framing::SequenceNumber& back, - SubscriptionType type) -{ - Mutex::ScopedLock locker(messageLock); - QueueCursor cursor(type); - back = sequence; - Message* message = messages->next(cursor); - front = message ? message->getSequence() : back+1; -} - -int Queue::getEventMode() { return eventMode; } - -void Queue::recoveryComplete(ExchangeRegistry& exchanges) -{ - // set the alternate exchange - if (!alternateExchangeName.empty()) { - Exchange::shared_ptr ae = exchanges.find(alternateExchangeName); - if (ae) setAlternateExchange(ae); - else QPID_LOG(warning, "Could not set alternate exchange \"" - << alternateExchangeName << "\" on queue \"" << name - << "\": exchange does not exist."); - } - //process any pending dequeues - for (std::vector::iterator i = pendingDequeues.begin(); i != pendingDequeues.end(); ++i) { - dequeueFromStore(i->getPersistentContext()); - } - pendingDequeues.clear(); -} - -/** updates queue observers and state when a message has become available for transfer - * Requires messageLock be held by caller. - */ -void Queue::observeEnqueue(const Message& m, const Mutex::ScopedLock& l) -{ - observers.enqueued(m, l); - mgntEnqStats(m, mgmtObject, brokerMgmtObject); -} - -bool Queue::checkNotDeleted(const Consumer::shared_ptr& c) -{ - if (deleted && !c->hideDeletedError()) - throw ResourceDeletedException(QPID_MSG("Queue " << getName() << " has been deleted.")); - return !deleted; -} - -bool Queue::isDeleted() const -{ - Mutex::ScopedLock lock(messageLock); - return deleted; -} - -void Queue::flush() -{ - ScopedUse u(barrier); - if (u.acquired && store) store->flush(*this); -} - - -bool Queue::bind(boost::shared_ptr exchange, const std::string& key, - const qpid::framing::FieldTable& arguments) -{ - if (!isDeleted() && exchange->bind(shared_from_this(), key, &arguments)) { - bound(exchange->getName(), key, arguments); - if (exchange->isDurable() && isDurable()) { - store->bind(*exchange, *this, key, arguments); - } - return true; - } else { - return false; - } -} - - -Broker* Queue::getBroker() -{ - return broker; -} - -void Queue::setDequeueSincePurge(uint32_t value) { - dequeueSincePurge = value; -} - -void Queue::reject(const QueueCursor& cursor) -{ - ScopedAutoDelete autodelete(*this); - Exchange::shared_ptr alternate = getAlternateExchange(); - Message copy; - boost::intrusive_ptr pmsg; - { - Mutex::ScopedLock locker(messageLock); - Message* message = messages->find(cursor); - if (message) { - if (alternate) copy = *message; - if (message->isPersistent()) pmsg = message->getPersistentContext(); - countRejected(); - observeDequeue(*message, locker, settings.autodelete ? &autodelete : 0); - messages->deleted(cursor); - } else { - return; - } - } - if (alternate) { - copy.resetDeliveryCount(); - DeliverableMessage delivery(copy, 0); - alternate->routeWithAlternate(delivery); - QPID_LOG(info, "Routed rejected message from " << getName() << " to " - << alternate->getName()); - } else { - //just drop it - QPID_LOG(info, "Dropping rejected message from " << getName()); - } - dequeueFromStore(pmsg); -} - -bool Queue::checkDepth(const QueueDepth& increment, const Message&) -{ - if (settings.maxDepth && (settings.maxDepth - current < increment)) { - if (mgmtObject) { - mgmtObject->inc_discardsOverflow(); - if (brokerMgmtObject) - brokerMgmtObject->inc_discardsOverflow(); - } - throw ResourceLimitExceededException(QPID_MSG("Maximum depth exceeded on " << name << ": current=[" << current << "], max=[" << settings.maxDepth << "]")); - } else { - current += increment; - return true; - } -} - -bool Queue::seek(QueueCursor& cursor, MessagePredicate predicate) -{ - Mutex::ScopedLock locker(messageLock); - //hold lock across calls to predicate, or take copy of message? - //currently hold lock, may want to revise depending on any new use - //cases - Message* message = messages->next(cursor); - while (message && (predicate && !predicate(*message))) { - message = messages->next(cursor); - } - return message != 0; -} - -bool Queue::seek(QueueCursor& cursor, MessagePredicate predicate, qpid::framing::SequenceNumber start) -{ - Mutex::ScopedLock locker(messageLock); - //hold lock across calls to predicate, or take copy of message? - //currently hold lock, may want to revise depending on any new use - //cases - Message* message; - message = messages->find(start, &cursor); - if (message && (!predicate || predicate(*message))) return true; - - return seek(cursor, predicate); -} - -bool Queue::seek(QueueCursor& cursor, qpid::framing::SequenceNumber start) -{ - Mutex::ScopedLock locker(messageLock); - return messages->find(start, &cursor); -} - -Queue::UsageBarrier::UsageBarrier(Queue& q) : parent(q), count(0) {} - -bool Queue::UsageBarrier::acquire() -{ - Monitor::ScopedLock l(usageLock); - if (parent.deleted) { - return false; - } else { - ++count; - return true; - } -} - -void Queue::UsageBarrier::release() -{ - Monitor::ScopedLock l(usageLock); - if (--count == 0) usageLock.notifyAll(); -} - -void Queue::UsageBarrier::destroy() -{ - Monitor::ScopedLock l(usageLock); - parent.deleted = true; - while (count) usageLock.wait(); -} - -void Queue::addArgument(const string& key, const types::Variant& value) { - settings.original[key] = value; - qpid::amqp_0_10::translate(settings.asMap(), encodableSettings); - boost::shared_ptr v; - qpid::amqp_0_10::translate(value, v); - settings.storeSettings.set(key, v); - if (mgmtObject != 0) mgmtObject->set_arguments(settings.asMap()); -} - - -void Queue::setRedirectPeer ( Queue::shared_ptr peer, bool isSrc) { - Mutex::ScopedLock locker(messageLock); - redirectPeer = peer; - redirectSource = isSrc; -} - -void Queue::setMgmtRedirectState( std::string peer, bool enabled, bool isSrc ) { - if (mgmtObject != 0) { - mgmtObject->set_redirectPeer(enabled ? peer : ""); - mgmtObject->set_redirectSource(isSrc); - } -} - -void Queue::setOwningUser(std::string& _userId) { - userId = _userId; - if (mgmtObject != 0) - mgmtObject->set_creator(userId); -} - -bool Queue::reroute(boost::shared_ptr 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; } -void Queue::QueueUsers::addLifecycleController() { assert(!controller); controller = true; } -void Queue::QueueUsers::addOther(){ ++others; } -void Queue::QueueUsers::removeConsumer() { assert(consumers > 0); --consumers; } -void Queue::QueueUsers::removeBrowser() { assert(browsers > 0); --browsers; } -void Queue::QueueUsers::removeLifecycleController() { assert(controller); controller = false; } -void Queue::QueueUsers::removeOther() { assert(others > 0); --others; } -bool Queue::QueueUsers::isInUseByController() const { return controller; } -bool Queue::QueueUsers::isUsed() const { return controller || consumers || browsers || others; } -uint32_t Queue::QueueUsers::getSubscriberCount() const { return consumers + browsers; } -bool Queue::QueueUsers::hasConsumers() const { return consumers; } - -Queue::ScopedAutoDelete::ScopedAutoDelete(Queue& q) : queue(q), eligible(false) {} -void Queue::ScopedAutoDelete::check(const sys::Mutex::ScopedLock& lock) -{ - eligible = queue.checkAutoDelete(lock); -} -Queue::ScopedAutoDelete::~ScopedAutoDelete() -{ - if (eligible) queue.scheduleAutoDelete(); -} - -}} - diff --git a/qpid/cpp/src/qpid/broker/Queue.h b/qpid/cpp/src/qpid/broker/Queue.h deleted file mode 100644 index 4b63a413b8..0000000000 --- a/qpid/cpp/src/qpid/broker/Queue.h +++ /dev/null @@ -1,552 +0,0 @@ -#ifndef _broker_Queue_h -#define _broker_Queue_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/BrokerImportExport.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/broker/Consumer.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Messages.h" -#include "qpid/broker/MessageInterceptor.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/QueueBindings.h" -#include "qpid/broker/QueueListeners.h" -#include "qpid/broker/QueueObservers.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/broker/TxOp.h" - -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/sys/AtomicCount.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Monitor.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Queue.h" -#include "qmf/org/apache/qpid/broker/Broker.h" -#include "qpid/framing/amqp_types.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace sys { -class TimerTask; -} -namespace broker { -class Broker; -class Exchange; -class MessageStore; -class QueueDepth; -class QueueEvents; -class QueueRegistry; -class QueueFactory; -class Selector; -class TransactionContext; -class TxBuffer; -class MessageDistributor; - -/** - * The brokers representation of an amqp queue. Messages are - * delivered to a queue from where they can be dispatched to - * registered consumers or be stored until dequeued or until one - * or more consumers registers. - */ -class Queue : public boost::enable_shared_from_this, - public PersistableQueue, public management::Manageable { - public: - typedef boost::function1 MessagePredicate; - - typedef boost::shared_ptr shared_ptr; - - protected: - friend struct AutoDeleteTask; - struct UsageBarrier - { - Queue& parent; - uint count; - qpid::sys::Monitor usageLock; - - UsageBarrier(Queue&); - bool acquire(); - void release(); - void destroy(); - }; - - struct ScopedUse - { - UsageBarrier& barrier; - const bool acquired; - ScopedUse(UsageBarrier& b) : barrier(b), acquired(barrier.acquire()) {} - ~ScopedUse() { if (acquired) barrier.release(); } - }; - - class TxPublish : public TxOp - { - Message message; - boost::shared_ptr queue; - bool prepared; - public: - TxPublish(const Message&,boost::shared_ptr); - bool prepare(TransactionContext* ctxt) throw(); - void commit() throw(); - void rollback() throw(); - void callObserver(const boost::shared_ptr&); - }; - - /** - * This class tracks whether a queue is in use and how it is being - * used. - */ - class QueueUsers - { - public: - QueueUsers(); - void addConsumer(); - void addBrowser(); - void addOther(); - void removeConsumer(); - void removeBrowser(); - void addLifecycleController(); - void removeLifecycleController(); - void removeOther(); - bool isUsed() const; - uint32_t getSubscriberCount() const; - bool hasConsumers() const; - bool isInUseByController() const; - private: - uint32_t consumers; - uint32_t browsers; - uint32_t others; - bool controller; - }; - - /** - * This class is used to check - and if necessary trigger - - * autodeletion when removing messages, as this could cause the - * queue to become empty (which is one possible trigger for - * autodeletion). - * - * The constructor and descructor should be called outside the - * message lock. The check method should be called while holding - * the message lock. - */ - class ScopedAutoDelete - { - public: - ScopedAutoDelete(Queue& q); - void check(const sys::Mutex::ScopedLock& lock); - ~ScopedAutoDelete(); - private: - Queue& queue; - bool eligible; - }; - - enum ConsumeCode {NO_MESSAGES=0, CANT_CONSUME=1, CONSUMED=2}; - typedef boost::function1 MessageFunctor; - - const std::string name; - MessageStore* store; - const OwnershipToken* owner; - QueueUsers users; - OwnershipToken* exclusive; - std::vector traceExclude; - QueueListeners listeners; - std::auto_ptr messages; - std::vector pendingDequeues; - /** messageLock is used to keep the Queue's state consistent while processing message - * events, such as message dispatch, enqueue, acquire, and dequeue. It must be held - * while updating certain members in order to keep these members consistent with - * each other: - * o messages - * o sequence - * o listeners - * o allocator - * o observeXXX() methods - * o observers - * o pendingDequeues (TBD: move under separate lock) - * o exclusive OwnershipToken (TBD: move under separate lock) - * o consumerCount (TBD: move under separate lock) - * o Queue::UsageBarrier (TBD: move under separate lock) - */ - mutable qpid::sys::Mutex messageLock; - mutable uint64_t persistenceId; - QueueSettings settings; - qpid::framing::FieldTable encodableSettings; - QueueDepth current; - QueueBindings bindings; - std::string alternateExchangeName; - std::string userId; // queue owner for ACL quota purposes - boost::shared_ptr alternateExchange; - framing::SequenceNumber sequence; - qmf::org::apache::qpid::broker::Queue::shared_ptr mgmtObject; - qmf::org::apache::qpid::broker::Broker::shared_ptr brokerMgmtObject; - sys::AtomicValue dequeueSincePurge; // Count dequeues since last purge. - int eventMode; - QueueObservers observers; - MessageInterceptors interceptors; - std::string seqNoKey; - Broker* broker; - bool deleted; - UsageBarrier barrier; - boost::intrusive_ptr autoDeleteTask; - boost::shared_ptr allocator; - boost::scoped_ptr selector; - qpid::sys::AtomicCount version; - - // Redirect source and target refer to each other. Only one is source. - Queue::shared_ptr redirectPeer; - bool redirectSource; - - bool checkAutoDelete(const qpid::sys::Mutex::ScopedLock&) const; - bool isUnused(const qpid::sys::Mutex::ScopedLock&) const; - bool isEmpty(const qpid::sys::Mutex::ScopedLock&) const; - virtual void push(Message& msg, bool isRecovery=false); - bool accept(const Message&); - void process(Message& msg); - bool enqueue(TransactionContext* ctxt, Message& msg); - bool getNextMessage(Message& msg, Consumer::shared_ptr& c); - - void removeListener(Consumer::shared_ptr); - - bool isExcluded(const Message& msg); - - /** update queue observers, stats, policy, etc when the messages' state changes. Lock - * must be held by caller */ - void observeEnqueue(const Message& msg, const sys::Mutex::ScopedLock& lock); - void observeAcquire(const Message& msg, const sys::Mutex::ScopedLock& lock); - void observeRequeue(const Message& msg, const sys::Mutex::ScopedLock& lock); - void observeDequeue(const Message& msg, const sys::Mutex::ScopedLock& lock, ScopedAutoDelete*); - void observeConsumerAdd( const Consumer&, const sys::Mutex::ScopedLock& lock); - void observeConsumerRemove( const Consumer&, const sys::Mutex::ScopedLock& lock); - - bool acquire(const qpid::framing::SequenceNumber& position, Message& msg, - const qpid::sys::Mutex::ScopedLock& locker); - - int getEventMode(); - void dequeueFromStore(boost::intrusive_ptr); - void abandoned(const Message& message); - bool checkNotDeleted(const Consumer::shared_ptr&); - void notifyDeleted(); - - /** Remove messages from the queue: - *@param maxCount Maximum number of messages to remove, 0 means unlimited. - *@param p Only remove messages for which p(msg) is true. - *@param f Call f on each message that is removed. - *@param st Use a cursor of this SubscriptionType to iterate messages to remove. - *@param triggerAutoDelete If true removing messages may trigger aut-delete. - *@param maxTests Max number of messages to test for removal, 0 means unlimited. - *@return Number of messages removed. - */ - uint32_t remove(uint32_t maxCount, - MessagePredicate p, MessageFunctor f, - SubscriptionType st, - bool triggerAutoDelete, - uint32_t maxTests=0); - - virtual bool checkDepth(const QueueDepth& increment, const Message&); - void tryAutoDelete(long expectedVersion); - public: - - typedef std::vector vector; - - QPID_BROKER_EXTERN Queue(const std::string& name, - const QueueSettings& settings = QueueSettings(), - MessageStore* const store = 0, - management::Manageable* parent = 0, - Broker* broker = 0); - QPID_BROKER_EXTERN virtual ~Queue(); - - /** allow the Consumer to consume or browse the next available message */ - QPID_BROKER_EXTERN bool dispatch(Consumer::shared_ptr); - - /** allow the Consumer to acquire a message that it has browsed. - * @param msg - message to be acquired. - * @return false if message is no longer available for acquire. - */ - QPID_BROKER_EXTERN bool acquire(const QueueCursor& msg, const std::string& consumer); - - /** - * Used to create a persistent record for the queue in store if required. - */ - QPID_BROKER_EXTERN void create(); - - QPID_BROKER_EXTERN void bound(const std::string& exchange, - const std::string& key, - const qpid::framing::FieldTable& args); - //TODO: get unbind out of the public interface; only there for purposes of one unit test - QPID_BROKER_EXTERN void unbind(ExchangeRegistry& exchanges); - /** - * Bind self to specified exchange, and record that binding for unbinding on delete. - */ - QPID_BROKER_EXTERN bool bind( - boost::shared_ptr exchange, const std::string& key, - const qpid::framing::FieldTable& arguments=qpid::framing::FieldTable()); - - /** - * Removes (and dequeues) a message by its sequence number (used - * for some broker features, e.g. queue replication) - * - * @param position the sequence number of the message to be dequeued. - * @return true if the message is dequeued. - */ - QPID_BROKER_EXTERN bool dequeueMessageAt(const qpid::framing::SequenceNumber& position); - - /** - * Delivers a message to the queue or to overflow partner. - */ - QPID_BROKER_EXTERN void deliver(Message, TxBuffer* = 0); - /** - * Delivers a message to the queue. Will record it as - * enqueued if persistent then process it. - */ - private: - QPID_BROKER_EXTERN void deliverTo(Message, TxBuffer* = 0); - public: - /** - * Merges message annotations for an in-memory message as a result of - * a modified disposition outcome - */ - QPID_BROKER_EXTERN void mergeMessageAnnotations(const QueueCursor& msg, - const qpid::types::Variant::Map& annotations); - - /** - * Returns a message to the in-memory queue (due to lack - * of acknowledegement from a receiver). If a consumer is - * available it will be dispatched immediately, else it - * will be returned to the front of the queue. - */ - QPID_BROKER_EXTERN void release(const QueueCursor& msg, bool markRedelivered=true); - QPID_BROKER_EXTERN void reject(const QueueCursor& msg); - - QPID_BROKER_EXTERN bool seek(QueueCursor&, MessagePredicate); - QPID_BROKER_EXTERN bool seek(QueueCursor&, MessagePredicate, qpid::framing::SequenceNumber start); - QPID_BROKER_EXTERN bool seek(QueueCursor&, qpid::framing::SequenceNumber start); - /** - * Used during recovery to add stored messages back to the queue - */ - QPID_BROKER_EXTERN void recover(Message& msg); - - QPID_BROKER_EXTERN void consume(Consumer::shared_ptr c, - bool exclusive = false, - const framing::FieldTable& arguments = framing::FieldTable(), - const std::string& connectionId=std::string(), - const std::string& userId=std::string()); - - QPID_BROKER_EXTERN void cancel(Consumer::shared_ptr c, - const std::string& connectionId=std::string(), - const std::string& userId=std::string()); - /** - * Used to indicate that the queue is being used in some other - * context than by a subscriber. The controlling flag should only - * be set if the mode of use is the one that caused the queue to - * be created. - */ - QPID_BROKER_EXTERN void markInUse(bool controlling=false); - QPID_BROKER_EXTERN void releaseFromUse(bool controlling=false, bool doDelete=true); - - QPID_BROKER_EXTERN uint32_t purge(const uint32_t purge_request=0, //defaults to all messages - boost::shared_ptr dest=boost::shared_ptr(), - const ::qpid::types::Variant::Map *filter=0); - QPID_BROKER_EXTERN void purgeExpired(sys::Duration); - - //move qty # of messages to destination Queue destq - QPID_BROKER_EXTERN uint32_t move( - const Queue::shared_ptr destq, uint32_t qty, - const qpid::types::Variant::Map *filter=0); - - QPID_BROKER_EXTERN uint32_t getMessageCount() const; - QPID_BROKER_EXTERN uint32_t getConsumerCount() const; - inline const std::string& getName() const { return name; } - QPID_BROKER_EXTERN bool isExclusiveOwner(const OwnershipToken* const o) const; - QPID_BROKER_EXTERN void releaseExclusiveOwnership(bool immediateExpiry=false); - QPID_BROKER_EXTERN bool setExclusiveOwner(const OwnershipToken* const o); - QPID_BROKER_EXTERN bool hasExclusiveConsumer() const; - QPID_BROKER_EXTERN bool hasExclusiveOwner() const; - inline bool isDurable() const { return store != 0; } - inline const QueueSettings& getSettings() const { return settings; } - inline const qpid::framing::FieldTable& getEncodableSettings() const { return encodableSettings; } - inline bool isAutoDelete() const { return settings.autodelete; } - inline bool isBrowseOnly() const { return settings.isBrowseOnly; } - QPID_BROKER_EXTERN bool canAutoDelete() const; - QPID_BROKER_EXTERN void scheduleAutoDelete(bool immediate=false); - QPID_BROKER_EXTERN bool isDeleted() const; - const QueueBindings& getBindings() const { return bindings; } - - /** - * Dequeue message referenced by cursor. If txn is specified, this will - * occur only when txn is committed. - */ - QPID_BROKER_EXTERN void dequeue(const QueueCursor& cursor, TxBuffer* txn); - - /** - * dequeue from store (only done once messages is acknowledged) - */ - QPID_BROKER_EXTERN void dequeue(TransactionContext* ctxt, const QueueCursor&); - - /** - * Inform the queue that a previous transactional dequeue - * committed. - */ - void dequeueCommitted(const QueueCursor& msg); - - /** Get the message at position pos, returns true if found and sets msg */ - QPID_BROKER_EXTERN bool find(framing::SequenceNumber pos, Message& msg ) const; - - // Remember the queue's owner so acl quotas can be restored after restart - void setOwningUser(std::string& _userId); - void updateAclUserQueueCount(); - - QPID_BROKER_EXTERN void setAlternateExchange(boost::shared_ptr exchange); - QPID_BROKER_EXTERN boost::shared_ptr getAlternateExchange(); - QPID_BROKER_EXTERN bool isLocal(const Message& msg); - - //PersistableQueue support: - QPID_BROKER_EXTERN uint64_t getPersistenceId() const; - QPID_BROKER_EXTERN void setPersistenceId(uint64_t persistenceId) const; - QPID_BROKER_EXTERN void encode(framing::Buffer& buffer) const; - QPID_BROKER_EXTERN uint32_t encodedSize() const; - - /** - * Restores a queue from encoded data (used in recovery) - * - * Note: restored queue will be neither auto-deleted or have an - * exclusive owner - */ - static Queue::shared_ptr restore(QueueRegistry& queues, framing::Buffer& buffer); - - virtual void setExternalQueueStore(ExternalQueueStore* inst); - - // Increment the rejected-by-consumer counter. - QPID_BROKER_EXTERN void countRejected() const; - - // Manageable entry points - QPID_BROKER_EXTERN management::ManagementObject::shared_ptr GetManagementObject(void) const; - management::Manageable::status_t - QPID_BROKER_EXTERN ManagementMethod (uint32_t methodId, management::Args& args, std::string& text); - QPID_BROKER_EXTERN void query(::qpid::types::Variant::Map&) const; - - /** Apply f to each Message on the queue. */ - template void eachMessage(F f) { - sys::Mutex::ScopedLock l(messageLock); - messages->foreach(f); - } - - /** Apply f to each QueueBinding on the queue */ - template void eachBinding(F f) { - bindings.eachBinding(f); - } - - /** - * Set the sequence number for the back of the queue, the - * next message enqueued will be pos+1. - * If pos > getPosition() this creates a gap in the sequence numbers. - * if pos < getPosition() the back of the queue is reset to pos, - * - * The _caller_ must ensure that any messages after pos have been dequeued. - * - * Used by HA code for queue replication. - */ - QPID_BROKER_EXTERN void setPosition(framing::SequenceNumber pos); - - /** - *@return sequence number for the back of the queue. The next message pushed - * will be at getPosition()+1 - */ - QPID_BROKER_EXTERN framing::SequenceNumber getPosition(); - - /** - * Set front and back. - * If the queue is empty then front = back+1 (the first message to - * consume will be the next message pushed.) - * - *@param front = Position of first message to consume. - *@param back = getPosition(), next message pushed will be getPosition()+1 - *@param type Subscription type to use to determine the front. - */ - QPID_BROKER_EXTERN void getRange( - framing::SequenceNumber& front, framing::SequenceNumber& back, - SubscriptionType type=CONSUMER - ); - - - QPID_BROKER_EXTERN void insertSequenceNumbers(const std::string& key); - - QPID_BROKER_EXTERN MessageInterceptors& getMessageInterceptors() { return interceptors; } - QPID_BROKER_EXTERN QueueObservers& getObservers() { return observers; } - - /** - * Notify queue that recovery has completed. - */ - QPID_BROKER_EXTERN void recoveryComplete(ExchangeRegistry& exchanges); - - /** - * Reserve space in policy for an enqueued message that - * has been recovered in the prepared state (dtx only) - */ - QPID_BROKER_EXTERN void recoverPrepared(const Message& msg); - void enqueueAborted(const Message& msg); - void enqueueCommited(Message& msg); - void dequeueAborted(Message& msg); - void dequeueCommited(const Message& msg); - - QPID_BROKER_EXTERN void flush(); - - QPID_BROKER_EXTERN Broker* getBroker(); - - uint32_t getDequeueSincePurge() { return dequeueSincePurge.get(); } - QPID_BROKER_EXTERN void setDequeueSincePurge(uint32_t value); - - /** Add an argument to be included in management messages about this queue. */ - QPID_BROKER_EXTERN void addArgument(const std::string& key, const types::Variant& value); - - /** - * Atomic Redirect - */ - QPID_BROKER_EXTERN void setRedirectPeer ( Queue::shared_ptr peer, bool isSrc ); - QPID_BROKER_EXTERN Queue::shared_ptr getRedirectPeer() { return redirectPeer; } - 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 e, const Message& m); - static bool isExpired(const std::string& queueName, const Message&, qpid::sys::AbsTime); - - private: - void destroyed(); // Only called by QueueRegistry::destroy() - friend class QueueFactory; - friend class QueueRegistry; -}; -} -} - - -#endif /*!_broker_Queue_h*/ diff --git a/qpid/cpp/src/qpid/broker/QueueBindings.cpp b/qpid/cpp/src/qpid/broker/QueueBindings.cpp deleted file mode 100644 index 1cc3486d9a..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueBindings.cpp +++ /dev/null @@ -1,53 +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/broker/Queue.h" -#include "qpid/broker/QueueBindings.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/framing/reply_exceptions.h" - -using qpid::framing::FieldTable; -using qpid::framing::NotFoundException; -using std::string; -using namespace qpid::broker; - -void QueueBindings::add(const string& exchange, const string& key, const FieldTable& args) -{ - sys::Mutex::ScopedLock l(lock); - bindings.push_back(QueueBinding(exchange, key, args)); -} - -void QueueBindings::unbind(ExchangeRegistry& exchanges, Queue::shared_ptr queue) -{ - Bindings local; - { - sys::Mutex::ScopedLock l(lock); - local = bindings; - } - - for (Bindings::iterator i = local.begin(); i != local.end(); i++) { - Exchange::shared_ptr ex = exchanges.find(i->exchange); - if (ex) ex->unbind(queue, i->key, &(i->args)); - } -} - -QueueBinding::QueueBinding(const string& _exchange, const string& _key, const FieldTable& _args) - : exchange(_exchange), key(_key), args(_args) -{} diff --git a/qpid/cpp/src/qpid/broker/QueueBindings.h b/qpid/cpp/src/qpid/broker/QueueBindings.h deleted file mode 100644 index f9b07e7431..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueBindings.h +++ /dev/null @@ -1,70 +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. - * - */ -#ifndef _QueueBindings_ -#define _QueueBindings_ - -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Mutex.h" -#include -#include -#include - -namespace qpid { -namespace broker { - -class ExchangeRegistry; -class Queue; - -struct QueueBinding{ - std::string exchange; - std::string key; - qpid::framing::FieldTable args; - QueueBinding(const std::string& exchange, const std::string& key, const qpid::framing::FieldTable& args); -}; - -class QueueBindings -{ - public: - - /** Apply f to each QueueBinding. */ - template void eachBinding(F f) const { - Bindings local; - { - sys::Mutex::ScopedLock l(lock); - local = bindings; - } - std::for_each(local.begin(), local.end(), f); - } - - void add(const std::string& exchange, const std::string& key, const qpid::framing::FieldTable& args); - void unbind(ExchangeRegistry& exchanges, boost::shared_ptr queue); - - private: - mutable sys::Mutex lock; - typedef std::vector Bindings; - Bindings bindings; -}; - - -}} // namespace qpid::broker - - -#endif diff --git a/qpid/cpp/src/qpid/broker/QueueCleaner.cpp b/qpid/cpp/src/qpid/broker/QueueCleaner.cpp deleted file mode 100644 index bf4b62c849..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueCleaner.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueCleaner.h" - -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/Time.h" - -#include -#include - -namespace qpid { -namespace broker { - -namespace { - typedef boost::function0 FireFunction; - class Task : public sys::TimerTask - { - public: - Task(FireFunction f, sys::Duration duration); - void fire(); - private: - FireFunction fireFunction; - }; - - Task::Task(FireFunction f, qpid::sys::Duration d) : sys::TimerTask(d,"QueueCleaner"), fireFunction(f) {} - - void Task::fire() - { - fireFunction(); - } -} -QueueCleaner::QueueCleaner(QueueRegistry& q, boost::shared_ptr p, sys::Timer* t) - : queues(q), timer(t), purging(boost::bind(&QueueCleaner::purge, this, _1), p) -{ - purging.start(); -} - -QueueCleaner::~QueueCleaner() -{ - purging.stop(); - if (task) task->cancel(); -} - -void QueueCleaner::start(qpid::sys::Duration p) -{ - period = p; - task = new Task(boost::bind(&QueueCleaner::fired, this), p); - timer->add(task); -} - -void QueueCleaner::setTimer(qpid::sys::Timer* timer) { - this->timer = timer; -} - -void QueueCleaner::fired() -{ - QPID_LOG(debug, "QueueCleaner::fired: requesting purge"); - queues.eachQueue(boost::bind(&PurgeSet::push, &purging, _1)); - task->restart(); // Update task restart time to now()+interval - timer->add(task); -} - -QueueCleaner::QueuePtrs::const_iterator QueueCleaner::purge(const QueueCleaner::QueuePtrs& batch) -{ - const sys::AbsTime tmoTime = sys::AbsTime(sys::AbsTime::now(), 1 * sys::TIME_SEC); - int nPurged = 0; - QueuePtrs::const_iterator batchItr = batch.begin(); - for ( ; batchItr != batch.end() && sys::AbsTime::now() < tmoTime; ++batchItr) { - task->restart(); // Update task restart time to now()+interval - (*batchItr)->purgeExpired(period); - nPurged++; - } - QPID_LOG(debug, "QueueCleaner::purge: purged " << nPurged << " of " << batch.size() << " queues"); - task->restart(); // Update task restart time to now()+interval - return batchItr; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/QueueCleaner.h b/qpid/cpp/src/qpid/broker/QueueCleaner.h deleted file mode 100644 index 499326460f..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueCleaner.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QPID_BROKER_QUEUECLEANER_H -#define QPID_BROKER_QUEUECLEANER_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/BrokerImportExport.h" -#include "qpid/sys/PollableQueue.h" -#include "qpid/sys/Time.h" - -#include -#include - -namespace qpid { - -namespace sys { - class Timer; - class TimerTask; -} - -namespace broker { - -class Queue; -class QueueRegistry; -/** - * TimerTask to purge expired messages from queues - */ -class QueueCleaner -{ - public: - QPID_BROKER_EXTERN QueueCleaner(QueueRegistry& queues, boost::shared_ptr, sys::Timer* timer); - QPID_BROKER_EXTERN ~QueueCleaner(); - QPID_BROKER_EXTERN void start(sys::Duration period); - QPID_BROKER_EXTERN void setTimer(sys::Timer* timer); - - private: - typedef boost::shared_ptr QueuePtr; - typedef std::deque< QueuePtr > QueuePtrs; - typedef qpid::sys::PollableQueue< QueuePtr > PurgeSet; - boost::intrusive_ptr task; - QueueRegistry& queues; - sys::Timer* timer; - sys::Duration period; - PurgeSet purging; - - void fired(); - QueuePtrs::const_iterator purge(const QueuePtrs&); - -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUECLEANER_H*/ diff --git a/qpid/cpp/src/qpid/broker/QueueCursor.cpp b/qpid/cpp/src/qpid/broker/QueueCursor.cpp deleted file mode 100644 index e48b18b748..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueCursor.cpp +++ /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. - * - */ -#include "QueueCursor.h" -#include "qpid/broker/Message.h" - -namespace qpid { -namespace broker { -QueueCursor::QueueCursor(SubscriptionType t) : type(t), position(0), version(0), valid(false) {} - -void QueueCursor::setPosition(int32_t p, int32_t v) -{ - position = p; - version = v; - valid = true; -} - -bool QueueCursor::check(const Message& m) -{ - return (m.getState() == AVAILABLE || ((type == REPLICATOR || type == PURGE) && m.getState() == ACQUIRED)); -} - -bool QueueCursor::isValid(int32_t v) -{ - return valid && (valid = (v == version)); -} -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/QueueCursor.h b/qpid/cpp/src/qpid/broker/QueueCursor.h deleted file mode 100644 index c7368177e9..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueCursor.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef QPID_BROKER_QUEUECURSOR_H -#define QPID_BROKER_QUEUECURSOR_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/BrokerImportExport.h" -#include "qpid/sys/IntegerTypes.h" -#include - -namespace qpid { -namespace broker { - -class Message; - -enum SubscriptionType -{ - CONSUMER, - BROWSER, - PURGE, - REPLICATOR -}; - -class CursorContext { - public: - virtual ~CursorContext() {} -}; -/** - * - */ -class QueueCursor -{ - public: - QPID_BROKER_EXTERN QueueCursor(SubscriptionType type = CONSUMER); - - private: - SubscriptionType type; - int32_t position; - int32_t version; - bool valid; - boost::shared_ptr context; - - void setPosition(int32_t p, int32_t v); - bool check(const Message& m); - bool isValid(int32_t v); - - friend class MessageDeque; - friend class MessageMap; - friend class PriorityQueue; - friend class PagedQueue; - template friend class IndexedDeque; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUECURSOR_H*/ diff --git a/qpid/cpp/src/qpid/broker/QueueDepth.cpp b/qpid/cpp/src/qpid/broker/QueueDepth.cpp deleted file mode 100644 index 69ec0ab4ac..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueDepth.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "QueueDepth.h" - -namespace qpid { -namespace broker { - -QueueDepth::QueueDepth() {} -QueueDepth::QueueDepth(uint32_t c, uint64_t s) : count(c), size(s) {} -QueueDepth& QueueDepth::operator+=(const QueueDepth& other) -{ - if (count.valid) count.value += other.count.value; - if (size.valid) size.value += other.size.value; - return *this; -} -QueueDepth& QueueDepth::operator-=(const QueueDepth& other) -{ - if (count.valid) count.value -= other.count.value; - if (size.valid) size.value -= other.size.value; - return *this; -} -bool QueueDepth::operator==(const QueueDepth& other) const -{ - //only compare values, not validity an invalid value is always 0; - //this means that an invalid value will match an empty queue - //depth, which is fine - return (count.value == other.count.value) - && (size.value == other.size.value); -} -bool QueueDepth::operator!=(const QueueDepth& other) const -{ - return !(*this == other); -} -bool QueueDepth::operator<(const QueueDepth& other) const -{ - if (count.valid && size.valid) - return count.value < other.count.value || size.value < other.size.value; - else if (count.valid) - return count.value < other.count.value; - else - return size.value < other.size.value; -} -bool QueueDepth::operator>(const QueueDepth& other) const -{ - if (count.valid && size.valid) - return count.value > other.count.value || size.value > other.size.value; - else if (count.valid) - return count.value > other.count.value; - else - return size.value > other.size.value; -} -bool QueueDepth::hasCount() const { return count.valid; } -uint32_t QueueDepth::getCount() const { return count.value; } -void QueueDepth::setCount(uint32_t c) { count.value = c; count.valid = true; } -bool QueueDepth::hasSize() const { return size.valid; } -uint64_t QueueDepth::getSize() const { return size.value; } -void QueueDepth::setSize(uint64_t c) { size.value = c; size.valid = true; } - -namespace{ - template QueueDepth::Optional add(const QueueDepth::Optional& a, const QueueDepth::Optional& b) - { - QueueDepth::Optional result; - if (a.valid && b.valid) { - result.valid = true; - result.value = a.value + b.value; - } - return result; - } - template QueueDepth::Optional subtract(const QueueDepth::Optional& a, const QueueDepth::Optional& b) - { - QueueDepth::Optional result; - if (a.valid && b.valid) { - result.valid = true; - result.value = a.value - b.value; - } - return result; - } -} -QueueDepth operator-(const QueueDepth& a, const QueueDepth& b) -{ - QueueDepth result; - result.count = subtract(a.count, b.count); - result.size = subtract(a.size, b.size); - return result; -} - -QueueDepth operator+(const QueueDepth& a, const QueueDepth& b) -{ - QueueDepth result; - result.count = add(a.count, b.count); - result.size = add(a.size, b.size); - return result; - -} - -std::ostream& operator<<(std::ostream& o, const QueueDepth& d) -{ - if (d.hasCount()) o << "count: " << d.getCount(); - if (d.hasSize()) { - if (d.hasCount()) o << ", "; - o << "size: " << d.getSize(); - } - return o; -} - -QueueDepth::operator bool() const { return hasCount() || hasSize(); } - - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/QueueDepth.h b/qpid/cpp/src/qpid/broker/QueueDepth.h deleted file mode 100644 index d93acb2a7a..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueDepth.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef QPID_BROKER_QUEUEDEPTH_H -#define QPID_BROKER_QUEUEDEPTH_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/BrokerImportExport.h" -#include "qpid/sys/IntegerTypes.h" -#include - -namespace qpid { -namespace broker { - -/** - * Represents a queue depth in message count and/or aggregate message - * size. - */ -class QueueDepth -{ - public: - QPID_BROKER_EXTERN QueueDepth(); - QPID_BROKER_EXTERN QueueDepth(uint32_t count, uint64_t size); - QPID_BROKER_EXTERN QueueDepth& operator+=(const QueueDepth&); - QPID_BROKER_EXTERN QueueDepth& operator-=(const QueueDepth&); - QPID_BROKER_EXTERN bool operator==(const QueueDepth&) const; - QPID_BROKER_EXTERN bool operator!=(const QueueDepth&) const; - QPID_BROKER_EXTERN bool operator<(const QueueDepth& other) const; - QPID_BROKER_EXTERN bool operator>(const QueueDepth& other) const; - QPID_BROKER_EXTERN operator bool() const; - QPID_BROKER_EXTERN bool hasCount() const; - QPID_BROKER_EXTERN uint32_t getCount() const; - QPID_BROKER_EXTERN void setCount(uint32_t); - QPID_BROKER_EXTERN bool hasSize() const; - QPID_BROKER_EXTERN uint64_t getSize() const; - QPID_BROKER_EXTERN void setSize(uint64_t); - friend QPID_BROKER_EXTERN QueueDepth operator-(const QueueDepth&, const QueueDepth&); - friend QPID_BROKER_EXTERN QueueDepth operator+(const QueueDepth&, const QueueDepth&); - template struct Optional - { - T value; - bool valid; - - Optional(T v) : value(v), valid(true) {} - Optional() : value(0), valid(false) {} - }; - private: - Optional count; - Optional size; -}; - -QPID_BROKER_EXTERN QueueDepth operator-(const QueueDepth&, const QueueDepth&); -QPID_BROKER_EXTERN QueueDepth operator+(const QueueDepth&, const QueueDepth&); -std::ostream& operator<<(std::ostream&, const QueueDepth&); - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUEDEPTH_H*/ diff --git a/qpid/cpp/src/qpid/broker/QueueFactory.cpp b/qpid/cpp/src/qpid/broker/QueueFactory.cpp deleted file mode 100644 index 16cdea3b0a..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueFactory.cpp +++ /dev/null @@ -1,142 +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/broker/QueueFactory.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/LossyLvq.h" -#include "qpid/broker/LossyQueue.h" -#include "qpid/broker/Lvq.h" -#include "qpid/broker/Messages.h" -#include "qpid/broker/MessageDistributor.h" -#include "qpid/broker/MessageGroupManager.h" -#include "qpid/broker/Fairshare.h" -#include "qpid/broker/MessageDeque.h" -#include "qpid/broker/MessageMap.h" -#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" -#include -#include - -namespace qpid { -namespace broker { - -QueueFactory::QueueFactory() : broker(0), store(0), parent(0) {} - -boost::shared_ptr QueueFactory::create(const std::string& name, const QueueSettings& settings) -{ - settings.validate(); - boost::shared_ptr flow_ptr(QueueFlowLimit::createLimit(name, settings)); - - //1. determine Queue type (i.e. whether we are subclassing Queue) - boost::shared_ptr queue; - if (settings.dropMessagesAtLimit) { - // -> if 'ring' policy is in use then subclass - if (settings.lvqKey.size()) { - //combination of ring and lvq: - std::auto_ptr map(new MessageMap(settings.lvqKey)); - queue = boost::shared_ptr(new LossyLvq(name, map, settings, settings.durable ? store : 0, parent, broker)); - } else { - //simple ring: - queue = boost::shared_ptr(new LossyQueue(name, settings, settings.durable ? store : 0, parent, broker)); - } - } else if (settings.selfDestructAtLimit) { - queue = boost::shared_ptr(new SelfDestructQueue(name, settings, settings.durable ? store : 0, parent, broker)); - } else if (settings.lvqKey.size()) { - std::auto_ptr map(new MessageMap(settings.lvqKey)); - queue = boost::shared_ptr(new Lvq(name, map, settings, settings.durable ? store : 0, parent, broker)); - } else { - queue = boost::shared_ptr(new Queue(name, settings, settings.durable ? store : 0, parent, broker)); - } - - //2. determine Messages type (i.e. structure) - if (settings.priorities) { - if (settings.defaultFairshare || settings.fairshare.size()) { - queue->messages = Fairshare::create(settings); - } else { - queue->messages = std::auto_ptr(new PriorityQueue(settings.priorities)); - } - } else if (settings.paging) { - if (!broker) { - QPID_LOG(warning, "Cannot create paged queue without broker context"); - } else if (!qpid::sys::MemoryMappedFile::isSupported()) { - QPID_LOG(warning, "Cannot create paged queue; memory mapped file support not available on this platform"); - } else if ( !broker->getPagingDir().isEnabled() ) { - QPID_LOG(warning, "Cannot create paged queue; no paging directory enabled"); - } else { - queue->messages = std::auto_ptr(new PagedQueue(name, broker->getPagingDir().getPath(), - settings.maxPages ? settings.maxPages : DEFAULT_MAX_PAGES, - settings.pageFactor ? settings.pageFactor : DEFAULT_PAGE_FACTOR, - broker->getProtocolRegistry())); - } - } else if (settings.lvqKey.empty()) {//LVQ already handled above - queue->messages = std::auto_ptr(new MessageDeque()); - } - - //3. determine MessageDistributor type - if (settings.groupKey.size()) { - boost::shared_ptr mgm(MessageGroupManager::create( name, *(queue->messages), settings)); - queue->allocator = mgm; - queue->getObservers().add(mgm); - } else { - queue->allocator = boost::shared_ptr(new FifoDistributor( *(queue->messages) )); - } - - - //4. threshold event config - if (broker && broker->getManagementAgent()) { - ThresholdAlerts::observe(*queue, *(broker->getManagementAgent()), settings, broker->getQueueThresholdEventRatio()); - } - //5. flow control config - if (flow_ptr) { - flow_ptr->observe(*queue); - } - - return queue; -} - -void QueueFactory::setBroker(Broker* b) -{ - broker = b; -} -Broker* QueueFactory::getBroker() -{ - return broker; -} -void QueueFactory::setStore (MessageStore* s) -{ - store = s; -} -MessageStore* QueueFactory::getStore() const -{ - return store; -} -void QueueFactory::setParent(management::Manageable* p) -{ - parent = p; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/QueueFactory.h b/qpid/cpp/src/qpid/broker/QueueFactory.h deleted file mode 100644 index 585983ba25..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueFactory.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef QPID_BROKER_QUEUEFACTORY_H -#define QPID_BROKER_QUEUEFACTORY_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/BrokerImportExport.h" -#include "qpid/types/Variant.h" -#include - -#define DEFAULT_MAX_PAGES 4 -#define DEFAULT_PAGE_FACTOR 1 - -namespace qpid { -namespace management { -class Manageable; -} -namespace broker { -class Broker; -class MessageStore; -class Queue; -struct QueueSettings; - -/** - * Handles the creation and configuration of a Queue instance in order - * to meet the required settings - */ -class QueueFactory -{ - public: - QPID_BROKER_EXTERN QueueFactory(); - - QPID_BROKER_EXTERN boost::shared_ptr create(const std::string& name, const QueueSettings& settings); - - void setBroker(Broker*); - Broker* getBroker(); - - /** - * Set the store to use. May only be called once. - */ - void setStore (MessageStore*); - - /** - * Return the message store used. - */ - MessageStore* getStore() const; - - /** - * Register the manageable parent for declared queues - */ - void setParent(management::Manageable*); - private: - Broker* broker; - MessageStore* store; - management::Manageable* parent; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUEFACTORY_H*/ diff --git a/qpid/cpp/src/qpid/broker/QueueFlowLimit.cpp b/qpid/cpp/src/qpid/broker/QueueFlowLimit.cpp deleted file mode 100644 index 3873e41cc9..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueFlowLimit.cpp +++ /dev/null @@ -1,307 +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/broker/QueueFlowLimit.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/Exception.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/SessionState.h" - -#include "qmf/org/apache/qpid/broker/Queue.h" - -#include - -#include - -using namespace qpid::broker; -using namespace qpid::framing; - -namespace { - /** ensure that the configured flow control stop and resume values are - * valid with respect to the maximum queue capacity, and each other - */ - template - void validateFlowConfig(T max, T& stop, T& resume, const std::string& type, const std::string& queue) - { - if (stop) { - if (resume > stop) { - throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_resume_" << type - << "=" << resume - << " must be less or equal to qpid.flow_stop_" << type - << "=" << stop)); - } - if (resume == 0) resume = stop; - if (max != 0 && (max < stop)) { - throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_stop_" << type - << "=" << stop - << " must be less than qpid.max_" << type - << "=" << max)); - } - } - } -} - - - -QueueFlowLimit::QueueFlowLimit(const std::string& _queueName, - uint32_t _flowStopCount, uint32_t _flowResumeCount, - uint64_t _flowStopSize, uint64_t _flowResumeSize) - : queue(0), queueName(_queueName), - flowStopCount(_flowStopCount), flowResumeCount(_flowResumeCount), - flowStopSize(_flowStopSize), flowResumeSize(_flowResumeSize), - flowStopped(false), count(0), size(0), broker(0) -{ - QPID_LOG(debug, "Queue \"" << queueName << "\": Flow limit created: flowStopCount=" << flowStopCount - << ", flowResumeCount=" << flowResumeCount - << ", flowStopSize=" << flowStopSize << ", flowResumeSize=" << flowResumeSize ); -} - - -QueueFlowLimit::~QueueFlowLimit() -{ - sys::Mutex::ScopedLock l(indexLock); - if (!index.empty()) { - // we're gone - release all pending msgs - for (std::map::iterator itr = index.begin(); - itr != index.end(); ++itr) - if (itr->second) - try { - itr->second.getPersistentContext()->getIngressCompletion().finishCompleter(); - } catch (...) {} // ignore - not safe for a destructor to throw. - index.clear(); - } -} - - -void QueueFlowLimit::enqueued(const Message& msg) -{ - sys::Mutex::ScopedLock l(indexLock); - - ++count; - size += msg.getMessageSize(); - - if (!flowStopped) { - if (flowStopCount && count > flowStopCount) { - flowStopped = true; - QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopCount << " enqueued messages. Producer flow control activated." ); - } else if (flowStopSize && size > flowStopSize) { - flowStopped = true; - QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopSize << " enqueued bytes. Producer flow control activated." ); - } - if (flowStopped && queueMgmtObj) { - queueMgmtObj->set_flowStopped(true); - queueMgmtObj->inc_flowStoppedCount(); - } - } - - if (flowStopped || !index.empty()) { - QPID_LOG(trace, "Queue \"" << queueName << "\": setting flow control for msg pos=" << msg.getSequence()); - msg.getPersistentContext()->getIngressCompletion().startCompleter(); // don't complete until flow resumes - bool unique; - unique = index.insert(std::pair(msg.getSequence(), msg)).second; - // Like this to avoid tripping up unused variable warning when NDEBUG set - if (!unique) assert(unique); - } -} - - - -void QueueFlowLimit::dequeued(const Message& msg) -{ - sys::Mutex::ScopedLock l(indexLock); - - if (count > 0) { - --count; - } else { - throw Exception(QPID_MSG("Flow limit count underflow on dequeue. Queue=" << queueName)); - } - - uint64_t _size = msg.getMessageSize(); - if (_size <= size) { - size -= _size; - } else { - throw Exception(QPID_MSG("Flow limit size underflow on dequeue. Queue=" << queueName)); - } - - if (flowStopped && - (flowResumeSize == 0 || size < flowResumeSize) && - (flowResumeCount == 0 || count < flowResumeCount)) { - flowStopped = false; - if (queueMgmtObj) - queueMgmtObj->set_flowStopped(false); - QPID_LOG(info, "Queue \"" << queueName << "\": has drained below the flow control resume level. Producer flow control deactivated." ); - } - - if (!index.empty()) { - if (!flowStopped) { - // flow enabled - release all pending msgs - for (std::map::iterator itr = index.begin(); - itr != index.end(); ++itr) - if (itr->second) - itr->second.getPersistentContext()->getIngressCompletion().finishCompleter(); - index.clear(); - } else { - // even if flow controlled, we must release this msg as it is being dequeued - std::map::iterator itr = index.find(msg.getSequence()); - if (itr != index.end()) { // this msg is flow controlled, release it: - msg.getPersistentContext()->getIngressCompletion().finishCompleter(); - index.erase(itr); - } - } - } -} - - -void QueueFlowLimit::encode(Buffer& buffer) const -{ - buffer.putLong(flowStopCount); - buffer.putLong(flowResumeCount); - buffer.putLongLong(flowStopSize); - buffer.putLongLong(flowResumeSize); - buffer.putLong(count); - buffer.putLongLong(size); -} - - -void QueueFlowLimit::decode ( Buffer& buffer ) -{ - flowStopCount = buffer.getLong(); - flowResumeCount = buffer.getLong(); - flowStopSize = buffer.getLongLong(); - flowResumeSize = buffer.getLongLong(); - count = buffer.getLong(); - size = buffer.getLongLong(); -} - - -uint32_t QueueFlowLimit::encodedSize() const { - return sizeof(uint32_t) + // flowStopCount - sizeof(uint32_t) + // flowResumecount - sizeof(uint64_t) + // flowStopSize - sizeof(uint64_t) + // flowResumeSize - sizeof(uint32_t) + // count - sizeof(uint64_t); // size -} - - -const std::string QueueFlowLimit::flowStopCountKey("qpid.flow_stop_count"); -const std::string QueueFlowLimit::flowResumeCountKey("qpid.flow_resume_count"); -const std::string QueueFlowLimit::flowStopSizeKey("qpid.flow_stop_size"); -const std::string QueueFlowLimit::flowResumeSizeKey("qpid.flow_resume_size"); -uint64_t QueueFlowLimit::defaultMaxSize; -uint QueueFlowLimit::defaultFlowStopRatio; -uint QueueFlowLimit::defaultFlowResumeRatio; - - -void QueueFlowLimit::setDefaults(uint64_t maxQueueSize, uint flowStopRatio, uint flowResumeRatio) -{ - defaultMaxSize = maxQueueSize; - defaultFlowStopRatio = flowStopRatio; - defaultFlowResumeRatio = flowResumeRatio; - - /** @todo KAG: Verify valid range on Broker::Options instead of here */ - if (flowStopRatio > 100 || flowResumeRatio > 100) - throw InvalidArgumentException(QPID_MSG("Default queue flow ratios must be between 0 and 100, inclusive:" - << " flowStopRatio=" << flowStopRatio - << " flowResumeRatio=" << flowResumeRatio)); - if (flowResumeRatio > flowStopRatio) - throw InvalidArgumentException(QPID_MSG("Default queue flow stop ratio must be >= flow resume ratio:" - << " flowStopRatio=" << flowStopRatio - << " flowResumeRatio=" << flowResumeRatio)); -} - - -void QueueFlowLimit::observe(Queue& queue) -{ - /* set up management stuff */ - broker = queue.getBroker(); - queueMgmtObj = boost::dynamic_pointer_cast<_qmfBroker::Queue> (queue.GetManagementObject()); - if (queueMgmtObj) { - queueMgmtObj->set_flowStopped(isFlowControlActive()); - } - - /* set up the observer */ - queue.getObservers().add(shared_from_this()); -} - -/** returns ptr to a QueueFlowLimit, else 0 if no limit */ -boost::shared_ptr QueueFlowLimit::createLimit(const std::string& queueName, const QueueSettings& settings) -{ - if (settings.dropMessagesAtLimit) { - // The size of a RING queue is limited by design - no need for flow control. - return boost::shared_ptr(); - } - if ((!settings.flowStop.hasCount()) && (!settings.flowStop.hasSize()) && (settings.flowResume.hasCount() || settings.flowResume.hasSize())) - QPID_LOG(warning, "queue " << queueName << ": user-configured flow limits are ignored as no stop limits provided"); - - uint32_t flowStopCount(0), flowResumeCount(0), maxMsgCount(settings.maxDepth.hasCount() ? settings.maxDepth.getCount() : 0); - uint64_t flowStopSize(0), flowResumeSize(0), maxByteCount(settings.maxDepth.hasSize() ? settings.maxDepth.getSize() : defaultMaxSize); - - // pre-fill by defaults, if exist - if (defaultFlowStopRatio) { // broker has a default ratio setup... - flowStopSize = (uint64_t)(maxByteCount * (defaultFlowStopRatio/100.0) + 0.5); - flowStopCount = (uint32_t)(maxMsgCount * (defaultFlowStopRatio/100.0) + 0.5); - } - - if (defaultFlowResumeRatio) { // broker has a default ratio setup... - flowResumeSize = (uint64_t)(maxByteCount * (defaultFlowResumeRatio/100.0)); - flowResumeCount = (uint32_t)(maxMsgCount * (defaultFlowResumeRatio/100.0)); - } - - // update by user-specified thresholds - if (settings.flowStop.hasCount()) - flowStopCount = settings.flowStop.getCount(); - if (settings.flowStop.hasSize()) - flowStopSize = settings.flowStop.getSize(); - if (settings.flowResume.hasCount()) - flowResumeCount = settings.flowResume.getCount(); - if (settings.flowResume.hasSize()) - flowResumeSize = settings.flowResume.getSize(); - - if (flowStopCount || flowStopSize) { - validateFlowConfig(maxMsgCount, flowStopCount, flowResumeCount, "count", queueName ); - validateFlowConfig(maxByteCount, flowStopSize, flowResumeSize, "size", queueName ); - return boost::shared_ptr(new QueueFlowLimit(queueName, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize)); - } - else - //don't have a non-zero value for either the count or the - //size to stop at, so no flow limit applicable - return boost::shared_ptr(); -} - -namespace qpid { -namespace broker { - -std::ostream& operator<<(std::ostream& out, const QueueFlowLimit& f) -{ - out << "; flowStopCount=" << f.flowStopCount << ", flowResumeCount=" << f.flowResumeCount; - out << "; flowStopSize=" << f.flowStopSize << ", flowResumeSize=" << f.flowResumeSize; - return out; -} - -} -} - diff --git a/qpid/cpp/src/qpid/broker/QueueFlowLimit.h b/qpid/cpp/src/qpid/broker/QueueFlowLimit.h deleted file mode 100644 index 92bd7f76a0..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueFlowLimit.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueueFlowLimit_ -#define _QueueFlowLimit_ - -#include -#include -#include -#include -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" -#include "qmf/org/apache/qpid/broker/Queue.h" - -#include - -namespace _qmfBroker = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -class Broker; -class Queue; -class Message; -struct QueueSettings; - -/** - * Producer flow control: when level is > flowStop*, flow control is ON. - * then level is < flowResume*, flow control is OFF. If == 0, flow control - * is not used. If both byte and msg count thresholds are set, then - * passing _either_ level may turn flow control ON, but _both_ must be - * below level before flow control will be turned OFF. - */ - class QueueFlowLimit : public QueueObserver, public boost::enable_shared_from_this -{ - static uint64_t defaultMaxSize; - static uint defaultFlowStopRatio; - static uint defaultFlowResumeRatio; - - Queue *queue; - std::string queueName; - - uint32_t flowStopCount; - uint32_t flowResumeCount; - uint64_t flowStopSize; - uint64_t flowResumeSize; - bool flowStopped; // true = producers held in flow control - - // current queue utilization - uint32_t count; - uint64_t size; - - public: - static QPID_BROKER_EXTERN const std::string flowStopCountKey; - static QPID_BROKER_EXTERN const std::string flowResumeCountKey; - static QPID_BROKER_EXTERN const std::string flowStopSizeKey; - static QPID_BROKER_EXTERN const std::string flowResumeSizeKey; - - QPID_BROKER_EXTERN virtual ~QueueFlowLimit(); - - /** the queue has added QueuedMessage */ - QPID_BROKER_EXTERN void enqueued(const Message&); - /** the queue has removed QueuedMessage */ - QPID_BROKER_EXTERN void dequeued(const Message&); - /** ignored */ - QPID_BROKER_EXTERN void acquired(const Message&) {}; - QPID_BROKER_EXTERN void requeued(const Message&) {}; - - uint32_t getFlowStopCount() const { return flowStopCount; } - uint32_t getFlowResumeCount() const { return flowResumeCount; } - uint64_t getFlowStopSize() const { return flowStopSize; } - uint64_t getFlowResumeSize() const { return flowResumeSize; } - - uint32_t getFlowCount() const { return count; } - uint64_t getFlowSize() const { return size; } - bool isFlowControlActive() const { return flowStopped; } - bool monitorFlowControl() const { return flowStopCount || flowStopSize; } - - void encode(framing::Buffer& buffer) const; - void decode(framing::Buffer& buffer); - uint32_t encodedSize() const; - - QPID_BROKER_EXTERN void observe(Queue& queue); - static QPID_BROKER_EXTERN boost::shared_ptr createLimit(const std::string& queueName, const QueueSettings& settings); - static QPID_BROKER_EXTERN void setDefaults(uint64_t defaultMaxSize, uint defaultFlowStopRatio, uint defaultFlowResumeRatio); - - friend QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&, const QueueFlowLimit&); - - protected: - // msgs waiting for flow to become available. - std::map index; - mutable qpid::sys::Mutex indexLock; - - _qmfBroker::Queue::shared_ptr queueMgmtObj; - - const Broker *broker; - - QPID_BROKER_EXTERN QueueFlowLimit(const std::string& _queueName, - uint32_t _flowStopCount, uint32_t _flowResumeCount, - uint64_t _flowStopSize, uint64_t _flowResumeSize); -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/QueueListeners.cpp b/qpid/cpp/src/qpid/broker/QueueListeners.cpp deleted file mode 100644 index 0338a674cf..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueListeners.cpp +++ /dev/null @@ -1,93 +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/broker/QueueListeners.h" -#include - -namespace qpid { -namespace broker { - -void QueueListeners::addListener(Consumer::shared_ptr c) -{ - if (!c->inListeners) { - if (c->acquires) { - add(consumers, c); - } else { - add(browsers, c); - } - c->inListeners = true; - } -} - -void QueueListeners::removeListener(Consumer::shared_ptr c) -{ - if (c->inListeners) { - if (c->acquires) { - remove(consumers, c); - } else { - remove(browsers, c); - } - c->inListeners = false; - } -} - -void QueueListeners::populate(NotificationSet& set) -{ - if (consumers.size()) { - set.consumer = consumers.front(); - consumers.pop_front(); - set.consumer->inListeners = false; - } - // Don't swap the deques, hang on to the memory allocated. - set.browsers = browsers; - browsers.clear(); - for (Listeners::iterator i = set.browsers.begin(); i != set.browsers.end(); i++) - (*i)->inListeners = false; -} - -void QueueListeners::add(Listeners& listeners, Consumer::shared_ptr c) -{ - listeners.push_back(c); -} - -void QueueListeners::remove(Listeners& listeners, Consumer::shared_ptr c) -{ - Listeners::iterator i = std::find(listeners.begin(), listeners.end(), c); - if (i != listeners.end()) listeners.erase(i); -} - -void QueueListeners::NotificationSet::notify() -{ - if (consumer) consumer->notify(); - std::for_each(browsers.begin(), browsers.end(), boost::mem_fn(&Consumer::notify)); -} - -void QueueListeners::ListenerSet::notifyAll() -{ - std::for_each(listeners.begin(), listeners.end(), boost::mem_fn(&Consumer::notify)); -} - -void QueueListeners::snapshot(ListenerSet& set) -{ - set.listeners.insert(set.listeners.end(), consumers.begin(), consumers.end()); - set.listeners.insert(set.listeners.end(), browsers.begin(), browsers.end()); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/QueueListeners.h b/qpid/cpp/src/qpid/broker/QueueListeners.h deleted file mode 100644 index ca844fd47e..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueListeners.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef QPID_BROKER_QUEUELISTENERS_H -#define QPID_BROKER_QUEUELISTENERS_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/Consumer.h" -#include - -namespace qpid { -namespace broker { - -/** - * Track and notify components that wish to be notified of messages - * that become available on a queue. - * - * None of the methods defined here are protected by locking. However - * the populate method allows a 'snapshot' to be taken of the - * listeners to be notified. NotificationSet::notify() may then be - * called outside of any lock that protects the QueueListeners - * instance from concurrent access. - */ -class QueueListeners -{ - public: - typedef std::deque Listeners; - - class NotificationSet - { - public: - void notify(); - private: - Listeners browsers; - Consumer::shared_ptr consumer; - friend class QueueListeners; - }; - - class ListenerSet - { - public: - void notifyAll(); - private: - Listeners listeners; - friend class QueueListeners; - }; - - void addListener(Consumer::shared_ptr); - void removeListener(Consumer::shared_ptr); - void populate(NotificationSet&); - void snapshot(ListenerSet&); - void notifyAll(); - - template void eachListener(F f) { - std::for_each(browsers.begin(), browsers.end(), f); - std::for_each(consumers.begin(), consumers.end(), f); - } - - private: - Listeners consumers; - Listeners browsers; - - void add(Listeners&, Consumer::shared_ptr); - void remove(Listeners&, Consumer::shared_ptr); - -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUELISTENERS_H*/ diff --git a/qpid/cpp/src/qpid/broker/QueueObserver.h b/qpid/cpp/src/qpid/broker/QueueObserver.h deleted file mode 100644 index 6d29f83721..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueObserver.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef QPID_BROKER_QUEUEOBSERVER_H -#define QPID_BROKER_QUEUEOBSERVER_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 broker { - -class Consumer; -class Message; - -/** - * Interface for notifying classes who want to act as 'observers' of a queue of particular - * events. - * - * The events that are monitored reflect the relationship between a particular message and - * the queue it has been delivered to. A message can be considered in one of three states - * with respect to the queue: - * - * 1) "Available" - available for transfer to consumers (i.e. for browse or acquire), - * - * 2) "Acquired" - owned by a particular consumer, no longer available to other consumers - * (by either browse or acquire), but still considered on the queue. - * - * 3) "Dequeued" - removed from the queue and no longer available to any consumer. - * - * The queue events that are observable are: - * - * "Enqueued" - the message is "Available" - on the queue for transfer to any consumer - * (e.g. browse or acquire) - * - * "Acquired" - - a consumer has claimed exclusive access to it. It is no longer available - * for other consumers to browse or acquire, but it is not yet considered dequeued as it - * may be requeued by the consumer. - * - * "Requeued" - a previously-acquired message is released by its owner: it is put back on - * the queue at its original position and returns to the "Available" state. - * - * "Dequeued" - a message is no longer queued. At this point, the queue no longer tracks - * the message, and the broker considers the consumer's transaction complete. - */ -class QueueObserver -{ - public: - virtual ~QueueObserver() {} - - // note: the Queue will hold the messageLock while calling these methods! - virtual void enqueued(const Message&) = 0; - virtual void dequeued(const Message&) = 0; - virtual void acquired(const Message&) = 0; - virtual void requeued(const Message&) = 0; - virtual void consumerAdded( const Consumer& ) {}; - virtual void consumerRemoved( const Consumer& ) {}; - virtual void destroy() {}; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUEOBSERVER_H*/ diff --git a/qpid/cpp/src/qpid/broker/QueueObservers.h b/qpid/cpp/src/qpid/broker/QueueObservers.h deleted file mode 100644 index 1bf5f1f696..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueObservers.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef QPID_BROKER_QUEUEOBSERVERS_H -#define QPID_BROKER_QUEUEOBSERVERS_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 "Observers.h" -#include "QueueObserver.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -/** - * A collection of queue observers. - */ -class QueueObservers : public Observers { - public: - typedef Observers Base; - - // The only public functions are inherited from Observers - using Base::each; // Avoid function hiding. - - friend class Queue; - - typedef const sys::Mutex::ScopedLock& Lock; - - QueueObservers(const std::string& q, sys::Mutex& lock) : Base(lock), qname(q) {} - - template void each(void (QueueObserver::*f)(const T&), const T& arg, const char* fname, Lock l) { - Base::each(boost::bind(&QueueObservers::wrap, this, f, boost::cref(arg), fname, _1), l); - } - - template void wrap(void (QueueObserver::*f)(const T&), const T& arg, const char* fname, const ObserverPtr& o) { - try { (o.get()->*f)(arg); } - catch (const std::exception& e) { - QPID_LOG(warning, "Exception on " << fname << " for queue " << qname << ": " << e.what()); - } - } - - - // Calls are locked externally by caller. - void enqueued(const Message& m, Lock l) { each(&QueueObserver::enqueued, m, "enqueue", l); } - void dequeued(const Message& m, Lock l) { each(&QueueObserver::dequeued, m, "dequeue", l); } - void acquired(const Message& m, Lock l) { each(&QueueObserver::acquired, m, "acquire", l); } - void requeued(const Message& m, Lock l) { each(&QueueObserver::requeued, m, "requeue", l); } - void consumerAdded(const Consumer& c, Lock l) { each(&QueueObserver::consumerAdded, c, "consumer added", l); } - void consumerRemoved(const Consumer& c, Lock l) { each(&QueueObserver::consumerRemoved, c, "consumer removed", l); } - void destroy(Lock l) { - Base::each(boost::bind(&QueueObserver::destroy, _1), l); - observers.clear(); - } - - std::string qname; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUEOBSERVERS_H*/ diff --git a/qpid/cpp/src/qpid/broker/QueueRegistry.cpp b/qpid/cpp/src/qpid/broker/QueueRegistry.cpp deleted file mode 100644 index 987832c47c..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueRegistry.cpp +++ /dev/null @@ -1,183 +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/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/Exchange.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/reply_exceptions.h" -#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h" -#include "qmf/org/apache/qpid/broker/EventQueueDelete.h" -#include -#include - -namespace _qmf = qmf::org::apache::qpid::broker; -using namespace qpid::broker; -using namespace qpid::sys; -using std::string; - -QueueRegistry::QueueRegistry(Broker* b) -{ - setBroker(b); -} - -QueueRegistry::~QueueRegistry(){} - -std::pair -QueueRegistry::declare(const string& name, const QueueSettings& settings, - boost::shared_ptr alternate, - bool recovering/*true if this declare is a - result of recovering queue - definition from persistent - record*/, - const OwnershipToken* owner, - std::string connectionId, - std::string userId) -{ - std::pair result; - { - RWlock::ScopedWlock locker(lock); - QueueMap::iterator i = queues.find(name); - if (i == queues.end()) { - Queue::shared_ptr queue = create(name, settings); - // 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 - queue->setOwningUser(userId); - - if (!recovering) { - //create persistent record if required - queue->create(); - } - queues[name] = queue; - result = std::pair(queue, true); - } else { - result = std::pair(i->second, false); - ++(i->second->version); - } - if (getBroker() && getBroker()->getManagementAgent()) { - getBroker()->getManagementAgent()->raiseEvent( - _qmf::EventQueueDeclare( - connectionId, userId, name, - settings.durable, owner, settings.autodelete, - alternate ? alternate->getName() : string(), - result.first->getSettings().asMap(), - result.second ? "created" : "existing")); - } - } - return result; -} - -void QueueRegistry::destroy( - const string& name, const string& connectionId, const string& userId) -{ - Queue::shared_ptr q; - { - qpid::sys::RWlock::ScopedWlock locker(lock); - QueueMap::iterator i = queues.find(name); - if (i != queues.end()) { - q = i->second; - eraseLH(i, q, name, connectionId, userId); - } - } - // Destroy management object, store record etc. The Queue will not - // actually be deleted till all shared_ptr to it are gone. - // - // Outside the lock (avoid deadlock) but guaranteed to be called exactly once, - // since q will only be set on the first call to destroy above. - if (q) - q->destroyed(); -} - -void QueueRegistry::eraseLH(QueueMap::iterator i, Queue::shared_ptr q, const string& name, const string& connectionId, const string& userId) -{ - queues.erase(i); - if (getBroker()) { - // NOTE: queueDestroy and raiseEvent must be called with the - // lock held in order to ensure events are generated - // in the correct order. - getBroker()->getBrokerObservers().queueDestroy(q); - if (getBroker()->getManagementAgent()) - getBroker()->getManagementAgent()->raiseEvent( - _qmf::EventQueueDelete(connectionId, userId, name)); - } -} - - -bool QueueRegistry::destroyIfUntouched(const string& name, long version, - const string& connectionId, const string& userId) -{ - Queue::shared_ptr q; - { - qpid::sys::RWlock::ScopedWlock locker(lock); - QueueMap::iterator i = queues.find(name); - if (i != queues.end()) { - if (i->second->version == version) { - q = i->second; - eraseLH(i, q, name, connectionId, userId); - } - } - } - // Destroy management object, store record etc. The Queue will not - // actually be deleted till all shared_ptr to it are gone. - // - // Outside the lock (avoid deadlock) but guaranteed to be called exactly once, - // since q will only be set on the first call to destroy above. - if (q) - q->destroyed(); - return q; -} - -Queue::shared_ptr QueueRegistry::find(const string& name){ - RWlock::ScopedRlock locker(lock); - QueueMap::iterator i = queues.find(name); - if (i == queues.end()) { - return Queue::shared_ptr(); - } else { - return i->second; - } -} - -Queue::shared_ptr QueueRegistry::get(const string& name) { - Queue::shared_ptr q = find(name); - if (!q) { - throw framing::NotFoundException(QPID_MSG("Queue not found: "< -#include -#include -#include - -namespace qpid { -namespace broker { - -class Queue; -class Exchange; -class OwnershipToken; - -/** - * A registry of queues indexed by queue name. - * - * Queues are reference counted using shared_ptr to ensure that they - * are deleted when and only when they are no longer in use. - * - */ -class QueueRegistry : private QueueFactory { - public: - QPID_BROKER_EXTERN QueueRegistry(Broker* b = 0); - QPID_BROKER_EXTERN ~QueueRegistry(); - - /** - * Declare a queue. - * - * @return The queue and a boolean flag which is true if the queue - * was created by this declare call false if it already existed. - */ - QPID_BROKER_EXTERN std::pair, bool> declare( - const std::string& name, - const QueueSettings& settings, - boost::shared_ptr alternateExchange = boost::shared_ptr(), - bool recovering = false, - const OwnershipToken* owner = 0, - std::string connectionId=std::string(), std::string userId=std::string()); - - /** - * Destroy the named queue. - * - * Note: if the queue is in use it is not actually destroyed until - * all shared_ptrs to it are destroyed. During that time it is - * possible that a new queue with the same name may be - * created. This should not create any problems as the new and - * old queues exist independently. The registry has - * forgotten the old queue so there can be no confusion for - * subsequent calls to find or declare with the same name. - * - */ - QPID_BROKER_EXTERN void destroy( - const std::string& name, - const std::string& connectionId=std::string(), - const std::string& userId=std::string()); - - QPID_BROKER_EXTERN bool destroyIfUntouched(const std::string& name, long version, - const std::string& connectionId=std::string(), - const std::string& userId=std::string()); - - /** - * Find the named queue. Return 0 if not found. - */ - QPID_BROKER_EXTERN boost::shared_ptr find(const std::string& name); - - /** - * Get the named queue. Throw exception if not found. - */ - QPID_BROKER_EXTERN boost::shared_ptr get(const std::string& name); - - /** - * Set the store to use. May only be called once. - */ - void setStore (MessageStore*); - - /** - * Return the message store used. - */ - MessageStore* getStore() const; - - /** - * Register the manageable parent for declared queues - */ - void setParent (management::Manageable*); - - /** Call f for each queue in the registry. */ - template void eachQueue(F f) const { - qpid::sys::RWlock::ScopedRlock l(lock); - for (QueueMap::const_iterator i = queues.begin(); i != queues.end(); ++i) - f(i->second); - } - -private: - typedef std::map > QueueMap; - QueueMap queues; - mutable qpid::sys::RWlock lock; - - void eraseLH(QueueMap::iterator, boost::shared_ptr, const std::string& name, const std::string& connectionId, const std::string& userId); -}; - - -}} // namespace qpid::broker - - -#endif diff --git a/qpid/cpp/src/qpid/broker/QueueSettings.cpp b/qpid/cpp/src/qpid/broker/QueueSettings.cpp deleted file mode 100644 index 29d482d7f2..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueSettings.cpp +++ /dev/null @@ -1,332 +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 "QueueSettings.h" -#include "QueueFlowLimit.h" -#include "MessageGroupManager.h" -#include "qpid/types/Variant.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/amqp_0_10/Codecs.h" - - -namespace qpid { -namespace broker { - -namespace { -const std::string MAX_COUNT("qpid.max_count"); -const std::string MAX_SIZE("qpid.max_size"); -const std::string MAX_FILE_COUNT("qpid.file_count"); -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"); -const std::string TRACE_EXCLUDES("qpid.trace.exclude"); -const std::string LVQ_KEY("qpid.last_value_queue_key"); -const std::string AUTO_DELETE_TIMEOUT("qpid.auto_delete_timeout"); -const std::string ALERT_REPEAT_GAP("qpid.alert_repeat_gap"); -const std::string ALERT_COUNT("qpid.alert_count"); -const std::string ALERT_SIZE("qpid.alert_size"); -const std::string ALERT_COUNT_UP("qpid.alert_count_up"); -const std::string ALERT_SIZE_UP("qpid.alert_size_up"); -const std::string ALERT_COUNT_DOWN("qpid.alert_count_down"); -const std::string ALERT_SIZE_DOWN("qpid.alert_size_down"); -const std::string PRIORITIES("qpid.priorities"); -const std::string FAIRSHARE("qpid.fairshare"); -const std::string FAIRSHARE_ALIAS("x-qpid-fairshare"); -const std::string PAGING("qpid.paging"); -const std::string MAX_PAGES("qpid.max_pages_loaded"); -const std::string PAGE_FACTOR("qpid.page_factor"); -const std::string FILTER("qpid.filter"); -const std::string LIFETIME_POLICY("qpid.lifetime-policy"); -const std::string DELETE_ON_CLOSE_KEY("delete-on-close"); -const std::string DELETE_IF_UNUSED_KEY("delete-if-unused"); -const std::string DELETE_IF_UNUSED_AND_EMPTY_KEY("delete-if-unused-and-empty"); -const std::string MANUAL("manual"); - -const std::string LVQ_LEGACY("qpid.last_value_queue"); -const std::string LVQ_LEGACY_KEY("qpid.LVQ_key"); -const std::string LVQ_LEGACY_NOBROWSE("qpid.last_value_queue_no_browse"); - -const std::string SEQUENCING("qpid.queue_msg_sequence"); - -bool handleFairshareSetting(const std::string& basename, const std::string& key, const qpid::types::Variant& value, QueueSettings& settings) -{ - if (key.find(basename) == 0) { - qpid::types::Variant index(key.substr(basename.size()+1)); - settings.fairshare[index] = value; - return true; - } else { - return false; - } -} -bool isFairshareSetting(const std::string& key, const qpid::types::Variant& value, QueueSettings& settings) -{ - return handleFairshareSetting(FAIRSHARE, key, value, settings) || handleFairshareSetting(FAIRSHARE_ALIAS, key, value, settings); -} -} - -const QueueSettings::Aliases QueueSettings::aliases; - -QueueSettings::QueueSettings(bool d, bool a) : - durable(d), - autodelete(a), - lifetime(DELETE_IF_UNUSED), - isTemporary(false), - priorities(0), - defaultFairshare(0), - shareGroups(false), - addTimestamp(false), - dropMessagesAtLimit(false), - selfDestructAtLimit(false), - paging(false), - maxPages(0), - pageFactor(0), - noLocal(false), - isBrowseOnly(false), - autoDeleteDelay(0), - alertRepeatInterval(60), - maxFileSize(0), - maxFileCount(0), - sequencing(false) -{} - -bool QueueSettings::handle(const std::string& key, const qpid::types::Variant& value) -{ - if (key == MAX_COUNT) { - maxDepth.setCount(value); - return true; - } else if (key == MAX_SIZE) { - maxDepth.setSize(value); - return true; - } else if (key == POLICY_TYPE) { - 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; - } else { - QPID_LOG(warning, "Unrecognised policy option: " << value); - return false; - } - } else if (key == NO_LOCAL) { - noLocal = value; - return true; - } else if (key == BROWSE_ONLY) { - isBrowseOnly = value; - return true; - } else if (key == TRACE_ID) { - traceId = value.asString(); - return true; - } else if (key == TRACE_EXCLUDES) { - traceExcludes = value.asString(); - return true; - } else if (key == PRIORITIES) { - priorities = value; - return true; - } else if (key == FAIRSHARE) { - defaultFairshare = value; - return true; - } else if (isFairshareSetting(key, value, *this)) { - return true; - } else if (key == MessageGroupManager::qpidMessageGroupKey) { - groupKey = value.asString(); - return true; - } else if (key == MessageGroupManager::qpidSharedGroup) { - shareGroups = value; - return true; - } else if (key == MessageGroupManager::qpidMessageGroupTimestamp) { - addTimestamp = value; - return true; - } else if (key == LVQ_KEY) { - lvqKey = value.asString(); - return true; - } else if (key == LVQ_LEGACY) { - if (lvqKey.empty()) lvqKey = LVQ_LEGACY_KEY; - return true; - } else if (key == LVQ_LEGACY_NOBROWSE) { - QPID_LOG(warning, "Ignoring 'no-browse' directive for LVQ; it is no longer necessary"); - if (lvqKey.empty()) lvqKey = LVQ_LEGACY_KEY; - return true; - } else if (key == AUTO_DELETE_TIMEOUT) { - autoDeleteDelay = value; - if (autoDeleteDelay) autodelete = true; - return true; - } else if (key == QueueFlowLimit::flowStopCountKey) { - flowStop.setCount(value); - return true; - } else if (key == QueueFlowLimit::flowResumeCountKey) { - flowResume.setCount(value); - return true; - } else if (key == QueueFlowLimit::flowStopSizeKey) { - flowStop.setSize(value); - return true; - } else if (key == QueueFlowLimit::flowResumeSizeKey) { - flowResume.setSize(value); - return true; - } else if (key == ALERT_REPEAT_GAP) { - alertRepeatInterval = value; - return true; - } else if ((key == ALERT_COUNT) || (key == ALERT_COUNT_UP)) { - alertThreshold.setCount(value); - return true; - } else if ((key == ALERT_SIZE) || (key == ALERT_SIZE_UP)) { - alertThreshold.setSize(value); - return true; - } else if (key == ALERT_COUNT_DOWN) { - alertThresholdDown.setCount(value); - return true; - } else if (key == ALERT_SIZE_DOWN) { - alertThresholdDown.setSize(value); - return true; - } else if (key == MAX_FILE_COUNT && value.asUint64() > 0) { - maxFileCount = value.asUint64(); - return false; // 'handle' here and also pass to store - } else if (key == MAX_FILE_SIZE && value.asUint64() > 0) { - maxFileSize = value.asUint64(); - return false; // 'handle' here and also pass to store - } else if (key == PAGING) { - paging = value; - return true; - } else if (key == MAX_PAGES) { - maxPages = value; - return true; - } else if (key == PAGE_FACTOR) { - pageFactor = value; - return true; - } else if (key == SEQUENCING) { - sequenceKey = value.getString(); - sequencing = !sequenceKey.empty(); - return true; - } else if (key == FILTER) { - filter = value.asString(); - return true; - } else if (key == LIFETIME_POLICY) { - if (value.asString() == DELETE_IF_UNUSED_KEY) { - lifetime = DELETE_IF_UNUSED; - autodelete = true; - } else if (value.asString() == DELETE_IF_UNUSED_AND_EMPTY_KEY) { - lifetime = DELETE_IF_UNUSED_AND_EMPTY; - autodelete = true; - } else if (value.asString() == MANUAL) { - autodelete = false; - } else if (value.asString() == DELETE_ON_CLOSE_KEY) { - lifetime = DELETE_ON_CLOSE; - autodelete = true; - } else { - QPID_LOG(warning, "Invalid value for " << LIFETIME_POLICY << ": " << value); - } - return true; - } else { - return false; - } -} - -void QueueSettings::validate() const -{ - if (lvqKey.size() && priorities > 0) - throw qpid::framing::InvalidArgumentException(QPID_MSG("Cannot specify " << LVQ_KEY << " and " << PRIORITIES << " for the same queue")); - if ((fairshare.size() || defaultFairshare) && priorities == 0) - throw qpid::framing::InvalidArgumentException(QPID_MSG("Cannot specify fairshare settings when queue is not enabled for priorities")); - if (fairshare.size() > priorities) - throw qpid::framing::InvalidArgumentException(QPID_MSG("Cannot have fairshare set for priority levels greater than " << priorities)); - if (groupKey.size() && lvqKey.size()) - throw qpid::framing::InvalidArgumentException(QPID_MSG("Cannot specify " << LVQ_KEY << " and " << MessageGroupManager::qpidMessageGroupKey << " for the same queue")); - if (groupKey.size() && priorities) - throw qpid::framing::InvalidArgumentException(QPID_MSG("Cannot specify " << PRIORITIES << " and " << MessageGroupManager::qpidMessageGroupKey << " for the same queue")); - if (shareGroups && groupKey.empty()) { - throw qpid::framing::InvalidArgumentException(QPID_MSG("Can only specify " << MessageGroupManager::qpidSharedGroup - << " if " << MessageGroupManager::qpidMessageGroupKey << " is set")); - } - if (addTimestamp && groupKey.empty()) { - throw qpid::framing::InvalidArgumentException(QPID_MSG("Can only specify " << MessageGroupManager::qpidMessageGroupTimestamp - << " if " << MessageGroupManager::qpidMessageGroupKey << " is set")); - } - - // @todo: remove once "sticky" consumers are supported - see QPID-3347 - if (!shareGroups && groupKey.size()) { - throw qpid::framing::InvalidArgumentException(QPID_MSG("Only shared groups are supported at present; " << MessageGroupManager::qpidSharedGroup - << " is required if " << MessageGroupManager::qpidMessageGroupKey << " is set")); - } - - if (paging) { - if(lvqKey.size()) { - throw qpid::framing::InvalidArgumentException(QPID_MSG("Cannot specify " << LVQ_KEY << " and " << PAGING << " for the same queue")); - } - if(priorities) { - throw qpid::framing::InvalidArgumentException(QPID_MSG("Cannot specify " << PRIORITIES << " and " << PAGING << " for the same queue")); - } - if(groupKey.size()) { - throw qpid::framing::InvalidArgumentException(QPID_MSG("Cannot specify " << MessageGroupManager::qpidMessageGroupKey << " and " << PAGING << " for the same queue")); - } - } else { - if (maxPages) { - throw qpid::framing::InvalidArgumentException(QPID_MSG("Can only specify " << MAX_PAGES << " if " << PAGING << " is set")); - } - if (pageFactor) { - throw qpid::framing::InvalidArgumentException(QPID_MSG("Can only specify " << PAGE_FACTOR << " if " << PAGING << " is set")); - } - } -} - -void QueueSettings::populate(const std::map& inputs, std::map& unused) -{ - original = inputs; - for (qpid::types::Variant::Map::const_iterator i = inputs.begin(); i != inputs.end(); ++i) { - Aliases::const_iterator a = aliases.find(i->first); - if (!handle((a != aliases.end() ? a->second : i->first), i->second)) unused.insert(*i); - } -} -void QueueSettings::populate(const qpid::framing::FieldTable& inputs, qpid::framing::FieldTable& unused) -{ - qpid::types::Variant::Map o; - qpid::amqp_0_10::translate(inputs, original); - populate(original, o); - qpid::amqp_0_10::translate(o, unused); -} -std::map QueueSettings::asMap() const -{ - return original; -} - -QueueSettings::Aliases::Aliases() -{ - insert(value_type("x-qpid-priorities", "qpid.priorities")); - insert(value_type("x-qpid-fairshare", "qpid.fairshare")); - insert(value_type("x-qpid-minimum-alert-repeat-gap", "qpid.alert_repeat_gap")); - insert(value_type("x-qpid-maximum-message-count", "qpid.alert_count")); - insert(value_type("x-qpid-maximum-message-size", "qpid.alert_size")); -} - -std::string QueueSettings::getLimitPolicy() const -{ - if (dropMessagesAtLimit) return POLICY_TYPE_RING; - else if (selfDestructAtLimit) return POLICY_TYPE_SELF_DESTRUCT; - else return POLICY_TYPE_REJECT; -} -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/QueueSettings.h b/qpid/cpp/src/qpid/broker/QueueSettings.h deleted file mode 100644 index 9fda51e17a..0000000000 --- a/qpid/cpp/src/qpid/broker/QueueSettings.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef QPID_BROKER_QUEUESETTINGS_H -#define QPID_BROKER_QUEUESETTINGS_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/BrokerImportExport.h" -#include "qpid/broker/QueueDepth.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/framing/FieldTable.h" -#include -#include - -namespace qpid { -namespace types { -class Variant; -} -namespace broker { - -/** - * Defines the various queue configuration settings that can be specified - */ -struct QueueSettings -{ - QPID_BROKER_EXTERN QueueSettings(bool durable=false, bool autodelete=false); - /** - * The lifetime policy dictates when an autodelete queue is - * eligible for delete. - */ - enum LifetimePolicy - { - DELETE_IF_UNUSED = 0, - DELETE_IF_EMPTY, - DELETE_IF_UNUSED_AND_EMPTY, - DELETE_ON_CLOSE - }; - - bool durable; - bool autodelete; - LifetimePolicy lifetime; - bool isTemporary; - - //basic queue types: - std::string lvqKey; - uint32_t priorities; - uint32_t defaultFairshare; - std::map fairshare; - - //message groups: - std::string groupKey; - bool shareGroups; - bool addTimestamp;//not actually used; always on at present? - - QueueDepth maxDepth; - bool dropMessagesAtLimit;//aka ring queue policy - bool selfDestructAtLimit; - - //PagedQueue: - bool paging; - uint maxPages; - uint pageFactor; - - bool noLocal; - bool isBrowseOnly; - std::string traceId; - std::string traceExcludes; - uint64_t autoDeleteDelay;//queueTtl? - - //flow control: - QueueDepth flowStop; - QueueDepth flowResume; - - //threshold events: - QueueDepth alertThreshold; - QueueDepth alertThresholdDown; - int64_t alertRepeatInterval; - - //file limits checked by Acl and shared with storeSettings - uint64_t maxFileSize; - uint64_t maxFileCount; - - std::string sequenceKey; - // store bool to avoid testing string value - bool sequencing; - - std::string filter; - - //yuck, yuck - qpid::framing::FieldTable storeSettings; - std::map original; - - bool handle(const std::string& key, const qpid::types::Variant& value); - void validate() const; - QPID_BROKER_EXTERN void populate(const std::map& inputs, std::map& unused); - QPID_BROKER_EXTERN void populate(const qpid::framing::FieldTable& inputs, qpid::framing::FieldTable& unused); - QPID_BROKER_EXTERN std::map asMap() const; - std::string getLimitPolicy() const; - - struct Aliases : std::map - { - Aliases(); - }; - static const Aliases aliases; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUESETTINGS_H*/ diff --git a/qpid/cpp/src/qpid/broker/QueuedMessage.cpp b/qpid/cpp/src/qpid/broker/QueuedMessage.cpp deleted file mode 100644 index d40cc901ff..0000000000 --- a/qpid/cpp/src/qpid/broker/QueuedMessage.cpp +++ /dev/null @@ -1,34 +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 "QueuedMessage.h" -#include "Queue.h" -#include - -namespace qpid { -namespace broker { - -std::ostream& operator<<(std::ostream& o, const QueuedMessage& qm) { - o << (qm.queue ? qm.queue->getName() : std::string()) << "[" << qm.position <<"]"; - return o; -} - - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/QueuedMessage.h b/qpid/cpp/src/qpid/broker/QueuedMessage.h deleted file mode 100644 index c80fff900a..0000000000 --- a/qpid/cpp/src/qpid/broker/QueuedMessage.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueuedMessage_ -#define _QueuedMessage_ - -#include "qpid/broker/Message.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/broker/BrokerImportExport.h" - -namespace qpid { -namespace broker { - -class Queue; - -struct QueuedMessage -{ - Message message; - framing::SequenceNumber position; - enum {AVAILABLE, ACQUIRED, DELETED, REMOVED} status; - Queue* queue; - - QueuedMessage() : queue(0) {} - QueuedMessage(Queue* q, Message msg, framing::SequenceNumber sn) : - message(msg), position(sn), queue(q) {} - QueuedMessage(Queue* q) : queue(q) {} -}; - -inline bool operator<(const QueuedMessage& a, const QueuedMessage& b) -{ - return a.position < b.position; -} - -QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&, const QueuedMessage&); -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoverableConfig.h b/qpid/cpp/src/qpid/broker/RecoverableConfig.h deleted file mode 100644 index 838a8582dc..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoverableConfig.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_RecoverableConfig_h -#define _broker_RecoverableConfig_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 - -namespace qpid { -namespace broker { - -/** - * The interface through which configurations are recovered. - */ -class RecoverableConfig -{ -public: - typedef boost::shared_ptr shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - virtual ~RecoverableConfig() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoverableExchange.h b/qpid/cpp/src/qpid/broker/RecoverableExchange.h deleted file mode 100644 index f8c08b2989..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoverableExchange.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _broker_RecoverableExchange_h -#define _broker_RecoverableExchange_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 -#include "qpid/framing/FieldTable.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which bindings are recovered. - */ -class RecoverableExchange -{ -public: - typedef boost::shared_ptr shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - /** - * Recover binding. Nb: queue must have been recovered earlier. - */ - virtual void bind(const std::string& queue, - const std::string& routingKey, - qpid::framing::FieldTable& args) = 0; - - virtual std::string getName() const = 0; - - virtual ~RecoverableExchange() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoverableMessage.h b/qpid/cpp/src/qpid/broker/RecoverableMessage.h deleted file mode 100644 index 3c82a69883..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoverableMessage.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _broker_RecoverableMessage_h -#define _broker_RecoverableMessage_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 -#include -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" - -namespace qpid { -namespace broker { -class Message; -/** - * The interface through which messages are reloaded on recovery. - */ -class RecoverableMessage -{ -public: - typedef boost::shared_ptr shared_ptr; - virtual void setPersistenceId(uint64_t id) = 0; - virtual void setRedelivered() = 0; - virtual void computeExpiration() = 0; - /** - * Used by store to determine whether to load content on recovery - * or let message load its own content as and when it requires it. - * - * @returns true if the content of the message should be loaded - */ - virtual bool loadContent(uint64_t available) = 0; - /** - * Loads the content held in the supplied buffer (may do checking - * of length as necessary) - */ - virtual void decodeContent(framing::Buffer& buffer) = 0; - virtual Message getMessage() = 0; - virtual ~RecoverableMessage() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h b/qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h deleted file mode 100644 index c257c2057b..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_BROKER_RECOVERABLEMESSAGEIMPL_H -#define QPID_BROKER_RECOVERABLEMESSAGEIMPL_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 "RecoverableMessage.h" -#include "Message.h" - -namespace qpid { -namespace broker { -class DtxBuffer; -class Queue; - -class RecoverableMessageImpl : public RecoverableMessage -{ - Message msg; -public: - QPID_BROKER_EXTERN RecoverableMessageImpl(const Message& _msg); - ~RecoverableMessageImpl() {}; - void setPersistenceId(uint64_t id); - void setRedelivered(); - void computeExpiration(); - bool loadContent(uint64_t available); - void decodeContent(framing::Buffer& buffer); - void recover(boost::shared_ptr queue); - void enqueue(boost::intrusive_ptr buffer, boost::shared_ptr queue); - void dequeue(boost::intrusive_ptr buffer, boost::shared_ptr queue); - Message getMessage(); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_RECOVERABLEMESSAGEIMPL_H*/ diff --git a/qpid/cpp/src/qpid/broker/RecoverableQueue.h b/qpid/cpp/src/qpid/broker/RecoverableQueue.h deleted file mode 100644 index ab300dbce9..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoverableQueue.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _broker_RecoverableQueue_h -#define _broker_RecoverableQueue_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/RecoverableMessage.h" -#include "qpid/types/Variant.h" -#include - -namespace qpid { -namespace broker { - -class ExternalQueueStore; -struct QueueSettings; - -/** - * The interface through which messages are added back to queues on - * recovery. - */ -class RecoverableQueue -{ -public: - typedef boost::shared_ptr shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - virtual uint64_t getPersistenceId() const = 0; - /** - * Used during recovery to add stored messages back to the queue - */ - virtual void recover(RecoverableMessage::shared_ptr msg) = 0; - virtual ~RecoverableQueue() {}; - - virtual const std::string& getName() const = 0; - virtual void setExternalQueueStore(ExternalQueueStore* inst) = 0; - virtual ExternalQueueStore* getExternalQueueStore() const = 0; - virtual const QueueSettings& getSettings() const = 0; - virtual void addArgument(const std::string& key, const qpid::types::Variant& value) = 0; - -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoverableTransaction.h b/qpid/cpp/src/qpid/broker/RecoverableTransaction.h deleted file mode 100644 index 1b7d94bd1a..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoverableTransaction.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _broker_RecoverableTransaction_h -#define _broker_RecoverableTransaction_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 - -#include "qpid/broker/RecoverableMessage.h" -#include "qpid/broker/RecoverableQueue.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which prepared 2pc transactions are - * recovered. - */ -class RecoverableTransaction -{ -public: - typedef boost::shared_ptr shared_ptr; - virtual void enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) = 0; - virtual void dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) = 0; - virtual ~RecoverableTransaction() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoveredDequeue.cpp b/qpid/cpp/src/qpid/broker/RecoveredDequeue.cpp deleted file mode 100644 index 6e21a5bc21..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoveredDequeue.cpp +++ /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. - * - */ - -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveredDequeue.h" - -using namespace qpid::broker; - -RecoveredDequeue::RecoveredDequeue(Queue::shared_ptr _queue, Message _msg) : queue(_queue), msg(_msg) -{ - queue->recoverPrepared(msg); -} - -bool RecoveredDequeue::prepare(TransactionContext*) throw() -{ - //should never be called; transaction has already prepared if an enqueue is recovered - return false; -} - -void RecoveredDequeue::commit() throw() -{ - queue->dequeueCommited(msg); -} - -void RecoveredDequeue::rollback() throw() -{ - queue->dequeueAborted(msg); -} - diff --git a/qpid/cpp/src/qpid/broker/RecoveredDequeue.h b/qpid/cpp/src/qpid/broker/RecoveredDequeue.h deleted file mode 100644 index b85919975c..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoveredDequeue.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveredDequeue_ -#define _RecoveredDequeue_ - -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/TxOp.h" - -#include -#include -#include - -namespace qpid { - namespace broker { - class RecoveredDequeue : public TxOp{ - boost::shared_ptr queue; - Message msg; - - public: - RecoveredDequeue(boost::shared_ptr queue, Message msg); - 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&) {} - virtual ~RecoveredDequeue(){} - - boost::shared_ptr getQueue() const { return queue; } - Message getMessage() const { return msg; } - }; - } -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoveredEnqueue.cpp b/qpid/cpp/src/qpid/broker/RecoveredEnqueue.cpp deleted file mode 100644 index 296d5194c0..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoveredEnqueue.cpp +++ /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. - * - */ - -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveredEnqueue.h" - -using namespace qpid::broker; - -RecoveredEnqueue::RecoveredEnqueue(Queue::shared_ptr _queue, Message _msg) : queue(_queue), msg(_msg) -{ - queue->recoverPrepared(msg); -} - -bool RecoveredEnqueue::prepare(TransactionContext*) throw(){ - //should never be called; transaction has already prepared if an enqueue is recovered - return false; -} - -void RecoveredEnqueue::commit() throw(){ - queue->enqueueCommited(msg); -} - -void RecoveredEnqueue::rollback() throw(){ - queue->enqueueAborted(msg); -} - diff --git a/qpid/cpp/src/qpid/broker/RecoveredEnqueue.h b/qpid/cpp/src/qpid/broker/RecoveredEnqueue.h deleted file mode 100644 index 01c350af92..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoveredEnqueue.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveredEnqueue_ -#define _RecoveredEnqueue_ - -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/TxOp.h" - -#include -#include -#include - -namespace qpid { -namespace broker { -class RecoveredEnqueue : public TxOp{ - boost::shared_ptr queue; - Message msg; - - public: - RecoveredEnqueue(boost::shared_ptr queue, Message msg); - 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&) {} - virtual ~RecoveredEnqueue(){} - - boost::shared_ptr getQueue() const { return queue; } - Message getMessage() const { return msg; } -}; -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoveryManager.h b/qpid/cpp/src/qpid/broker/RecoveryManager.h deleted file mode 100644 index 2929e92250..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoveryManager.h +++ /dev/null @@ -1,61 +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. - * - */ -#ifndef _RecoveryManager_ -#define _RecoveryManager_ - -#include "qpid/broker/RecoverableExchange.h" -#include "qpid/broker/RecoverableQueue.h" -#include "qpid/broker/RecoverableMessage.h" -#include "qpid/broker/RecoverableTransaction.h" -#include "qpid/broker/RecoverableConfig.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/Buffer.h" - -namespace qpid { -namespace broker { - -class RecoveryManager{ - public: - virtual ~RecoveryManager(){} - virtual RecoverableExchange::shared_ptr recoverExchange(framing::Buffer& buffer) = 0; - virtual RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer) = 0; - virtual RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer) = 0; - virtual RecoverableTransaction::shared_ptr recoverTransaction(const std::string& xid, - std::auto_ptr txn) = 0; - virtual RecoverableConfig::shared_ptr recoverConfig(framing::Buffer& buffer) = 0; - - virtual void recoveryComplete() = 0; -}; - -class Recoverable { - public: - virtual ~Recoverable() {} - - /** - * Request recovery of queue and message state. - */ - virtual void recover(RecoveryManager& recoverer) = 0; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RecoveryManagerImpl.cpp b/qpid/cpp/src/qpid/broker/RecoveryManagerImpl.cpp deleted file mode 100644 index dd9bfc57f6..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoveryManagerImpl.cpp +++ /dev/null @@ -1,288 +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/broker/RecoveryManagerImpl.h" - -#include "qpid/broker/Message.h" -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/PersistableObject.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/Protocol.h" -#include "qpid/broker/RecoverableMessageImpl.h" -#include "qpid/broker/RecoveredEnqueue.h" -#include "qpid/broker/RecoveredDequeue.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/framing/reply_exceptions.h" - -using boost::dynamic_pointer_cast; -using boost::intrusive_ptr; -using std::string; - -namespace qpid { -namespace broker { - -RecoveryManagerImpl::RecoveryManagerImpl(QueueRegistry& _queues, ExchangeRegistry& _exchanges, LinkRegistry& _links, - DtxManager& _dtxMgr, ProtocolRegistry& p, RecoveredObjects& o) - : queues(_queues), exchanges(_exchanges), links(_links), dtxMgr(_dtxMgr), protocols(p), objects(o) {} - -RecoveryManagerImpl::~RecoveryManagerImpl() {} - -class RecoverableQueueImpl : public RecoverableQueue -{ - Queue::shared_ptr queue; -public: - RecoverableQueueImpl(const boost::shared_ptr& _queue) : queue(_queue) {} - ~RecoverableQueueImpl() {}; - void setPersistenceId(uint64_t id); - uint64_t getPersistenceId() const; - const std::string& getName() const; - void setExternalQueueStore(ExternalQueueStore* inst); - ExternalQueueStore* getExternalQueueStore() const; - const QueueSettings& getSettings() const; - void addArgument(const std::string& key, const types::Variant& value); - void recover(RecoverableMessage::shared_ptr msg); - void enqueue(boost::intrusive_ptr buffer, RecoverableMessage::shared_ptr msg); - void dequeue(boost::intrusive_ptr buffer, RecoverableMessage::shared_ptr msg); - -}; - -class RecoverableExchangeImpl : public RecoverableExchange -{ - Exchange::shared_ptr exchange; - QueueRegistry& queues; -public: - RecoverableExchangeImpl(Exchange::shared_ptr _exchange, QueueRegistry& _queues) : exchange(_exchange), queues(_queues) {} - void setPersistenceId(uint64_t id); - void bind(const std::string& queue, const std::string& routingKey, qpid::framing::FieldTable& args); - string getName() const { return exchange->getName(); } -}; - -class RecoverableConfigImpl : public RecoverableConfig -{ - Link::shared_ptr link; - Bridge::shared_ptr bridge; -public: - RecoverableConfigImpl(Link::shared_ptr _link) : link(_link) {} - RecoverableConfigImpl(Bridge::shared_ptr _bridge) : bridge(_bridge) {} - void setPersistenceId(uint64_t id); -}; - -class RecoverableTransactionImpl : public RecoverableTransaction -{ - boost::intrusive_ptr buffer; -public: - RecoverableTransactionImpl(boost::intrusive_ptr _buffer) : buffer(_buffer) {} - void enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message); - void dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message); -}; - -RecoverableExchange::shared_ptr RecoveryManagerImpl::recoverExchange(framing::Buffer& buffer) -{ - Exchange::shared_ptr e = Exchange::decode(exchanges, buffer); - if (e) { - return RecoverableExchange::shared_ptr(new RecoverableExchangeImpl(e, queues)); - } else { - return RecoverableExchange::shared_ptr(); - } -} - -RecoverableQueue::shared_ptr RecoveryManagerImpl::recoverQueue(framing::Buffer& buffer) -{ - Queue::shared_ptr queue = Queue::restore(queues, buffer); - try { - Exchange::shared_ptr exchange = exchanges.getDefault(); - if (exchange) { - exchange->bind(queue, queue->getName(), 0); - queue->bound(exchange->getName(), queue->getName(), framing::FieldTable()); - } - } catch (const framing::NotFoundException& /*e*/) { - //assume no default exchange has been declared - } - return RecoverableQueue::shared_ptr(new RecoverableQueueImpl(queue)); -} - -RecoverableMessage::shared_ptr RecoveryManagerImpl::recoverMessage(framing::Buffer& buffer) -{ - RecoverableMessage::shared_ptr m = protocols.recover(buffer); - return m; -} - -RecoverableTransaction::shared_ptr RecoveryManagerImpl::recoverTransaction(const std::string& xid, - std::auto_ptr txn) -{ - boost::intrusive_ptr buffer(new DtxBuffer()); - dtxMgr.recover(xid, txn, buffer); - return RecoverableTransaction::shared_ptr(new RecoverableTransactionImpl(buffer)); -} - -RecoverableConfig::shared_ptr RecoveryManagerImpl::recoverConfig(framing::Buffer& buffer) -{ - string kind; - uint32_t p = buffer.getPosition(); - buffer.getShortString (kind); - buffer.setPosition(p); - - if (Link::isEncodedLink(kind)) - return RecoverableConfig::shared_ptr(new RecoverableConfigImpl(Link::decode (links, buffer))); - else if (Bridge::isEncodedBridge(kind)) - return RecoverableConfig::shared_ptr(new RecoverableConfigImpl(Bridge::decode (links, buffer))); - - return objects.recover(buffer); -} - -void RecoveryManagerImpl::recoveryComplete() -{ - //notify all queues and exchanges - queues.eachQueue(boost::bind(&Queue::recoveryComplete, _1, boost::ref(exchanges))); - exchanges.eachExchange(boost::bind(&Exchange::recoveryComplete, _1, boost::ref(exchanges))); -} - -RecoverableMessageImpl:: RecoverableMessageImpl(const Message& _msg) : msg(_msg) {} - -bool RecoverableMessageImpl::loadContent(uint64_t /*available*/) -{ - return true; -} - -void RecoverableMessageImpl::decodeContent(framing::Buffer& buffer) -{ - msg.getPersistentContext()->decodeContent(buffer); -} - -void RecoverableMessageImpl::recover(Queue::shared_ptr queue) -{ - queue->recover(msg); -} - -void RecoverableMessageImpl::setPersistenceId(uint64_t id) -{ - msg.getPersistentContext()->setPersistenceId(id); -} - -void RecoverableMessageImpl::setRedelivered() -{ - msg.deliver();//increment delivery count (but at present that isn't recorded durably) -} - -void RecoverableMessageImpl::computeExpiration() -{ - msg.getSharedState().computeExpiration(); -} - -Message RecoverableMessageImpl::getMessage() -{ - return msg; -} - -void RecoverableQueueImpl::recover(RecoverableMessage::shared_ptr msg) -{ - dynamic_pointer_cast(msg)->recover(queue); -} - -void RecoverableQueueImpl::setPersistenceId(uint64_t id) -{ - queue->setPersistenceId(id); -} - -uint64_t RecoverableQueueImpl::getPersistenceId() const -{ - return queue->getPersistenceId(); -} - -const std::string& RecoverableQueueImpl::getName() const -{ - return queue->getName(); -} - -void RecoverableQueueImpl::setExternalQueueStore(ExternalQueueStore* inst) -{ - queue->setExternalQueueStore(inst); -} - -ExternalQueueStore* RecoverableQueueImpl::getExternalQueueStore() const -{ - return queue->getExternalQueueStore(); -} - -const QueueSettings& RecoverableQueueImpl::getSettings() const -{ - return queue->getSettings(); -} - -void RecoverableQueueImpl::addArgument(const std::string& key, const types::Variant& value) -{ - queue->addArgument(key, value); -} - -void RecoverableExchangeImpl::setPersistenceId(uint64_t id) -{ - exchange->setPersistenceId(id); -} - -void RecoverableConfigImpl::setPersistenceId(uint64_t id) -{ - if (link.get()) - link->setPersistenceId(id); - else if (bridge.get()) - bridge->setPersistenceId(id); -} - -void RecoverableExchangeImpl::bind(const string& queueName, - const string& key, - framing::FieldTable& args) -{ - Queue::shared_ptr queue = queues.find(queueName); - exchange->bind(queue, key, &args); - queue->bound(exchange->getName(), key, args); -} - -void RecoverableMessageImpl::dequeue(boost::intrusive_ptr buffer, Queue::shared_ptr queue) -{ - buffer->enlist(TxOp::shared_ptr(new RecoveredDequeue(queue, msg))); -} - -void RecoverableMessageImpl::enqueue(boost::intrusive_ptr buffer, Queue::shared_ptr queue) -{ - buffer->enlist(TxOp::shared_ptr(new RecoveredEnqueue(queue, msg))); -} - -void RecoverableQueueImpl::dequeue(boost::intrusive_ptr buffer, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast(message)->dequeue(buffer, queue); -} - -void RecoverableQueueImpl::enqueue(boost::intrusive_ptr buffer, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast(message)->enqueue(buffer, queue); -} - -void RecoverableTransactionImpl::dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast(queue)->dequeue(buffer, message); -} - -void RecoverableTransactionImpl::enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast(queue)->enqueue(buffer, message); -} - -}} diff --git a/qpid/cpp/src/qpid/broker/RecoveryManagerImpl.h b/qpid/cpp/src/qpid/broker/RecoveryManagerImpl.h deleted file mode 100644 index 22ea6f8d04..0000000000 --- a/qpid/cpp/src/qpid/broker/RecoveryManagerImpl.h +++ /dev/null @@ -1,65 +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. - * - */ -#ifndef _RecoveryManagerImpl_ -#define _RecoveryManagerImpl_ - -#include -#include -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/RecoveryManager.h" - -namespace qpid { -namespace broker { -class Broker; -class PersistableObject; -class ProtocolRegistry; -class RecoveredObjects; - - class RecoveryManagerImpl : public RecoveryManager { - QueueRegistry& queues; - ExchangeRegistry& exchanges; - LinkRegistry& links; - DtxManager& dtxMgr; - ProtocolRegistry& protocols; - RecoveredObjects& objects; - public: - RecoveryManagerImpl(QueueRegistry& queues, ExchangeRegistry& exchanges, LinkRegistry& links, - DtxManager& dtxMgr, ProtocolRegistry&, RecoveredObjects&); - ~RecoveryManagerImpl(); - - RecoverableExchange::shared_ptr recoverExchange(framing::Buffer& buffer); - RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer); - RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer); - RecoverableTransaction::shared_ptr recoverTransaction(const std::string& xid, - std::auto_ptr txn); - RecoverableConfig::shared_ptr recoverConfig(framing::Buffer& buffer); - void recoveryComplete(); - }; - - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/RetryList.cpp b/qpid/cpp/src/qpid/broker/RetryList.cpp deleted file mode 100644 index b0477dd0f7..0000000000 --- a/qpid/cpp/src/qpid/broker/RetryList.cpp +++ /dev/null @@ -1,56 +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/broker/RetryList.h" - -namespace qpid { -namespace broker { - -RetryList::RetryList() : urlIndex(0), addressIndex(0) {} - -void RetryList::reset(const std::vector& u) -{ - urls = u; - urlIndex = addressIndex = 0;//reset indices -} - -bool RetryList::next(Address& address) -{ - while (urlIndex < urls.size()) { - if (addressIndex < urls[urlIndex].size()) { - address = urls[urlIndex][addressIndex++]; - return true; - } - urlIndex++; - addressIndex = 0; - } - urlIndex = addressIndex = 0;//reset indices - return false; -} - -std::ostream& operator<<(std::ostream& os, const RetryList& l) -{ - for (size_t i = 0; i < l.urls.size(); i++) { - os << l.urls[i] << " "; - } - return os; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/RetryList.h b/qpid/cpp/src/qpid/broker/RetryList.h deleted file mode 100644 index 9c4b779bcb..0000000000 --- a/qpid/cpp/src/qpid/broker/RetryList.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef QPID_BROKER_RETRYLIST_H -#define QPID_BROKER_RETRYLIST_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/BrokerImportExport.h" -#include "qpid/Url.h" - -namespace qpid { -namespace broker { - -/** - * Simple utility for managing a list of urls to try on reconnecting a - * link. Currently only supports TCP urls. - */ -class RetryList -{ - public: - QPID_BROKER_EXTERN RetryList(); - QPID_BROKER_EXTERN void reset(const std::vector& urls); - QPID_BROKER_EXTERN bool next(Address& address); - private: - std::vector urls; - size_t urlIndex; - size_t addressIndex; - - friend std::ostream& operator<<(std::ostream& os, const RetryList& l); -}; - -std::ostream& operator<<(std::ostream& os, const RetryList& l); - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_RETRYLIST_H*/ diff --git a/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp b/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp deleted file mode 100644 index b17507850f..0000000000 --- a/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp +++ /dev/null @@ -1,566 +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/broker/AclModule.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/SecuritySettings.h" - -#include - -#include "config.h" - -#if HAVE_SASL -#include -#include -#include -#include "qpid/sys/cyrus/CyrusSecurityLayer.h" -using qpid::sys::cyrus::CyrusSecurityLayer; -#endif - -using std::string; -using namespace qpid::framing; -using qpid::sys::SecurityLayer; -using qpid::sys::SecuritySettings; -using boost::format; -using boost::str; - - -namespace qpid { -namespace broker { - - - -class NullAuthenticator : public SaslAuthenticator -{ - amqp_0_10::Connection& connection; - framing::AMQP_ClientProxy::Connection client; - std::string realm; - const bool encrypt; -public: - NullAuthenticator(amqp_0_10::Connection& connection, bool encrypt); - ~NullAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string* response); - void step(const std::string&) {} - std::auto_ptr getSecurityLayer(uint16_t maxFrameSize); -}; - -#if HAVE_SASL - - - -class CyrusAuthenticator : public SaslAuthenticator -{ - sasl_conn_t *sasl_conn; - amqp_0_10::Connection& connection; - framing::AMQP_ClientProxy::Connection client; - const bool encrypt; - - void processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len); - bool getUsername(std::string& uid); - -public: - CyrusAuthenticator(amqp_0_10::Connection& connection, bool encrypt); - ~CyrusAuthenticator(); - void init(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string* response); - void step(const std::string& response); - void getError(std::string& error); - void getUid(std::string& uid) { getUsername(uid); } - std::auto_ptr getSecurityLayer(uint16_t maxFrameSize); -}; - -bool SaslAuthenticator::available(void) { - return true; -} - -// Called by sasl_server_init() when config file name is constructed to allow clients to verify file -// Returning SASL_FAIL here will cause sasl_server_init() to fail and an exception will be thrown -int _sasl_verifyfile_callback(void *, const char *configFileName, sasl_verify_type_t type) -{ - if (type == SASL_VRFY_CONF) { - struct stat st; - // verify the file exists - if ( ::stat ( configFileName, & st) ) { - QPID_LOG(error, "SASL: config file doesn't exist: " << configFileName); - return SASL_FAIL; - } - // verify the file can be read by the broker - if ( ::access ( configFileName, R_OK ) ) { - QPID_LOG(error, "SASL: broker unable to read the config file. Check file permissions: " << configFileName); - return SASL_FAIL; - } - } - return SASL_OK; -} - -#ifndef sasl_callback_ft -typedef int (*sasl_callback_ft)(void); -#endif - -// passed to sasl_server_init() -static sasl_callback_t _callbacks[] = -{ - { SASL_CB_VERIFYFILE, (sasl_callback_ft)&_sasl_verifyfile_callback, NULL }, - { SASL_CB_LIST_END, NULL, NULL } -}; -sasl_callback_t *callbacks = _callbacks; - -// Initialize the SASL mechanism; throw if it fails. -void SaslAuthenticator::init(const std::string& saslName, std::string const & saslConfigPath ) -{ - // Check if we have a version of SASL that supports sasl_set_path() -#if (SASL_VERSION_FULL >= ((2<<16)|(1<<8)|22)) - // If we are not given a sasl path, do nothing and allow the default to be used. - if ( saslConfigPath.empty() ) { - // don't pass callbacks if there is no config path - callbacks = NULL; - QPID_LOG ( info, "SASL: no config path set - using default." ); - } - else { - struct stat st; - - // Make sure the directory exists and we can read up to it. - if ( ::stat ( saslConfigPath.c_str(), & st) ) { - // Note: not using strerror() here because I think its messages are a little too hazy. - if ( errno == ENOENT ) - throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: no such directory: " << saslConfigPath ) ); - if ( errno == EACCES ) - throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: cannot read parent of: " << saslConfigPath ) ); - // catch-all stat failure - throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: cannot stat: " << saslConfigPath ) ); - } - - // Make sure that saslConfigPath is a directory. - if (!S_ISDIR(st.st_mode)) { - throw Exception ( QPID_MSG ( "SASL: not a directory: " << saslConfigPath ) ); - } - - // Make sure the directory is readable. - if ( ::access ( saslConfigPath.c_str(), R_OK ) ) { - throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: directory not readable:" << saslConfigPath ) ); - } - - // This shouldn't fail now, but check anyway. - int code = sasl_set_path(SASL_PATH_TYPE_CONFIG, const_cast(saslConfigPath.c_str())); - if(SASL_OK != code) - throw Exception(QPID_MSG("SASL: sasl_set_path failed [" << code << "] " )); - - QPID_LOG(info, "SASL: config path set to " << saslConfigPath ); - } -#endif - - int code = sasl_server_init(callbacks, saslName.c_str()); - if (code != SASL_OK) { - // TODO: Figure out who owns the char* returned by - // sasl_errstring, though it probably does not matter much - throw Exception(QPID_MSG("SASL: failed to parse SASL configuration file in (" << saslConfigPath << "), error: " << sasl_errstring(code, NULL, NULL))); - } -} - -void SaslAuthenticator::fini(void) -{ - sasl_done(); -} - -#else - -typedef NullAuthenticator CyrusAuthenticator; - -bool SaslAuthenticator::available(void) { - return false; -} - -void SaslAuthenticator::init(const std::string& /*saslName*/, std::string const & /*saslConfigPath*/ ) -{ - throw Exception("Requested authentication but SASL unavailable"); -} - -void SaslAuthenticator::fini(void) -{ - return; -} - -#endif - -std::auto_ptr SaslAuthenticator::createAuthenticator(amqp_0_10::Connection& c ) -{ - if (c.getBroker().isAuthenticating()) { - return std::auto_ptr( - new CyrusAuthenticator(c, c.getBroker().requireEncrypted())); - } else { - QPID_LOG(debug, "SASL: No Authentication Performed"); - return std::auto_ptr(new NullAuthenticator(c, c.getBroker().requireEncrypted())); - } -} - - -NullAuthenticator::NullAuthenticator(amqp_0_10::Connection& c, bool e) : connection(c), client(c.getOutput()), - realm(c.getBroker().getRealm()), encrypt(e) {} -NullAuthenticator::~NullAuthenticator() {} - -void NullAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr(new Str16Value("ANONYMOUS"))); - mechanisms.add(boost::shared_ptr(new Str16Value("PLAIN")));//useful for testing -} - -void NullAuthenticator::start(const string& mechanism, const string* response) -{ - if (encrypt) { - // encryption required - check to see if we are running over an - // encrypted SSL connection. - SecuritySettings external = connection.getExternalSecuritySettings(); - if (external.ssf < 1) // < 1 == unencrypted - { - QPID_LOG(error, "Rejected un-encrypted connection."); - throw ConnectionForcedException("Connection must be encrypted."); - } - } - if (mechanism == "PLAIN") { // Old behavior - if (response && response->size() > 0) { - string uid; - string::size_type i = response->find((char)0); - if (i == 0 && response->size() > 1) { - //no authorization id; use authentication id - i = response->find((char)0, 1); - if (i != string::npos) uid = response->substr(1, i-1); - } else if (i != string::npos) { - //authorization id is first null delimited field - uid = response->substr(0, i); - }//else not a valid SASL PLAIN response, throw error? - if (!uid.empty()) { - //append realm if it has not already been added - i = uid.find(realm); - if (i == string::npos || realm.size() + i < uid.size()) { - uid = str(format("%1%@%2%") % uid % realm); - } - connection.setUserId(uid); - } - } - } else { - connection.setUserId("anonymous"); - } - AclModule* acl = connection.getBroker().getAcl(); - if (acl && !acl->approveConnection(connection)) - { - throw ConnectionForcedException("User connection denied by configured limit"); - } - qmf::org::apache::qpid::broker::Connection::shared_ptr cnxMgmt = connection.getMgmtObject(); - if ( cnxMgmt ) - cnxMgmt->set_saslMechanism(mechanism); - - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, connection.getHeartbeatMax()); -} - - -std::auto_ptr NullAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr securityLayer; - return securityLayer; -} - - -#if HAVE_SASL - -CyrusAuthenticator::CyrusAuthenticator(amqp_0_10::Connection& c, bool _encrypt) : - sasl_conn(0), connection(c), client(c.getOutput()), encrypt(_encrypt) -{ - init(); -} - -void CyrusAuthenticator::init() -{ - /* The realm is - * currently the most important argument below. When - * performing authentication the user that is authenticating - * will be looked up in a specific realm. If none is given - * then the realm defaults to the hostname, which can cause - * confusion when the daemon is run on different hosts that - * may be logically sharing a realm (aka a user domain). This - * is especially important for SASL PLAIN authentication, - * which cannot specify a realm for the user that is - * authenticating. - */ - int code; - - std::string realm = connection.getBroker().getRealm(); - std::string service = connection.getBroker().getSaslServiceName(); - code = sasl_server_new(service.empty() ? BROKER_SASL_NAME : service.c_str(), /* Service name */ - NULL, /* Server FQDN, gethostname() */ - realm.c_str(), /* Authentication realm */ - NULL, /* Local IP, needed for some mechanism */ - NULL, /* Remote IP, needed for some mechanism */ - NULL, /* Callbacks */ - 0, /* Connection flags */ - &sasl_conn); - - if (SASL_OK != code) { - QPID_LOG(error, "SASL: Connection creation failed: [" << code << "] " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw ConnectionForcedException("Unable to perform authentication"); - } - - sasl_security_properties_t secprops; - - //TODO: should the actual SSF values be configurable here? - secprops.min_ssf = encrypt ? 10: 0; - secprops.max_ssf = 256; - - // If the transport provides encryption, notify the SASL library of - // the key length and set the ssf range to prevent double encryption. - SecuritySettings external = connection.getExternalSecuritySettings(); - QPID_LOG(debug, "External ssf=" << external.ssf << " and auth=" << external.authid); - sasl_ssf_t external_ssf = (sasl_ssf_t) external.ssf; - - if ((external_ssf) && (external.authid.empty())) { - QPID_LOG(warning, "SASL error: unable to offer EXTERNAL mechanism as authid cannot be determined"); - } - - if (external_ssf) { - int result = sasl_setprop(sasl_conn, SASL_SSF_EXTERNAL, &external_ssf); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result)); - } - - secprops.max_ssf = secprops.min_ssf = 0; - } - - QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << - ", max_ssf: " << secprops.max_ssf << - ", external_ssf: " << external_ssf ); - - if (!external.authid.empty()) { - const char* external_authid = external.authid.c_str(); - int result = sasl_setprop(sasl_conn, SASL_AUTH_EXTERNAL, external_authid); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external auth: " << result)); - } - - QPID_LOG(debug, "external auth detected and set to " << external_authid); - } - - secprops.maxbufsize = 65535; - secprops.property_names = 0; - secprops.property_values = 0; - secprops.security_flags = 0; /* or SASL_SEC_NOANONYMOUS etc as appropriate */ - /* - * The nodict flag restricts SASL authentication mechanisms - * to those that are not susceptible to dictionary attacks. - * They are: - * SRP - * PASSDSS-3DES-1 - * EXTERNAL - */ - if (external.nodict) secprops.security_flags |= SASL_SEC_NODICTIONARY; - int result = sasl_setprop(sasl_conn, SASL_SEC_PROPS, &secprops); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << result)); - } -} - -CyrusAuthenticator::~CyrusAuthenticator() -{ - if (sasl_conn) { - sasl_dispose(&sasl_conn); - sasl_conn = 0; - } -} - -void CyrusAuthenticator::getError(string& error) -{ - error = string(sasl_errdetail(sasl_conn)); -} - -bool CyrusAuthenticator::getUsername(string& uid) -{ - const void* ptr; - - int code = sasl_getprop(sasl_conn, SASL_USERNAME, &ptr); - if (SASL_OK == code) { - uid = string(const_cast(static_cast(ptr))); - return true; - } else { - QPID_LOG(warning, "Failed to retrieve sasl username"); - return false; - } -} - -void CyrusAuthenticator::getMechanisms(Array& mechanisms) -{ - const char *separator = " "; - const char *list; - unsigned int list_len; - int count; - - int code = sasl_listmech(sasl_conn, NULL, - "", separator, "", - &list, &list_len, - &count); - - if (SASL_OK != code) { - QPID_LOG(info, "SASL: Mechanism listing failed: " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw ConnectionForcedException("Mechanism listing failed"); - } else { - string mechanism; - unsigned int start; - unsigned int end; - - QPID_LOG(info, "SASL: Mechanism list: " << list); - - end = 0; - do { - start = end; - - // Seek to end of next mechanism - while (end < list_len && separator[0] != list[end]) - end++; - - // Record the mechanism - mechanisms.add(boost::shared_ptr(new Str16Value(string(list, start, end - start)))); - end++; - } while (end < list_len); - } -} - -void CyrusAuthenticator::start(const string& mechanism, const string* response) -{ - const char *challenge; - unsigned int challenge_len; - - // This should be at same debug level as mech list in getMechanisms(). - QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism); - int code = sasl_server_start(sasl_conn, - mechanism.c_str(), - (response ? response->c_str() : 0), (response ? response->size() : 0), - &challenge, &challenge_len); - - processAuthenticationStep(code, challenge, challenge_len); - qmf::org::apache::qpid::broker::Connection::shared_ptr cnxMgmt = connection.getMgmtObject(); - if ( cnxMgmt ) - cnxMgmt->set_saslMechanism(mechanism); -} - -void CyrusAuthenticator::step(const string& response) -{ - const char *challenge; - unsigned int challenge_len; - - int code = sasl_server_step(sasl_conn, - response.c_str(), response.length(), - &challenge, &challenge_len); - - processAuthenticationStep(code, challenge, challenge_len); -} - -void CyrusAuthenticator::processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len) -{ - if (SASL_OK == code) { - std::string uid; - if (!getUsername(uid)) { - // TODO: Change this to an exception signaling - // authentication failure, when one is available - throw ConnectionForcedException("Authenticated username unavailable"); - } - - connection.setUserId(uid); - - AclModule* acl = connection.getBroker().getAcl(); - if (acl && !acl->approveConnection(connection)) - { - throw ConnectionForcedException("User connection denied by configured limit"); - } - - QPID_LOG(info, connection.getMgmtId() << " SASL: Authentication succeeded for: " << uid); - - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, connection.getHeartbeatMax()); - } else if (SASL_CONTINUE == code) { - string challenge_str(challenge, challenge_len); - - QPID_LOG(debug, "SASL: sending challenge to client"); - - client.secure(challenge_str); - } else { - std::string uid; - //save error detail before trying to retrieve username as error in doing so will overwrite it - std::string errordetail = sasl_errdetail(sasl_conn); - if (!getUsername(uid)) { - QPID_LOG(info, "SASL: Authentication failed (no username available yet):" << errordetail); - } else if (SASL_NOUSER == code) { - // SASL_NOUSER is returned when either: - // - the user name supplied was not in the sasl db or - // - the sasl db could not be read - // - because of file permissions or - // - because the file was not found - QPID_LOG(info, "SASL: Authentication failed. User not found or sasldb not accessible.(" << code << ") for " << uid); - } else { - QPID_LOG(info, "SASL: Authentication failed for " << uid << ":" << errordetail); - } - - // TODO: Change to more specific exceptions, when they are - // available - switch (code) { - case SASL_NOMECH: - throw ConnectionForcedException("Unsupported mechanism"); - break; - case SASL_TRYAGAIN: - throw ConnectionForcedException("Transient failure, try again"); - break; - default: - throw ConnectionForcedException("Authentication failed"); - break; - } - } -} - -std::auto_ptr CyrusAuthenticator::getSecurityLayer(uint16_t maxFrameSize) -{ - - const void* value(0); - int result = sasl_getprop(sasl_conn, SASL_SSF, &value); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(sasl_conn))); - } - uint ssf = *(reinterpret_cast(value)); - std::auto_ptr securityLayer; - if (ssf) { - securityLayer = std::auto_ptr(new CyrusSecurityLayer(sasl_conn, maxFrameSize, ssf)); - } - qmf::org::apache::qpid::broker::Connection::shared_ptr cnxMgmt = connection.getMgmtObject(); - if ( cnxMgmt ) - cnxMgmt->set_saslSsf(ssf); - return securityLayer; -} - -#endif - -}} diff --git a/qpid/cpp/src/qpid/broker/SaslAuthenticator.h b/qpid/cpp/src/qpid/broker/SaslAuthenticator.h deleted file mode 100644 index 97434d6ffe..0000000000 --- a/qpid/cpp/src/qpid/broker/SaslAuthenticator.h +++ /dev/null @@ -1,66 +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. - * - */ -#ifndef _SaslAuthenticator_ -#define _SaslAuthenticator_ - - -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/Exception.h" -#include "qpid/sys/SecurityLayer.h" -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -namespace amqp_0_10 { -class Connection; -} - -class SaslAuthenticator -{ -public: - virtual ~SaslAuthenticator() {} - virtual void getMechanisms(framing::Array& mechanisms) = 0; - virtual void start(const std::string& mechanism, const std::string* response) = 0; - virtual void step(const std::string& response) = 0; - virtual void getUid(std::string&) {} - virtual bool getUsername(std::string&) { return false; }; - virtual void getError(std::string&) {} - virtual std::auto_ptr getSecurityLayer(uint16_t maxFrameSize) = 0; - - static bool available(void); - - // Initialize the SASL mechanism; throw if it fails. - static void init(const std::string& saslName, std::string const & saslConfigPath ); - static void fini(void); - - static std::auto_ptr createAuthenticator(amqp_0_10::Connection& connection); - - virtual void callUserIdCallbacks() { } -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/SecureConnection.cpp b/qpid/cpp/src/qpid/broker/SecureConnection.cpp deleted file mode 100644 index 59ac9ef132..0000000000 --- a/qpid/cpp/src/qpid/broker/SecureConnection.cpp +++ /dev/null @@ -1,90 +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/broker/SecureConnection.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/framing/reply_exceptions.h" - -namespace qpid { -namespace broker { - -using qpid::sys::SecurityLayer; - -SecureConnection::SecureConnection() : secured(false) {} - -size_t SecureConnection::decode(const char* buffer, size_t size) -{ - if (!secured && securityLayer.get()) { - //security layer comes into effect on first read after its - //activated - secured = true; - } - if (secured) { - return securityLayer->decode(buffer, size); - } else { - return codec->decode(buffer, size); - } -} - -size_t SecureConnection::encode(char* buffer, size_t size) -{ - if (secured) { - return securityLayer->encode(buffer, size); - } else { - return codec->encode(buffer, size); - } -} - -bool SecureConnection::canEncode() -{ - if (secured) return securityLayer->canEncode(); - else return codec->canEncode(); -} - -void SecureConnection::closed() -{ - codec->closed(); -} - -bool SecureConnection::isClosed() const -{ - return codec->isClosed(); -} - -framing::ProtocolVersion SecureConnection::getVersion() const -{ - return codec->getVersion(); -} - -void SecureConnection:: setCodec(std::auto_ptr c) -{ - codec = c; -} - -void SecureConnection::activateSecurityLayer(std::auto_ptr sl, bool secureImmediately) -{ - securityLayer = sl; - securityLayer->init(codec.get()); - - if ( secureImmediately ) - secured = true; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/SecureConnection.h b/qpid/cpp/src/qpid/broker/SecureConnection.h deleted file mode 100644 index 632087350e..0000000000 --- a/qpid/cpp/src/qpid/broker/SecureConnection.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_BROKER_SECURECONNECTION_H -#define QPID_BROKER_SECURECONNECTION_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/ConnectionCodec.h" -#include - -namespace qpid { - -namespace sys { -class SecurityLayer; -} - -namespace broker { - -/** - * A ConnectionCodec 'wrapper' that allows a connection to be - * 'secured' e.g. encrypted based on settings negotiatiated at the - * time of establishment. - */ -class SecureConnection : public qpid::sys::ConnectionCodec -{ - public: - SecureConnection(); - size_t decode(const char* buffer, size_t size); - size_t encode(char* buffer, size_t size); - bool canEncode(); - void closed(); - bool isClosed() const; - framing::ProtocolVersion getVersion() const; - void setCodec(std::auto_ptr); - void activateSecurityLayer(std::auto_ptr, bool secureImmediately=false); - private: - std::auto_ptr codec; - std::auto_ptr securityLayer; - bool secured; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SECURECONNECTION_H*/ diff --git a/qpid/cpp/src/qpid/broker/Selector.cpp b/qpid/cpp/src/qpid/broker/Selector.cpp deleted file mode 100644 index bf30df59e4..0000000000 --- a/qpid/cpp/src/qpid/broker/Selector.cpp +++ /dev/null @@ -1,280 +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/broker/Selector.h" - -#include "qpid/amqp/CharSequence.h" -#include "qpid/amqp/MapHandler.h" -#include "qpid/amqp/MessageId.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/SelectorExpression.h" -#include "qpid/broker/SelectorValue.h" -#include "qpid/log/Statement.h" -#include "qpid/types/Variant.h" - -#include -#include -#include -#include -#include "qpid/sys/unordered_map.h" - -#include -#include - -namespace qpid { -namespace broker { - -using std::string; -using qpid::sys::unordered_map; -using qpid::amqp::CharSequence; -using qpid::amqp::MapHandler; -using qpid::amqp::MessageId; - -/** - * Identifier (amqp.) | JMS... | amqp 1.0 equivalent - * durable | | durable header section - * delivery_mode | DeliveryMode | [durable ? 'PERSISTENT' : 'NON_PERSISTENT'] (computed value) - * priority | Priority | priority header section - * delivery_count | | delivery-count header section - * redelivered |[Redelivered] | (delivery_count>0) (computed value) - * subject | Type | subject properties section - * correlation_id | CorrelationID| correlation-id properties section - * to |[Destination] | to properties section - * absolute_expiry_time |[Expiration] | absolute-expiry-time properties section - * message_id | MessageID | message-id properties section - * reply_to |[ReplyTo] | reply-to properties section - * creation_time | Timestamp | creation-time properties section - * jms_type | Type | jms-type message-annotations section - */ -const string EMPTY; -const string PERSISTENT("PERSISTENT"); -const string NON_PERSISTENT("NON_PERSISTENT"); - -namespace { - typedef std::map Aliases; - Aliases define_aliases() - { - Aliases aliases; - aliases["JMSType"] = "subject"; - aliases["JMSCorrelationID"] = "correlation_id"; - aliases["JMSMessageID"] = "message_id"; - aliases["JMSDeliveryMode"] = "delivery_mode"; - aliases["JMSRedelivered"] = "redelivered"; - aliases["JMSPriority"] = "priority"; - aliases["JMSDestination"] = "to"; - aliases["JMSReplyTo"] = "reply_to"; - aliases["JMSTimestamp"] = "creation_time"; - aliases["JMSExpiration"] = "absolute_expiry_time"; - return aliases; - } - const Aliases aliases = define_aliases(); -} - -class MessageSelectorEnv : public SelectorEnv { - const Message& msg; - mutable boost::ptr_vector returnedStrings; - mutable unordered_map returnedValues; - mutable bool valuesLookedup; - - const Value& value(const string&) const; - const Value specialValue(const string&) const; - -public: - MessageSelectorEnv(const Message&); -}; - -MessageSelectorEnv::MessageSelectorEnv(const Message& m) : - msg(m), - valuesLookedup(false) -{} - -const Value MessageSelectorEnv::specialValue(const string& id) const -{ - Value v; - // TODO: Just use a simple if chain for now - improve this later - if ( id=="delivery_mode" ) { - v = msg.getEncoding().isPersistent() ? PERSISTENT : NON_PERSISTENT; - } else if ( id=="subject" ) { - std::string s = msg.getSubject(); - if (!s.empty()) { - returnedStrings.push_back(new string(s)); - v = returnedStrings[returnedStrings.size()-1]; - } - } else if ( id=="redelivered" ) { - // Although redelivered is defined to be true delivery-count>0 if it is 0 now - // it will be 1 by the time the message is delivered - v = msg.getDeliveryCount()>=0 ? true : false; - } else if ( id=="priority" ) { - v = int64_t(msg.getPriority()); - } else if ( id=="correlation_id" ) { - MessageId cId = msg.getEncoding().getCorrelationId(); - if (cId) { - returnedStrings.push_back(new string(cId.str())); - v = returnedStrings[returnedStrings.size()-1]; - } - } else if ( id=="message_id" ) { - MessageId mId = msg.getEncoding().getMessageId(); - if (mId) { - returnedStrings.push_back(new string(mId.str())); - v = returnedStrings[returnedStrings.size()-1]; - } - } else if ( id=="to" ) { - std::string s = msg.getTo(); - if (!s.empty()) { - returnedStrings.push_back(new string(s)); - v = returnedStrings[returnedStrings.size()-1]; - } - } else if ( id=="reply_to" ) { - std::string s = msg.getReplyTo(); - if (!s.empty()) { - returnedStrings.push_back(new string(s)); - v = returnedStrings[returnedStrings.size()-1]; - } - } else if ( id=="absolute_expiry_time" ) { - qpid::sys::AbsTime expiry = msg.getExpiration(); - // Java property has value of 0 for no expiry - v = (expiry==qpid::sys::FAR_FUTURE) ? 0 - : qpid::sys::Duration(qpid::sys::AbsTime::epoch(), expiry) / qpid::sys::TIME_MSEC; - } else if ( id=="creation_time" ) { - // Use the time put on queue (if it is enabled) as 0-10 has no standard way to get message - // creation time and we're not paying attention to the 1.0 creation time yet. - v = int64_t(msg.getTimestamp() * 1000); // getTimestamp() returns time in seconds we need milliseconds - } else if ( id=="jms_type" ) { - // Currently we can't distinguish between an empty JMSType and no JMSType - // We'll assume for now that setting an empty JMSType doesn't make a lot of sense - const string jmsType = msg.getAnnotation("jms-type").asString(); - if ( !jmsType.empty() ) { - returnedStrings.push_back(new string(jmsType)); - v = returnedStrings[returnedStrings.size()-1]; - } - } else { - v = Value(); - } - return v; -} - -struct ValueHandler : public broker::MapHandler { - unordered_map& values; - boost::ptr_vector& strings; - - ValueHandler(unordered_map& v, boost::ptr_vector& s) : - values(v), - strings(s) - {} - - template - void handle(const CharSequence& key, const T& value) - { - values[string(key.data, key.size)] = value; - } - - void handleVoid(const CharSequence&) {} - void handleBool(const CharSequence& key, bool value) { handle(key, value); } - void handleUint8(const CharSequence& key, uint8_t value) { handle(key, value); } - void handleUint16(const CharSequence& key, uint16_t value) { handle(key, value); } - void handleUint32(const CharSequence& key, uint32_t value) { handle(key, value); } - void handleUint64(const CharSequence& key, uint64_t value) { - if ( value>uint64_t(std::numeric_limits::max()) ) { - handle(key, value); - } else { - handle(key, value); - } - } - void handleInt8(const CharSequence& key, int8_t value) { handle(key, value); } - void handleInt16(const CharSequence& key, int16_t value) { handle(key, value); } - void handleInt32(const CharSequence& key, int32_t value) { handle(key, value); } - void handleInt64(const CharSequence& key, int64_t value) { handle(key, value); } - void handleFloat(const CharSequence& key, float value) { handle(key, value); } - void handleDouble(const CharSequence& key, double value) { handle(key, value); } - void handleString(const CharSequence& key, const CharSequence& value, const CharSequence&) { - strings.push_back(new string(value.data, value.size)); - handle(key, strings[strings.size()-1]); - } -}; - -const Value& MessageSelectorEnv::value(const string& identifier) const -{ - // Check for amqp prefix and strip it if present - if ( identifier.substr(0, 5) == "amqp." ) { - if ( returnedValues.count(identifier)==0 ) { - QPID_LOG(debug, "Selector lookup special identifier: " << identifier); - returnedValues[identifier] = specialValue(identifier.substr(5)); - } - } else if (identifier.substr(0, 3) == "JMS") { - Aliases::const_iterator equivalent = aliases.find(identifier); - if (equivalent != aliases.end()) { - QPID_LOG(debug, "Selector lookup JMS identifier: " << identifier << " treated as alias for " << equivalent->second); - returnedValues[identifier] = specialValue(equivalent->second); - } else { - QPID_LOG(info, "Unrecognised JMS identifier in selector: " << identifier); - } - } else if (!valuesLookedup) { - QPID_LOG(debug, "Selector lookup triggered by: " << identifier); - // Iterate over all the message properties - ValueHandler handler(returnedValues, returnedStrings); - msg.getEncoding().processProperties(handler); - valuesLookedup = true; - // Anything that wasn't found will have a void value now - } - const Value& v = returnedValues[identifier]; - QPID_LOG(debug, "Selector identifier: " << identifier << "->" << v); - return v; -} - -Selector::Selector(const string& e) -try : - parse(TopExpression::parse(e)), - expression(e) -{ - bool debugOut; - QPID_LOG_TEST(debug, debugOut); - if (debugOut) { - std::stringstream ss; - parse->repr(ss); - QPID_LOG(debug, "Selector parsed[" << e << "] into: " << ss.str()); - } -} -catch (std::range_error& ex) { - QPID_LOG(debug, "Selector failed[" << e << "] -> " << ex.what()); - throw; -} - -Selector::~Selector() -{ -} - -bool Selector::eval(const SelectorEnv& env) -{ - return parse->eval(env); -} - -bool Selector::filter(const Message& msg) -{ - const MessageSelectorEnv env(msg); - return eval(env); -} - -boost::shared_ptr returnSelector(const string& e) -{ - return boost::shared_ptr(new Selector(e)); -} - -}} diff --git a/qpid/cpp/src/qpid/broker/Selector.h b/qpid/cpp/src/qpid/broker/Selector.h deleted file mode 100644 index 0e151ecd0e..0000000000 --- a/qpid/cpp/src/qpid/broker/Selector.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef QPID_BROKER_SELECTOR_H -#define QPID_BROKER_SELECTOR_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/BrokerImportExport.h" - -#include - -#include -#include - -namespace qpid { -namespace broker { - -class Message; -class Value; -class TopExpression; - -/** - * Interface to provide values to a Selector evaluation - */ -class SelectorEnv { -public: - virtual ~SelectorEnv() {}; - - virtual const Value& value(const std::string&) const = 0; -}; - -class Selector { - boost::scoped_ptr parse; - const std::string expression; - -public: - QPID_BROKER_EXTERN Selector(const std::string&); - QPID_BROKER_EXTERN ~Selector(); - - /** - * Evaluate parsed expression with a given environment - */ - QPID_BROKER_EXTERN bool eval(const SelectorEnv& env); - - /** - * Apply selector to message - * @param msg message to filter against selector - * @return true if msg meets the selector specification - */ - QPID_BROKER_EXTERN bool filter(const Message& msg); -}; - -/** - * Return a Selector as specified by the string: - * - Structured like this so that we can move to caching Selectors with the same - * specifications and just returning an existing one - */ -boost::shared_ptr returnSelector(const std::string&); - -}} - -#endif - diff --git a/qpid/cpp/src/qpid/broker/SelectorExpression.cpp b/qpid/cpp/src/qpid/broker/SelectorExpression.cpp deleted file mode 100644 index 1f2161471f..0000000000 --- a/qpid/cpp/src/qpid/broker/SelectorExpression.cpp +++ /dev/null @@ -1,1114 +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/broker/SelectorExpression.h" - -#include "qpid/broker/Selector.h" -#include "qpid/broker/SelectorToken.h" -#include "qpid/broker/SelectorValue.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/regex.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * Syntax for JMS style selector expressions (informal): - * This is a mixture of regular expression and EBNF formalism - * - * The top level term is SelectExpression - * - * // Lexical elements - * - * Alpha ::= [a-zA-Z] - * Digit ::= [0-9] - * HexDigit ::= [0-9a-fA-F] - * OctDigit ::= [0-7] - * BinDigit ::= [0-1] - * - * IdentifierInitial ::= Alpha | "_" | "$" - * IdentifierPart ::= IdentifierInitial | Digit | "." - * Identifier ::= IdentifierInitial IdentifierPart* - * Constraint : Identifier NOT IN ("NULL", "TRUE", "FALSE", "NOT", "AND", "OR", "BETWEEN", "LIKE", "IN", "IS") // Case insensitive - * - * LiteralString ::= ("'" [^']* "'")+ // Repeats to cope with embedded single quote - * - * // LiteralExactNumeric is a little simplified as it also allows underscores ("_") as internal seperators and suffix "l" or "L" - * LiteralExactNumeric ::= "0x" HexDigit+ | "0X" HexDigit+ | "0b" BinDigit+ | "0B" BinDigit+ | "0" OctDigit* | Digit+ - * - * // LiteralApproxNumeric is a little simplified as it also allows suffix "d", "D", "f", "F" - * Exponent ::= ('+'|'-')? LiteralExactNumeric - * LiteralApproxNumeric ::= ( Digit "." Digit* ( "E" Exponent )? ) | - * ( "." Digit+ ( "E" Exponent )? ) | - * ( Digit+ "E" Exponent ) - * LiteralBool ::= "TRUE" | "FALSE" - * - * Literal ::= LiteralBool | LiteralString | LiteralApproxNumeric | LiteralExactNumeric - * - * EqOps ::= "=" | "<>" - * ComparisonOps ::= EqOps | ">" | ">=" | "<" | "<=" - * AddOps ::= "+" | "-" - * MultiplyOps ::= "*" | "/" - * - * // Expression Syntax - * - * SelectExpression ::= OrExpression? // An empty expression is equivalent to "true" - * - * OrExpression ::= AndExpression ( "OR" AndExpression )* - * - * AndExpression :: = ComparisonExpression ( "AND" ComparisonExpression )* - * - * ComparisonExpression ::= AddExpression "IS" "NOT"? "NULL" | - * AddExpression "NOT"? "LIKE" LiteralString [ "ESCAPE" LiteralString ] | - * AddExpression "NOT"? "BETWEEN" AddExpression "AND" AddExpression | - * AddExpression "NOT"? "IN" "(" PrimaryExpression ("," PrimaryExpression)* ")" | - * AddExpression ComparisonOps AddExpression | - * "NOT" ComparisonExpression | - * AddExpression - * - * AddExpression :: = MultiplyExpression ( AddOps MultiplyExpression )* - * - * MultiplyExpression :: = UnaryArithExpression ( MultiplyOps UnaryArithExpression )* - * - * UnaryArithExpression ::= "-" LiteralExactNumeric | // This is a special case to simplify negative ints - * AddOps AddExpression | - * "(" OrExpression ")" | - * PrimaryExpression - * - * PrimaryExpression :: = Identifier | - * Literal - */ - - -using std::string; -using std::ostream; - -namespace qpid { -namespace broker { - -class Expression { -public: - virtual ~Expression() {} - virtual void repr(std::ostream&) const = 0; - virtual Value eval(const SelectorEnv&) const = 0; - - virtual BoolOrNone eval_bool(const SelectorEnv& env) const { - Value v = eval(env); - if (v.type==Value::T_BOOL) return BoolOrNone(v.b); - else return BN_UNKNOWN; - } -}; - -class BoolExpression : public Expression { -public: - virtual ~BoolExpression() {} - virtual void repr(std::ostream&) const = 0; - virtual BoolOrNone eval_bool(const SelectorEnv&) const = 0; - - Value eval(const SelectorEnv& env) const { - return eval_bool(env); - } -}; - -// Operators - -class ComparisonOperator { -public: - virtual ~ComparisonOperator() {} - virtual void repr(ostream&) const = 0; - virtual BoolOrNone eval(Expression&, Expression&, const SelectorEnv&) const = 0; -}; - -class UnaryBooleanOperator { -public: - virtual ~UnaryBooleanOperator() {} - virtual void repr(ostream&) const = 0; - virtual BoolOrNone eval(Expression&, const SelectorEnv&) const = 0; -}; - -class ArithmeticOperator { -public: - virtual ~ArithmeticOperator() {} - virtual void repr(ostream&) const = 0; - virtual Value eval(Expression&, Expression&, const SelectorEnv&) const = 0; -}; - -class UnaryArithmeticOperator { -public: - virtual ~UnaryArithmeticOperator() {} - virtual void repr(ostream&) const = 0; - virtual Value eval(Expression&, const SelectorEnv&) const = 0; -}; - -//////////////////////////////////////////////////// - -// Convenience outputters - -ostream& operator<<(ostream& os, const Expression& e) -{ - e.repr(os); - return os; -} - -ostream& operator<<(ostream& os, const ComparisonOperator& e) -{ - e.repr(os); - return os; -} - -ostream& operator<<(ostream& os, const UnaryBooleanOperator& e) -{ - e.repr(os); - return os; -} - -ostream& operator<<(ostream& os, const ArithmeticOperator& e) -{ - e.repr(os); - return os; -} - -ostream& operator<<(ostream& os, const UnaryArithmeticOperator& e) -{ - e.repr(os); - return os; -} - -// Boolean Expression types... - -class ComparisonExpression : public BoolExpression { - ComparisonOperator* op; - boost::scoped_ptr e1; - boost::scoped_ptr e2; - -public: - ComparisonExpression(ComparisonOperator* o, Expression* e, Expression* e_): - op(o), - e1(e), - e2(e_) - {} - - void repr(ostream& os) const { - os << "(" << *e1 << *op << *e2 << ")"; - } - - BoolOrNone eval_bool(const SelectorEnv& env) const { - return op->eval(*e1, *e2, env); - } -}; - -class OrExpression : public BoolExpression { - boost::scoped_ptr e1; - boost::scoped_ptr e2; - -public: - OrExpression(Expression* e, Expression* e_): - e1(e), - e2(e_) - {} - - void repr(ostream& os) const { - os << "(" << *e1 << " OR " << *e2 << ")"; - } - - BoolOrNone eval_bool(const SelectorEnv& env) const { - BoolOrNone bn1(e1->eval_bool(env)); - if (bn1==BN_TRUE) return BN_TRUE; - BoolOrNone bn2(e2->eval_bool(env)); - if (bn2==BN_TRUE) return BN_TRUE; - if (bn1==BN_FALSE && bn2==BN_FALSE) return BN_FALSE; - else return BN_UNKNOWN; - } -}; - -class AndExpression : public BoolExpression { - boost::scoped_ptr e1; - boost::scoped_ptr e2; - -public: - AndExpression(Expression* e, Expression* e_): - e1(e), - e2(e_) - {} - - void repr(ostream& os) const { - os << "(" << *e1 << " AND " << *e2 << ")"; - } - - BoolOrNone eval_bool(const SelectorEnv& env) const { - BoolOrNone bn1(e1->eval_bool(env)); - if (bn1==BN_FALSE) return BN_FALSE; - BoolOrNone bn2(e2->eval_bool(env)); - if (bn2==BN_FALSE) return BN_FALSE; - if (bn1==BN_TRUE && bn2==BN_TRUE) return BN_TRUE; - else return BN_UNKNOWN; - } -}; - -class UnaryBooleanExpression : public BoolExpression { - UnaryBooleanOperator* op; - boost::scoped_ptr e1; - -public: - UnaryBooleanExpression(UnaryBooleanOperator* o, Expression* e) : - op(o), - e1(e) - {} - - void repr(ostream& os) const { - os << *op << "(" << *e1 << ")"; - } - - BoolOrNone eval_bool(const SelectorEnv& env) const { - return op->eval(*e1, env); - } -}; - -class LikeExpression : public BoolExpression { - boost::scoped_ptr e; - string reString; - qpid::sys::regex regexBuffer; - - static string toRegex(const string& s, const string& escape) { - string regex("^"); - if (escape.size()>1) throw std::logic_error("Internal error"); - char e = 0; - if (escape.size()==1) { - e = escape[0]; - } - // Translate % -> .*, _ -> ., . ->\. *->\* - bool doEscape = false; - for (string::const_iterator i = s.begin(); i!=s.end(); ++i) { - if ( e!=0 && *i==e ) { - doEscape = true; - continue; - } - switch(*i) { - case '%': - if (doEscape) regex += *i; - else regex += ".*"; - break; - case '_': - if (doEscape) regex += *i; - else regex += "."; - break; - case ']': - regex += "[]]"; - break; - case '-': - regex += "[-]"; - break; - // Don't add any more cases here: these are sufficient, - // adding more might turn on inadvertent matching - case '\\': - case '^': - case '$': - case '.': - case '*': - case '[': - regex += "\\"; - // Fallthrough - default: - regex += *i; - break; - } - doEscape = false; - } - regex += "$"; - return regex; - } - -public: - LikeExpression(Expression* e_, const string& like, const string& escape="") : - e(e_), - reString(toRegex(like, escape)), - regexBuffer(reString) - {} - - void repr(ostream& os) const { - os << *e << " REGEX_MATCH '" << reString << "'"; - } - - BoolOrNone eval_bool(const SelectorEnv& env) const { - Value v(e->eval(env)); - if ( v.type!=Value::T_STRING ) return BN_UNKNOWN; - return BoolOrNone(qpid::sys::regex_match(*v.s, regexBuffer)); - } -}; - -class BetweenExpression : public BoolExpression { - boost::scoped_ptr e; - boost::scoped_ptr l; - boost::scoped_ptr u; - -public: - BetweenExpression(Expression* e_, Expression* l_, Expression* u_) : - e(e_), - l(l_), - u(u_) - {} - - void repr(ostream& os) const { - os << *e << " BETWEEN " << *l << " AND " << *u; - } - - BoolOrNone eval_bool(const SelectorEnv& env) const { - Value ve(e->eval(env)); - Value vl(l->eval(env)); - Value vu(u->eval(env)); - if (unknown(ve) || unknown(vl) || unknown(vu)) return BN_UNKNOWN; - return BoolOrNone(ve>=vl && ve<=vu); - } -}; - -class InExpression : public BoolExpression { - boost::scoped_ptr e; - boost::ptr_vector l; - -public: - InExpression(Expression* e_, boost::ptr_vector& l_) : - e(e_) - { - l.swap(l_); - } - - void repr(ostream& os) const { - os << *e << " IN ("; - for (std::size_t i = 0; ieval(env)); - if (unknown(ve)) return BN_UNKNOWN; - BoolOrNone r = BN_FALSE; - for (std::size_t i = 0; i e; - boost::ptr_vector l; - -public: - NotInExpression(Expression* e_, boost::ptr_vector& l_) : - e(e_) - { - l.swap(l_); - } - - void repr(ostream& os) const { - os << *e << " NOT IN ("; - for (std::size_t i = 0; ieval(env)); - if (unknown(ve)) return BN_UNKNOWN; - BoolOrNone r = BN_TRUE; - for (std::size_t i = 0; i e1; - boost::scoped_ptr e2; - -public: - ArithmeticExpression(ArithmeticOperator* o, Expression* e, Expression* e_): - op(o), - e1(e), - e2(e_) - {} - - void repr(ostream& os) const { - os << "(" << *e1 << *op << *e2 << ")"; - } - - Value eval(const SelectorEnv& env) const { - return op->eval(*e1, *e2, env); - } -}; - -class UnaryArithExpression : public Expression { - UnaryArithmeticOperator* op; - boost::scoped_ptr e1; - -public: - UnaryArithExpression(UnaryArithmeticOperator* o, Expression* e) : - op(o), - e1(e) - {} - - void repr(ostream& os) const { - os << *op << "(" << *e1 << ")"; - } - - Value eval(const SelectorEnv& env) const { - return op->eval(*e1, env); - } -}; - -// Expression types... - -class Literal : public Expression { - const Value value; - -public: - template - Literal(const T& v) : - value(v) - {} - - void repr(ostream& os) const { - os << value; - } - - Value eval(const SelectorEnv&) const { - return value; - } -}; - -class StringLiteral : public Expression { - const string value; - -public: - StringLiteral(const string& v) : - value(v) - {} - - void repr(ostream& os) const { - os << "'" << value << "'"; - } - - Value eval(const SelectorEnv&) const { - return value; - } -}; - -class Identifier : public Expression { - string identifier; - -public: - Identifier(const string& i) : - identifier(i) - {} - - void repr(ostream& os) const { - os << "I:" << identifier; - } - - Value eval(const SelectorEnv& env) const { - return env.value(identifier); - } -}; - -//////////////////////////////////////////////////// - -// Some operators... - -typedef bool BoolOp(const Value&, const Value&); - -BoolOrNone booleval(BoolOp* op, Expression& e1, Expression& e2, const SelectorEnv& env) { - const Value v1(e1.eval(env)); - if (!unknown(v1)) { - const Value v2(e2.eval(env)); - if (!unknown(v2)) { - return BoolOrNone(op(v1, v2)); - } - } - return BN_UNKNOWN; -} - -// "=" -class Eq : public ComparisonOperator { - void repr(ostream& os) const { - os << "="; - } - - BoolOrNone eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return booleval(&operator==, e1, e2, env); - } -}; - -// "<>" -class Neq : public ComparisonOperator { - void repr(ostream& os) const { - os << "<>"; - } - - BoolOrNone eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return booleval(&operator!=, e1, e2, env); - } -}; - -// "<" -class Ls : public ComparisonOperator { - void repr(ostream& os) const { - os << "<"; - } - - BoolOrNone eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return booleval(&operator<, e1, e2, env); - } -}; - -// ">" -class Gr : public ComparisonOperator { - void repr(ostream& os) const { - os << ">"; - } - - BoolOrNone eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return booleval(&operator>, e1, e2, env); - } -}; - -// "<=" -class Lseq : public ComparisonOperator { - void repr(ostream& os) const { - os << "<="; - } - - BoolOrNone eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return booleval(&operator<=, e1, e2, env); - } -}; - -// ">=" -class Greq : public ComparisonOperator { - void repr(ostream& os) const { - os << ">="; - } - - BoolOrNone eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return booleval(&operator>=, e1, e2, env); - } -}; - -// "IS NULL" -class IsNull : public UnaryBooleanOperator { - void repr(ostream& os) const { - os << "IsNull"; - } - - BoolOrNone eval(Expression& e, const SelectorEnv& env) const { - return BoolOrNone(unknown(e.eval(env))); - } -}; - -// "IS NOT NULL" -class IsNonNull : public UnaryBooleanOperator { - void repr(ostream& os) const { - os << "IsNonNull"; - } - - BoolOrNone eval(Expression& e, const SelectorEnv& env) const { - return BoolOrNone(!unknown(e.eval(env))); - } -}; - -// "NOT" -class Not : public UnaryBooleanOperator { - void repr(ostream& os) const { - os << "NOT"; - } - - BoolOrNone eval(Expression& e, const SelectorEnv& env) const { - BoolOrNone bn = e.eval_bool(env); - if (bn==BN_UNKNOWN) return bn; - else return BoolOrNone(!bn); - } -}; - -class Negate : public UnaryArithmeticOperator { - void repr(ostream& os) const { - os << "-"; - } - - Value eval(Expression& e, const SelectorEnv& env) const { - return -e.eval(env); - } -}; - -class Add : public ArithmeticOperator { - void repr(ostream& os) const { - os << "+"; - } - - Value eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return e1.eval(env)+e2.eval(env); - } -}; - -class Sub : public ArithmeticOperator { - void repr(ostream& os) const { - os << "-"; - } - - Value eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return e1.eval(env)-e2.eval(env); - } -}; - -class Mult : public ArithmeticOperator { - void repr(ostream& os) const { - os << "*"; - } - - Value eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return e1.eval(env)*e2.eval(env); - } -}; - -class Div : public ArithmeticOperator { - void repr(ostream& os) const { - os << "/"; - } - - Value eval(Expression& e1, Expression& e2, const SelectorEnv& env) const { - return e1.eval(env)/e2.eval(env); - } -}; - -Eq eqOp; -Neq neqOp; -Ls lsOp; -Gr grOp; -Lseq lseqOp; -Greq greqOp; -IsNull isNullOp; -IsNonNull isNonNullOp; -Not notOp; - -Negate negate; -Add add; -Sub sub; -Mult mult; -Div div; - -//////////////////////////////////////////////////// - -// Top level parser -class TopBoolExpression : public TopExpression { - boost::scoped_ptr expression; - - void repr(ostream& os) const { - expression->repr(os); - } - - bool eval(const SelectorEnv& env) const { - BoolOrNone bn = expression->eval_bool(env); - if (bn==BN_TRUE) return true; - else return false; - } - -public: - TopBoolExpression(Expression* be) : - expression(be) - {} -}; - -void throwParseError(Tokeniser& tokeniser, const string& msg) { - tokeniser.returnTokens(); - string error("Illegal selector: '"); - error += tokeniser.nextToken().val; - error += "': "; - error += msg; - throw std::range_error(error); -} - -class Parse { - -friend TopExpression* TopExpression::parse(const string&); - -string error; - -Expression* selectorExpression(Tokeniser& tokeniser) -{ - if ( tokeniser.nextToken().type==T_EOS ) { - return (new Literal(true)); - } - tokeniser.returnTokens(); - std::auto_ptr e(orExpression(tokeniser)); - return e.release(); -} - -Expression* orExpression(Tokeniser& tokeniser) -{ - std::auto_ptr e(andExpression(tokeniser)); - if (!e.get()) return 0; - while ( tokeniser.nextToken().type==T_OR ) { - std::auto_ptr e1(e); - std::auto_ptr e2(andExpression(tokeniser)); - if (!e2.get()) return 0; - e.reset(new OrExpression(e1.release(), e2.release())); - } - tokeniser.returnTokens(); - return e.release(); -} - -Expression* andExpression(Tokeniser& tokeniser) -{ - std::auto_ptr e(comparisonExpression(tokeniser)); - if (!e.get()) return 0; - while ( tokeniser.nextToken().type==T_AND ) { - std::auto_ptr e1(e); - std::auto_ptr e2(comparisonExpression(tokeniser)); - if (!e2.get()) return 0; - e.reset(new AndExpression(e1.release(), e2.release())); - } - tokeniser.returnTokens(); - return e.release(); -} - -BoolExpression* specialComparisons(Tokeniser& tokeniser, std::auto_ptr e1, bool negated = false) { - switch (tokeniser.nextToken().type) { - case T_LIKE: { - const Token t = tokeniser.nextToken(); - if ( t.type!=T_STRING ) { - error = "expected string after LIKE"; - return 0; - } - // Check for "ESCAPE" - std::auto_ptr l; - if ( tokeniser.nextToken().type==T_ESCAPE ) { - const Token e = tokeniser.nextToken(); - if ( e.type!=T_STRING ) { - error = "expected string after ESCAPE"; - return 0; - } - if (e.val.size()>1) { - throwParseError(tokeniser, "single character string required after ESCAPE"); - } - if (e.val=="%" || e.val=="_") { - throwParseError(tokeniser, "'%' and '_' are not allowed as ESCAPE characters"); - } - l.reset(new LikeExpression(e1.release(), t.val, e.val)); - } else { - tokeniser.returnTokens(); - l.reset(new LikeExpression(e1.release(), t.val)); - } - return negated ? new UnaryBooleanExpression(¬Op, l.release()) : l.release(); - } - case T_BETWEEN: { - std::auto_ptr lower(addExpression(tokeniser)); - if ( !lower.get() ) return 0; - if ( tokeniser.nextToken().type!=T_AND ) { - error = "expected AND after BETWEEN"; - return 0; - } - std::auto_ptr upper(addExpression(tokeniser)); - if ( !upper.get() ) return 0; - std::auto_ptr b(new BetweenExpression(e1.release(), lower.release(), upper.release())); - return negated ? new UnaryBooleanExpression(¬Op, b.release()) : b.release(); - } - case T_IN: { - if ( tokeniser.nextToken().type!=T_LPAREN ) { - error = "missing '(' after IN"; - return 0; - } - boost::ptr_vector list; - do { - std::auto_ptr e(addExpression(tokeniser)); - if (!e.get()) return 0; - list.push_back(e.release()); - } while (tokeniser.nextToken().type==T_COMMA); - tokeniser.returnTokens(); - if ( tokeniser.nextToken().type!=T_RPAREN ) { - error = "missing ',' or ')' after IN"; - return 0; - } - if (negated) return new NotInExpression(e1.release(), list); - else return new InExpression(e1.release(), list); - } - default: - error = "expected LIKE, IN or BETWEEN"; - return 0; - } -} - -Expression* comparisonExpression(Tokeniser& tokeniser) -{ - const Token t = tokeniser.nextToken(); - if ( t.type==T_NOT ) { - std::auto_ptr e(comparisonExpression(tokeniser)); - if (!e.get()) return 0; - return new UnaryBooleanExpression(¬Op, e.release()); - } - - tokeniser.returnTokens(); - std::auto_ptr e1(addExpression(tokeniser)); - if (!e1.get()) return 0; - - switch (tokeniser.nextToken().type) { - // Check for "IS NULL" and "IS NOT NULL" - case T_IS: - // The rest must be T_NULL or T_NOT, T_NULL - switch (tokeniser.nextToken().type) { - case T_NULL: - return new UnaryBooleanExpression(&isNullOp, e1.release()); - case T_NOT: - if ( tokeniser.nextToken().type == T_NULL) - return new UnaryBooleanExpression(&isNonNullOp, e1.release()); - default: - error = "expected NULL or NOT NULL after IS"; - return 0; - } - case T_NOT: { - return specialComparisons(tokeniser, e1, true); - } - case T_BETWEEN: - case T_LIKE: - case T_IN: { - tokeniser.returnTokens(); - return specialComparisons(tokeniser, e1); - } - default: - break; - } - tokeniser.returnTokens(); - - ComparisonOperator* op; - switch (tokeniser.nextToken().type) { - case T_EQUAL: op = &eqOp; break; - case T_NEQ: op = &neqOp; break; - case T_LESS: op = &lsOp; break; - case T_GRT: op = &grOp; break; - case T_LSEQ: op = &lseqOp; break; - case T_GREQ: op = &greqOp; break; - default: - tokeniser.returnTokens(); - return e1.release(); - } - - std::auto_ptr e2(addExpression(tokeniser)); - if (!e2.get()) return 0; - - return new ComparisonExpression(op, e1.release(), e2.release()); -} - -Expression* addExpression(Tokeniser& tokeniser) -{ - std::auto_ptr e(multiplyExpression(tokeniser)); - if (!e.get()) return 0; - - Token t = tokeniser.nextToken(); - while (t.type==T_PLUS || t.type==T_MINUS ) { - ArithmeticOperator* op; - switch (t.type) { - case T_PLUS: op = &add; break; - case T_MINUS: op = ⊂ break; - default: - error = "internal error processing binary + or -"; - return 0; - } - std::auto_ptr e1(e); - std::auto_ptr e2(multiplyExpression(tokeniser)); - if (!e2.get()) return 0; - e.reset(new ArithmeticExpression(op, e1.release(), e2.release())); - t = tokeniser.nextToken(); - } - - tokeniser.returnTokens(); - return e.release(); -} - -Expression* multiplyExpression(Tokeniser& tokeniser) -{ - std::auto_ptr e(unaryArithExpression(tokeniser)); - if (!e.get()) return 0; - - Token t = tokeniser.nextToken(); - while (t.type==T_MULT || t.type==T_DIV ) { - ArithmeticOperator* op; - switch (t.type) { - case T_MULT: op = &mult; break; - case T_DIV: op = ÷ break; - default: - error = "internal error processing * or /"; - return 0; - } - std::auto_ptr e1(e); - std::auto_ptr e2(unaryArithExpression(tokeniser)); - if (!e2.get()) return 0; - e.reset(new ArithmeticExpression(op, e1.release(), e2.release())); - t = tokeniser.nextToken(); - } - - tokeniser.returnTokens(); - return e.release(); -} - -Expression* unaryArithExpression(Tokeniser& tokeniser) -{ - const Token t = tokeniser.nextToken(); - switch (t.type) { - case T_LPAREN: { - std::auto_ptr e(orExpression(tokeniser)); - if (!e.get()) return 0; - if ( tokeniser.nextToken().type!=T_RPAREN ) { - error = "missing ')' after '('"; - return 0; - } - return e.release(); - } - case T_PLUS: - break; // Unary + is no op - case T_MINUS: { - const Token t = tokeniser.nextToken(); - // Special case for negative numerics - if (t.type==T_NUMERIC_EXACT) { - std::auto_ptr e(parseExactNumeric(t, true)); - return e.release(); - } else { - tokeniser.returnTokens(); - std::auto_ptr e(unaryArithExpression(tokeniser)); - if (!e.get()) return 0; - return new UnaryArithExpression(&negate, e.release()); - } - } - default: - tokeniser.returnTokens(); - break; - } - - std::auto_ptr e(primaryExpression(tokeniser)); - return e.release(); -} - -Expression* parseExactNumeric(const Token& token, bool negate) -{ - int base = 0; - string s; - std::remove_copy(token.val.begin(), token.val.end(), std::back_inserter(s), '_'); - if (s[1]=='b' || s[1]=='B') { - base = 2; - s = s.substr(2); - } else if (s[1]=='x' || s[1]=='X') { - base = 16; - s = s.substr(2); - } if (s[0]=='0') { - base = 8; - } - errno = 0; - uint64_t value = strtoull(s.c_str(), 0, base); - if (!errno && (base || value<=INT64_MAX)) { - int64_t r = value; - return new Literal((negate ? -r : r)); - } - if (negate && value==INT64_MAX+1ull) return new Literal(INT64_MIN); - error = "integer literal too big"; - return 0; -} - -Expression* parseApproxNumeric(const Token& token) -{ - errno = 0; - string s; - std::remove_copy(token.val.begin(), token.val.end(), std::back_inserter(s), '_'); - double value = std::strtod(s.c_str(), 0); - if (!errno) return new Literal(value); - error = "floating literal overflow/underflow"; - return 0; -} - -Expression* primaryExpression(Tokeniser& tokeniser - -) -{ - const Token& t = tokeniser.nextToken(); - switch (t.type) { - case T_IDENTIFIER: - return new Identifier(t.val); - case T_STRING: - return new StringLiteral(t.val); - case T_FALSE: - return new Literal(false); - case T_TRUE: - return new Literal(true); - case T_NUMERIC_EXACT: - return parseExactNumeric(t, false); - case T_NUMERIC_APPROX: - return parseApproxNumeric(t); - default: - error = "expected literal or identifier"; - return 0; - } -} - -}; - -TopExpression* TopExpression::parse(const string& exp) -{ - string::const_iterator s = exp.begin(); - string::const_iterator e = exp.end(); - Tokeniser tokeniser(s,e); - Parse parse; - std::auto_ptr b(parse.selectorExpression(tokeniser)); - if (!b.get()) { - throwParseError(tokeniser, parse.error); - } - if (tokeniser.nextToken().type != T_EOS) { - throwParseError(tokeniser, "extra input"); - } - return new TopBoolExpression(b.release()); -} - -}} diff --git a/qpid/cpp/src/qpid/broker/SelectorExpression.h b/qpid/cpp/src/qpid/broker/SelectorExpression.h deleted file mode 100644 index 158f086287..0000000000 --- a/qpid/cpp/src/qpid/broker/SelectorExpression.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef QPID_BROKER_SELECTOREXPRESSION_H -#define QPID_BROKER_SELECTOREXPRESSION_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 -#include - -namespace qpid { -namespace broker { - -class SelectorEnv; - -class TopExpression { -public: - virtual ~TopExpression() {}; - virtual void repr(std::ostream&) const = 0; - virtual bool eval(const SelectorEnv&) const = 0; - - static TopExpression* parse(const std::string& exp); -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/SelectorToken.cpp b/qpid/cpp/src/qpid/broker/SelectorToken.cpp deleted file mode 100644 index 02d716dad7..0000000000 --- a/qpid/cpp/src/qpid/broker/SelectorToken.cpp +++ /dev/null @@ -1,345 +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/broker/SelectorToken.h" - -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -// Tokenisers always take string const_iterators to mark the beginning and end of the string being tokenised -// if the tokenise is successful then the start iterator is advanced, if the tokenise fails then the start -// iterator is unchanged. - -std::ostream& operator<<(std::ostream& os, const Token& t) -{ - os << "T<" << t.type << ", " << t.val << ">"; - return os; -} - -TokenException::TokenException(const std::string& msg) : - range_error(msg) -{} - -// Lexically, reserved words are a subset of identifiers -// so we parse an identifier first then check if it is a reserved word and -// convert it if it is a reserved word -namespace { - -struct RWEntry { - const char* word; - TokenType type; -}; - -inline bool caseless(const char* s1, const char* s2) -{ - do { - char ls1 = std::tolower(*s1); - char ls2 = std::tolower(*s2); - if (ls1ls2) - return false; - } while ( *s1++ && *s2++ ); - // Equal - return false; -} - -inline bool operator<(const RWEntry& lhs, const RWEntry& rhs) { - return caseless(lhs.word, rhs.word); -} - -} - -bool tokeniseReservedWord(Token& tok) -{ - // This must be sorted!! - static const RWEntry reserved[] = { - {"and", T_AND}, - {"between", T_BETWEEN}, - {"escape", T_ESCAPE}, - {"false", T_FALSE}, - {"in", T_IN}, - {"is", T_IS}, - {"like", T_LIKE}, - {"not", T_NOT}, - {"null", T_NULL}, - {"or", T_OR}, - {"true", T_TRUE} - }; - - const int reserved_size = sizeof(reserved)/sizeof(RWEntry); - - if ( tok.type != T_IDENTIFIER ) return false; - - RWEntry rw; - rw.word = tok.val.c_str(); - std::pair entry = std::equal_range(&reserved[0], &reserved[reserved_size], rw); - - if ( entry.first==entry.second ) return false; - - tok.type = entry.first->type; - return true; -} - -// parsing strings is complicated by the need to allow embedded quotes by doubling the quote character -bool processString(std::string::const_iterator& s, std::string::const_iterator& e, char quoteChar, TokenType type, Token& tok) -{ - // We only get here once the tokeniser recognises the initial quote for a string - // so we don't need to check for it again. - std::string::const_iterator q = std::find(s+1, e, quoteChar); - if ( q==e ) return false; - - std::string content(s+1, q); - ++q; - - while ( q!=e && *q==quoteChar ) { - std::string::const_iterator p = q; - q = std::find(p+1, e, quoteChar); - if ( q==e ) return false; - content += std::string(p, q); - ++q; - } - - tok = Token(type, s, content); - s = q; - return true; -} - -inline bool isIdentifierStart(char c) -{ - return std::isalpha(c) || c=='_' || c=='$'; -} - -inline bool isIdentifierPart(char c) -{ - return std::isalnum(c) || c=='_' || c=='$' || c=='.'; -} - -static const std::string END(""); -bool tokenise(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok) -{ - std::string::const_iterator t = s; - - // Hand constructed state machine recogniser - enum { - START, - REJECT, - IDENTIFIER, - ZERO, - DIGIT, - HEXDIGIT_START, - HEXDIGIT, - OCTDIGIT, - BINDIGIT_START, - BINDIGIT, - DECIMAL_START, - DECIMAL, - EXPONENT_SIGN, - EXPONENT_START, - EXPONENT, - ACCEPT_IDENTIFIER, - ACCEPT_INC, - ACCEPT_NOINC - } state = START; - - TokenType tokType = T_EOS; - while (true) - switch (state) { - case START: - if (t==e) {tok = Token(T_EOS, s, END); return true;} - else if (std::isspace(*t)) {++t; ++s; continue;} - else switch (*t) { - case '(': tokType = T_LPAREN; state = ACCEPT_INC; continue; - case ')': tokType = T_RPAREN; state = ACCEPT_INC; continue; - case ',': tokType = T_COMMA; state = ACCEPT_INC; continue; - case '+': tokType = T_PLUS; state = ACCEPT_INC; continue; - case '-': tokType = T_MINUS; state = ACCEPT_INC; continue; - case '*': tokType = T_MULT; state = ACCEPT_INC; continue; - case '/': tokType = T_DIV; state = ACCEPT_INC; continue; - case '=': tokType = T_EQUAL; state = ACCEPT_INC; continue; - case '<': - ++t; - if (t==e || (*t!='>' && *t!='=')) - {tokType = T_LESS; state = ACCEPT_NOINC; continue; } - else - {tokType = (*t=='>') ? T_NEQ : T_LSEQ; state = ACCEPT_INC; continue; } - case '>': - ++t; - if (t==e || *t!='=') - {tokType = T_GRT; state = ACCEPT_NOINC; continue;} - else - {tokType = T_GREQ; state = ACCEPT_INC; continue;} - default: - break; - } - if (isIdentifierStart(*t)) {++t; state = IDENTIFIER;} - else if (*t=='\'') {return processString(s, e, '\'', T_STRING, tok);} - else if (*t=='\"') {return processString(s, e, '\"', T_IDENTIFIER, tok);} - else if (*t=='0') {++t; state = ZERO;} - else if (std::isdigit(*t)) {++t; state = DIGIT;} - else if (*t=='.') {++t; state = DECIMAL_START;} - else state = REJECT; - continue; - case IDENTIFIER: - if (t==e) {state = ACCEPT_IDENTIFIER;} - else if (isIdentifierPart(*t)) {++t; state = IDENTIFIER;} - else state = ACCEPT_IDENTIFIER; - continue; - case DECIMAL_START: - if (t==e) {state = REJECT;} - else if (std::isdigit(*t)) {++t; state = DECIMAL;} - else state = REJECT; - continue; - case EXPONENT_SIGN: - if (t==e) {state = REJECT;} - else if (*t=='-' || *t=='+') {++t; state = EXPONENT_START;} - else if (std::isdigit(*t)) {++t; state = EXPONENT;} - else state = REJECT; - continue; - case EXPONENT_START: - if (t==e) {state = REJECT;} - else if (std::isdigit(*t)) {++t; state = EXPONENT;} - else state = REJECT; - continue; - case ZERO: - if (t==e) {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - else if (*t=='.') {++t; state = DECIMAL;} - else if (*t=='x' || *t=='X') {++t; state = HEXDIGIT_START;} - else if (*t=='b' || *t=='B') {++t; state = BINDIGIT_START;} - else state = OCTDIGIT; - continue; - case HEXDIGIT_START: - if (t==e) {state = REJECT;} - else if (std::isxdigit(*t)) {++t; state = HEXDIGIT;} - else state = REJECT; - continue; - case HEXDIGIT: - if (t==e) {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - else if (*t=='l' || *t=='L') {tokType = T_NUMERIC_EXACT; state = ACCEPT_INC;} - else if (std::isxdigit(*t) || *t=='_') {++t; state = HEXDIGIT;} - else if (*t=='p' || *t=='P') {++t; state = EXPONENT_SIGN;} - else {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - continue; - case BINDIGIT_START: - if (t==e) {state = REJECT;} - else if (*t=='0' || *t=='1') {++t; state = BINDIGIT;} - else state = REJECT; - continue; - case BINDIGIT: - if (t==e) {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - else if (*t=='l' || *t=='L') {tokType = T_NUMERIC_EXACT; state = ACCEPT_INC;} - else if (*t=='0' || *t=='1' || *t=='_') {++t; state = BINDIGIT;} - else {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - continue; - case OCTDIGIT: - if (t==e) {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - else if (*t=='l' || *t=='L') {tokType = T_NUMERIC_EXACT; state = ACCEPT_INC;} - else if ((std::isdigit(*t) && *t<'8') || *t=='_') {++t; state = OCTDIGIT;} - else {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - continue; - case DIGIT: - if (t==e) {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - else if (*t=='l' || *t=='L') {tokType = T_NUMERIC_EXACT; state = ACCEPT_INC;} - else if (*t=='f' || *t=='F' || *t=='d' || *t=='D') {tokType = T_NUMERIC_APPROX; state = ACCEPT_INC;} - else if (std::isdigit(*t) || *t=='_') {++t; state = DIGIT;} - else if (*t=='.') {++t; state = DECIMAL;} - else if (*t=='e' || *t=='E') {++t; state = EXPONENT_SIGN;} - else {tokType = T_NUMERIC_EXACT; state = ACCEPT_NOINC;} - continue; - case DECIMAL: - if (t==e) {tokType = T_NUMERIC_APPROX; state = ACCEPT_NOINC;} - else if (std::isdigit(*t) || *t=='_') {++t; state = DECIMAL;} - else if (*t=='e' || *t=='E') {++t; state = EXPONENT_SIGN;} - else if (*t=='f' || *t=='F' || *t=='d' || *t=='D') {tokType = T_NUMERIC_APPROX; state = ACCEPT_INC;} - else {tokType = T_NUMERIC_APPROX; state = ACCEPT_NOINC;} - continue; - case EXPONENT: - if (t==e) {tokType = T_NUMERIC_APPROX; state = ACCEPT_NOINC;} - else if (std::isdigit(*t)) {++t; state = EXPONENT;} - else if (*t=='f' || *t=='F' || *t=='d' || *t=='D') {tokType = T_NUMERIC_APPROX; state = ACCEPT_INC;} - else {tokType = T_NUMERIC_APPROX; state = ACCEPT_NOINC;} - continue; - case ACCEPT_INC: - ++t; - case ACCEPT_NOINC: - tok = Token(tokType, s, t); - s = t; - return true; - case ACCEPT_IDENTIFIER: - tok = Token(T_IDENTIFIER, s, t); - s = t; - tokeniseReservedWord(tok); - return true; - case REJECT: - return false; - }; -} - -Tokeniser::Tokeniser(const std::string::const_iterator& s, const std::string::const_iterator& e) : - tokp(0), - inStart(s), - inp(s), - inEnd(e) -{ -} - -/** - * Skip any whitespace then look for a token, throwing an exception if no valid token - * is found. - * - * Advance the string iterator past the parsed token on success. On failure the string iterator is - * in an undefined location. - */ -const Token& Tokeniser::nextToken() -{ - if ( tokens.size()>tokp ) return tokens[tokp++]; - - // Don't extend stream of tokens further than the end of stream; - if ( tokp>0 && tokens[tokp-1].type==T_EOS ) return tokens[tokp-1]; - - tokens.push_back(Token()); - Token& tok = tokens[tokp++]; - - if (tokenise(inp, inEnd, tok)) return tok; - - throw TokenException("Found illegal character"); -} - -void Tokeniser::returnTokens(unsigned int n) -{ - assert( n<=tokp ); - tokp-=n; -} - -std::string Tokeniser::remaining() -{ - Token& currentTok = tokens[tokp]; - return std::string(currentTok.tokenStart, inEnd); -} - - -}} diff --git a/qpid/cpp/src/qpid/broker/SelectorToken.h b/qpid/cpp/src/qpid/broker/SelectorToken.h deleted file mode 100644 index bd60b69dce..0000000000 --- a/qpid/cpp/src/qpid/broker/SelectorToken.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef QPID_BROKER_SELECTORTOKEN_H -#define QPID_BROKER_SELECTORTOKEN_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/BrokerImportExport.h" - -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -typedef enum { - T_EOS, - T_NULL, - T_TRUE, - T_FALSE, - T_NOT, - T_AND, - T_OR, - T_IN, - T_IS, - T_BETWEEN, - T_LIKE, - T_ESCAPE, - T_IDENTIFIER, - T_STRING, - T_NUMERIC_EXACT, - T_NUMERIC_APPROX, - T_LPAREN, - T_RPAREN, - T_COMMA, - T_PLUS, - T_MINUS, - T_MULT, - T_DIV, - T_EQUAL, - T_NEQ, - T_LESS, - T_GRT, - T_LSEQ, - T_GREQ -} TokenType; - -struct Token { - TokenType type; - std::string val; - std::string::const_iterator tokenStart; - - Token() - {} - - Token(TokenType t, const std::string& v) : - type(t), - val(v) - {} - - Token(TokenType t, const std::string::const_iterator& s, const std::string& v) : - type(t), - val(v), - tokenStart(s) - {} - - Token(TokenType t, const std::string::const_iterator& s, const std::string::const_iterator& e) : - type(t), - val(std::string(s,e)), - tokenStart(s) - {} - - bool operator==(const Token& r) const - { - return - (type == T_EOS && r.type == T_EOS) || - (type == r.type && val == r.val); - } -}; - -QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream& os, const Token& t); - -class TokenException : public std::range_error { -public: - TokenException(const std::string&); -}; - -QPID_BROKER_EXTERN bool tokenise(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok); - -class Tokeniser { - std::vector tokens; - unsigned int tokp; - - std::string::const_iterator inStart; - std::string::const_iterator inp; - std::string::const_iterator inEnd; - -public: - QPID_BROKER_EXTERN Tokeniser(const std::string::const_iterator& s, const std::string::const_iterator& e); - QPID_BROKER_EXTERN void returnTokens(unsigned int n = 1); - QPID_BROKER_EXTERN const Token& nextToken(); - QPID_BROKER_EXTERN std::string remaining(); -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/SelectorValue.cpp b/qpid/cpp/src/qpid/broker/SelectorValue.cpp deleted file mode 100644 index f2e50db5d7..0000000000 --- a/qpid/cpp/src/qpid/broker/SelectorValue.cpp +++ /dev/null @@ -1,212 +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/broker/SelectorValue.h" - -#include -#include - -using std::ostream; - -namespace qpid { -namespace broker { - -ostream& operator<<(ostream& os, const Value& v) -{ - switch (v.type) { - case Value::T_UNKNOWN: os << "UNKNOWN"; break; - case Value::T_BOOL: os << "BOOL:" << std::boolalpha << v.b; break; - case Value::T_EXACT: os << "EXACT:" << v.i; break; - case Value::T_INEXACT: os << "APPROX:" << v.x; break; - case Value::T_STRING: os << "STRING:'" << *v.s << "'"; break; - }; - return os; -} - -class NumericPairBase { -public: - virtual ~NumericPairBase() {} - virtual Value add() = 0; - virtual Value sub() = 0; - virtual Value mul() = 0; - virtual Value div() = 0; - - virtual bool eq() = 0; - virtual bool ne() = 0; - virtual bool ls() = 0; - virtual bool gr() = 0; - virtual bool le() = 0; - virtual bool ge() = 0; -}; - -template -class NumericPair : public NumericPairBase { - const T n1; - const T n2; - - Value add() { return n1+n2; } - Value sub() { return n1-n2; } - Value mul() { return n1*n2; } - Value div() { return n1/n2; } - - bool eq() { return n1==n2; } - bool ne() { return n1!=n2; } - bool ls() { return n1n2; } - bool le() { return n1<=n2; } - bool ge() { return n1>=n2; } - -public: - NumericPair(T x, T y) : - n1(x), - n2(y) - {} -}; - -NumericPairBase* promoteNumeric(const Value& v1, const Value& v2) -{ - if (!numeric(v1) || !numeric(v2)) return 0; - - if (!sameType(v1,v2)) { - switch (v1.type) { - case Value::T_INEXACT: return new NumericPair(v1.x, v2.i); - case Value::T_EXACT: return new NumericPair(v1.i, v2.x); - default: - assert(false); - } - } else { - switch (v1.type) { - case Value::T_INEXACT: return new NumericPair(v1.x, v2.x); - case Value::T_EXACT: return new NumericPair(v1.i, v2.i); - default: - assert(false); - } - } - // Can never get here - but this stops a warning - return 0; -} - -bool operator==(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->eq(); - - if (!sameType(v1,v2)) return false; - switch (v1.type) { - case Value::T_BOOL: return v1.b == v2.b; - case Value::T_STRING: return *v1.s == *v2.s; - default: // Cannot ever get here - return false; - } -} - -bool operator!=(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->ne(); - - if (!sameType(v1,v2)) return false; - switch (v1.type) { - case Value::T_BOOL: return v1.b != v2.b; - case Value::T_STRING: return *v1.s != *v2.s; - default: // Cannot ever get here - return false; - } -} - -bool operator<(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->ls(); - - return false; -} - -bool operator>(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->gr(); - - return false; -} - -bool operator<=(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->le(); - - return false; -} - -bool operator>=(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->ge(); - - return false; -} - -Value operator+(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->add(); - - return Value(); -} - -Value operator-(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->sub(); - - return Value(); -} - -Value operator*(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->mul(); - - return Value(); -} - -Value operator/(const Value& v1, const Value& v2) -{ - boost::scoped_ptr nbp(promoteNumeric(v1, v2)); - if (nbp) return nbp->div(); - - return Value(); -} - -Value operator-(const Value& v) -{ - switch (v.type) { - case Value::T_EXACT: - return -v.i; - case Value::T_INEXACT: - return -v.x; - default: - break; - } - return Value(); -} - -}} diff --git a/qpid/cpp/src/qpid/broker/SelectorValue.h b/qpid/cpp/src/qpid/broker/SelectorValue.h deleted file mode 100644 index aa2197b225..0000000000 --- a/qpid/cpp/src/qpid/broker/SelectorValue.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef QPID_BROKER_SELECTORVALUE_H -#define QPID_BROKER_SELECTORVALUE_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 -#include - -namespace qpid { -namespace broker { - -enum BoolOrNone { - BN_FALSE = false, - BN_TRUE = true, - BN_UNKNOWN -}; - -// The user of the Value class for strings must ensure that -// the string has a lifetime longer than the string used and -// is responsible for managing its lifetime. -class Value { -public: - union { - bool b; - int64_t i; - double x; - const std::string* s; - }; - enum { - T_UNKNOWN, - T_BOOL, - T_STRING, - T_EXACT, - T_INEXACT - } type; - - // Default copy contructor - // Default assignment operator - // Default destructor - Value() : - type(T_UNKNOWN) - {} - - Value(const std::string& s0) : - s(&s0), - type(T_STRING) - {} - - Value(const int64_t i0) : - i(i0), - type(T_EXACT) - {} - - Value(const int32_t i0) : - i(i0), - type(T_EXACT) - {} - - Value(const double x0) : - x(x0), - type(T_INEXACT) - {} - - Value(bool b0) : - b(b0), - type(T_BOOL) - {} - - Value(BoolOrNone bn) : - b(bn), - type(bn==BN_UNKNOWN ? T_UNKNOWN : T_BOOL) - {} -}; - -inline bool unknown(const Value& v) { - return v.type == Value::T_UNKNOWN; -} - -inline bool numeric(const Value& v) { - return v.type == Value::T_EXACT || v.type == Value::T_INEXACT; -} - -inline bool sameType(const Value& v1, const Value& v2) { - return v1.type == v2.type; -} - -std::ostream& operator<<(std::ostream& os, const Value& v); - -bool operator==(const Value&, const Value&); -bool operator!=(const Value&, const Value&); -bool operator<(const Value&, const Value&); -bool operator>(const Value&, const Value&); -bool operator<=(const Value&, const Value&); -bool operator>=(const Value&, const Value&); - -Value operator+(const Value&, const Value&); -Value operator-(const Value&, const Value&); -Value operator*(const Value&, const Value&); -Value operator/(const Value&, const Value&); -Value operator-(const Value&); - -}} - -#endif diff --git a/qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp b/qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp deleted file mode 100644 index 55f644ed86..0000000000 --- a/qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp +++ /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. - * - */ -#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 << ")"); - } - current += increment; - return true; -} -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/SelfDestructQueue.h b/qpid/cpp/src/qpid/broker/SelfDestructQueue.h deleted file mode 100644 index 110eb1dcf7..0000000000 --- a/qpid/cpp/src/qpid/broker/SelfDestructQueue.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_BROKER_SELFDESTRUCTQUEUE_H -#define QPID_BROKER_SELFDESTRUCTQUEUE_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/Queue.h" - -namespace qpid { -namespace broker { - -/** - * 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 -{ - 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 deleted file mode 100644 index 1b3823c845..0000000000 --- a/qpid/cpp/src/qpid/broker/SemanticState.cpp +++ /dev/null @@ -1,896 +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/broker/SessionState.h" - -#include "qpid/broker/AsyncCommandCallback.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/DtxAck.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#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" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/IsInSequenceSet.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/ptr_map.h" -#include "qpid/broker/AclModule.h" -#include "qpid/broker/FedOps.h" -#include "qpid/sys/ConnectionOutputHandler.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include - -namespace { -const std::string X_SCOPE("x-scope"); -const std::string SESSION("session"); -} - -namespace qpid { -namespace broker { - -using namespace std; -using boost::intrusive_ptr; -using boost::shared_ptr; -using boost::bind; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -using qpid::ptr_map_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -SemanticState::SemanticState(SessionState& ss) - : session(ss), - tagGenerator("sgen"), - dtxSelected(false), - authMsg(getSession().getBroker().isAuthenticating() && !getSession().getConnection().isFederationLink()), - userID(getSession().getConnection().getUserId()), - closeComplete(false), - connectionId(getSession().getConnection().getMgmtId()) -{} - -SemanticState::~SemanticState() { - closed(); -} - -void SemanticState::closed() { - if (!closeComplete) { - //prevent requeued messages being redelivered to consumers - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - disable(i->second); - } - if (dtxBuffer.get()) { - dtxBuffer->fail(); - } - unbindSessionBindings(); - requeue(); - - //now unsubscribe, which may trigger queue deletion and thus - //needs to occur after the requeueing of unacked messages - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - cancel(i->second); - } - closeComplete = true; - if (txBuffer) txBuffer->rollback(); - } -} - -bool SemanticState::exists(const string& consumerTag){ - return consumers.find(consumerTag) != consumers.end(); -} - -namespace { - const std::string SEPARATOR("::"); -} - -void SemanticState::consume(const string& tag, - Queue::shared_ptr queue, bool ackRequired, bool acquire, - bool exclusive, const string& resumeId, uint64_t resumeTtl, - const FieldTable& arguments) -{ - // "tag" is only guaranteed to be unique to this session (see AMQP 0-10 Message.subscribe, destination). - // Create a globally unique name so the broker can identify individual consumers - std::string name = session.getSessionId().str() + SEPARATOR + tag; - const ConsumerFactories::Factories& cf( - session.getBroker().getConsumerFactories().get()); - ConsumerImpl::shared_ptr c; - for (ConsumerFactories::Factories::const_iterator i = cf.begin(); i != cf.end() && !c; ++i) - c = (*i)->create(this, name, queue, ackRequired, acquire, exclusive, tag, - resumeId, resumeTtl, arguments); - if (!c) // Create plain consumer - c = ConsumerImpl::shared_ptr( - new ConsumerImpl(this, name, queue, ackRequired, acquire ? CONSUMER : BROWSER, exclusive, tag, - resumeId, resumeTtl, arguments)); - queue->consume(c, exclusive, arguments, connectionId, userID);//may throw exception - consumers[tag] = c; -} - -bool SemanticState::cancel(const string& tag) -{ - ConsumerImplMap::iterator i = consumers.find(tag); - if (i != consumers.end()) { - cancel(i->second); - consumers.erase(i); - //should cancel all unacked messages for this consumer so that - //they are not redelivered on recovery - for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::cancel, _1, tag)); - //can also remove any records that are now redundant - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), bind(&DeliveryRecord::isRedundant, _1)); - unacked.erase(removed, unacked.end()); - getSession().setUnackedCount(unacked.size()); - return true; - } else { - return false; - } -} - - -void SemanticState::startTx() -{ - accumulatedAck.clear(); - txBuffer = boost::intrusive_ptr(new TxBuffer()); - session.getBroker().getBrokerObservers().startTx(txBuffer); - session.startTx(); //just to update statistics -} - -namespace { -struct StartTxOnExit { - SemanticState& session; - StartTxOnExit(SemanticState& ss) : session(ss) {} - ~StartTxOnExit() { session.startTx(); } -}; -} // namespace - -void SemanticState::commit(MessageStore* const store) -{ - if (!txBuffer) throw - CommandInvalidException( - QPID_MSG("Session has not been selected for use with transactions")); - // Start a new TX regardless of outcome of this one. - StartTxOnExit e(*this); - session.getCurrentCommand().setCompleteSync(false); // Async completion - txBuffer->begin(); // Begin async completion. - session.commitTx(); //just to update statistics - TxOp::shared_ptr txAck(static_cast(new TxAccept(accumulatedAck, unacked))); - txBuffer->enlist(txAck); - // In a HA cluster, tx.commit may complete asynchronously. - txBuffer->startCommit(store); - AsyncCommandCallback callback( - session, - boost::bind(&TxBuffer::endCommit, txBuffer, store), - true // This is a sync point - ); - txBuffer->end(callback); -} - -void SemanticState::rollback() -{ - if (!txBuffer) - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with transactions")); - StartTxOnExit e(*this); - session.rollbackTx(); // Just to update statistics - txBuffer->rollback(); -} - -void SemanticState::selectDtx() -{ - dtxSelected = true; -} - -void SemanticState::startDtx(const std::string& xid, DtxManager& mgr, bool join) -{ - if (!dtxSelected) { - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with dtx")); - } - dtxBuffer = new DtxBuffer(xid); - txBuffer = dtxBuffer; - session.getBroker().getBrokerObservers().startDtx(dtxBuffer); - if (join) { - mgr.join(xid, dtxBuffer); - } else { - mgr.start(xid, dtxBuffer); - } -} - -void SemanticState::endDtx(const std::string& xid, bool fail) -{ - if (!dtxBuffer) { - throw IllegalStateException(QPID_MSG("xid " << xid << " not associated with this session")); - } - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on end")); - - } - - txBuffer = 0;//ops on this session no longer transactional - - checkDtxTimeout(); - if (fail) { - dtxBuffer->fail(); - } else { - dtxBuffer->markEnded(); - } - dtxBuffer = 0; -} - -void SemanticState::suspendDtx(const std::string& xid) -{ - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on suspend")); - } - txBuffer = 0;//ops on this session no longer transactional - - checkDtxTimeout(); - dtxBuffer->setSuspended(true); - suspendedXids[xid] = dtxBuffer; - dtxBuffer = 0; -} - -void SemanticState::resumeDtx(const std::string& xid) -{ - if (!dtxSelected) { - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with dtx")); - } - - dtxBuffer = suspendedXids[xid]; - if (!dtxBuffer) { - throw CommandInvalidException(QPID_MSG("xid " << xid << " not attached")); - } else { - suspendedXids.erase(xid); - } - - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on resume")); - - } - if (!dtxBuffer->isSuspended()) { - throw CommandInvalidException(QPID_MSG("xid " << xid << " not suspended")); - } - - checkDtxTimeout(); - dtxBuffer->setSuspended(false); - txBuffer = dtxBuffer; -} - -void SemanticState::checkDtxTimeout() -{ - if (dtxBuffer->isExpired()) { - dtxBuffer = 0; - throw DtxTimeoutException(); - } -} - -void SemanticState::record(const DeliveryRecord& delivery) -{ - unacked.push_back(delivery); - getSession().setUnackedCount(unacked.size()); -} - -const std::string QPID_SYNC_FREQUENCY("qpid.sync_frequency"); -const std::string APACHE_SELECTOR("x-apache-selector"); - -SemanticStateConsumerImpl::SemanticStateConsumerImpl(SemanticState* _parent, - const string& _name, - Queue::shared_ptr _queue, - bool ack, - SubscriptionType type, - bool _exclusive, - const string& _tag, - const string& _resumeId, - uint64_t _resumeTtl, - const framing::FieldTable& _arguments - -) : - Consumer(_name, type, _tag), - parent(_parent), - queue(_queue), - ackExpected(ack), - acquire(type == CONSUMER), - blocked(true), - exclusive(_exclusive), - resumeId(_resumeId), - selector(returnSelector(_arguments.getAsString(APACHE_SELECTOR))), - resumeTtl(_resumeTtl), - arguments(_arguments), - notifyEnabled(true), - syncFrequency(_arguments.getAsInt(QPID_SYNC_FREQUENCY)), - deliveryCount(0), - protocols(parent->getSession().getBroker().getProtocolRegistry()) -{ - if (parent != 0 && queue.get() != 0 && queue->GetManagementObject() !=0) - { - ManagementAgent* agent = parent->session.getBroker().getManagementAgent(); - qpid::management::Manageable* ms = dynamic_cast (&(parent->session)); - - if (agent != 0) - { - mgmtObject = _qmf::Subscription::shared_ptr(new _qmf::Subscription(agent, this, ms , queue->GetManagementObject()->getObjectId(), getTag(), - !acquire, ackExpected, exclusive, ManagementAgent::toMap(arguments))); - agent->addObject (mgmtObject); - mgmtObject->set_creditMode("WINDOW"); - } - } -} - -ManagementObject::shared_ptr SemanticStateConsumerImpl::GetManagementObject (void) const -{ - return mgmtObject; -} - -Manageable::status_t SemanticStateConsumerImpl::ManagementMethod (uint32_t methodId, Args&, string&) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - QPID_LOG (debug, "Queue::ManagementMethod [id=" << methodId << "]"); - - return status; -} - - -OwnershipToken* SemanticStateConsumerImpl::getSession() -{ - return &(parent->session); -} - -bool SemanticStateConsumerImpl::deliver(const QueueCursor& cursor, const Message& msg) -{ - return deliver(cursor, msg, shared_from_this()); -} -bool SemanticStateConsumerImpl::deliver(const QueueCursor& cursor, const Message& msg, boost::shared_ptr consumer) -{ - allocateCredit(msg); - boost::intrusive_ptr transfer = protocols.translate(msg); - DeliveryRecord record(cursor, msg.getSequence(), msg.getReplicationId(), queue, getTag(), - consumer, acquire, !ackExpected, credit.isWindowMode(), transfer->getRequiredCredit()); - bool sync = syncFrequency && ++deliveryCount >= syncFrequency; - if (sync) deliveryCount = 0;//reset - - record.setId(parent->session.deliver(*transfer, getTag(), msg.isRedelivered(), msg.getTtl(), - ackExpected ? message::ACCEPT_MODE_EXPLICIT : message::ACCEPT_MODE_NONE, - acquire ? message::ACQUIRE_MODE_PRE_ACQUIRED : message::ACQUIRE_MODE_NOT_ACQUIRED, - msg.getAnnotations(), - sync)); - if (credit.isWindowMode() || ackExpected || !acquire) { - parent->record(record); - } - if (acquire && !ackExpected) { // auto acquire && auto accept - queue->dequeue(0 /*ctxt*/, cursor); - } - if (mgmtObject) { mgmtObject->inc_delivered(); } - return true; -} - -bool SemanticStateConsumerImpl::filter(const Message& msg) -{ - return !selector || selector->filter(msg); -} - -bool SemanticStateConsumerImpl::accept(const Message& msg) -{ - // TODO aconway 2009-06-08: if we have byte & message credit but - // checkCredit fails because the message is to big, we should - // remain on queue's listener list for possible smaller messages - // in future. - // - blocked = !checkCredit(msg); - return !blocked; -} - -namespace { -struct ConsumerName { - const SemanticStateConsumerImpl& consumer; - ConsumerName(const SemanticStateConsumerImpl& ci) : consumer(ci) {} -}; - -ostream& operator<<(ostream& o, const ConsumerName& pc) { - return o << pc.consumer.getTag() << " on " - << pc.consumer.getParent().getSession().getSessionId(); -} -} - -void SemanticStateConsumerImpl::allocateCredit(const Message& msg) -{ - Credit original = credit; - boost::intrusive_ptr transfer = protocols.translate(msg); - credit.consume(1, transfer->getRequiredCredit()); - QPID_LOG(debug, "Credit allocated for " << ConsumerName(*this) - << ", was " << original << " now " << credit); - -} - -bool SemanticStateConsumerImpl::checkCredit(const Message& msg) -{ - boost::intrusive_ptr transfer = protocols.translate(msg); - bool enoughCredit = credit.check(1, transfer->getRequiredCredit()); - QPID_LOG(debug, "Subscription " << ConsumerName(*this) << " has " << (enoughCredit ? "sufficient " : "insufficient") - << " credit for message of " << transfer->getRequiredCredit() << " bytes: " - << credit); - return enoughCredit; -} - -SemanticStateConsumerImpl::~SemanticStateConsumerImpl() -{ - if (mgmtObject != 0) { - mgmtObject->debugStats("destroying"); - mgmtObject->resourceDestroy (); - } -} - -void SemanticState::disable(ConsumerImpl::shared_ptr c) -{ - c->disableNotify(); - if (session.isAttached()) - session.getConnection().removeOutputTask(c.get()); -} - -void SemanticState::cancel(ConsumerImpl::shared_ptr c) -{ - disable(c); - Queue::shared_ptr queue = c->getQueue(); - if(queue) { - queue->cancel(c, connectionId, userID); - } - c->cancel(); -} - -TxBuffer* SemanticState::getTxBuffer() -{ - return txBuffer.get(); -} - -void SemanticState::route(Message& msg, Deliverable& strategy) { - std::string exchangeName = qpid::broker::amqp_0_10::MessageTransfer::get(msg).getExchangeName(); - if (!cacheExchange || cacheExchange->getName() != exchangeName || cacheExchange->isDestroyed()) - cacheExchange = session.getBroker().getExchanges().get(exchangeName); - - /* verify the userid if specified: */ - std::string id = msg.getUserId(); - if (authMsg && !id.empty() && !session.getConnection().isAuthenticatedUser(id)) - { - QPID_LOG(debug, "authorised user id : " << userID << " but user id in message declared as " << id); - throw UnauthorizedAccessException(QPID_MSG("authorised user id : " << userID << " but user id in message declared as " << id)); - } - - AclModule* acl = getSession().getBroker().getAcl(); - if (acl && acl->doTransferAcl()) - { - if (!acl->authorise(getSession().getConnection().getUserId(),acl::ACT_PUBLISH,acl::OBJ_EXCHANGE,exchangeName, msg.getRoutingKey() )) - throw UnauthorizedAccessException(QPID_MSG(userID << " cannot publish to " << - exchangeName << " with routing-key " << msg.getRoutingKey())); - } - - cacheExchange->route(strategy); - - if (!strategy.delivered) { - //TODO:if discard-unroutable, just drop it - //TODO:else if accept-mode is explicit, reject it - //else route it to alternate exchange - if (cacheExchange->getAlternate()) { - cacheExchange->getAlternate()->route(strategy); - } - } - -} - -void SemanticState::requestDispatch() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) - i->second->requestDispatch(); -} - -void SemanticStateConsumerImpl::requestDispatch() -{ - if (blocked) { - parent->session.getConnection().addOutputTask(this); - parent->session.getConnection().activateOutput(); - blocked = false; - } -} - -bool SemanticState::complete(DeliveryRecord& delivery) -{ - ConsumerImplMap::iterator i = consumers.find(delivery.getTag()); - if (i != consumers.end()) { - i->second->complete(delivery); - } - return delivery.isRedundant(); -} - -void SemanticStateConsumerImpl::complete(DeliveryRecord& delivery) -{ - if (!delivery.isComplete()) { - delivery.complete(); - if (credit.isWindowMode()) { - credit.moveWindow(1, delivery.getCredit()); - } - } -} - -void SemanticState::requeue() -{ - //take copy and clear unacked as requeue may result in redelivery to this session - //which will in turn result in additions to unacked - DeliveryRecords copy = unacked; - unacked.clear(); - for_each(copy.rbegin(), copy.rend(), mem_fun_ref(&DeliveryRecord::requeue)); - getSession().setUnackedCount(unacked.size()); -} - - -SessionContext& SemanticState::getSession() { return session; } -const SessionContext& SemanticState::getSession() const { return session; } - - -const SemanticStateConsumerImpl::shared_ptr SemanticState::find(const std::string& destination) const -{ - ConsumerImpl::shared_ptr consumer; - if (!find(destination, consumer)) { - throw NotFoundException(QPID_MSG("Unknown destination " << destination << " session=" << session.getSessionId())); - } else { - return consumer; - } -} - -bool SemanticState::find(const std::string& destination, ConsumerImpl::shared_ptr& consumer) const -{ - // @todo KAG gsim: shouldn't the consumers map be locked???? - ConsumerImplMap::const_iterator i = consumers.find(destination); - if (i == consumers.end()) { - return false; - } - consumer = i->second; - return true; -} - -void SemanticState::setWindowMode(const std::string& destination) -{ - find(destination)->setWindowMode(); -} - -void SemanticState::setCreditMode(const std::string& destination) -{ - find(destination)->setCreditMode(); -} - -void SemanticState::addByteCredit(const std::string& destination, uint32_t value) -{ - ConsumerImpl::shared_ptr c = find(destination); - c->addByteCredit(value); - c->requestDispatch(); -} - - -void SemanticState::addMessageCredit(const std::string& destination, uint32_t value) -{ - ConsumerImpl::shared_ptr c = find(destination); - c->addMessageCredit(value); - c->requestDispatch(); -} - -void SemanticState::flush(const std::string& destination) -{ - find(destination)->flush(); -} - - -void SemanticState::stop(const std::string& destination) -{ - find(destination)->stop(); -} - -void SemanticStateConsumerImpl::setWindowMode() -{ - credit.setWindowMode(true); - if (mgmtObject){ - mgmtObject->set_creditMode("WINDOW"); - } -} - -void SemanticStateConsumerImpl::setCreditMode() -{ - credit.setWindowMode(false); - if (mgmtObject){ - mgmtObject->set_creditMode("CREDIT"); - } -} - -void SemanticStateConsumerImpl::addByteCredit(uint32_t value) -{ - credit.addByteCredit(value); -} - -void SemanticStateConsumerImpl::addMessageCredit(uint32_t value) -{ - credit.addMessageCredit(value); -} - -bool SemanticStateConsumerImpl::haveCredit() -{ - if (credit) { - return true; - } else { - blocked = true; - return false; - } -} - -bool SemanticStateConsumerImpl::doDispatch() -{ - return queue->dispatch(shared_from_this()); -} - -void SemanticStateConsumerImpl::flush() -{ - while(haveCredit() && doDispatch()) - ; - credit.cancel(); -} - -void SemanticStateConsumerImpl::stop() -{ - credit.cancel(); -} - -Queue::shared_ptr SemanticState::getQueue(const string& name) const { - Queue::shared_ptr queue; - if (name.empty()) { - throw NotAllowedException(QPID_MSG("No queue name specified.")); - } else { - queue = session.getBroker().getQueues().get(name); - } - return queue; -} - -AckRange SemanticState::findRange(DeliveryId first, DeliveryId last) -{ - return DeliveryRecord::findRange(unacked, first, last); -} - -void SemanticState::acquire(DeliveryId first, DeliveryId last, DeliveryIds& acquired) -{ - AckRange range = findRange(first, last); - for_each(range.start, range.end, AcquireFunctor(acquired)); -} - -void SemanticState::release(DeliveryId first, DeliveryId last, bool setRedelivered) -{ - AckRange range = findRange(first, last); - //release results in the message being added to the head so want - //to release in reverse order to keep the original transfer order - DeliveryRecords::reverse_iterator start(range.end); - DeliveryRecords::reverse_iterator end(range.start); - for_each(start, end, boost::bind(&DeliveryRecord::release, _1, setRedelivered)); - - DeliveryRecords::iterator removed = - remove_if(range.start, range.end, bind(&DeliveryRecord::isRedundant, _1)); - unacked.erase(removed, range.end); - getSession().setUnackedCount(unacked.size()); -} - -void SemanticState::reject(DeliveryId first, DeliveryId last) -{ - AckRange range = findRange(first, last); - for_each(range.start, range.end, mem_fun_ref(&DeliveryRecord::reject)); - //may need to remove the delivery records as well - for (DeliveryRecords::iterator i = range.start; i != unacked.end() && i->getId() <= last; ) { - if (i->isRedundant()) i = unacked.erase(i); - else i++; - } - getSession().setUnackedCount(unacked.size()); -} - -bool SemanticStateConsumerImpl::doOutput() -{ - try { - return haveCredit() && doDispatch(); - } catch (const SessionException& e) { - throw SessionOutputException(e, parent->session.getChannel()); - } -} - -void SemanticStateConsumerImpl::enableNotify() -{ - Mutex::ScopedLock l(lock); - notifyEnabled = true; -} - -void SemanticStateConsumerImpl::disableNotify() -{ - Mutex::ScopedLock l(lock); - notifyEnabled = false; -} - -bool SemanticStateConsumerImpl::isNotifyEnabled() const { - Mutex::ScopedLock l(lock); - return notifyEnabled; -} - -void SemanticStateConsumerImpl::notify() -{ - Mutex::ScopedLock l(lock); - if (notifyEnabled) { - parent->session.getConnection().addOutputTask(this); - parent->session.getConnection().activateOutput(); - } -} - - -// Test that a DeliveryRecord's ID is in a sequence set and some other -// predicate on DeliveryRecord holds. -template struct IsInSequenceSetAnd { - IsInSequenceSet isInSet; - Predicate predicate; - IsInSequenceSetAnd(const SequenceSet& s, Predicate p) : isInSet(s), predicate(p) {} - bool operator()(DeliveryRecord& dr) { - return isInSet(dr.getId()) && predicate(dr); - } -}; - -template IsInSequenceSetAnd -isInSequenceSetAnd(const SequenceSet& s, Predicate p) { - return IsInSequenceSetAnd(s,p); -} - -void SemanticState::accepted(const SequenceSet& commands) { - if (txBuffer.get()) { - //in transactional mode, don't dequeue or remove, just - //maintain set of acknowledged messages: - accumulatedAck.add(commands); - - if (dtxBuffer.get()) { - //if enlisted in a dtx, copy the relevant slice from - //unacked and record it against that transaction - 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 - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&DeliveryRecord::setEnded, _1))); - unacked.erase(removed, unacked.end()); - } - } else { - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&DeliveryRecord::accept, _1, - (TransactionContext*) 0))); - unacked.erase(removed, unacked.end()); - } - getSession().setUnackedCount(unacked.size()); -} - -void SemanticState::completed(const SequenceSet& commands) { - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&SemanticState::complete, this, _1))); - unacked.erase(removed, unacked.end()); - requestDispatch(); - getSession().setUnackedCount(unacked.size()); -} - -void SemanticState::attached() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - i->second->enableNotify(); - session.getConnection().addOutputTask(i->second.get()); - } - session.getConnection().activateOutput(); -} - -void SemanticState::detached() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - i->second->disableNotify(); - session.getConnection().removeOutputTask(i->second.get()); - } -} - -void SemanticState::addBinding(const string& queueName, const string& exchangeName, - const string& routingKey, const framing::FieldTable& arguments) -{ - QPID_LOG (debug, "SemanticState::addBinding [" - << "queue=" << queueName << ", " - << "exchange=" << exchangeName << ", " - << "key=" << routingKey << ", " - << "args=" << arguments << "]"); - std::string fedOp = arguments.getAsString(qpidFedOp); - if ((arguments.isSet(qpidFedOp)) && (fedOp.empty())) { - fedOp = fedOpBind; - } - std::string fedOrigin = arguments.getAsString(qpidFedOrigin); - if ((arguments.getAsString(X_SCOPE) == SESSION) || (fedOp == fedOpBind)) { - bindings.insert(boost::make_tuple(queueName, exchangeName, routingKey, fedOrigin)); - } - else if (fedOp == fedOpUnbind) { - bindings.erase(boost::make_tuple(queueName, exchangeName, routingKey, fedOrigin)); - } -} - -void SemanticState::removeBinding(const string& queueName, const string& exchangeName, - const string& routingKey) -{ - QPID_LOG (debug, "SemanticState::removeBinding [" - << "queue=" << queueName << ", " - << "exchange=" << exchangeName << ", " - << "key=" << routingKey) - bindings.erase(boost::make_tuple(queueName, exchangeName, routingKey, "")); -} - -void SemanticState::unbindSessionBindings() -{ - //unbind session-scoped bindings - for (Bindings::iterator i = bindings.begin(); i != bindings.end(); i++) { - QPID_LOG (debug, "SemanticState::unbindSessionBindings [" - << "queue=" << i->get<0>() << ", " - << "exchange=" << i->get<1>()<< ", " - << "key=" << i->get<2>() << ", " - << "fedOrigin=" << i->get<3>() << "]"); - try { - std::string fedOrigin = i->get<3>(); - if (!fedOrigin.empty()) { - framing::FieldTable fedArguments; - fedArguments.setString(qpidFedOp, fedOpUnbind); - fedArguments.setString(qpidFedOrigin, fedOrigin); - session.getBroker().bind(i->get<0>(), i->get<1>(), i->get<2>(), fedArguments, - &session, userID, connectionId); - } else { - session.getBroker().unbind(i->get<0>(), i->get<1>(), i->get<2>(), - &session, userID, connectionId); - } - } - catch (...) { - } - } - bindings.clear(); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/SemanticState.h b/qpid/cpp/src/qpid/broker/SemanticState.h deleted file mode 100644 index e5456067a8..0000000000 --- a/qpid/cpp/src/qpid/broker/SemanticState.h +++ /dev/null @@ -1,295 +0,0 @@ -#ifndef QPID_BROKER_SEMANTICSTATE_H -#define QPID_BROKER_SEMANTICSTATE_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/BrokerImportExport.h" -#include "qpid/broker/Consumer.h" -#include "qpid/broker/Credit.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/NameGenerator.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/broker/TxBuffer.h" - -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/AggregateOutput.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/broker/AclModule.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Subscription.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -class Exchange; -class MessageStore; -class ProtocolRegistry; -class Selector; -class SessionContext; -class SessionState; - -/** - * - * SemanticState implements the behavior of a Session, especially the - * state of consumers subscribed to queues. The code for ConsumerImpl - * is also in SemanticState.cpp - * - * SemanticState holds the AMQP Execution and Model state of an open - * session, whether attached to a channel or suspended. It is not - * dependent on any specific AMQP version. - * - * Message delivery is driven by ConsumerImpl::doOutput(), which is - * called when a client's socket is ready to write data. - * - */ -class SemanticStateConsumerImpl; -class SemanticState : private boost::noncopyable { - friend class SemanticStateConsumerImpl; - - public: - typedef SemanticStateConsumerImpl ConsumerImpl; - typedef std::map > DtxBufferMap; - - private: - typedef std::map > ConsumerImplMap; - typedef boost::tuple Binding; - typedef std::set Bindings; - - SessionState& session; - ConsumerImplMap consumers; - NameGenerator tagGenerator; - DeliveryRecords unacked; - boost::intrusive_ptr txBuffer; - boost::intrusive_ptr dtxBuffer; - bool dtxSelected; - DtxBufferMap suspendedXids; - framing::SequenceSet accumulatedAck; - boost::shared_ptr cacheExchange; - const bool authMsg; - const std::string userID; - bool closeComplete; - //needed for queue delete events in auto-delete: - const std::string connectionId; - - Bindings bindings; - - void checkDtxTimeout(); - - bool complete(DeliveryRecord&); - AckRange findRange(DeliveryId first, DeliveryId last); - void requestDispatch(); - void cancel(boost::shared_ptr); - void disable(boost::shared_ptr); - void unbindSessionBindings(); - - public: - - SemanticState(SessionState&); - ~SemanticState(); - - SessionContext& getSession(); - const SessionContext& getSession() const; - SessionState& getSessionState() { return session; } - - const boost::shared_ptr find(const std::string& destination) const; - bool find(const std::string& destination, boost::shared_ptr&) const; - - /** - * Get named queue, never returns 0. - * @return: named queue - * @exception: ChannelException if no queue of that name is found. - * @exception: ConnectionException if name="" and session has no default. - */ - boost::shared_ptr getQueue(const std::string& name) const; - - bool exists(const std::string& consumerTag); - - void consume(const std::string& destination, - boost::shared_ptr queue, - bool ackRequired, bool acquire, bool exclusive, - const std::string& resumeId=std::string(), uint64_t resumeTtl=0, - const framing::FieldTable& = framing::FieldTable()); - - bool cancel(const std::string& tag); - - void setWindowMode(const std::string& destination); - void setCreditMode(const std::string& destination); - void addByteCredit(const std::string& destination, uint32_t value); - void addMessageCredit(const std::string& destination, uint32_t value); - void flush(const std::string& destination); - void stop(const std::string& destination); - - void startTx(); - void commit(MessageStore* const store); - void rollback(); - void selectDtx(); - bool getDtxSelected() const { return dtxSelected; } - void startDtx(const std::string& xid, DtxManager& mgr, bool join); - void endDtx(const std::string& xid, bool fail); - void suspendDtx(const std::string& xid); - void resumeDtx(const std::string& xid); - TxBuffer* getTxBuffer(); - void requeue(); - void acquire(DeliveryId first, DeliveryId last, DeliveryIds& acquired); - void release(DeliveryId first, DeliveryId last, bool setRedelivered); - void reject(DeliveryId first, DeliveryId last); - void route(Message& msg, Deliverable& strategy); - - void completed(const framing::SequenceSet& commands); - void accepted(const framing::SequenceSet& commands); - - void attached(); - void detached(); - void closed(); - - DeliveryRecords& getUnacked() { return unacked; } - framing::SequenceSet getAccumulatedAck() const { return accumulatedAck; } - boost::intrusive_ptr getTxBuffer() const { return txBuffer; } - boost::intrusive_ptr getDtxBuffer() const { return dtxBuffer; } - void setTxBuffer(const boost::intrusive_ptr& txb) { txBuffer = txb; } - void setDtxBuffer(const boost::intrusive_ptr& dtxb) { dtxBuffer = dtxb; txBuffer = dtxb; } - void setAccumulatedAck(const framing::SequenceSet& s) { accumulatedAck = s; } - void record(const DeliveryRecord& delivery); - DtxBufferMap& getSuspendedXids() { return suspendedXids; } - - void addBinding(const std::string& queueName, const std::string& exchangeName, - const std::string& routingKey, const framing::FieldTable& arguments); - void removeBinding(const std::string& queueName, const std::string& exchangeName, - const std::string& routingKey); -}; - -class SemanticStateConsumerImpl : public Consumer, public sys::OutputTask, - public boost::enable_shared_from_this, - public management::Manageable -{ - protected: - mutable qpid::sys::Mutex lock; - SemanticState* const parent; - const boost::shared_ptr queue; - - private: - const bool ackExpected; - const bool acquire; - bool blocked; - bool exclusive; - std::string resumeId; - boost::shared_ptr selector; - uint64_t resumeTtl; - framing::FieldTable arguments; - Credit credit; - bool notifyEnabled; - const int syncFrequency; - int deliveryCount; - qmf::org::apache::qpid::broker::Subscription::shared_ptr mgmtObject; - ProtocolRegistry& protocols; - - bool checkCredit(const Message& msg); - void allocateCredit(const Message& msg); - bool haveCredit(); - - protected: - QPID_BROKER_EXTERN virtual bool doDispatch(); - size_t unacked() { return parent->unacked.size(); } - QPID_BROKER_EXTERN bool deliver(const QueueCursor&, const Message&, boost::shared_ptr); - - public: - typedef boost::shared_ptr shared_ptr; - - QPID_BROKER_EXTERN SemanticStateConsumerImpl(SemanticState* parent, - const std::string& name, boost::shared_ptr queue, - bool ack, SubscriptionType type, bool exclusive, - const std::string& tag, const std::string& resumeId, - uint64_t resumeTtl, const framing::FieldTable& arguments); - QPID_BROKER_EXTERN ~SemanticStateConsumerImpl(); - QPID_BROKER_EXTERN OwnershipToken* getSession(); - QPID_BROKER_EXTERN bool deliver(const QueueCursor&, const Message&); - QPID_BROKER_EXTERN bool filter(const Message&); - QPID_BROKER_EXTERN bool accept(const Message&); - QPID_BROKER_EXTERN void cancel() {} - - QPID_BROKER_EXTERN void disableNotify(); - QPID_BROKER_EXTERN void enableNotify(); - QPID_BROKER_EXTERN void notify(); - QPID_BROKER_EXTERN bool isNotifyEnabled() const; - - QPID_BROKER_EXTERN void requestDispatch(); - - QPID_BROKER_EXTERN void setWindowMode(); - QPID_BROKER_EXTERN void setCreditMode(); - QPID_BROKER_EXTERN void addByteCredit(uint32_t value); - QPID_BROKER_EXTERN void addMessageCredit(uint32_t value); - QPID_BROKER_EXTERN void flush(); - QPID_BROKER_EXTERN void stop(); - QPID_BROKER_EXTERN void complete(DeliveryRecord&); - boost::shared_ptr getQueue() const { return queue; } - bool isBlocked() const { return blocked; } - bool setBlocked(bool set) { std::swap(set, blocked); return set; } - - QPID_BROKER_EXTERN bool doOutput(); - - Credit& getCredit() { return credit; } - const Credit& getCredit() const { return credit; } - bool isAckExpected() const { return ackExpected; } - bool isAcquire() const { return acquire; } - bool isExclusive() const { return exclusive; } - std::string getResumeId() const { return resumeId; }; - uint64_t getResumeTtl() const { return resumeTtl; } - uint32_t getDeliveryCount() const { return deliveryCount; } - void setDeliveryCount(uint32_t _deliveryCount) { deliveryCount = _deliveryCount; } - const framing::FieldTable& getArguments() const { return arguments; } - - SemanticState& getParent() { return *parent; } - const SemanticState& getParent() const { return *parent; } - - void acknowledged(const DeliveryRecord&) {} - - // manageable entry points - QPID_BROKER_EXTERN management::ManagementObject::shared_ptr - GetManagementObject(void) const; - - QPID_BROKER_EXTERN management::Manageable::status_t - ManagementMethod(uint32_t methodId, management::Args& args, std::string& text); -}; - -}} // namespace qpid::broker - - - - -#endif /*!QPID_BROKER_SEMANTICSTATE_H*/ diff --git a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp deleted file mode 100644 index c4a0d9f008..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/* - * - * 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/broker/SessionAdapter.h" - -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/broker/Queue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/broker/SessionState.h" - #include -#include -#include - -namespace qpid { -namespace broker { - -using std::string; - -using namespace qpid; -using namespace qpid::framing; -using namespace qpid::framing::dtx; -using namespace qpid::management; - -typedef std::vector QueueVector; - -SessionAdapter::SessionAdapter(SemanticState& s) : - HandlerImpl(s), - exchangeImpl(s), - queueImpl(s), - messageImpl(s), - executionImpl(s), - txImpl(s), - dtxImpl(s) -{} - -static const std::string _TRUE("true"); -static const std::string _FALSE("false"); - -void SessionAdapter::ExchangeHandlerImpl::declare(const string& exchange, const string& type, - const string& alternateExchange, - bool passive, bool durable, bool autodelete, const FieldTable& args){ - - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = getBroker().getExchanges().get(alternateExchange); - } - if(passive){ - AclModule* acl = getBroker().getAcl(); - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_TYPE, type)); - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_AUTODELETE, autodelete ? _TRUE : _FALSE)); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_EXCHANGE,exchange,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange access request from " << getConnection().getUserId())); - } - Exchange::shared_ptr actual(getBroker().getExchanges().get(exchange)); - checkType(actual, type); - checkAlternate(actual, alternate); - }else{ - if(exchange.find("amq.") == 0 || exchange.find("qpid.") == 0) { - throw framing::NotAllowedException(QPID_MSG("Exchange names beginning with \"amq.\" or \"qpid.\" are reserved. (exchange=\"" << exchange << "\")")); - } - try{ - std::pair response = - getBroker().createExchange(exchange, type, durable, autodelete, alternateExchange, args, - getConnection().getUserId(), getConnection().getMgmtId()); - if (!response.second) { - //exchange already there, not created - checkType(response.first, type); - checkAlternate(response.first, alternate); - QPID_LOG_CAT(debug, model, "Create exchange. name:" << exchange - << " user:" << getConnection().getUserId() - << " rhost:" << getConnection().getMgmtId() - << " type:" << type - << " alternateExchange:" << alternateExchange - << " durable:" << (durable ? "T" : "F") - << " autodelete:" << (autodelete ? "T" : "F")); - } - }catch(UnknownExchangeTypeException& /*e*/){ - throw NotFoundException(QPID_MSG("Exchange type not implemented: " << type)); - } - } -} - -void SessionAdapter::ExchangeHandlerImpl::checkType(Exchange::shared_ptr exchange, const std::string& type) -{ - if (!type.empty() && exchange->getType() != type) { - throw NotAllowedException(QPID_MSG("Exchange declared to be of type " << exchange->getType() << ", requested " << type)); - } -} - -void SessionAdapter::ExchangeHandlerImpl::checkAlternate(Exchange::shared_ptr exchange, Exchange::shared_ptr alternate) -{ - if (alternate && ((exchange->getAlternate() && alternate != exchange->getAlternate()) - || !exchange->getAlternate())) - throw NotAllowedException(QPID_MSG("Exchange declared with alternate-exchange " - << (exchange->getAlternate() ? exchange->getAlternate()->getName() : "") - << ", requested " - << alternate->getName())); -} - -void SessionAdapter::ExchangeHandlerImpl::delete_(const string& name, bool /*ifUnused*/) -{ - //TODO: implement if-unused - getBroker().deleteExchange(name, getConnection().getUserId(), getConnection().getMgmtId()); -} - -ExchangeQueryResult SessionAdapter::ExchangeHandlerImpl::query(const string& name) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_EXCHANGE,name,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange query request from " << getConnection().getUserId())); - } - Exchange::shared_ptr exchange(getBroker().getExchanges().find(name)); - if (exchange) - return ExchangeQueryResult(exchange->getType(), exchange->isDurable(), false, exchange->getArgs()); - else - return ExchangeQueryResult("", false, true, FieldTable()); -} - -void SessionAdapter::ExchangeHandlerImpl::bind(const string& queueName, - const string& exchangeName, const string& routingKey, - const FieldTable& arguments) -{ - getBroker().bind(queueName, exchangeName, routingKey, arguments, &session, - getConnection().getUserId(), getConnection().getMgmtId()); - state.addBinding(queueName, exchangeName, routingKey, arguments); -} - -void SessionAdapter::ExchangeHandlerImpl::unbind(const string& queueName, - const string& exchangeName, - const string& routingKey) -{ - state.removeBinding(queueName, exchangeName, routingKey); - getBroker().unbind(queueName, exchangeName, routingKey, &session, - getConnection().getUserId(), getConnection().getMgmtId()); -} - -ExchangeBoundResult SessionAdapter::ExchangeHandlerImpl::bound(const std::string& exchangeName, - const std::string& queueName, - const std::string& key, - const framing::FieldTable& args) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_EXCHANGE,exchangeName,¶ms) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange bound request from " << getConnection().getUserId())); - } - - Exchange::shared_ptr exchange = getBroker().getExchanges().find(exchangeName); - - Queue::shared_ptr queue; - if (!queueName.empty()) { - queue = getBroker().getQueues().find(queueName); - } - - if (!exchange) { - return ExchangeBoundResult(true, (!queueName.empty() && !queue), false, false, false); - } else if (!queueName.empty() && !queue) { - return ExchangeBoundResult(false, true, false, false, false); - } else if (exchange->isBound(queue, key.empty() ? 0 : &key, args.count() > 0 ? &args : &args)) { - return ExchangeBoundResult(false, false, false, false, false); - } else { - //need to test each specified option individually - bool queueMatched = queueName.empty() || exchange->isBound(queue, 0, 0); - bool keyMatched = key.empty() || exchange->isBound(Queue::shared_ptr(), &key, 0); - bool argsMatched = args.count() == 0 || exchange->isBound(Queue::shared_ptr(), 0, &args); - - return ExchangeBoundResult(false, false, !queueMatched, !keyMatched, !argsMatched); - } -} - -SessionAdapter::QueueHandlerImpl::QueueHandlerImpl(SemanticState& session) - : HandlerHelper(session), broker(getBroker()), - //record connection id and userid for deleting exclsuive queues after session has ended: - connectionId(getConnection().getMgmtId()), userId(getConnection().getUserId()) -{} - - -SessionAdapter::QueueHandlerImpl::~QueueHandlerImpl() -{ - try { - destroyExclusiveQueues(); - } catch (std::exception& e) { - QPID_LOG(error, e.what()); - } -} - -void SessionAdapter::QueueHandlerImpl::destroyExclusiveQueues() -{ - while (!exclusiveQueues.empty()) { - Queue::shared_ptr q(exclusiveQueues.front()); - q->releaseExclusiveOwnership(); - exclusiveQueues.erase(exclusiveQueues.begin()); - } -} - -bool SessionAdapter::QueueHandlerImpl::isLocal(const OwnershipToken* t) const -{ - return session.isLocal(t); -} - - -QueueQueryResult SessionAdapter::QueueHandlerImpl::query(const string& name) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_QUEUE,name,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue query request from " << getConnection().getUserId())); - } - - Queue::shared_ptr queue = session.getBroker().getQueues().find(name); - if (queue) { - - Exchange::shared_ptr alternateExchange = queue->getAlternateExchange(); - - return QueueQueryResult(queue->getName(), - alternateExchange ? alternateExchange->getName() : "", - queue->isDurable(), - queue->hasExclusiveOwner(), - queue->isAutoDelete(), - queue->getEncodableSettings(), - queue->getMessageCount(), - queue->getConsumerCount()); - } else { - return QueueQueryResult(); - } -} - -void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string& alternateExchange, - bool passive, bool durable, bool exclusive, - bool autoDelete, const qpid::framing::FieldTable& arguments) -{ - Queue::shared_ptr queue; - if (passive && !name.empty()) { - AclModule* acl = getBroker().getAcl(); - if (acl) { - std::map params; - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_EXCLUSIVE, std::string(exclusive ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_AUTODELETE, std::string(autoDelete ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type"))); - params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast(arguments.getAsInt("qpid.max_count")))); - params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast(arguments.getAsInt64("qpid.max_size")))); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_QUEUE,name,¶ms) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue access request from " << getConnection().getUserId())); - } - queue = getQueue(name); - //TODO: check alternate-exchange is as expected - } else { - QueueSettings settings(durable, autoDelete); - try { - settings.populate(arguments, settings.storeSettings); - } catch (const qpid::types::Exception& e) { - throw InvalidArgumentException(e.what()); - } - - std::pair queue_created = - getBroker().createQueue(name, settings, - exclusive ? &session : 0, - alternateExchange, - getConnection().getUserId(), - getConnection().getMgmtId()); - queue = queue_created.first; - assert(queue); - if (queue_created.second) { // This is a new queue - //handle automatic cleanup: - if (exclusive && queue->setExclusiveOwner(&session)) { - exclusiveQueues.push_back(queue); - } - } else { - if (exclusive && queue->setExclusiveOwner(&session)) { - exclusiveQueues.push_back(queue); - } - QPID_LOG_CAT(debug, model, "Create queue. name:" << name - << " user:" << getConnection().getUserId() - << " rhost:" << getConnection().getMgmtId() - << " durable:" << (durable ? "T" : "F") - << " exclusive:" << (exclusive ? "T" : "F") - << " autodelete:" << (autoDelete ? "T" : "F") - << " alternateExchange:" << alternateExchange - ); - } - - } - - if (exclusive && !queue->isExclusiveOwner(&session)) - throw ResourceLockedException(QPID_MSG("Cannot grant exclusive access to queue " - << queue->getName())); -} - -void SessionAdapter::QueueHandlerImpl::purge(const string& queue){ - AclModule* acl = getBroker().getAcl(); - if (acl) - { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_PURGE,acl::OBJ_QUEUE,queue,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue purge request from " << getConnection().getUserId())); - } - getQueue(queue)->purge(); -} - -void SessionAdapter::QueueHandlerImpl::checkDelete(Queue::shared_ptr queue, bool ifUnused, bool ifEmpty) -{ - if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(&session)) { - throw ResourceLockedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; it is exclusive to another session")); - } else if(ifEmpty && queue->getMessageCount() > 0) { - throw PreconditionFailedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; queue not empty")); - } else if(ifUnused && queue->getConsumerCount() > 0) { - throw PreconditionFailedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; queue in use")); - } else if (queue->isExclusiveOwner(&session)) { - //remove the queue from the list of exclusive queues if necessary - QueueVector::iterator i = std::find(exclusiveQueues.begin(), - exclusiveQueues.end(), - queue); - if (i < exclusiveQueues.end()) exclusiveQueues.erase(i); - } -} - -void SessionAdapter::QueueHandlerImpl::delete_(const string& queue, bool ifUnused, bool ifEmpty) -{ - getBroker().deleteQueue(queue, getConnection().getUserId(), getConnection().getMgmtId(), - boost::bind(&SessionAdapter::QueueHandlerImpl::checkDelete, this, _1, ifUnused, ifEmpty)); -} - -SessionAdapter::MessageHandlerImpl::MessageHandlerImpl(SemanticState& s) : - HandlerHelper(s), - releaseRedeliveredOp(boost::bind(&SemanticState::release, &state, _1, _2, true)), - releaseOp(boost::bind(&SemanticState::release, &state, _1, _2, false)), - rejectOp(boost::bind(&SemanticState::reject, &state, _1, _2)) - {} - -// -// Message class method handlers -// - -void SessionAdapter::MessageHandlerImpl::transfer(const string& /*destination*/, - uint8_t /*acceptMode*/, - uint8_t /*acquireMode*/) -{ - //not yet used (content containing assemblies treated differently at present - std::cout << "SessionAdapter::MessageHandlerImpl::transfer() called" << std::endl; -} - -void SessionAdapter::MessageHandlerImpl::release(const SequenceSet& transfers, bool setRedelivered) -{ - transfers.for_each(setRedelivered ? releaseRedeliveredOp : releaseOp); -} - -void -SessionAdapter::MessageHandlerImpl::subscribe(const string& queueName, - const string& destination, - uint8_t acceptMode, - uint8_t acquireMode, - bool exclusive, - const string& resumeId, - uint64_t resumeTtl, - const FieldTable& arguments) -{ - - AclModule* acl = getBroker().getAcl(); - if (acl) - { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_CONSUME,acl::OBJ_QUEUE,queueName,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied Queue subscribe request from " << getConnection().getUserId())); - } - - Queue::shared_ptr queue = getQueue(queueName); - if(!destination.empty() && state.exists(destination)) - throw NotAllowedException(QPID_MSG("Consumer tags must be unique")); - - if (queue->getSettings().isBrowseOnly && acquireMode == 0) { - QPID_LOG(info, "Overriding request to consume from browse-only queue " << queue->getName()); - acquireMode = 1; - } - - // We allow browsing (acquireMode == 1) of exclusive queues, this is required by HA. - if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(&session) && acquireMode == 0) - throw ResourceLockedException(QPID_MSG("Cannot subscribe to exclusive queue " - << queue->getName())); - - state.consume(destination, queue, - acceptMode == 0, acquireMode == 0, exclusive, - resumeId, resumeTtl, arguments); - - QPID_LOG_CAT(debug, model, "Create subscription. queue:" << queueName - << " destination:" << destination - << " user:" << getConnection().getUserId() - << " rhost:" << getConnection().getMgmtId() - << " exclusive:" << (exclusive ? "T" : "F") - ); -} - -void -SessionAdapter::MessageHandlerImpl::cancel(const string& destination ) -{ - if (!state.cancel(destination)) { - throw NotFoundException(QPID_MSG("No such subscription: " << destination)); - } - QPID_LOG_CAT(debug, model, "Delete subscription. destination:" << destination - << " user:" << getConnection().getUserId() - << " rhost:" << getConnection().getMgmtId() ); -} - -void -SessionAdapter::MessageHandlerImpl::reject(const SequenceSet& transfers, uint16_t /*code*/, const string& /*text*/ ) -{ - transfers.for_each(rejectOp); -} - -void SessionAdapter::MessageHandlerImpl::flow(const std::string& destination, uint8_t unit, uint32_t value) -{ - if (unit == 0) { - //message - state.addMessageCredit(destination, value); - } else if (unit == 1) { - //bytes - state.addByteCredit(destination, value); - } else { - //unknown - throw InvalidArgumentException(QPID_MSG("Invalid value for unit " << unit)); - } - -} - -void SessionAdapter::MessageHandlerImpl::setFlowMode(const std::string& destination, uint8_t mode) -{ - if (mode == 0) { - //credit - state.setCreditMode(destination); - } else if (mode == 1) { - //window - state.setWindowMode(destination); - } else{ - throw InvalidArgumentException(QPID_MSG("Invalid value for mode " << mode)); - } -} - -void SessionAdapter::MessageHandlerImpl::flush(const std::string& destination) -{ - state.flush(destination); -} - -void SessionAdapter::MessageHandlerImpl::stop(const std::string& destination) -{ - state.stop(destination); -} - -void SessionAdapter::MessageHandlerImpl::accept(const framing::SequenceSet& commands) -{ - state.accepted(commands); -} - -framing::MessageAcquireResult SessionAdapter::MessageHandlerImpl::acquire(const framing::SequenceSet& transfers) -{ - // FIXME aconway 2008-05-12: create SequenceSet directly, no need for intermediate results vector. - SequenceNumberSet results; - RangedOperation f = boost::bind(&SemanticState::acquire, &state, _1, _2, boost::ref(results)); - transfers.for_each(f); - - results = results.condense(); - SequenceSet acquisitions; - RangedOperation g = boost::bind(&SequenceSet::add, &acquisitions, _1, _2); - results.processRanges(g); - - return MessageAcquireResult(acquisitions); -} - -framing::MessageResumeResult SessionAdapter::MessageHandlerImpl::resume(const std::string& /*destination*/, - const std::string& /*resumeId*/) -{ - throw NotImplementedException("resuming transfers not yet supported"); -} - - - -void SessionAdapter::ExecutionHandlerImpl::sync() -{ - session.addPendingExecutionSync(); - /** @todo KAG - need a generic mechanism to allow a command to returning "not completed" status back to SessionState */ - -} - -void SessionAdapter::ExecutionHandlerImpl::result(const SequenceNumber& /*commandId*/, const string& /*value*/) -{ - //TODO: but currently never used client->server -} - -void SessionAdapter::ExecutionHandlerImpl::exception(uint16_t errorCode, - const SequenceNumber& /*commandId*/, - uint8_t /*classCode*/, - uint8_t /*commandCode*/, - uint8_t /*fieldIndex*/, - const std::string& description, - const framing::FieldTable& /*errorInfo*/) -{ - broker::SessionHandler* s = state.getSessionState().getHandler(); - if (s) s->incomingExecutionException( - framing::execution::ErrorCode(errorCode), description); -} - - - -void SessionAdapter::TxHandlerImpl::select() -{ - state.startTx(); -} - -void SessionAdapter::TxHandlerImpl::commit() -{ - state.commit(&getBroker().getStore()); -} - -void SessionAdapter::TxHandlerImpl::rollback() -{ - state.rollback(); -} - -void SessionAdapter::DtxHandlerImpl::select() -{ - state.selectDtx(); -} - -XaResult SessionAdapter::DtxHandlerImpl::end(const Xid& xid, - bool fail, - bool suspend) -{ - try { - if (fail) { - state.endDtx(DtxManager::convert(xid), true); - if (suspend) { - throw CommandInvalidException(QPID_MSG("End and suspend cannot both be set.")); - } else { - return XaResult(XA_STATUS_XA_RBROLLBACK); - } - } else { - if (suspend) { - state.suspendDtx(DtxManager::convert(xid)); - } else { - state.endDtx(DtxManager::convert(xid), false); - } - return XaResult(XA_STATUS_XA_OK); - } - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::start(const Xid& xid, - bool join, - bool resume) -{ - if (join && resume) { - throw CommandInvalidException(QPID_MSG("Join and resume cannot both be set.")); - } - try { - if (resume) { - state.resumeDtx(DtxManager::convert(xid)); - } else { - state.startDtx(DtxManager::convert(xid), getBroker().getDtxManager(), join); - } - return XaResult(XA_STATUS_XA_OK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::prepare(const Xid& xid) -{ - try { - bool ok = getBroker().getDtxManager().prepare(DtxManager::convert(xid)); - return XaResult(ok ? XA_STATUS_XA_OK : XA_STATUS_XA_RBROLLBACK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::commit(const Xid& xid, - bool onePhase) -{ - try { - bool ok = getBroker().getDtxManager().commit(DtxManager::convert(xid), onePhase); - return XaResult(ok ? XA_STATUS_XA_OK : XA_STATUS_XA_RBROLLBACK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - - -XaResult SessionAdapter::DtxHandlerImpl::rollback(const Xid& xid) -{ - try { - getBroker().getDtxManager().rollback(DtxManager::convert(xid)); - return XaResult(XA_STATUS_XA_OK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -DtxRecoverResult SessionAdapter::DtxHandlerImpl::recover() -{ - std::set xids; - getBroker().getStore().collectPreparedXids(xids); - /* - * create array of long structs - */ - Array indoubt(0xAB); - for (std::set::iterator i = xids.begin(); i != xids.end(); i++) { - boost::shared_ptr xid(new Struct32Value(*i)); - indoubt.add(xid); - } - return DtxRecoverResult(indoubt); -} - -void SessionAdapter::DtxHandlerImpl::forget(const Xid& xid) -{ - //Currently no heuristic completion is supported, so this should never be used. - throw NotImplementedException(QPID_MSG("Forget not implemented. Branch with xid " << xid << " not heuristically completed!")); -} - -DtxGetTimeoutResult SessionAdapter::DtxHandlerImpl::getTimeout(const Xid& xid) -{ - uint32_t timeout = getBroker().getDtxManager().getTimeout(DtxManager::convert(xid)); - return DtxGetTimeoutResult(timeout); -} - - -void SessionAdapter::DtxHandlerImpl::setTimeout(const Xid& xid, - uint32_t timeout) -{ - if ((timeout > getBroker().getDtxMaxTimeout()) && (getBroker().getDtxMaxTimeout() > 0)) - throw InvalidArgumentException(QPID_MSG("xid " << xid << " has timeout " << timeout << " bigger than maximum allowed " << getBroker().getDtxMaxTimeout())); - getBroker().getDtxManager().setTimeout(DtxManager::convert(xid), timeout); -} - - -Queue::shared_ptr SessionAdapter::HandlerHelper::getQueue(const string& name) const { - Queue::shared_ptr queue; - if (name.empty()) { - throw framing::IllegalArgumentException(QPID_MSG("No queue name specified.")); - } else { - queue = session.getBroker().getQueues().get(name); - } - return queue; -} - -}} // namespace qpid::broker - - diff --git a/qpid/cpp/src/qpid/broker/SessionAdapter.h b/qpid/cpp/src/qpid/broker/SessionAdapter.h deleted file mode 100644 index 6c09d68254..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionAdapter.h +++ /dev/null @@ -1,272 +0,0 @@ -#ifndef _broker_SessionAdapter_h -#define _broker_SessionAdapter_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/broker/HandlerImpl.h" - -#include "qpid/Exception.h" -#include "qpid/framing/AMQP_ServerOperations.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/StructHelper.h" - -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -class Channel; -class Connection; -class Broker; -class Queue; - -/** - * SessionAdapter translates protocol-specific AMQP commands for one - * specific version of AMQP into calls on the core broker objects. It - * is a container for a collection of adapters. - * - * Each adapter class provides a client proxy to send methods to the - * peer broker or client. - * - */ - - class SessionAdapter : public HandlerImpl, public framing::AMQP_ServerOperations -{ - public: - SessionAdapter(SemanticState& session); - - framing::ProtocolVersion getVersion() const { return session.getConnection().getVersion();} - - MessageHandler* getMessageHandler(){ return &messageImpl; } - ExchangeHandler* getExchangeHandler(){ return &exchangeImpl; } - QueueHandler* getQueueHandler(){ return &queueImpl; } - ExecutionHandler* getExecutionHandler(){ return &executionImpl; } - TxHandler* getTxHandler(){ return &txImpl; } - DtxHandler* getDtxHandler(){ return &dtxImpl; } - - ConnectionHandler* getConnectionHandler() { throw framing::NotImplementedException("Class not implemented"); } - SessionHandler* getSessionHandler() { throw framing::NotImplementedException("Class not implemented"); } - FileHandler* getFileHandler() { throw framing::NotImplementedException("Class not implemented"); } - StreamHandler* getStreamHandler() { throw framing::NotImplementedException("Class not implemented"); } - - template void eachExclusiveQueue(F f) - { - queueImpl.eachExclusiveQueue(f); - } - - - private: - //common base for utility methods etc that are specific to this adapter - struct HandlerHelper : public HandlerImpl - { - HandlerHelper(SemanticState& s) : HandlerImpl(s) {} - - boost::shared_ptr getQueue(const std::string& name) const; - }; - - - class ExchangeHandlerImpl : - public ExchangeHandler, - public HandlerHelper - { - public: - ExchangeHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void declare(const std::string& exchange, const std::string& type, - const std::string& alternateExchange, - bool passive, bool durable, bool autoDelete, - const qpid::framing::FieldTable& arguments); - void delete_(const std::string& exchange, bool ifUnused); - framing::ExchangeQueryResult query(const std::string& name); - void bind(const std::string& queue, - const std::string& exchange, const std::string& routingKey, - const qpid::framing::FieldTable& arguments); - void unbind(const std::string& queue, - const std::string& exchange, - const std::string& routingKey); - framing::ExchangeBoundResult bound(const std::string& exchange, - const std::string& queue, - const std::string& routingKey, - const framing::FieldTable& arguments); - private: - void checkType(boost::shared_ptr exchange, const std::string& type); - - void checkAlternate(boost::shared_ptr exchange, - boost::shared_ptr alternate); - }; - - class QueueHandlerImpl : public QueueHandler, - public HandlerHelper - { - Broker& broker; - std::vector< boost::shared_ptr > exclusiveQueues; - //connectionId and userId are needed for queue-delete events for auto deleted, exclusive queues - std::string connectionId; - std::string userId; - - public: - QueueHandlerImpl(SemanticState& session); - ~QueueHandlerImpl(); - - void declare(const std::string& queue, - const std::string& alternateExchange, - bool passive, bool durable, bool exclusive, - bool autoDelete, - const qpid::framing::FieldTable& arguments); - void delete_(const std::string& queue, - bool ifUnused, bool ifEmpty); - void purge(const std::string& queue); - framing::QueueQueryResult query(const std::string& queue); - bool isLocal(const OwnershipToken* t) const; - - void destroyExclusiveQueues(); - void checkDelete(boost::shared_ptr queue, bool ifUnused, bool ifEmpty); - template void eachExclusiveQueue(F f) - { - std::for_each(exclusiveQueues.begin(), exclusiveQueues.end(), f); - } - }; - - class MessageHandlerImpl : - public MessageHandler, - public HandlerHelper - { - typedef boost::function RangedOperation; - RangedOperation releaseRedeliveredOp; - RangedOperation releaseOp; - RangedOperation rejectOp; - RangedOperation acceptOp; - - public: - MessageHandlerImpl(SemanticState& session); - void transfer(const std::string& destination, - uint8_t acceptMode, - uint8_t acquireMode); - - void accept(const framing::SequenceSet& commands); - - void reject(const framing::SequenceSet& commands, - uint16_t code, - const std::string& text); - - void release(const framing::SequenceSet& commands, - bool setRedelivered); - - framing::MessageAcquireResult acquire(const framing::SequenceSet&); - - void subscribe(const std::string& queue, - const std::string& destination, - uint8_t acceptMode, - uint8_t acquireMode, - bool exclusive, - const std::string& resumeId, - uint64_t resumeTtl, - const framing::FieldTable& arguments); - - void cancel(const std::string& destination); - - void setFlowMode(const std::string& destination, - uint8_t flowMode); - - void flow(const std::string& destination, - uint8_t unit, - uint32_t value); - - void flush(const std::string& destination); - - void stop(const std::string& destination); - - framing::MessageResumeResult resume(const std::string& destination, - const std::string& resumeId); - - }; - - class ExecutionHandlerImpl : public ExecutionHandler, public HandlerHelper - { - public: - ExecutionHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void sync(); - void result(const framing::SequenceNumber& commandId, const std::string& value); - void exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t fieldIndex, - const std::string& description, - const framing::FieldTable& errorInfo); - - }; - - class TxHandlerImpl : public TxHandler, public HandlerHelper - { - public: - TxHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void select(); - void commit(); - void rollback(); - }; - - class DtxHandlerImpl : public DtxHandler, public HandlerHelper - { - public: - DtxHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void select(); - - framing::XaResult start(const framing::Xid& xid, - bool join, - bool resume); - - framing::XaResult end(const framing::Xid& xid, - bool fail, - bool suspend); - - framing::XaResult commit(const framing::Xid& xid, - bool onePhase); - - void forget(const framing::Xid& xid); - - framing::DtxGetTimeoutResult getTimeout(const framing::Xid& xid); - - framing::XaResult prepare(const framing::Xid& xid); - - framing::DtxRecoverResult recover(); - - framing::XaResult rollback(const framing::Xid& xid); - - void setTimeout(const framing::Xid& xid, uint32_t timeout); - }; - - ExchangeHandlerImpl exchangeImpl; - QueueHandlerImpl queueImpl; - MessageHandlerImpl messageImpl; - ExecutionHandlerImpl executionImpl; - TxHandlerImpl txImpl; - DtxHandlerImpl dtxImpl; -}; -}} // namespace qpid::broker - - - -#endif /*!_broker_SessionAdapter_h*/ diff --git a/qpid/cpp/src/qpid/broker/SessionContext.h b/qpid/cpp/src/qpid/broker/SessionContext.h deleted file mode 100644 index 53f3e1bab3..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionContext.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_BROKER_SESSIONCONTEXT_H -#define QPID_BROKER_SESSIONCONTEXT_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/OwnershipToken.h" - -#include - -namespace qpid { - -class SessionId; - -namespace framing { -class AMQP_ClientProxy; -} -namespace broker { - -class Broker; -namespace amqp_0_10 { -class Connection; -} - -class SessionContext : public OwnershipToken -{ - public: - virtual ~SessionContext(){} - virtual bool isAttached() const = 0; - virtual amqp_0_10::Connection& getConnection() = 0; - virtual framing::AMQP_ClientProxy& getProxy() = 0; - virtual Broker& getBroker() = 0; - virtual uint16_t getChannel() const = 0; - virtual const SessionId& getSessionId() const = 0; - virtual bool addPendingExecutionSync() = 0; - virtual void setUnackedCount(uint64_t) {} -}; - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSIONCONTEXT_H*/ diff --git a/qpid/cpp/src/qpid/broker/SessionHandler.cpp b/qpid/cpp/src/qpid/broker/SessionHandler.cpp deleted file mode 100644 index 3d5faf2dab..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionHandler.cpp +++ /dev/null @@ -1,163 +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/broker/SessionHandler.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/SessionState.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/ConnectionOutputHandler.h" - -#include - -namespace qpid { -namespace broker { -using namespace framing; -using namespace std; -using namespace qpid::sys; - -namespace { -class DefaultErrorListener : public SessionHandler::ErrorListener { - public: - void connectionException(framing::connection::CloseCode code, const std::string& msg) { - QPID_LOG(error, "Connection exception: " << framing::createConnectionException(code, msg).what()); - } - void channelException(framing::session::DetachCode code, const std::string& msg) { - QPID_LOG(error, "Channel exception: " << framing::createChannelException(code, msg).what()); - } - void executionException(framing::execution::ErrorCode code, const std::string& msg) { - QPID_LOG(error, "Execution exception: " << framing::createSessionException(code, msg).what()); - } - void incomingExecutionException(framing::execution::ErrorCode code, const std::string& msg) { - QPID_LOG(debug, "Incoming execution exception: " << framing::createSessionException(code, msg).what()); - } - void detach() {} - - private: -}; -} - -SessionHandler::SessionHandler(amqp_0_10::Connection& c, ChannelId ch) - : qpid::amqp_0_10::SessionHandler(&c.getOutput(), ch), - connection(c), - proxy(out), - errorListener(boost::shared_ptr(new DefaultErrorListener())) -{ - c.getBroker().getSessionHandlerObservers().newSessionHandler(*this); -} - -SessionHandler::~SessionHandler() -{ - if (session.get()) - connection.getBroker().getSessionManager().forget(session->getId()); -} - -void SessionHandler::connectionException( - framing::connection::CloseCode code, const std::string& msg) -{ - // NOTE: must tell the error listener _before_ calling connection.close() - if (errorListener) - errorListener->connectionException(code, msg); - connection.close(code, msg); -} - -void SessionHandler::channelException( - framing::session::DetachCode code, const std::string& msg) -{ - if (errorListener) - errorListener->channelException(code, msg); -} - -void SessionHandler::executionException( - framing::execution::ErrorCode code, const std::string& msg) -{ - if (errorListener) - errorListener->executionException(code, msg); -} - -void SessionHandler::incomingExecutionException( - framing::execution::ErrorCode code, const std::string& msg) -{ - if (errorListener) - errorListener->incomingExecutionException(code, msg); -} - -amqp_0_10::Connection& SessionHandler::getConnection() { return connection; } - -const amqp_0_10::Connection& SessionHandler::getConnection() const { return connection; } - -void SessionHandler::handleDetach() { - qpid::amqp_0_10::SessionHandler::handleDetach(); - assert(&connection.getChannel(channel.get()) == this); - if (session.get()) - connection.getBroker().getSessionManager().detach(session); - assert(!session.get()); - if (errorListener) errorListener->detach(); - connection.closeChannel(channel.get()); -} - -void SessionHandler::setState(const std::string& name, bool force) { - assert(!session.get()); - SessionId id(connection.getUserId(), name); - session = connection.getBroker().getSessionManager().attach(*this, id, force); -} - -void SessionHandler::detaching() -{ - assert(session.get()); - session->disableOutput(); -} - -FrameHandler* SessionHandler::getInHandler() { return session.get() ? &session->in : 0; } -qpid::SessionState* SessionHandler::getState() { return session.get(); } - -void SessionHandler::readyToSend() { - if (session.get()) session->readyToSend(); -} - -/** - * Used by inter-broker bridges to set up session id and attach - */ -void SessionHandler::attachAs(const std::string& name) -{ - SessionId id(connection.getUserId(), name); - SessionState::Configuration config = connection.getBroker().getSessionManager().getSessionConfig(); - session.reset(new SessionState(connection.getBroker(), *this, id, config)); - sendAttach(false); -} - -/** - * TODO: this is a little ugly, fix it; its currently still relied on - * for 'push' bridges - */ -void SessionHandler::attached(const std::string& name) -{ - if (session.get()) { - session->addManagementObject(); // Delayed from attachAs() - qpid::amqp_0_10::SessionHandler::attached(name); - } else { - SessionId id(connection.getUserId(), name); - SessionState::Configuration config = connection.getBroker().getSessionManager().getSessionConfig(); - session.reset(new SessionState(connection.getBroker(), *this, id, config)); - markReadyToSend(); - } -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/SessionHandler.h b/qpid/cpp/src/qpid/broker/SessionHandler.h deleted file mode 100644 index ee6baed0b6..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionHandler.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef QPID_BROKER_SESSIONHANDLER_H -#define QPID_BROKER_SESSIONHANDLER_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/BrokerImportExport.h" -#include "qpid/amqp_0_10/SessionHandler.h" -#include "qpid/broker/SessionHandler.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include - -namespace qpid { -class SessionState; - -namespace broker { -namespace amqp_0_10 { -class Connection; -} -class SessionState; - -/** - * A SessionHandler is associated with each active channel. It - * receives incoming frames, handles session controls and manages the - * association between the channel and a session. - */ -class SessionHandler : public qpid::amqp_0_10::SessionHandler { - public: - class ErrorListener { - public: - virtual ~ErrorListener() {} - - /** Called when there is an outgoing connection-exception */ - virtual void connectionException( - framing::connection::CloseCode code, const std::string& msg) = 0; - /** Called when there is an outgoing channel-exception */ - virtual void channelException( - framing::session::DetachCode, const std::string& msg) = 0; - /** Called when there is an outgoing execution-exception */ - virtual void executionException( - framing::execution::ErrorCode, const std::string& msg) = 0; - - /** Called when there is an incoming execution-exception. - * Useful for inter-broker bridges. - */ - virtual void incomingExecutionException( - framing::execution::ErrorCode, const std::string& msg) = 0; - - /** Called when it is safe to delete the ErrorListener. */ - virtual void detach() = 0; - }; - - /** - *@param e must not be deleted until ErrorListener::detach has been called */ - SessionHandler(amqp_0_10::Connection&, framing::ChannelId); - ~SessionHandler(); - - /** Get broker::SessionState */ - SessionState* getSession() { return session.get(); } - const SessionState* getSession() const { return session.get(); } - - QPID_BROKER_EXTERN amqp_0_10::Connection& getConnection(); - QPID_BROKER_EXTERN const amqp_0_10::Connection& getConnection() const; - - framing::AMQP_ClientProxy& getProxy() { return proxy; } - const framing::AMQP_ClientProxy& getProxy() const { return proxy; } - - virtual void handleDetach(); - void attached(const std::string& name);//used by 'pushing' inter-broker bridges - void attachAs(const std::string& name);//used by 'pulling' inter-broker bridges - - QPID_BROKER_EXTERN void setErrorListener(boost::shared_ptr e) { errorListener = e; } - - // Called by SessionAdapter - void incomingExecutionException(framing::execution::ErrorCode, const std::string& msg); - - protected: - void setState(const std::string& sessionName, bool force); - qpid::SessionState* getState(); - framing::FrameHandler* getInHandler(); - void connectionException(framing::connection::CloseCode code, const std::string& msg); - void channelException(framing::session::DetachCode, const std::string& msg); - void executionException(framing::execution::ErrorCode, const std::string& msg); - void detaching(); - void readyToSend(); - - private: - struct SetChannelProxy : public framing::AMQP_ClientProxy { // Proxy that sets the channel. - framing::ChannelHandler setChannel; - SetChannelProxy(uint16_t ch, framing::FrameHandler* out) - : framing::AMQP_ClientProxy(setChannel), setChannel(ch, out) {} - }; - - amqp_0_10::Connection& connection; - framing::AMQP_ClientProxy proxy; - std::auto_ptr session; - boost::shared_ptr errorListener; -}; - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSIONHANDLER_H*/ diff --git a/qpid/cpp/src/qpid/broker/SessionHandlerObserver.h b/qpid/cpp/src/qpid/broker/SessionHandlerObserver.h deleted file mode 100644 index 6d0ea16254..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionHandlerObserver.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef QPID_BROKER_SESSIONHANDLEROBSERVER_H -#define QPID_BROKER_SESSIONHANDLEROBSERVER_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 "Observers.h" - -namespace qpid { -namespace broker { -class SessionHandler; - -/** - * Observer of session handler events. - */ -class SessionHandlerObserver -{ - public: - virtual ~SessionHandlerObserver() {} - virtual void newSessionHandler(SessionHandler&) {} -}; - - -class SessionHandlerObservers : public Observers { - public: - void newSessionHandler(SessionHandler& sh) { - each(boost::bind(&SessionHandlerObserver::newSessionHandler, _1, boost::ref(sh))); - } -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SESSIONHANDLEROBSERVER_H*/ diff --git a/qpid/cpp/src/qpid/broker/SessionManager.cpp b/qpid/cpp/src/qpid/broker/SessionManager.cpp deleted file mode 100644 index 7195e73ce5..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionManager.cpp +++ /dev/null @@ -1,104 +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/broker/SessionManager.h" -#include "qpid/broker/SessionState.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/log/Helpers.h" -#include "qpid/memory.h" - -#include -#include - -#include -#include -#include - -namespace qpid { -namespace broker { - -using boost::intrusive_ptr; -using namespace sys; -using namespace framing; - -SessionManager::SessionManager(const SessionState::Configuration& c, Broker& b) - : config(c), broker(b) {} - -SessionManager::~SessionManager() { - detached.clear(); // Must clear before destructor as session dtor will call forget() -} - -std::auto_ptr SessionManager::attach(SessionHandler& h, const SessionId& id, bool force) { - Mutex::ScopedLock l(lock); - eraseExpired(); // Clean up expired table - std::pair insert = attached.insert(id); - if (!insert.second && !force) - throw SessionBusyException(QPID_MSG("Session already attached: " << id)); - Detached::iterator i = std::find(detached.begin(), detached.end(), id); - std::auto_ptr state; - if (i == detached.end()) - state.reset(new SessionState(broker, h, id, config)); - else { - state.reset(detached.release(i).release()); - state->attach(h); - } - return state; -} - -void SessionManager::detach(std::auto_ptr session) { - Mutex::ScopedLock l(lock); - attached.erase(session->getId()); - session->detach(); - if (session->getTimeout() > 0) { - session->expiry = AbsTime(now(), session->getTimeout()*TIME_SEC); - if (session->mgmtObject != 0) { - session->mgmtObject->set_expireTime (Duration::FromEpoch()+session->getTimeout()*TIME_SEC); - } - detached.push_back(session.release()); // In expiry order - eraseExpired(); - } -} - -void SessionManager::forget(const SessionId& id) { - Mutex::ScopedLock l(lock); - attached.erase(id); -} - -void SessionManager::eraseExpired() { - // Called with lock held. - if (!detached.empty()) { - // This used to use a more elegant invocation of std::lower_bound - // but violated the strict weak ordering rule which Visual Studio - // enforced. See QPID-1424 for more info should you be tempted to - // replace the loop with something more elegant. - AbsTime now = AbsTime::now(); - Detached::iterator keep = detached.begin(); - while ((keep != detached.end()) && ((*keep).expiry < now)) - keep++; - if (detached.begin() != keep) { - QPID_LOG(debug, "Expiring sessions: " << log::formatList(detached.begin(), keep)); - detached.erase(detached.begin(), keep); - } - } -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/SessionManager.h b/qpid/cpp/src/qpid/broker/SessionManager.h deleted file mode 100644 index db88e7ec10..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionManager.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef QPID_BROKER_SESSIONMANAGER_H -#define QPID_BROKER_SESSIONMANAGER_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 -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -namespace qpid { -namespace broker { -class Broker; -class SessionState; -class SessionHandler; - -/** - * Create and manage SessionState objects. - */ -class SessionManager : private boost::noncopyable { - public: - SessionManager(const qpid::SessionState::Configuration&, Broker&); - - ~SessionManager(); - - /** Open a new active session, caller takes ownership */ - std::auto_ptr attach(SessionHandler& h, const SessionId& id, bool/*force*/); - - /** Return a detached session to the manager, start the timeout counter. */ - void detach(std::auto_ptr); - - /** Forget about an attached session. Called by SessionState destructor. */ - void forget(const SessionId&); - - Broker& getBroker() const { return broker; } - - const qpid::SessionState::Configuration& getSessionConfig() const { return config; } - - private: - typedef boost::ptr_vector Detached; // Sorted in expiry order. - typedef std::set Attached; - - void eraseExpired(); - - sys::Mutex lock; - Detached detached; - Attached attached; - qpid::SessionState::Configuration config; - Broker& broker; -}; - - - -}} // namespace qpid::broker - - - - - -#endif /*!QPID_BROKER_SESSIONMANAGER_H*/ diff --git a/qpid/cpp/src/qpid/broker/SessionOutputException.h b/qpid/cpp/src/qpid/broker/SessionOutputException.h deleted file mode 100644 index 7c1c5de926..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionOutputException.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_BROKER_SESSIONOUTPUTEXCEPTION_H -#define QPID_BROKER_SESSIONOUTPUTEXCEPTION_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" - -namespace qpid { -namespace broker { - -/** - * This exception is used to signal 'session' exceptions (aka - * execution exceptions in AMQP 0-10 terms) that occur during output - * processing. It simply allows the channel of the session to be - * specified in addition to the other details. Special treatment is - * required at present because the output processing chain is - * different from that which handles incoming commands (specifically - * AggregateOutput cannot reasonably handle exceptions as it has no - * context). - */ -struct SessionOutputException : qpid::SessionException -{ - const uint16_t channel; - SessionOutputException(const qpid::SessionException& e, uint16_t c) : qpid::SessionException(e.code, e.getMessage()), channel(c) {} -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SESSIONOUTPUTEXCEPTION_H*/ diff --git a/qpid/cpp/src/qpid/broker/SessionState.cpp b/qpid/cpp/src/qpid/broker/SessionState.cpp deleted file mode 100644 index 6836794622..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionState.cpp +++ /dev/null @@ -1,527 +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/broker/SessionState.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/SessionManager.h" -#include "qpid/broker/SessionHandler.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/ServerInvoker.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" - -#include -#include - -namespace qpid { -namespace broker { - -using namespace framing; -using sys::Mutex; -using boost::intrusive_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::sys::AbsTime; -//using qpid::sys::Timer; -namespace _qmf = qmf::org::apache::qpid::broker; - -SessionState::SessionState( - Broker& b, SessionHandler& h, const SessionId& id, - const SessionState::Configuration& config) - : qpid::SessionState(id, config), - broker(b), handler(&h), - semanticState(*this), - adapter(semanticState), - asyncCommandCompleter(new AsyncCommandCompleter(this)) -{ - addManagementObject(); - attach(h); -} - -void SessionState::addManagementObject() { - if (GetManagementObject()) return; // Already added. - Manageable* parent = broker.GetVhostObject (); - if (parent != 0) { - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent != 0) { - std::string name(getId().str()); - std::string fullName(name); - if (name.length() >= std::numeric_limits::max()) - name.resize(std::numeric_limits::max()-1); - mgmtObject = _qmf::Session::shared_ptr(new _qmf::Session (agent, this, parent, name)); - mgmtObject->set_fullName (fullName); - mgmtObject->set_attached (0); - mgmtObject->clr_expireTime(); - agent->addObject(mgmtObject); - } - } -} - -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) - mgmtObject->resourceDestroy (); -} - -AMQP_ClientProxy& SessionState::getProxy() { - assert(isAttached()); - return handler->getProxy(); -} - -uint16_t SessionState::getChannel() const { - assert(isAttached()); - return handler->getChannel(); -} - -amqp_0_10::Connection& SessionState::getConnection() { - assert(isAttached()); - return handler->getConnection(); -} - -bool SessionState::isLocal(const OwnershipToken* t) const -{ - return isAttached() && &(handler->getConnection()) == t; -} - -void SessionState::detach() { - QPID_LOG(debug, getId() << ": detached on broker."); - asyncCommandCompleter->detached(); - disableOutput(); - handler = 0; - if (mgmtObject != 0) - mgmtObject->set_attached (0); -} - -void SessionState::disableOutput() -{ - semanticState.detached(); //prevents further activateOutput calls until reattached -} - -void SessionState::attach(SessionHandler& h) { - QPID_LOG(debug, getId() << ": attached on broker."); - handler = &h; - if (mgmtObject != 0) - { - mgmtObject->set_attached (1); - mgmtObject->set_connectionRef (h.getConnection().GetManagementObject()->getObjectId()); - mgmtObject->set_channelId (h.getChannel()); - } - asyncCommandCompleter->attached(); -} - -ManagementObject::shared_ptr SessionState::GetManagementObject(void) const -{ - return mgmtObject; -} - -Manageable::status_t SessionState::ManagementMethod (uint32_t methodId, - Args& /*args*/, - std::string& /*text*/) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - switch (methodId) - { - case _qmf::Session::METHOD_DETACH : - if (handler != 0) { - handler->sendDetach(); - } - status = Manageable::STATUS_OK; - break; - - case _qmf::Session::METHOD_CLOSE : - /* - if (handler != 0) - { - handler->getConnection().closeChannel(handler->getChannel()); - } - status = Manageable::STATUS_OK; - break; - */ - - case _qmf::Session::METHOD_SOLICITACK : - case _qmf::Session::METHOD_RESETLIFESPAN : - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } - - return status; -} - -void SessionState::handleCommand(framing::AMQMethodBody* method) { - Invoker::Result result = invoke(adapter, *method); - if (!result.wasHandled()) - throw NotImplementedException(QPID_MSG("Not implemented: " << *method)); - if (currentCommand.isCompleteSync()) - completeCommand( - currentCommand.getId(), false/*needAccept*/, currentCommand.isSyncRequired(), - result.getResult()); -} - - -void SessionState::handleContent(AMQFrame& frame) -{ - if (frame.getBof() && frame.getBos()) //start of frameset - msgBuilder.start(currentCommand.getId()); - intrusive_ptr msg(msgBuilder.getMessage()); - msgBuilder.handle(frame); - if (frame.getEof() && frame.getEos()) {//end of frameset - if (frame.getBof()) { - //i.e this is a just a command frame, add a dummy header - AMQFrame header((AMQHeaderBody())); - header.setBof(false); - header.setEof(false); - msg->getFrames().append(header); - } - DeliverableMessage deliverable(Message(msg, msg), semanticState.getTxBuffer()); - if (broker.isTimestamping()) - msg->setTimestamp(); - msg->setPublisher(&(getConnection())); - msg->computeExpiration(); - - - IncompleteIngressMsgXfer xfer(this, msg); - msg->getIngressCompletion().begin(); - // This call should come before routing, because it calcs required credit. - msgBuilder.end(); - semanticState.route(deliverable.getMessage(), deliverable); - msg->getIngressCompletion().end(xfer); // allows msg to complete xfer - } -} - -void SessionState::sendAcceptAndCompletion() -{ - if (!accepted.empty()) { - getProxy().getMessage().accept(accepted); - accepted.clear(); - } - sendCompletion(); -} - -/** Invoked when the given command is finished being processed by all interested - * parties (eg. it is done being enqueued to all queues, its credit has been - * accounted for, etc). At this point the command is considered by this - * receiver as 'completed' (as defined by AMQP 0_10) - */ -void SessionState::completeCommand(SequenceNumber id, - bool requiresAccept, - bool requiresSync, - const std::string& result=std::string()) -{ - bool callSendCompletion = false; - receiverCompleted(id); - if (requiresAccept) - // will cause cmd's seq to appear in the next message.accept we send. - accepted.add(id); - - if (!result.empty()) - getProxy().getExecution().result(id, result); - - // Are there any outstanding Execution.Sync commands pending the - // completion of this cmd? If so, complete them. - while (!pendingExecutionSyncs.empty() && - (receiverGetIncomplete().empty() || - receiverGetIncomplete().front() >= pendingExecutionSyncs.front())) - { - const SequenceNumber syncId = pendingExecutionSyncs.front(); - pendingExecutionSyncs.pop(); - QPID_LOG(debug, getId() << ": delayed execution.sync " << syncId << " is completed."); - if (receiverGetIncomplete().contains(syncId)) - receiverCompleted(syncId); - callSendCompletion = true; // likely peer is pending for this completion. - } - - // if the sender has requested immediate notification of the completion... - if (requiresSync || callSendCompletion) { - sendAcceptAndCompletion(); - } -} - -void SessionState::handleIn(AMQFrame& frame) { - //TODO: make command handling more uniform, regardless of whether - //commands carry content. - AMQMethodBody* m = frame.getMethod(); - currentCommand = CurrentCommand(receiverGetCurrent(), m && m->isSync()); - - if (m == 0 || m->isContentBearing()) { - handleContent(frame); - } else if (frame.getBof() && frame.getEof()) { - handleCommand(frame.getMethod()); - } else { - throw InternalErrorException("Cannot handle multi-frame command segments yet"); - } -} - -void SessionState::handleOut(AMQFrame& frame) { - assert(handler); - handler->out(frame); -} - -DeliveryId SessionState::deliver(const qpid::broker::amqp_0_10::MessageTransfer& message, - const std::string& destination, bool isRedelivered, uint64_t ttl, - qpid::framing::message::AcceptMode acceptMode, qpid::framing::message::AcquireMode acquireMode, - const qpid::types::Variant::Map& annotations, bool sync) -{ - uint32_t maxFrameSize = getConnection().getFrameMax(); - assert(senderGetCommandPoint().offset == 0); - SequenceNumber commandId = senderGetCommandPoint().command; - - framing::AMQFrame method((framing::MessageTransferBody(framing::ProtocolVersion(), destination, acceptMode, acquireMode))); - method.setEof(false); - getProxy().getHandler().handle(method); - message.sendHeader(getProxy().getHandler(), maxFrameSize, isRedelivered, ttl, annotations); - message.sendContent(getProxy().getHandler(), maxFrameSize); - - assert(senderGetCommandPoint() == SessionPoint(commandId+1, 0)); // Delivery has moved sendPoint. - if (sync) { - AMQP_ClientProxy::Execution& p(getProxy().getExecution()); - Proxy::ScopedSync s(p); - p.sync(); - } - return commandId; -} - -void SessionState::sendCompletion() { - handler->sendCompletion(); -} - -void SessionState::senderCompleted(const SequenceSet& commands) { - qpid::SessionState::senderCompleted(commands); - semanticState.completed(commands); -} - -void SessionState::readyToSend() { - QPID_LOG(debug, getId() << ": ready to send, activating output."); - assert(handler); - semanticState.attached(); -} - -Broker& SessionState::getBroker() { return broker; } - -// Session resume is not fully implemented so it is useless to set a -// non-0 timeout. -void SessionState::setTimeout(uint32_t) { } - -// Current received command is an execution.sync command. -// Complete this command only when all preceding commands have completed. -// (called via the invoker() in handleCommand() above) -bool SessionState::addPendingExecutionSync() { - SequenceNumber id = currentCommand.getId(); - if (addPendingExecutionSync(id)) { - currentCommand.setCompleteSync(false); - QPID_LOG(debug, getId() << ": delaying completion of execution.sync " << id); - return true; - } - return false; -} - -bool SessionState::addPendingExecutionSync(SequenceNumber id) -{ - if (receiverGetIncomplete().front() < id) { - pendingExecutionSyncs.push(id); - asyncCommandCompleter->flushPendingMessages(); - return true; - } - return false; -} - -/** factory for creating a reference-counted IncompleteIngressMsgXfer object - * which will be attached to a message that will be completed asynchronously. - */ -boost::intrusive_ptr -SessionState::IncompleteIngressMsgXfer::clone() -{ - // Optimization: this routine is *only* invoked when the message needs to be asynchronously completed. - // If the client is pending the message.transfer completion, flush now to force immediate write to journal. - if (requiresSync) - msg->flush(); - else { - // otherwise, we need to track this message in order to flush it if an execution.sync arrives - // before it has been completed (see flushPendingMessages()) - pending = true; - completerContext->addPendingMessage(msg); - } - - return boost::intrusive_ptr(new SessionState::IncompleteIngressMsgXfer(*this)); -} - - -/** Invoked by the asynchronous completer associated with a received - * msg that is pending Completion. May be invoked by the IO thread - * (sync == true), or some external thread (!sync). - */ -void SessionState::IncompleteIngressMsgXfer::completed(bool sync) -{ - if (pending) completerContext->deletePendingMessage(id); - if (!sync) { - /** note well: this path may execute in any thread. It is safe to access - * the scheduledCompleterContext, since *this has a shared pointer to it. - * but not session! - */ - session = 0; - QPID_LOG(debug, ": async completion callback scheduled for msg seq=" << id); - completerContext->scheduleCommandCompletion(id, requiresAccept, requiresSync); - } else { - // this path runs directly from the ac->end() call in handleContent() above, - // so *session is definately valid. - if (session->isAttached()) { - QPID_LOG(debug, ": receive completed for msg seq=" << id); - session->completeCommand(id, requiresAccept, requiresSync); - } - } - completerContext = 0; -} - - -/** Track an ingress message that is pending completion */ -void SessionState::AsyncCommandCompleter::addPendingMessage(boost::intrusive_ptr msg) -{ - qpid::sys::ScopedLock l(completerLock); - std::pair > item(msg->getCommandId(), msg); - bool unique = pendingMsgs.insert(item).second; - if (!unique) { - assert(false); - } -} - - -/** pending message has completed */ -void SessionState::AsyncCommandCompleter::deletePendingMessage(SequenceNumber id) -{ - qpid::sys::ScopedLock l(completerLock); - pendingMsgs.erase(id); -} - - -/** done when an execution.sync arrives */ -void SessionState::AsyncCommandCompleter::flushPendingMessages() -{ - std::map > copy; - { - qpid::sys::ScopedLock l(completerLock); - pendingMsgs.swap(copy); // we've only tracked these in case a flush is needed, so nuke 'em now. - } - // drop lock, so it is safe to call "flush()" - for (std::map >::iterator i = copy.begin(); - i != copy.end(); ++i) { - i->second->flush(); - } -} - - -/** mark an ingress Message.Transfer command as completed. - * This method must be thread safe - it may run on any thread. - */ -void SessionState::AsyncCommandCompleter::scheduleCommandCompletion( - SequenceNumber cmd, - bool requiresAccept, - bool requiresSync) -{ - qpid::sys::ScopedLock l(completerLock); - - if (session && isAttached) { - CommandInfo info(cmd, requiresAccept, requiresSync); - completedCmds.push_back(info); - if (completedCmds.size() == 1) { - session->getConnection().requestIOProcessing( - boost::bind(&AsyncCommandCompleter::completeCommands, - session->asyncCommandCompleter)); - } - } -} - -void SessionState::AsyncCommandCompleter::schedule(boost::function f) { - if (session && isAttached) session->getConnection().requestIOProcessing(f); -} - -/** Cause the session to complete all completed commands. - * Executes on the IO thread. - */ -void SessionState::AsyncCommandCompleter::completeCommands() -{ - qpid::sys::ScopedLock l(completerLock); - - // when session is destroyed, it clears the session pointer via cancel(). - if (session && session->isAttached()) { - for (std::vector::iterator cmd = completedCmds.begin(); - cmd != completedCmds.end(); ++cmd) { - session->completeCommand( - cmd->cmd, cmd->requiresAccept, cmd->requiresSync); - } - } - completedCmds.clear(); -} - - -/** cancel any pending calls to scheduleComplete */ -void SessionState::AsyncCommandCompleter::cancel() -{ - qpid::sys::ScopedLock l(completerLock); - session = 0; -} - - -/** inform the completer that the session has attached, - * allows command completion scheduling from any thread */ -void SessionState::AsyncCommandCompleter::attached() -{ - qpid::sys::ScopedLock l(completerLock); - isAttached = true; -} - - -/** inform the completer that the session has detached, - * disables command completion scheduling from any thread */ -void SessionState::AsyncCommandCompleter::detached() -{ - qpid::sys::ScopedLock l(completerLock); - isAttached = false; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/SessionState.h b/qpid/cpp/src/qpid/broker/SessionState.h deleted file mode 100644 index b1f18747f3..0000000000 --- a/qpid/cpp/src/qpid/broker/SessionState.h +++ /dev/null @@ -1,332 +0,0 @@ -#ifndef QPID_BROKER_SESSION_H -#define QPID_BROKER_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/SessionState.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/Time.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Session.h" -#include "qpid/broker/SessionAdapter.h" -#include "qpid/broker/AsyncCompletion.h" -#include "qpid/broker/MessageBuilder.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/sys/Monitor.h" - -#include -#include -#include - -#include -#include -#include -#include - -namespace qpid { - -namespace framing { -class AMQP_ClientProxy; -} - -namespace sys { -class TimerTask; -} - -namespace broker { - -class Broker; -class ConnectionState; -class SessionHandler; -class SessionManager; - -/** - * Broker-side session state includes session's handler chains, which - * may themselves have state. - */ -class SessionState : public qpid::SessionState, - public SessionContext, - public management::Manageable, - public framing::FrameHandler::InOutHandler -{ - public: - SessionState(Broker&, SessionHandler&, const SessionId&, - const SessionState::Configuration&); - ~SessionState(); - bool isAttached() const { return handler; } - - void detach(); - void attach(SessionHandler& handler); - void disableOutput(); - - SessionHandler* getHandler() { return handler; } - - /** @pre isAttached() */ - framing::AMQP_ClientProxy& getProxy(); - - /** @pre isAttached() */ - uint16_t getChannel() const; - - /** @pre isAttached() */ - amqp_0_10::Connection& getConnection(); - bool isLocal(const OwnershipToken* t) const; - - Broker& getBroker(); - - void setTimeout(uint32_t seconds); - - void senderCompleted(const framing::SequenceSet& ranges); - - void sendCompletion(); - - DeliveryId deliver(const qpid::broker::amqp_0_10::MessageTransfer& message, - const std::string& destination, bool isRedelivered, uint64_t ttl, - qpid::framing::message::AcceptMode, qpid::framing::message::AcquireMode, - const qpid::types::Variant::Map& annotations, bool sync); - - // Manageable entry points - management::ManagementObject::shared_ptr GetManagementObject(void) const; - management::Manageable::status_t - ManagementMethod (uint32_t methodId, management::Args& args, std::string&); - - void readyToSend(); - - const SessionId& getSessionId() const { return getId(); } - - /** - * Used by ExecutionHandler sync command processing. Notifies - * the SessionState of a received Execution.Sync command. - * Return true if there are incomplete commands before the execution sync. - */ - bool addPendingExecutionSync(); - - /** - * Mark commannd ID as an execution sync point, completions will be sent - * when all commands up to that point are completed. - */ - bool addPendingExecutionSync(SequenceNumber id); - - - void setUnackedCount(uint64_t count) { - if (mgmtObject) - mgmtObject->set_unackedMessages(count); - } - - // Used to delay creation of management object for sessions - // belonging to inter-broker bridges - void addManagementObject(); - - // transaction-related methods just to update statistics - void startTx(); - void commitTx(); - void rollbackTx(); - - /** Send result and completion for a given command to the client. */ - void completeCommand(SequenceNumber id, bool requiresAccept, bool requiresSync, - const std::string& result); - - MessageBuilder& getMessageBuilder() { return msgBuilder; } - - private: - void handleCommand(framing::AMQMethodBody* method); - void handleContent(framing::AMQFrame& frame); - - void handleIn(framing::AMQFrame& frame); - void handleOut(framing::AMQFrame& frame); - - // End of the input & output chains. - void handleInLast(framing::AMQFrame& frame); - void handleOutLast(framing::AMQFrame& frame); - - void sendAcceptAndCompletion(); - - Broker& broker; - SessionHandler* handler; - sys::AbsTime expiry; // Used by SessionManager. - SemanticState semanticState; - SessionAdapter adapter; - MessageBuilder msgBuilder; - qmf::org::apache::qpid::broker::Session::shared_ptr mgmtObject; - qpid::framing::SequenceSet accepted; - - // sequence numbers for pending received Execution.Sync commands - std::queue pendingExecutionSyncs; - - public: - - /** Information about the currently executing command. - * Can only be used in the IO thread during command execution. - */ - class CurrentCommand { - public: - CurrentCommand( - SequenceNumber id_=0, bool syncRequired_=false, bool completeSync_=true ) : - id(id_), syncRequired(syncRequired_), completeSync(completeSync_) - {} - - SequenceNumber getId() const { return id; } - - /**@return true if the sync flag was set for the command. */ - bool isSyncRequired() const { return syncRequired; } - - /**@return true if the command should be completed synchronously - * in the handling thread. - */ - bool isCompleteSync() const { return completeSync; } - void setCompleteSync(bool b) { completeSync = b; } - - private: - SequenceNumber id; ///< Command identifier. - bool syncRequired; ///< True if sync flag set for the command. - bool completeSync; ///< Will be completed by handCommand. - }; - - CurrentCommand& getCurrentCommand() { return currentCommand; } - - /** This class provides a context for completing asynchronous commands in a thread - * safe manner. Asynchronous commands save their completion state in this class. - * This class then schedules the completeCommands() method in the IO thread. - * While running in the IO thread, completeCommands() may safely complete all - * saved commands without the risk of colliding with other operations on this - * SessionState. - */ - class AsyncCommandCompleter : public RefCounted { - private: - SessionState *session; - bool isAttached; - qpid::sys::Mutex completerLock; - - struct CommandInfo { - SequenceNumber cmd; // message.transfer command id - bool requiresAccept; - bool requiresSync; - - CommandInfo( - SequenceNumber c, bool a, bool s) - : cmd(c), requiresAccept(a), requiresSync(s) {} - }; - - std::vector completedCmds; - // If an ingress message does not require a Sync, we need to - // hold a reference to it in case an Execution.Sync command is received and we - // have to manually flush the message. - std::map > pendingMsgs; - - /** complete all pending commands, runs in IO thread */ - void completeCommands(); - - public: - AsyncCommandCompleter(SessionState *s) : session(s), isAttached(s->isAttached()) {}; - ~AsyncCommandCompleter() {}; - - /** track a message pending ingress completion */ - void addPendingMessage(boost::intrusive_ptr m); - void deletePendingMessage(SequenceNumber id); - void flushPendingMessages(); - /** schedule the processing of command completion. */ - void scheduleCommandCompletion(SequenceNumber cmd, - bool requiresAccept, - bool requiresSync); - void schedule(boost::function); - void cancel(); // called by SessionState destructor. - void attached(); // called by SessionState on attach() - void detached(); // called by SessionState on detach() - - SessionState* getSession() const { return session; } - }; - - boost::intrusive_ptr getAsyncCommandCompleter() { - return asyncCommandCompleter; - } - - /** Abstract class that represents a single asynchronous command that is - * pending completion. - */ - class AsyncCommandContext : public AsyncCompletion::Callback - { - public: - AsyncCommandContext(SessionState& ss ) - : id(ss.getCurrentCommand().getId()), - requiresSync(ss.getCurrentCommand().isSyncRequired()), - completerContext(ss.getAsyncCommandCompleter()) - {} - - virtual ~AsyncCommandContext() {} - - protected: - SequenceNumber id; - bool requiresSync; - boost::intrusive_ptr completerContext; - }; - - - private: - boost::intrusive_ptr asyncCommandCompleter; - CurrentCommand currentCommand; - - /** incomplete Message.transfer commands - inbound to broker from client - */ - class IncompleteIngressMsgXfer : public SessionState::AsyncCommandContext - { - public: - IncompleteIngressMsgXfer( SessionState *ss, - boost::intrusive_ptr m) - : AsyncCommandContext(*ss), - session(ss), - msg(m), - requiresAccept(m->requiresAccept()), - requiresSync(m->getFrames().getMethod()->isSync()), - pending(false) - { - assert(id == m->getCommandId()); - } - - virtual ~IncompleteIngressMsgXfer() {} - - virtual void completed(bool); - virtual boost::intrusive_ptr clone(); - - private: - SessionState *session; // only valid if sync flag in callback is true - boost::intrusive_ptr msg; - bool requiresAccept; - bool requiresSync; - bool pending; // true if msg saved on pending list... - }; - - friend class SessionManager; -}; - - -inline std::ostream& operator<<(std::ostream& out, const SessionState& session) { - return out << session.getId(); -} - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSION_H*/ diff --git a/qpid/cpp/src/qpid/broker/SignalHandler.cpp b/qpid/cpp/src/qpid/broker/SignalHandler.cpp deleted file mode 100644 index 16c141f21c..0000000000 --- a/qpid/cpp/src/qpid/broker/SignalHandler.cpp +++ /dev/null @@ -1,54 +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/broker/SignalHandler.h" -#include "qpid/broker/Broker.h" -#include "qpid/sys/Mutex.h" -#include - -namespace qpid { -namespace broker { - -// Lock is to ensure that broker is not concurrently set to 0 and -// deleted while we are in a call to broker->shutdown() - -sys::Mutex brokerLock; -Broker* SignalHandler::broker; - -void SignalHandler::setBroker(Broker* b) { - sys::Mutex::ScopedLock l(brokerLock); - broker = b; - signal(SIGINT,shutdownHandler); - signal(SIGTERM, shutdownHandler); - signal(SIGHUP,SIG_IGN); - signal(SIGCHLD,SIG_IGN); -} - -void SignalHandler::shutdown() { shutdownHandler(0); } - -void SignalHandler::shutdownHandler(int) { - sys::Mutex::ScopedLock l(brokerLock); - if (broker) { - broker->shutdown(); - broker = 0; - } -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/SignalHandler.h b/qpid/cpp/src/qpid/broker/SignalHandler.h deleted file mode 100644 index 7bfa9ea630..0000000000 --- a/qpid/cpp/src/qpid/broker/SignalHandler.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_BROKER_SIGNALHANDLER_H -#define QPID_BROKER_SIGNALHANDLER_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 broker { - -class Broker; - -/** - * Handle signals e.g. to shut-down a broker. - */ -class SignalHandler -{ - public: - /** Set the broker to be shutdown on signals. - * Must be reset by calling setBroker(0) before the broker is deleted. - */ - static void setBroker(Broker* broker); - - /** Initiate shut-down of broker */ - static void shutdown(); - - private: - static void shutdownHandler(int); - static Broker* broker; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SIGNALHANDLER_H*/ diff --git a/qpid/cpp/src/qpid/broker/System.cpp b/qpid/cpp/src/qpid/broker/System.cpp deleted file mode 100644 index f3535b0eec..0000000000 --- a/qpid/cpp/src/qpid/broker/System.cpp +++ /dev/null @@ -1,88 +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/broker/System.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/types/Uuid.h" -#include -#include - -using qpid::management::ManagementAgent; -using namespace qpid::broker; -using namespace std; -namespace _qmf = qmf::org::apache::qpid::broker; - -System::System (string _dataDir, Broker* broker) -{ - ManagementAgent* agent = broker ? broker->getManagementAgent() : 0; - - if (agent != 0) - { - - if (_dataDir.empty ()) - { - systemId.generate (); - } - else - { - string filename (_dataDir + "/systemId"); - ifstream inFile (filename.c_str ()); - - if (inFile.good ()) - { - inFile >> systemId; - inFile.close (); - } - else - { - systemId.generate (); - ofstream outFile (filename.c_str ()); - if (outFile.good ()) - { - outFile << systemId << endl; - outFile.close (); - } - } - } - - mgmtObject = _qmf::System::shared_ptr(new _qmf::System(agent, this, systemId)); - qpid::sys::SystemInfo::getSystemId (osName, - nodeName, - release, - version, - machine); - mgmtObject->set_osName (osName); - mgmtObject->set_nodeName (nodeName); - mgmtObject->set_release (release); - mgmtObject->set_version (version); - mgmtObject->set_machine (machine); - - agent->addObject(mgmtObject, 0, true); - } -} - -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 deleted file mode 100644 index 4a4af275c4..0000000000 --- a/qpid/cpp/src/qpid/broker/System.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _BrokerSystem_ -#define _BrokerSystem_ - -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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/framing/Uuid.h" -#include "qmf/org/apache/qpid/broker/System.h" -#include -#include - -namespace qpid { -namespace broker { - -class Broker; - -class System : public management::Manageable -{ - private: - - qmf::org::apache::qpid::broker::System::shared_ptr mgmtObject; - framing::Uuid systemId; - std::string osName, nodeName, release, version, machine; - - public: - - typedef boost::shared_ptr shared_ptr; - - System (std::string _dataDir, Broker* broker = 0); - - ~System (); - - management::ManagementObject::shared_ptr GetManagementObject(void) const - { return mgmtObject; } - - - /** Persistent UUID assigned by the management system to this broker. */ - framing::Uuid getSystemId() const { return systemId; } - /** Returns the OS name; e.g., GNU/Linux or Windows */ - std::string getOsName() const { return osName; } - /** Returns the node name. Usually the same as the host name. */ - std::string getNodeName() const { return nodeName; } - /** Returns the OS release identifier. */ - std::string getRelease() const { return release; } - /** Returns the OS release version (kernel, build, sp, etc.) */ - std::string getVersion() const { return version; } - /** Returns the hardware type. */ - std::string getMachine() const { return machine; } -}; - -}} - -#endif /*!_BrokerSystem_*/ diff --git a/qpid/cpp/src/qpid/broker/ThresholdAlerts.cpp b/qpid/cpp/src/qpid/broker/ThresholdAlerts.cpp deleted file mode 100644 index 41d20342c8..0000000000 --- a/qpid/cpp/src/qpid/broker/ThresholdAlerts.cpp +++ /dev/null @@ -1,113 +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/broker/ThresholdAlerts.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Message.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/broker/EventQueueThresholdCrossedUpward.h" -#include "qmf/org/apache/qpid/broker/EventQueueThresholdCrossedDownward.h" -#include "qmf/org/apache/qpid/broker/EventQueueThresholdExceeded.h" - -namespace qpid { -namespace broker { - -ThresholdAlerts::ThresholdAlerts(const std::string& n, - qpid::management::ManagementAgent& a, - const uint32_t ctu, - const uint32_t ctd, - const uint64_t stu, - const uint64_t std, - const bool bw) - : name(n), agent(a), - countThreshold(ctu), countThresholdDown(ctd), - sizeThreshold(stu), sizeThresholdDown(std), - count(0), size(0), countGoingUp(true), sizeGoingUp(true), backwardCompat(bw) {} - -void ThresholdAlerts::enqueued(const Message& m) -{ - size += m.getMessageSize(); - ++count; - - if (sizeGoingUp && sizeThreshold && size >= sizeThreshold) { - sizeGoingUp = false; - agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdCrossedUpward(name, count, size)); - if (backwardCompat) - agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdExceeded(name, count, size)); - } - - if (countGoingUp && countThreshold && count >= countThreshold) { - countGoingUp = false; - agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdCrossedUpward(name, count, size)); - if (backwardCompat) - agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdExceeded(name, count, size)); - } -} - -void ThresholdAlerts::dequeued(const Message& m) -{ - size -= m.getMessageSize(); - --count; - - if (!sizeGoingUp && sizeThreshold && size <= sizeThresholdDown) { - sizeGoingUp = true; - agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdCrossedDownward(name, count, size)); - } - - if (!countGoingUp && countThreshold && count <= countThresholdDown) { - countGoingUp = true; - agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdCrossedDownward(name, count, size)); - } -} - - - -void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent, - const uint64_t ctu, - const uint64_t _ctd, - const uint64_t stu, - const uint64_t _std) -{ - if (ctu || stu) { - uint64_t ctd = (_ctd == 0 || _ctd >= ctu) ? ctu >> 1 : _ctd; - uint64_t std = (_std == 0 || _std >= stu) ? stu >> 1 : _std; - - boost::shared_ptr observer( - new ThresholdAlerts(queue.getName(), agent, ctu, ctd, stu, std, (_ctd == 0 && _std == 0)) - ); - queue.getObservers().add(observer); - } -} - -void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent, - const QueueSettings& settings, uint16_t limitRatio) -{ - //If no explicit threshold settings were given use specified - //percentage of any limit from the policy. - uint32_t countThreshold = settings.alertThreshold.hasCount() ? settings.alertThreshold.getCount() : (settings.maxDepth.getCount()*limitRatio/100); - uint32_t sizeThreshold = settings.alertThreshold.hasSize() ? settings.alertThreshold.getSize() : (settings.maxDepth.getSize()*limitRatio/100); - uint32_t countThresholdDown = settings.alertThresholdDown.hasCount() ? settings.alertThresholdDown.getCount() : 0; - uint32_t sizeThresholdDown = settings.alertThresholdDown.hasSize() ? settings.alertThresholdDown.getSize() : 0; - - observe(queue, agent, countThreshold, countThresholdDown , sizeThreshold, sizeThresholdDown); -} - -}} diff --git a/qpid/cpp/src/qpid/broker/ThresholdAlerts.h b/qpid/cpp/src/qpid/broker/ThresholdAlerts.h deleted file mode 100644 index a8ff5270f3..0000000000 --- a/qpid/cpp/src/qpid/broker/ThresholdAlerts.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef QPID_BROKER_THRESHOLDALERTS_H -#define QPID_BROKER_THRESHOLDALERTS_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/QueueObserver.h" -#include "qpid/types/Variant.h" -#include - -namespace qpid { -namespace management { -class ManagementAgent; -} -namespace broker { - -class Queue; -struct QueueSettings; -/** - * Class to manage generation of QMF alerts when particular thresholds - * are breached on a queue. - */ -class ThresholdAlerts : public QueueObserver -{ - public: - ThresholdAlerts(const std::string& name, - qpid::management::ManagementAgent& agent, - const uint32_t countThreshold, - const uint32_t countThresholdDown, - const uint64_t sizeThreshold, - const uint64_t sizeThresholdDown, - const bool backwardCompat); - void enqueued(const Message&); - void dequeued(const Message&); - void acquired(const Message&) {}; - void requeued(const Message&) {}; - - static void observe(Queue& queue, qpid::management::ManagementAgent& agent, - const uint64_t countThreshold, - const uint64_t countThresholdDown, - const uint64_t sizeThreshold, - const uint64_t sizeThresholdDown); - static void observe(Queue& queue, qpid::management::ManagementAgent& agent, - const QueueSettings& settings, uint16_t limitRatio); - private: - const std::string name; - qpid::management::ManagementAgent& agent; - const uint32_t countThreshold; - const uint32_t countThresholdDown; - const uint64_t sizeThreshold; - const uint64_t sizeThresholdDown; - uint64_t count; - uint64_t size; - bool countGoingUp; - bool sizeGoingUp; - bool backwardCompat; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_THRESHOLDALERTS_H*/ diff --git a/qpid/cpp/src/qpid/broker/TopicExchange.cpp b/qpid/cpp/src/qpid/broker/TopicExchange.cpp deleted file mode 100644 index 558c900a4f..0000000000 --- a/qpid/cpp/src/qpid/broker/TopicExchange.cpp +++ /dev/null @@ -1,350 +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/broker/TopicExchange.h" -#include "qpid/broker/FedOps.h" -#include "qpid/log/Statement.h" -#include - - -namespace qpid { -namespace broker { - -using namespace qpid::framing; -using namespace qpid::sys; -using namespace std; -namespace _qmf = qmf::org::apache::qpid::broker; - -// iterator for federation ReOrigin bind operation -class TopicExchange::ReOriginIter : public BindingNode::TreeIterator { -public: - ReOriginIter() {}; - ~ReOriginIter() {}; - bool visit(BindingNode& node) { - if (node.bindings.fedBinding.hasLocal()) { - keys2prop.push_back(node.routePattern); - } - return true; - } - std::vector keys2prop; -}; - - -// match iterator used by route(): builds BindingList of all unique queues -// that match the routing key. -class TopicExchange::BindingsFinderIter : public BindingNode::TreeIterator { -public: - BindingsFinderIter(BindingList &bl) : b(bl) {}; - ~BindingsFinderIter() {}; - - BindingList& b; - std::set qSet; - - bool visit(BindingNode& node) { - - Binding::vector& qv(node.bindings.bindingVector); - for (Binding::vector::iterator j = qv.begin(); j != qv.end(); j++) { - // do not duplicate queues on the binding list - if (qSet.insert(j->get()->queue->getName()).second) { - b->push_back(*j); - } - } - return true; - } -}; - - - -// Iterator to visit all bindings until a given queue is found -class TopicExchange::QueueFinderIter : public BindingNode::TreeIterator { -public: - QueueFinderIter(Queue::shared_ptr queue) : queue(queue), found(false) {}; - ~QueueFinderIter() {}; - bool visit(BindingNode& node) { - - Binding::vector& qv(node.bindings.bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) { - if ((*q)->queue == queue) { - found = true; - return false; // search done - } - } - return true; // continue search - } - - Queue::shared_ptr queue; - bool found; -}; - - -class TopicExchange::Normalizer : public TokenIterator { - public: - Normalizer(string& p) - : TokenIterator(&p[0], &p[0]+p.size()), pattern(p) - { normalize(); } - - private: - // Apply 2 transformations: #.* -> *.# and #.# -> # - void normalize() { - while (!finished()) { - if (match1('#')) { - const char* hash1=token.first; - next(); - if (!finished()) { - if (match1('#')) { // Erase #.# -> # - pattern.erase(hash1-pattern.data(), 2); - token.first -= 2; - token.second -= 2; - end -= 2; - } - else if (match1('*')) { // Swap #.* -> *.# - swap(*const_cast(hash1), - *const_cast(token.first)); - } - } - } - else - next(); - } - } - - string& pattern; -}; - - - -// Convert sequences of * and # to a sequence of * followed by a single # -string TopicExchange::normalize(const string& pattern) { - string normal(pattern); - Normalizer n(normal); - return normal; -} - - -TopicExchange::TopicExchange(const string& _name, Manageable* _parent, Broker* b) - : Exchange(_name, _parent, b), - nBindings(0) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -TopicExchange::TopicExchange(const std::string& _name, bool _durable, bool autodelete, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, autodelete, _args, _parent, b), - nBindings(0) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit. - string fedOp(args ? args->getAsString(qpidFedOp) : fedOpBind); - string fedTags(args ? args->getAsString(qpidFedTags) : ""); - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - string routingPattern = normalize(routingKey); - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - RWlock::ScopedWlock l(lock); - BindingKey *bk = bindingTree.add(routingPattern); - if (bk) { - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) { - if ((*q)->queue == queue) { - // already bound, but may be from a different fedOrigin - bk->fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } - - Binding::shared_ptr binding (new Binding (routingPattern, queue, this, args ? *args : FieldTable(), fedOrigin)); - binding->startManagement(); - bk->bindingVector.push_back(binding); - nBindings++; - propagate = bk->fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - QPID_LOG(debug, "Binding key [" << routingPattern << "] to queue " << queue->getName() - << " on exchange " << getName() << " (origin=" << fedOrigin << ")"); - } - } else if (fedOp == fedOpUnbind) { - RWlock::ScopedWlock l(lock); - BindingKey* bk = getQueueBinding(queue, routingPattern); - if (bk) { - QPID_LOG(debug, "FedOpUnbind [" << routingPattern << "] from exchange " << getName() - << " on queue=" << queue->getName() << " origin=" << fedOrigin); - propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin); - // if this was the last binding for the queue, delete the binding - if (bk->fedBinding.countFedBindings(queue->getName()) == 0) { - deleteBinding(queue, routingPattern, bk); - } - } - } else if (fedOp == fedOpReorigin) { - /** gather up all the keys that need rebinding in a local vector - * while holding the lock. Then propagate once the lock is - * released - */ - ReOriginIter reOriginIter; - { - RWlock::ScopedRlock l(lock); - bindingTree.iterateAll( reOriginIter ); - } /* lock dropped */ - - for (std::vector::const_iterator key = reOriginIter.keys2prop.begin(); - key != reOriginIter.keys2prop.end(); key++) { - propagateFedOp( *key, string(), fedOpBind, string()); - } - } - - cc.clearCache(); // clear the cache before we IVE route. - routeIVE(); - if (propagate) - propagateFedOp(routingKey, fedTags, fedOp, fedOrigin); - return true; -} - -bool TopicExchange::unbind(Queue::shared_ptr queue, const string& constRoutingKey, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - QPID_LOG(debug, "Unbinding key [" << constRoutingKey << "] from queue " << queue->getName() - << " on exchange " << getName() << " origin=" << fedOrigin << ")" ); - - ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit. - RWlock::ScopedWlock l(lock); - string routingKey = normalize(constRoutingKey); - BindingKey* bk = getQueueBinding(queue, routingKey); - if (!bk) return false; - bool propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin); - deleteBinding(queue, routingKey, bk); - if (propagate) - propagateFedOp(routingKey, string(), fedOpUnbind, string()); - if (nBindings == 0) checkAutodelete(); - return true; -} - - -bool TopicExchange::deleteBinding(Queue::shared_ptr queue, - const std::string& routingKey, - BindingKey *bk) -{ - // Note well: write lock held by caller - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) - if ((*q)->queue == queue) - break; - if(q == qv.end()) return false; - qv.erase(q); - assert(nBindings > 0); - nBindings--; - - if(qv.empty()) { - bindingTree.remove(routingKey); - } - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - QPID_LOG(debug, "Unbound key [" << routingKey << "] from queue " << queue->getName() - << " on exchange " << getName()); - return true; -} - -/** returns a pointer to the BindingKey if the given queue is bound to this - * exchange using the routing pattern. 0 if queue binding does not exist. - */ -TopicExchange::BindingKey *TopicExchange::getQueueBinding(Queue::shared_ptr queue, const string& pattern) -{ - // Note well: lock held by caller.... - BindingKey *bk = bindingTree.get(pattern); // Exact match against binding pattern - if (!bk) return 0; - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) - if ((*q)->queue == queue) - break; - return (q != qv.end()) ? bk : 0; -} - -void TopicExchange::route(Deliverable& msg) -{ - const string& routingKey = msg.getMessage().getRoutingKey(); - // Note: PERFORMANCE CRITICAL!!! - BindingList b; - std::map::iterator it; - { // only lock the cache for read - RWlock::ScopedRlock cl(cacheLock); - it = bindingCache.find(routingKey); - if (it != bindingCache.end()) { - b = it->second; - } - } - PreRoute pr(msg, this); - if (!b.get()) // no cache hit - { - RWlock::ScopedRlock l(lock); - b = BindingList(new std::vector >); - BindingsFinderIter bindingsFinder(b); - bindingTree.iterateMatch(routingKey, bindingsFinder); - RWlock::ScopedWlock cwl(cacheLock); - bindingCache[routingKey] = b; // update cache - } - doRoute(msg, b); -} - -bool TopicExchange::isBound(Queue::shared_ptr queue, const string* const routingKey, const FieldTable* const) -{ - RWlock::ScopedRlock l(lock); - if (routingKey && queue) { - string key(normalize(*routingKey)); - return getQueueBinding(queue, key) != 0; - } else if (!routingKey && !queue) { - return nBindings > 0; - } else if (routingKey) { - if (bindingTree.get(*routingKey)) { - return true; - } - } else { - QueueFinderIter queueFinder(queue); - bindingTree.iterateAll( queueFinder ); - return queueFinder.found; - } - return false; -} - -TopicExchange::~TopicExchange() { - if (mgmtExchange != 0) - mgmtExchange->debugStats("destroying"); -} - -const std::string TopicExchange::typeName("topic"); - -bool TopicExchange::hasBindings() -{ - RWlock::ScopedRlock l(lock); - return nBindings > 0; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/TopicExchange.h b/qpid/cpp/src/qpid/broker/TopicExchange.h deleted file mode 100644 index d54f23a70d..0000000000 --- a/qpid/cpp/src/qpid/broker/TopicExchange.h +++ /dev/null @@ -1,122 +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. - * - */ -#ifndef _TopicExchange_ -#define _TopicExchange_ - -#include -#include -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/TopicKeyNode.h" - - -namespace qpid { -namespace broker { - -class TopicExchange : public virtual Exchange { - - class Normalizer; - - struct BindingKey { // binding for this node - Binding::vector bindingVector; - FedBinding fedBinding; - }; - - typedef TopicKeyNode BindingNode; - - BindingKey *getQueueBinding(Queue::shared_ptr queue, const std::string& pattern); - bool deleteBinding(Queue::shared_ptr queue, - const std::string& routingKey, - BindingKey *bk); - - class ReOriginIter; - class BindingsFinderIter; - class QueueFinderIter; - - BindingNode bindingTree; - unsigned long nBindings; - qpid::sys::RWlock lock; // protects bindingTree and nBindings - qpid::sys::RWlock cacheLock; // protects cache - std::map bindingCache; // cache of matched routes. - - class ClearCache { - private: - qpid::sys::RWlock* cacheLock; - std::map* bindingCache; - bool cleared; - public: - ClearCache(qpid::sys::RWlock* l, std::map* bc) : - cacheLock(l), bindingCache(bc),cleared(false) {}; - void clearCache() { - qpid::sys::RWlock::ScopedWlock l(*cacheLock); - if (!cleared) { - bindingCache->clear(); - cleared =true; - } - }; - ~ClearCache(){ - clearCache(); - }; - }; - -public: - QPID_BROKER_EXTERN static const std::string typeName; - - static QPID_BROKER_EXTERN std::string normalize(const std::string& pattern); - - QPID_BROKER_EXTERN TopicExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN TopicExchange(const std::string& _name, - bool _durable, bool autodelete, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~TopicExchange(); - virtual bool supportsDynamicBinding() { return true; } - - class TopicExchangeTester; - friend class TopicExchangeTester; - protected: - bool hasBindings(); -}; - - -} -} - -#endif diff --git a/qpid/cpp/src/qpid/broker/TopicKeyNode.h b/qpid/cpp/src/qpid/broker/TopicKeyNode.h deleted file mode 100644 index ac760b198e..0000000000 --- a/qpid/cpp/src/qpid/broker/TopicKeyNode.h +++ /dev/null @@ -1,371 +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. - * - */ -#ifndef _QPID_BROKER_TOPIC_KEY_NODE_ -#define _QPID_BROKER_TOPIC_KEY_NODE_ - -#include "qpid/broker/BrokerImportExport.h" -#include -#include -#include -#include - - -namespace qpid { -namespace broker { - -static const std::string STAR("*"); -static const std::string HASH("#"); - - -// Iterate over a string of '.'-separated tokens. -struct TokenIterator { - typedef std::pair Token; - - TokenIterator(const char* b, const char* e) : end(e), token(std::make_pair(b, std::find(b,e,'.'))) {} - - TokenIterator(const std::string& key) : end(&key[0]+key.size()), token(std::make_pair(&key[0], std::find(&key[0],end,'.'))) {} - - bool finished() const { return !token.first; } - - void next() { - if (token.second == end) - token.first = token.second = 0; - else { - token.first=token.second+1; - token.second=(std::find(token.first, end, '.')); - } - } - - void pop(std::string &top) { - ptrdiff_t l = len(); - if (l) { - top.assign(token.first, l); - } else top.clear(); - next(); - } - - bool match1(char c) const { - return token.second==token.first+1 && *token.first == c; - } - - bool match(const Token& token2) const { - ptrdiff_t l=len(); - return l == token2.second-token2.first && - strncmp(token.first, token2.first, l) == 0; - } - - bool match(const std::string& str) const { - ptrdiff_t l=len(); - return l == ptrdiff_t(str.size()) && - str.compare(0, l, token.first, l) == 0; - } - - ptrdiff_t len() const { return token.second - token.first; } - - - const char* end; - Token token; -}; - - -// Binding database: -// The dotted form of a binding key is broken up and stored in a directed tree graph. -// Common binding prefix are merged. This allows the route match alogrithm to quickly -// isolate those sub-trees that match a given routingKey. -// For example, given the routes: -// a.b.c.<...> -// a.b.d.<...> -// a.x.y.<...> -// The resulting tree would be: -// a-->b-->c-->... -// | +-->d-->... -// +-->x-->y-->... -// -template -class QPID_BROKER_CLASS_EXTERN TopicKeyNode { - - public: - - typedef boost::shared_ptr shared_ptr; - - // for database transversal (visit a node). - class TreeIterator { - public: - TreeIterator() {}; - virtual ~TreeIterator() {}; - virtual bool visit(TopicKeyNode& node) = 0; - }; - - TopicKeyNode() : isStar(false), isHash(false) {} - TopicKeyNode(const std::string& _t) : token(_t), isStar(_t == STAR), isHash(_t == HASH) {} - QPID_BROKER_EXTERN virtual ~TopicKeyNode() { - childTokens.clear(); - } - - // add normalizedRoute to tree, return associated T - QPID_BROKER_EXTERN T* add(const std::string& normalizedRoute) { - TokenIterator bKey(normalizedRoute); - return add(bKey, normalizedRoute); - } - - // return T associated with normalizedRoute - QPID_BROKER_EXTERN T* get(const std::string& normalizedRoute) { - TokenIterator bKey(normalizedRoute); - return get(bKey); - } - - // remove T associated with normalizedRoute - QPID_BROKER_EXTERN void remove(const std::string& normalizedRoute) { - TokenIterator bKey2(normalizedRoute); - remove(bKey2, normalizedRoute); - } - - // applies iter against each node in tree until iter returns false - QPID_BROKER_EXTERN bool iterateAll(TreeIterator& iter) { - if (!iter.visit(*this)) return false; - if (starChild && !starChild->iterateAll(iter)) return false; - if (hashChild && !hashChild->iterateAll(iter)) return false; - for (typename ChildMap::iterator ptr = childTokens.begin(); - ptr != childTokens.end(); ptr++) { - if (!ptr->second->iterateAll(iter)) return false; - } - return true; - } - - // applies iter against only matching nodes until iter returns false - QPID_BROKER_EXTERN bool iterateMatch(const std::string& routingKey, TreeIterator& iter) { - TokenIterator rKey(routingKey); - return iterateMatch( rKey, iter ); - } - - std::string routePattern; // normalized binding that matches this node - T bindings; // for matches against this node - - private: - - std::string token; // portion of pattern represented by this node - bool isStar; - bool isHash; - - // children - typedef std::map ChildMap; - ChildMap childTokens; - typename TopicKeyNode::shared_ptr starChild; // "*" subtree - typename TopicKeyNode::shared_ptr hashChild; // "#" subtree - - unsigned int getChildCount() { return childTokens.size() + - (starChild ? 1 : 0) + (hashChild ? 1 : 0); } - - T* add(TokenIterator& bKey, const std::string& fullPattern){ - if (bKey.finished()) { - // this node's binding - if (routePattern.empty()) { - routePattern = fullPattern; - } else assert(routePattern == fullPattern); - - return &bindings; - - } else { - // pop the topmost token & recurse... - - if (bKey.match(STAR)) { - if (!starChild) { - starChild.reset(new TopicKeyNode(STAR)); - } - bKey.next(); - return starChild->add(bKey, fullPattern); - - } else if (bKey.match(HASH)) { - if (!hashChild) { - hashChild.reset(new TopicKeyNode(HASH)); - } - bKey.next(); - return hashChild->add(bKey, fullPattern); - - } else { - typename ChildMap::iterator ptr; - std::string next_token; - bKey.pop(next_token); - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->add(bKey, fullPattern); - } else { - typename TopicKeyNode::shared_ptr child(new TopicKeyNode(next_token)); - childTokens[next_token] = child; - return child->add(bKey, fullPattern); - } - } - } - } - - - bool remove(TokenIterator& bKey, const std::string& fullPattern) { - bool remove; - if (!bKey.finished()) { - if (bKey.match(STAR)) { - bKey.next(); - if (starChild) { - remove = starChild->remove(bKey, fullPattern); - if (remove) { - starChild.reset(); - } - } - } else if (bKey.match(HASH)) { - bKey.next(); - if (hashChild) { - remove = hashChild->remove(bKey, fullPattern); - if (remove) { - hashChild.reset(); - } - } - } else { - typename ChildMap::iterator ptr; - std::string next_token; - bKey.pop(next_token); - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - remove = ptr->second->remove(bKey, fullPattern); - if (remove) { - childTokens.erase(ptr); - } - } - } - } - - // no bindings and no children == parent can delete this node. - return getChildCount() == 0 && bindings.bindingVector.empty(); - } - - - T* get(TokenIterator& bKey) { - if (bKey.finished()) { - return &bindings; - } - - std::string next_token; - bKey.pop(next_token); - - if (next_token == STAR) { - if (starChild) - return starChild->get(bKey); - } else if (next_token == HASH) { - if (hashChild) - return hashChild->get(bKey); - } else { - typename ChildMap::iterator ptr; - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->get(bKey); - } - } - - return 0; - } - - - bool iterateMatch(TokenIterator& rKey, TreeIterator& iter) { - if (isStar) return iterateMatchStar(rKey, iter); - if (isHash) return iterateMatchHash(rKey, iter); - return iterateMatchString(rKey, iter); - } - - - bool iterateMatchString(TokenIterator& rKey, TreeIterator& iter){ - // invariant: key has matched all previous tokens up to this node. - if (rKey.finished()) { - // exact match this node: visit if bound - if (!bindings.bindingVector.empty()) - if (!iter.visit(*this)) return false; - } - - // check remaining key against children, even if empty. - return iterateMatchChildren(rKey, iter); - } - - - bool iterateMatchStar(TokenIterator& rKey, TreeIterator& iter) { - // must match one token: - if (rKey.finished()) - return true; // match failed, but continue iteration on siblings - - // pop the topmost token - rKey.next(); - - if (rKey.finished()) { - // exact match this node: visit if bound - if (!bindings.bindingVector.empty()) - if (!iter.visit(*this)) return false; - } - - return iterateMatchChildren(rKey, iter); - } - - - bool iterateMatchHash(TokenIterator& rKey, TreeIterator& iter) { - // consume each token and look for a match on the - // remaining key. - while (!rKey.finished()) { - if (!iterateMatchChildren(rKey, iter)) return false; - rKey.next(); - } - - if (!bindings.bindingVector.empty()) - return iter.visit(*this); - - return true; - } - - - bool iterateMatchChildren(const TokenIterator& key, TreeIterator& iter) { - // always try glob - it can match empty keys - if (hashChild) { - TokenIterator tmp(key); - if (!hashChild->iterateMatch(tmp, iter)) - return false; - } - - if (!key.finished()) { - if (starChild) { - TokenIterator tmp(key); - if (!starChild->iterateMatch(tmp, iter)) - return false; - } - - if (!childTokens.empty()) { - TokenIterator newKey(key); - std::string next_token; - newKey.pop(next_token); - - typename ChildMap::iterator ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->iterateMatch(newKey, iter); - } - } - } - - return true; - } -}; - -} -} - -#endif diff --git a/qpid/cpp/src/qpid/broker/TransactionObserver.h b/qpid/cpp/src/qpid/broker/TransactionObserver.h deleted file mode 100644 index 5333d7b8d6..0000000000 --- a/qpid/cpp/src/qpid/broker/TransactionObserver.h +++ /dev/null @@ -1,82 +0,0 @@ -#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 - -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 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/TransactionalStore.h b/qpid/cpp/src/qpid/broker/TransactionalStore.h deleted file mode 100644 index 2a2bac0c51..0000000000 --- a/qpid/cpp/src/qpid/broker/TransactionalStore.h +++ /dev/null @@ -1,60 +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. - * - */ -#ifndef _TransactionalStore_ -#define _TransactionalStore_ - -#include -#include -#include - -namespace qpid { -namespace broker { - -struct InvalidTransactionContextException : public std::exception {}; - -class TransactionContext { -public: - virtual ~TransactionContext(){} -}; - -class TPCTransactionContext : public TransactionContext { -public: - virtual ~TPCTransactionContext(){} -}; - -class TransactionalStore { -public: - virtual std::auto_ptr begin() = 0; - virtual std::auto_ptr begin(const std::string& xid) = 0; - virtual void prepare(TPCTransactionContext& txn) = 0; - virtual void commit(TransactionContext& txn) = 0; - virtual void abort(TransactionContext& txn) = 0; - - virtual void collectPreparedXids(std::set& xids) = 0; - - virtual ~TransactionalStore(){} -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/TxAccept.cpp b/qpid/cpp/src/qpid/broker/TxAccept.cpp deleted file mode 100644 index 496f8a2a42..0000000000 --- a/qpid/cpp/src/qpid/broker/TxAccept.cpp +++ /dev/null @@ -1,95 +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/broker/TxAccept.h" -#include "qpid/broker/TransactionObserver.h" -#include "qpid/broker/Queue.h" -#include "qpid/log/Statement.h" - -using std::bind1st; -using std::bind2nd; -using std::mem_fun_ref; -using namespace qpid::broker; -using qpid::framing::SequenceSet; -using qpid::framing::SequenceNumber; - - -TxAccept::TxAccept(const SequenceSet& _acked, DeliveryRecords& _unacked) : - acked(_acked), unacked(_unacked) -{} - -void TxAccept::each(boost::function f) { - DeliveryRecords::iterator dr = unacked.begin(); - SequenceSet::iterator seq = acked.begin(); - while(dr != unacked.end() && seq != acked.end()) { - if (dr->getId() == *seq) { - f(*dr); - ++dr; - ++seq; - } - else if (dr->getId() < *seq) ++dr; - else if (dr->getId() > *seq) ++seq; - } -} - -bool TxAccept::prepare(TransactionContext* ctxt) throw() -{ - try{ - each(bind(&DeliveryRecord::dequeue, _1, ctxt)); - return true; - }catch(const std::exception& e){ - QPID_LOG(error, "Failed to prepare: " << e.what()); - return false; - }catch(...){ - QPID_LOG(error, "Failed to prepare"); - return false; - } -} - -void TxAccept::commit() throw() -{ - try { - each(bind(&DeliveryRecord::committed, _1)); - each(bind(&DeliveryRecord::setEnded, _1)); - //now remove if isRedundant(): - if (!acked.empty()) { - AckRange r = DeliveryRecord::findRange(unacked, acked.front(), acked.back()); - DeliveryRecords::iterator removed = - remove_if(r.start, r.end, mem_fun_ref(&DeliveryRecord::isRedundant)); - unacked.erase(removed, r.end); - } - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } -} - -void TxAccept::rollback() throw() {} - -namespace { -void callObserverDR(boost::shared_ptr 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 deleted file mode 100644 index 97e82ffa3f..0000000000 --- a/qpid/cpp/src/qpid/broker/TxAccept.h +++ /dev/null @@ -1,64 +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. - * - */ -#ifndef _TxAccept_ -#define _TxAccept_ - -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/TxOp.h" -#include -#include -#include -#include - -namespace qpid { -namespace broker { -/** - * Defines the transactional behaviour for accepts received by - * a transactional channel. - */ -class TxAccept : public TxOp { - typedef boost::shared_ptr ObserverPtr; - - void each(boost::function); - - framing::SequenceSet acked; - DeliveryRecords& unacked; - - 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(){} -}; -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/broker/TxBuffer.cpp b/qpid/cpp/src/qpid/broker/TxBuffer.cpp deleted file mode 100644 index f7552f16a3..0000000000 --- a/qpid/cpp/src/qpid/broker/TxBuffer.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 "qpid/broker/TxBuffer.h" -#include "qpid/broker/TransactionObserver.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" - -#include -#include - -namespace qpid { -namespace broker{ - -using boost::mem_fn; -using framing::InternalErrorException; - -TxBuffer::TxBuffer() : observer(new NullTransactionObserver) {} - -bool TxBuffer::prepare(TransactionContext* const ctxt) -{ - // The observer may call startCompleter to delay completion. - if (!observer->prepare()) return false; - for(op_iterator i = ops.begin(); i != ops.end(); i++){ - if(!(*i)->prepare(ctxt)) return false; - } - // At this point prepare has succeeded locally but if completion is delayed, - // then completing threads may call setError to indicate an error. - return true; -} - -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); -} - -void TxBuffer::startCommit(TransactionalStore* const store) -{ - if (!store) throw Exception("Can't commit transaction, no store."); - txContext.reset(store->begin().release()); - if (!prepare(txContext.get())) - setError("Transaction prepare failed."); -} - -// Called when async completion is complete. -std::string TxBuffer::endCommit(TransactionalStore* const store) { - std::string e; - { - sys::Mutex::ScopedLock l(errorLock); - e = error; - } - if (!e.empty()) { - store->abort(*txContext); - rollback(); - throw InternalErrorException(e); - } - else { - store->commit(*txContext); - commit(); - } - return std::string(); // There is no result from tx.commit -} - -void TxBuffer::setError(const std::string& e) { - QPID_LOG(error, "Asynchronous transaction error: " << e); - sys::Mutex::ScopedLock l(errorLock); - if (!error.empty()) error += " "; - error += e; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/TxBuffer.h b/qpid/cpp/src/qpid/broker/TxBuffer.h deleted file mode 100644 index 2478b78138..0000000000 --- a/qpid/cpp/src/qpid/broker/TxBuffer.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef QPID_BROKER_TXBUFFER_H -#define QPID_BROKER_TXBUFFER_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/BrokerImportExport.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/broker/TxOp.h" -#include "qpid/broker/AsyncCompletion.h" -#include "qpid/sys/Mutex.h" -#include -#include -#include - - -namespace qpid { -namespace broker { -class TransactionObserver; - -/** - * Represents a single transaction. As such, an instance of this class - * will hold a list of operations representing the workload of the - * 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 - * consistent. (3) can only be done on commit, after a successful - * prepare. There is a little more flexibility with (2) but any - * changes made during prepare should be subject to the control of the - * TransactionalStore in use. - * - * TxBuffer inherits AsyncCompletion because transactions can be completed - * asynchronously if the broker is part of a HA cluster. - */ -class TxBuffer : public AsyncCompletion { - private: - typedef std::vector::iterator op_iterator; - std::vector ops; - boost::shared_ptr observer; - std::auto_ptr txContext; - std::string error; - sys::Mutex errorLock; - - public: - 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(); - - /** - * Start a local commit - may complete asynchronously. - */ - QPID_BROKER_EXTERN void startCommit(TransactionalStore* const store); - - /** End a commit, called via async completion. - *@return encoded result, not used here. - */ - QPID_BROKER_EXTERN std::string endCommit(TransactionalStore* const store); - - QPID_BROKER_EXTERN void setObserver(boost::shared_ptr o) { - observer = o; - } - - QPID_BROKER_EXTERN boost::shared_ptr getObserver() const { - return observer; - } - - /** Set an error to be raised from endCommit when the commit completes. - * Called from completer threads if we are doing async completion. - * This is the only TxBuffer function called outside the IO thread. - */ - QPID_BROKER_EXTERN void setError(const std::string& message); -}; - -}} // namespace qpid::broker - - -#endif /*!QPID_BROKER_TXBUFFER_H*/ diff --git a/qpid/cpp/src/qpid/broker/TxDequeue.cpp b/qpid/cpp/src/qpid/broker/TxDequeue.cpp deleted file mode 100644 index e9a2e0ca98..0000000000 --- a/qpid/cpp/src/qpid/broker/TxDequeue.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/TxDequeue.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/TransactionObserver.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -TxDequeue::TxDequeue(QueueCursor m, boost::shared_ptr q, - qpid::framing::SequenceNumber mId, qpid::framing::SequenceNumber rId) - : message(m), queue(q), messageId(mId), replicationId(rId), releaseOnAbort(true), redeliveredOnAbort(true) {} - -bool TxDequeue::prepare(TransactionContext* ctxt) throw() -{ - try{ - queue->dequeue(ctxt, message); - return true; - }catch(const std::exception& e){ - QPID_LOG(error, "Failed to prepare: " << e.what()); - return false; - }catch(...){ - QPID_LOG(error, "Failed to prepare"); - return false; - } -} - -void TxDequeue::commit() throw() -{ - try { - queue->dequeueCommitted(message); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } -} - -void TxDequeue::rollback() throw() -{ - if (releaseOnAbort) queue->release(message, redeliveredOnAbort); -} - -void TxDequeue::callObserver(const boost::shared_ptr& observer) -{ - observer->dequeue(queue, messageId, replicationId); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/TxDequeue.h b/qpid/cpp/src/qpid/broker/TxDequeue.h deleted file mode 100644 index e861bcaa77..0000000000 --- a/qpid/cpp/src/qpid/broker/TxDequeue.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_BROKER_TXDEQUEUE_H -#define QPID_BROKER_TXDEQUEUE_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/QueueCursor.h" -#include "qpid/broker/TxOp.h" -#include "qpid/framing/SequenceNumber.h" - -namespace qpid { -namespace broker { -class Queue; - -/** - * Transaction dequeue operation - */ -class TxDequeue: public TxOp -{ - public: - TxDequeue(QueueCursor message, boost::shared_ptr queue, - qpid::framing::SequenceNumber messageId, qpid::framing::SequenceNumber replicationId); - bool prepare(TransactionContext* ctxt) throw(); - void commit() throw(); - void rollback() throw(); - void callObserver(const boost::shared_ptr&); - private: - QueueCursor message; - boost::shared_ptr queue; - qpid::framing::SequenceNumber messageId; - qpid::framing::SequenceNumber replicationId; - bool releaseOnAbort; - bool redeliveredOnAbort; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_TXDEQUEUE_H*/ diff --git a/qpid/cpp/src/qpid/broker/TxOp.h b/qpid/cpp/src/qpid/broker/TxOp.h deleted file mode 100644 index 00303eb27c..0000000000 --- a/qpid/cpp/src/qpid/broker/TxOp.h +++ /dev/null @@ -1,45 +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. - * - */ -#ifndef _TxOp_ -#define _TxOp_ - -#include "qpid/broker/TransactionalStore.h" -#include - -namespace qpid { -namespace broker { -class TransactionObserver; - -class TxOp{ - public: - typedef boost::shared_ptr shared_ptr; - - virtual bool prepare(TransactionContext*) throw() = 0; - virtual void commit() throw() = 0; - virtual void rollback() throw() = 0; - virtual void callObserver(const boost::shared_ptr&) = 0; - virtual ~TxOp(){} -}; - -}} // namespace qpid::broker - - -#endif diff --git a/qpid/cpp/src/qpid/broker/Vhost.cpp b/qpid/cpp/src/qpid/broker/Vhost.cpp deleted file mode 100644 index 8fd88601f5..0000000000 --- a/qpid/cpp/src/qpid/broker/Vhost.cpp +++ /dev/null @@ -1,54 +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/broker/Vhost.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" - -using namespace qpid::broker; -using qpid::management::ManagementAgent; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { namespace management { -class Manageable; -}} - -Vhost::Vhost (qpid::management::Manageable* parentBroker, Broker* broker) -{ - if (parentBroker != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - - if (agent != 0) - { - mgmtObject = _qmf::Vhost::shared_ptr(new _qmf::Vhost(agent, this, parentBroker, "/")); - agent->addObject(mgmtObject, 0, true); - } - } -} - -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 deleted file mode 100644 index 06a11db8ea..0000000000 --- a/qpid/cpp/src/qpid/broker/Vhost.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _Vhost_ -#define _Vhost_ - -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT 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 "qmf/org/apache/qpid/broker/Vhost.h" -#include - -namespace qpid { -namespace broker { - -class Broker; -class Vhost : public management::Manageable -{ - private: - - qmf::org::apache::qpid::broker::Vhost::shared_ptr mgmtObject; - - public: - - typedef boost::shared_ptr shared_ptr; - - Vhost (management::Manageable* parentBroker, Broker* broker = 0); - - ~Vhost (); - - management::ManagementObject::shared_ptr GetManagementObject (void) const - { return mgmtObject; } - void setFederationTag(const std::string& tag); -}; - -}} - -#endif /*!_Vhost_*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Authorise.cpp b/qpid/cpp/src/qpid/broker/amqp/Authorise.cpp deleted file mode 100644 index 57d995cb07..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Authorise.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "Authorise.h" -#include "Exception.h" -#include "Filter.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/broker/AclModule.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/types/Variant.h" -#include -#include - -namespace qpid { -namespace broker { -namespace amqp { -namespace { -const std::string B_TRUE("true"); -const std::string B_FALSE("false"); -const std::string POLICY_TYPE("qpid.policy_type"); -} - -Authorise::Authorise(const std::string& u, AclModule* a) : user(u), acl(a) {} -void Authorise::access(const std::string& name) -{ - if (acl) { - std::map params; - if (!acl->authorise(user, acl::ACT_ACCESS, acl::OBJ_EXCHANGE, name, ¶ms)) - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG("ACL denied exchange access request from " << user)); - } -} -void Authorise::access(boost::shared_ptr exchange) -{ - if (acl) { - std::map params; - params.insert(std::make_pair(acl::PROP_TYPE, exchange->getType())); - params.insert(std::make_pair(acl::PROP_DURABLE, exchange->isDurable() ? B_TRUE : B_FALSE)); - if (!acl->authorise(user, acl::ACT_ACCESS, acl::OBJ_EXCHANGE, exchange->getName(), ¶ms)) - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG("ACL denied exchange access request from " << user)); - } -} -void Authorise::access(boost::shared_ptr queue) -{ - if (acl) { - const QueueSettings& settings = queue->getSettings(); - std::map params; - boost::shared_ptr altex = queue->getAlternateExchange(); - if (altex) - params.insert(std::make_pair(acl::PROP_ALTERNATE, altex->getName())); - params.insert(std::make_pair(acl::PROP_DURABLE, settings.durable ? B_TRUE : B_FALSE)); - params.insert(std::make_pair(acl::PROP_EXCLUSIVE, queue->hasExclusiveOwner() ? B_TRUE : B_FALSE)); - params.insert(std::make_pair(acl::PROP_AUTODELETE, settings.autodelete ? B_TRUE : B_FALSE)); - qpid::types::Variant::Map::const_iterator i = settings.original.find(POLICY_TYPE); - if (i != settings.original.end()) - params.insert(std::make_pair(acl::PROP_POLICYTYPE, i->second.asString())); - if (settings.maxDepth.hasCount()) - params.insert(std::make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast(settings.maxDepth.getCount()))); - if (settings.maxDepth.hasCount()) - params.insert(std::make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast(settings.maxDepth.getSize()))); - if (!acl->authorise(user, acl::ACT_ACCESS, acl::OBJ_QUEUE, queue->getName(), ¶ms) ) - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG("ACL denied queue access request from " << user)); - } -} - -void Authorise::incoming(boost::shared_ptr exchange) -{ - access(exchange); - //can't check publish permission here as do not yet know routing key -} -void Authorise::incoming(boost::shared_ptr queue) -{ - access(queue); - if (acl) { - if (!acl->authorise(user, acl::ACT_PUBLISH, acl::OBJ_EXCHANGE, std::string()/*default exchange*/, queue->getName())) - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG(user << " cannot publish to queue " << queue->getName())); - } -} -void Authorise::outgoing(boost::shared_ptr exchange, boost::shared_ptr queue, const Filter& filter) -{ - access(exchange); - if (acl) { - std::map params; - params.insert(std::make_pair(acl::PROP_QUEUENAME, queue->getName())); - params.insert(std::make_pair(acl::PROP_ROUTINGKEY, filter.getBindingKey(exchange))); - - if (!acl->authorise(user, acl::ACT_BIND, acl::OBJ_EXCHANGE, exchange->getName(), ¶ms)) - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG("ACL denied exchange bind request from " << user)); - - if (!acl->authorise(user, acl::ACT_CONSUME, acl::OBJ_QUEUE, queue->getName(), NULL)) - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG("ACL denied queue subscribe request from " << user)); - } -} - -void Authorise::outgoing(boost::shared_ptr queue) -{ - access(queue); - if (acl) { - if (!acl->authorise(user, acl::ACT_CONSUME, acl::OBJ_QUEUE, queue->getName(), NULL)) - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG("ACL denied queue subscribe request from " << user)); - } -} - -void Authorise::route(boost::shared_ptr exchange, const Message& msg) -{ - if (acl && acl->doTransferAcl()) { - if (!acl->authorise(user, acl::ACT_PUBLISH, acl::OBJ_EXCHANGE, exchange->getName(), msg.getRoutingKey())) - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG(user << " cannot publish to " << exchange->getName() << " with routing-key " << msg.getRoutingKey())); - } -} - -void Authorise::interlink() -{ - if (acl && acl->userAclRules()) { - if (!acl->authorise(user, acl::ACT_CREATE, acl::OBJ_LINK, "")){ - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG("ACL denied " << user << " a AMQP 1.0 link")); - } - } -} - -void Authorise::access(const std::string& node, bool queueRequested, bool exchangeRequested) -{ - if (acl) { - std::map params; - bool checkExchange = true; - bool checkQueue = true; - if (exchangeRequested) checkQueue = false; - else if (queueRequested) checkExchange = false; - - bool allowExchange = !checkExchange || acl->authorise(user, acl::ACT_ACCESS, acl::OBJ_EXCHANGE, node, ¶ms); - bool allowQueue = !checkQueue || acl->authorise(user, acl::ACT_ACCESS, acl::OBJ_QUEUE, node, ¶ms); - - if (!allowQueue || !allowExchange) { - throw Exception(qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS, QPID_MSG("ACL denied access request to " << node << " from " << user)); - } - } -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Authorise.h b/qpid/cpp/src/qpid/broker/amqp/Authorise.h deleted file mode 100644 index 3506cab845..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Authorise.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef QPID_BROKER_AMQP_AUTHORISE_H -#define QPID_BROKER_AMQP_AUTHORISE_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 -#include - -namespace qpid { -namespace broker { -class AclModule; -class Exchange; -class Message; -class Queue; -namespace amqp { -class Filter; - -/** - * Class to handle authorisation requests (and hide the ACL mess behind) - */ -class Authorise -{ - public: - Authorise(const std::string& user, AclModule*); - void access(const std::string& name); - void access(boost::shared_ptr); - void access(boost::shared_ptr); - void incoming(boost::shared_ptr); - void incoming(boost::shared_ptr); - void outgoing(boost::shared_ptr, boost::shared_ptr, const Filter&); - void outgoing(boost::shared_ptr); - void route(boost::shared_ptr, const Message&); - void interlink(); - /** - * Used to determine whether the user has access permission for a - * given node name. If a specific type of node was requested, only - * acces to that type is checked. Otherwise access to either queue - * or exchange is required. - */ - void access(const std::string& name, bool queueRequested, bool exchangeRequested); - private: - const std::string user; - AclModule* const acl; - -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_AUTHORISE_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/BrokerContext.cpp b/qpid/cpp/src/qpid/broker/amqp/BrokerContext.cpp deleted file mode 100644 index 9f7ae17293..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/BrokerContext.cpp +++ /dev/null @@ -1,33 +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 "BrokerContext.h" - -namespace qpid { -namespace broker { -namespace amqp { -BrokerContext::BrokerContext(Broker& b, Interconnects& i, TopicRegistry& t, NodePolicyRegistry& np, const std::string& d) : broker(b), interconnects(i), topics(t), nodePolicies(np), domain(d) {} -BrokerContext::BrokerContext(BrokerContext& c) : broker(c.broker), interconnects(c.interconnects), topics(c.topics), nodePolicies(c.nodePolicies), domain(c.domain) {} -Broker& BrokerContext::getBroker() { return broker; } -Interconnects& BrokerContext::getInterconnects() { return interconnects; } -TopicRegistry& BrokerContext::getTopics() { return topics; } -NodePolicyRegistry& BrokerContext::getNodePolicies() { return nodePolicies; } -std::string BrokerContext::getDomain() { return domain; } -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/BrokerContext.h b/qpid/cpp/src/qpid/broker/amqp/BrokerContext.h deleted file mode 100644 index feb35e39c4..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/BrokerContext.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef QPID_BROKER_AMQP_BROKERCONTEXT_H -#define QPID_BROKER_AMQP_BROKERCONTEXT_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 - -namespace qpid { -namespace broker { -class Broker; -namespace amqp { -class Interconnects; -class TopicRegistry; -class NodePolicyRegistry; -/** - * Context providing access to broker scoped entities. - */ -class BrokerContext -{ - public: - BrokerContext(Broker&, Interconnects&, TopicRegistry&, NodePolicyRegistry&, const std::string&); - BrokerContext(BrokerContext&); - Broker& getBroker(); - Interconnects& getInterconnects(); - TopicRegistry& getTopics(); - NodePolicyRegistry& getNodePolicies(); - std::string getDomain(); - private: - Broker& broker; - Interconnects& interconnects; - TopicRegistry& topics; - NodePolicyRegistry& nodePolicies; - std::string domain; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_BROKERCONTEXT_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Connection.cpp b/qpid/cpp/src/qpid/broker/amqp/Connection.cpp deleted file mode 100644 index 9a25e35e6d..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Connection.cpp +++ /dev/null @@ -1,697 +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 "Connection.h" -#include "DataReader.h" -#include "Session.h" -#include "Exception.h" -#include "qpid/broker/AclModule.h" -#include "qpid/broker/Broker.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/Version.h" -#include "config.h" -#include -extern "C" { -#include -#include -#ifdef HAVE_PROTON_EVENTS -#include -#endif -} - -namespace qpid { -namespace broker { -namespace amqp { -namespace { - -void do_trace(pn_transport_t* transport, const char* message) -{ - Connection* c = reinterpret_cast(pn_transport_get_context(transport)); - if (c) c->trace(message); -} - -void set_tracer(pn_transport_t* transport, void* context) -{ - pn_transport_set_context(transport, context); - pn_transport_set_tracer(transport, &do_trace); -} - -#ifdef USE_PROTON_TRANSPORT_CONDITION -std::string get_error(pn_connection_t* connection, pn_transport_t* transport) -{ - std::stringstream text; - pn_error_t* cerror = pn_connection_error(connection); - if (cerror) text << "connection error " << pn_error_text(cerror) << " [" << cerror << "]"; - pn_condition_t* tcondition = pn_transport_condition(transport); - if (pn_condition_is_set(tcondition)) text << "transport error: " << pn_condition_get_name(tcondition) << ", " << pn_condition_get_description(tcondition); - return text.str(); -} -#else -std::string get_error(pn_connection_t* connection, pn_transport_t* transport) -{ - std::stringstream text; - pn_error_t* cerror = pn_connection_error(connection); - if (cerror) text << "connection error " << pn_error_text(cerror) << " [" << cerror << "]"; - pn_error_t* terror = pn_transport_error(transport); - if (terror) text << "transport error " << pn_error_text(terror) << " [" << terror << "]"; - return text.str(); -} -#endif - -} - -void Connection::trace(const char* message) const -{ - QPID_LOG_CAT(trace, protocol, "[" << id << "]: " << message); -} - -namespace { -struct ConnectionTickerTask : public qpid::sys::TimerTask -{ - qpid::sys::Timer& timer; - Connection& connection; - ConnectionTickerTask(uint64_t interval, qpid::sys::Timer& t, Connection& c) : - TimerTask(qpid::sys::Duration(interval*qpid::sys::TIME_MSEC), "ConnectionTicker"), - timer(t), - connection(c) - {} - - void fire() { - // Setup next firing - setupNextFire(); - timer.add(this); - - // Send Ticker - connection.requestIO(); - } -}; -const std::string ANONYMOUS_RELAY("ANONYMOUS-RELAY"); -} - -Connection::Connection(qpid::sys::OutputControl& o, const std::string& i, BrokerContext& b, bool saslInUse, bool brokerInitiated) - : BrokerContext(b), ManagedConnection(getBroker(), i, brokerInitiated), - connection(pn_connection()), - transport(pn_transport()), - collector(0), - out(o), id(i), haveOutput(true), closeInitiated(false), closeRequested(false), ioRequested(false) -{ -#ifdef HAVE_PROTON_EVENTS - collector = pn_collector(); - pn_connection_collect(connection, collector); -#endif - - if (pn_transport_bind(transport, connection)) { - //error - QPID_LOG(error, "Failed to bind transport to connection: " << getError()); - } - out.activateOutput(); - bool enableTrace(false); - QPID_LOG_TEST_CAT(trace, protocol, enableTrace); - if (enableTrace) { - pn_transport_trace(transport, PN_TRACE_FRM); - set_tracer(transport, this); - } - - getBroker().getConnectionObservers().connection(*this); - if (!saslInUse) { - //feed in a dummy AMQP 1.0 header as engine expects one, but - //we already read it (if sasl is in use we read the sasl - //header,not the AMQP 1.0 header). - std::vector protocolHeader(8); - qpid::framing::ProtocolInitiation pi(getVersion()); - qpid::framing::Buffer buffer(&protocolHeader[0], protocolHeader.size()); - pi.encode(buffer); - pn_transport_input(transport, &protocolHeader[0], protocolHeader.size()); - - setUserId("none"); - } -} - -void Connection::requestIO() -{ - ioRequested = true; - out.activateOutput(); -} - -Connection::~Connection() -{ - if (ticker) ticker->cancel(); - getBroker().getConnectionObservers().closed(*this); - pn_connection_free(connection); - pn_transport_free(transport); -#ifdef HAVE_PROTON_EVENTS - pn_collector_free(collector); -#endif -} - -pn_transport_t* Connection::getTransport() -{ - return transport; -} -size_t Connection::decode(const char* buffer, size_t size) -{ - QPID_LOG(trace, id << " decode(" << size << ")"); - if (size == 0) return 0; - - ssize_t n = pn_transport_input(transport, const_cast(buffer), size); - if (n > 0 || n == PN_EOS) { - // PN_EOS either means we received a Close (which also means we've - // consumed all the input), OR some Very Bad Thing happened and this - // connection is toast. - if (n == PN_EOS) - { - std::string error; - if (checkTransportError(error)) { - // "He's dead, Jim." - QPID_LOG_CAT(error, network, id << " connection failed: " << error); - out.abort(); - return 0; - } else { - n = size; // assume all consumed - } - } - QPID_LOG_CAT(debug, network, id << " decoded " << n << " bytes from " << size); - try { - process(); - } catch (const Exception& e) { - QPID_LOG(error, id << ": " << e.what()); - pn_condition_t* error = pn_connection_condition(connection); - pn_condition_set_name(error, e.symbol()); - pn_condition_set_description(error, e.what()); - close(); - } catch (const std::exception& e) { - QPID_LOG(error, id << ": " << e.what()); - pn_condition_t* error = pn_connection_condition(connection); - pn_condition_set_name(error, qpid::amqp::error_conditions::INTERNAL_ERROR.c_str()); - pn_condition_set_description(error, e.what()); - close(); - } - // QPID-6698: don't use wallclock here, use monotonic clock - int64_t now = qpid::sys::Duration(qpid::sys::ZERO, qpid::sys::AbsTime::now()); - pn_transport_tick(transport, now / int64_t(qpid::sys::TIME_MSEC)); - if (!haveOutput) { - haveOutput = true; - out.activateOutput(); - } - return n; - } else if (n == PN_ERR) { - std::string error; - checkTransportError(error); - QPID_LOG_CAT(error, network, id << " connection error: " << error); - out.abort(); - return 0; - } else { - return 0; - } -} - -size_t Connection::encode(char* buffer, size_t size) -{ - QPID_LOG(trace, "encode(" << size << ")"); - doOutput(size); - ssize_t n = pn_transport_output(transport, buffer, size); - if (n > 0) { - QPID_LOG_CAT(debug, network, id << " encoded " << n << " bytes from " << size) - haveOutput = true; - if (ticker) ticker->restart(); - return n; - } else if (n == PN_EOS) { - haveOutput = false; - // Normal close, or error? - std::string error; - if (checkTransportError(error)) { - QPID_LOG_CAT(error, network, id << " connection failed: " << error); - out.abort(); - } - return 0; - } else if (n == PN_ERR) { - std::string error; - checkTransportError(error); - QPID_LOG_CAT(error, network, id << " connection error: " << error); - out.abort(); - return 0; - } else { - haveOutput = false; - return 0; - } -} - -void Connection::doOutput(size_t capacity) -{ - ssize_t n = 0; - do { - if (dispatch()) { - processDeliveries(); - ssize_t next = pn_transport_pending(transport); - if (n == next) break; - n = next; - } else break; - } while (n > 0 && n < (ssize_t) capacity); -} - -bool Connection::dispatch() -{ - bool result = false; - for (Sessions::iterator i = sessions.begin();i != sessions.end();) { - if (i->second->endedByManagement()) { - pn_session_close(i->first); - i->second->close(); - sessions.erase(i++); - result = true; - QPID_LOG_CAT(debug, model, id << " session ended by management"); - } else { - if (i->second->dispatch()) result = true; - ++i; - } - } - return result; -} - -bool Connection::canEncode() -{ - if (!closeInitiated) { - if (closeRequested) { - close(); - return true; - } - try { - if (dispatch()) haveOutput = true; - process(); - } catch (const Exception& e) { - QPID_LOG(error, id << ": " << e.what()); - pn_condition_t* error = pn_connection_condition(connection); - pn_condition_set_name(error, e.symbol()); - pn_condition_set_description(error, e.what()); - close(); - haveOutput = true; - } catch (const std::exception& e) { - QPID_LOG(error, id << ": " << e.what()); - pn_condition_t* error = pn_connection_condition(connection); - pn_condition_set_name(error, qpid::amqp::error_conditions::INTERNAL_ERROR.c_str()); - pn_condition_set_description(error, e.what()); - close(); - haveOutput = true; - } - } else { - QPID_LOG(info, "Connection " << id << " has been closed locally"); - } - if (ioRequested.valueCompareAndSwap(true, false)) haveOutput = true; - // QPID-6698: don't use wallclock here, use monotonic clock - int64_t now = qpid::sys::Duration(qpid::sys::ZERO, qpid::sys::AbsTime::now()); - pn_transport_tick(transport, (now / int64_t(qpid::sys::TIME_MSEC))); - QPID_LOG_CAT(trace, network, id << " canEncode(): " << haveOutput) - return haveOutput; -} - -void Connection::open() -{ - readPeerProperties(); - - pn_connection_set_container(connection, getBroker().getFederationTag().c_str()); - uint32_t timeout = pn_transport_get_remote_idle_timeout(transport); - if (timeout) { - // if idle generate empty frames at 1/2 the timeout interval as keepalives: - ticker = boost::intrusive_ptr(new ConnectionTickerTask((timeout/2)+1, - getBroker().getTimer(), - *this)); - getBroker().getTimer().add(ticker); - - // Note: in version 0-10 of the protocol, idle timeout applies to both - // ends. AMQP 1.0 changes that - it's now asymmetric: each end can - // configure/disable it independently. For backward compatibility, by - // default mimic the old behavior and set our local timeout. - // Use 2x the remote's timeout, as per the spec the remote should - // advertise 1/2 its actual timeout threshold - pn_transport_set_idle_timeout(transport, timeout * 2); - QPID_LOG_CAT(debug, network, id << " AMQP 1.0 idle-timeout set:" - << " local=" << pn_transport_get_idle_timeout(transport) - << " remote=" << pn_transport_get_remote_idle_timeout(transport)); - } - - pn_data_t* offered_capabilities = pn_connection_offered_capabilities(connection); - if (offered_capabilities) { - pn_data_put_array(offered_capabilities, false, PN_SYMBOL); - pn_data_enter(offered_capabilities); - pn_data_put_symbol(offered_capabilities, pn_bytes(ANONYMOUS_RELAY.size(), ANONYMOUS_RELAY.c_str())); - pn_data_exit(offered_capabilities); - pn_data_rewind(offered_capabilities); - } - - // QPID-6592: put self-identifying information into the connection - // properties. Use keys defined by the 0-10 spec, as AMQP 1.0 has yet to - // define any. - // - pn_data_t *props = pn_connection_properties(connection); - if (props) { - boost::shared_ptr sysInfo = getBroker().getSystem(); - - pn_data_clear(props); - pn_data_put_map(props); - pn_data_enter(props); - pn_data_put_symbol(props, pn_bytes(7, "product")); - pn_data_put_string(props, pn_bytes(qpid::product.size(), qpid::product.c_str())); - pn_data_put_symbol(props, pn_bytes(7, "version")); - pn_data_put_string(props, pn_bytes(qpid::version.size(), qpid::version.c_str())); - if (sysInfo) { - std::string osName(sysInfo->getOsName()); - std::string nodeName(sysInfo->getNodeName()); - pn_data_put_symbol(props, pn_bytes(8, "platform")); - pn_data_put_string(props, pn_bytes(osName.size(), osName.c_str())); - pn_data_put_symbol(props, pn_bytes(4, "host")); - pn_data_put_string(props, pn_bytes(nodeName.size(), nodeName.c_str())); - } - pn_data_exit(props); - pn_data_rewind(props); - } - - pn_connection_open(connection); - out.connectionEstablished(); - opened(); - getBroker().getConnectionObservers().opened(*this); -} - -void Connection::readPeerProperties() -{ - qpid::types::Variant::Map properties; - DataReader::read(pn_connection_remote_properties(connection), properties); - setPeerProperties(properties); -} - -void Connection::closed() -{ - if (ticker) ticker->cancel(); - for (Sessions::iterator i = sessions.begin(); i != sessions.end(); ++i) { - i->second->close(); - } -} -void Connection::close() -{ - if (!closeInitiated) { - closeInitiated = true; - closed(); - QPID_LOG_CAT(debug, model, id << " connection closed"); - pn_connection_close(connection); - } -} -bool Connection::isClosed() const -{ - return pn_connection_state(connection) & PN_REMOTE_CLOSED; -} -framing::ProtocolVersion Connection::getVersion() const -{ - return qpid::framing::ProtocolVersion(1,0); -} - -void Connection::process() -{ - QPID_LOG(trace, id << " process()"); -#ifdef HAVE_PROTON_EVENTS - pn_event_t *event = pn_collector_peek(collector); - while (event) { - switch (pn_event_type(event)) { - case PN_CONNECTION_REMOTE_OPEN: - doConnectionRemoteOpen(); - break; - case PN_CONNECTION_REMOTE_CLOSE: - doConnectionRemoteClose(); - break; - case PN_SESSION_REMOTE_OPEN: - doSessionRemoteOpen(pn_event_session(event)); - break; - case PN_SESSION_REMOTE_CLOSE: - doSessionRemoteClose(pn_event_session(event)); - break; - case PN_LINK_REMOTE_OPEN: - doLinkRemoteOpen(pn_event_link(event)); - break; - case PN_LINK_REMOTE_DETACH: - doLinkRemoteDetach(pn_event_link(event), false); - break; - case PN_LINK_REMOTE_CLOSE: - doLinkRemoteClose(pn_event_link(event)); - break; - case PN_DELIVERY: - doDeliveryUpdated(pn_event_delivery(event)); - break; - default: - break; - } - pn_collector_pop(collector); - event = pn_collector_peek(collector); - } - -#else // !HAVE_PROTON_EVENTS - - const pn_state_t REQUIRES_OPEN = PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE; - const pn_state_t REQUIRES_CLOSE = PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED; - - if ((pn_connection_state(connection) & REQUIRES_OPEN) == REQUIRES_OPEN) { - doConnectionRemoteOpen(); - } - - for (pn_session_t* s = pn_session_head(connection, REQUIRES_OPEN); s; s = pn_session_next(s, REQUIRES_OPEN)) { - doSessionRemoteOpen(s); - } - for (pn_link_t* l = pn_link_head(connection, REQUIRES_OPEN); l; l = pn_link_next(l, REQUIRES_OPEN)) { - doLinkRemoteOpen(l); - } - - processDeliveries(); - - for (pn_link_t* l = pn_link_head(connection, REQUIRES_CLOSE), *next = 0; - l; l = next) { - next = pn_link_next(l, REQUIRES_CLOSE); - doLinkRemoteClose(l); - } - for (pn_session_t* s = pn_session_head(connection, REQUIRES_CLOSE), *next = 0; - s; s = next) { - next = pn_session_next(s, REQUIRES_CLOSE); - doSessionRemoteClose(s); - } - if ((pn_connection_state(connection) & REQUIRES_CLOSE) == REQUIRES_CLOSE) { - doConnectionRemoteClose(); - } -#endif // !HAVE_PROTON_EVENTS -} -void Connection::processDeliveries() -{ -#ifdef HAVE_PROTON_EVENTS - // with the event API, there's no way to selectively process only - // the delivery-related events. We have to process all events: - process(); -#else - for (pn_delivery_t* delivery = pn_work_head(connection); delivery; delivery = pn_work_next(delivery)) { - doDeliveryUpdated(delivery); - } -#endif -} - -std::string Connection::getError() -{ - return get_error(connection, transport); -} - -void Connection::abort() -{ - out.abort(); -} - -void Connection::setUserId(const std::string& user) -{ - ManagedConnection::setUserId(user); - AclModule* acl = getBroker().getAcl(); - if (acl && !acl->approveConnection(*this)) - { - throw Exception(qpid::amqp::error_conditions::RESOURCE_LIMIT_EXCEEDED, "User connection denied by configured limit"); - } -} - -void Connection::closedByManagement() -{ - closeRequested = true; - out.activateOutput(); -} - -// the peer has issued an Open performative -void Connection::doConnectionRemoteOpen() -{ - // respond in kind if we haven't yet - if ((pn_connection_state(connection) & PN_LOCAL_UNINIT) == PN_LOCAL_UNINIT) { - QPID_LOG_CAT(debug, model, id << " connection opened"); - open(); - setContainerId(pn_connection_remote_container(connection)); - } -} - -// the peer has issued a Close performative -void Connection::doConnectionRemoteClose() -{ - if ((pn_connection_state(connection) & PN_LOCAL_CLOSED) == 0) { - QPID_LOG_CAT(debug, model, id << " connection closed"); - pn_connection_close(connection); - } -} - -// the peer has issued a Begin performative -void Connection::doSessionRemoteOpen(pn_session_t *session) -{ - if ((pn_session_state(session) & PN_LOCAL_UNINIT) == PN_LOCAL_UNINIT) { - QPID_LOG_CAT(debug, model, id << " session begun"); - pn_session_open(session); - boost::shared_ptr ssn(new Session(session, *this, out)); - sessions[session] = ssn; - } -} - -// the peer has issued an End performative -void Connection::doSessionRemoteClose(pn_session_t *session) -{ - if ((pn_session_state(session) & PN_LOCAL_CLOSED) == 0) { - pn_session_close(session); - Sessions::iterator i = sessions.find(session); - if (i != sessions.end()) { - i->second->close(); - sessions.erase(i); - QPID_LOG_CAT(debug, model, id << " session ended"); - } else { - QPID_LOG(error, id << " peer attempted to close unrecognised session"); - } - } - pn_session_free(session); -} - -// the peer has issued an Attach performative -void Connection::doLinkRemoteOpen(pn_link_t *link) -{ - if ((pn_link_state(link) & PN_LOCAL_UNINIT) == PN_LOCAL_UNINIT) { - pn_link_open(link); - Sessions::iterator session = sessions.find(pn_link_session(link)); - if (session == sessions.end()) { - QPID_LOG(error, id << " Link attached on unknown session!"); - } else { - try { - session->second->attach(link); - QPID_LOG_CAT(debug, protocol, id << " link " << link << " attached on " << pn_link_session(link)); - } catch (const Exception& e) { - QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what()); - pn_condition_t* error = pn_link_condition(link); - pn_condition_set_name(error, e.symbol()); - pn_condition_set_description(error, e.what()); - pn_link_close(link); - } catch (const qpid::framing::UnauthorizedAccessException& e) { - QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what()); - pn_condition_t* error = pn_link_condition(link); - pn_condition_set_name(error, qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS.c_str()); - pn_condition_set_description(error, e.what()); - pn_link_close(link); - } catch (const std::exception& e) { - QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what()); - pn_condition_t* error = pn_link_condition(link); - pn_condition_set_name(error, qpid::amqp::error_conditions::INTERNAL_ERROR.c_str()); - pn_condition_set_description(error, e.what()); - pn_link_close(link); - } - } - } -} - -// the peer has issued a Detach performative with closed=true -void Connection::doLinkRemoteClose(pn_link_t *link) -{ - doLinkRemoteDetach(link, true); -} -// the peer has issued a Detach performative -void Connection::doLinkRemoteDetach(pn_link_t *link, bool closed) -{ - if ((pn_link_state(link) & PN_LOCAL_CLOSED) == 0) { - if (closed) pn_link_close(link); - //pn_link_detach was only introduced after 0.7, as was the event interface: -#ifdef HAVE_PROTON_EVENTS - else pn_link_detach(link); -#endif - Sessions::iterator session = sessions.find(pn_link_session(link)); - if (session == sessions.end()) { - QPID_LOG(error, id << " peer attempted to detach link on unknown session!"); - } else { - session->second->detach(link, closed); - QPID_LOG_CAT(debug, model, id << " link detached"); - } - } - pn_link_free(link); -} - -// the status of the delivery has changed -void Connection::doDeliveryUpdated(pn_delivery_t *delivery) -{ - pn_link_t* link = pn_delivery_link(delivery); - if (pn_link_state(link) & PN_LOCAL_CLOSED) return; - - try { - if (pn_link_is_receiver(link)) { - Sessions::iterator i = sessions.find(pn_link_session(link)); - if (i != sessions.end()) { - i->second->readable(link, delivery); - } else { - pn_delivery_update(delivery, PN_REJECTED); - } - } else { //i.e. SENDER - Sessions::iterator i = sessions.find(pn_link_session(link)); - if (i != sessions.end()) { - QPID_LOG(trace, id << " handling outgoing delivery for " << link << " on session " << pn_link_session(link)); - i->second->writable(link, delivery); - } else { - QPID_LOG(error, id << " Got delivery for non-existent session: " << pn_link_session(link) << ", link: " << link); - } - } - } catch (const Exception& e) { - QPID_LOG_CAT(error, protocol, "Error processing deliveries: " << e.what()); - pn_condition_t* error = pn_link_condition(link); - pn_condition_set_name(error, e.symbol()); - pn_condition_set_description(error, e.what()); - pn_link_close(link); - } -} - -// check for failures of the transport: -bool Connection::checkTransportError(std::string& text) -{ - std::stringstream info; - -#ifdef USE_PROTON_TRANSPORT_CONDITION - pn_condition_t* tcondition = pn_transport_condition(transport); - if (pn_condition_is_set(tcondition)) - info << "transport error: " << pn_condition_get_name(tcondition) << ", " << pn_condition_get_description(tcondition); -#else - pn_error_t* terror = pn_transport_error(transport); - if (terror) info << "transport error " << pn_error_text(terror) << " [" << terror << "]"; -#endif - - text = info.str(); - return !text.empty(); -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Connection.h b/qpid/cpp/src/qpid/broker/amqp/Connection.h deleted file mode 100644 index 0d06f18924..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Connection.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef QPID_BROKER_AMQP1_CONNECTION_H -#define QPID_BROKER_AMQP1_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 "qpid/sys/ConnectionCodec.h" -#include "qpid/broker/amqp/BrokerContext.h" -#include "qpid/broker/amqp/ManagedConnection.h" -#include "qpid/sys/AtomicValue.h" -#include -#include -#include - -struct pn_connection_t; -struct pn_session_t; -struct pn_transport_t; -struct pn_collector_t; -struct pn_link_t; -struct pn_delivery_t; - -namespace qpid { -namespace sys { -class TimerTask; -} -namespace broker { - -class Broker; - -namespace amqp { - -class Interconnects; -class Session; -/** - * AMQP 1.0 protocol support for broker - */ -class Connection : public BrokerContext, public sys::ConnectionCodec, public ManagedConnection -{ - public: - Connection(qpid::sys::OutputControl& out, const std::string& id, BrokerContext& context, bool saslInUse, bool brokerInitiated); - virtual ~Connection(); - size_t decode(const char* buffer, size_t size); - virtual size_t encode(char* buffer, size_t size); - bool canEncode(); - - void closed(); - bool isClosed() const; - - framing::ProtocolVersion getVersion() const; - pn_transport_t* getTransport(); - void setUserId(const std::string&); - void abort(); - void trace(const char*) const; - void requestIO(); - protected: - typedef std::map > Sessions; - pn_connection_t* connection; - pn_transport_t* transport; - pn_collector_t* collector; - qpid::sys::OutputControl& out; - const std::string id; - bool haveOutput; - Sessions sessions; - bool closeInitiated; - bool closeRequested; - boost::intrusive_ptr ticker; - qpid::sys::AtomicValue ioRequested; - - virtual void process(); - void doOutput(size_t); - bool dispatch(); - void processDeliveries(); - std::string getError(); - void close(); - void open(); - void readPeerProperties(); - void closedByManagement(); - - private: - bool checkTransportError(std::string&); - - // handle Proton engine events - void doConnectionRemoteOpen(); - void doConnectionRemoteClose(); - void doSessionRemoteOpen(pn_session_t *session); - void doSessionRemoteClose(pn_session_t *session); - void doLinkRemoteOpen(pn_link_t *link); - void doLinkRemoteClose(pn_link_t *link); - void doLinkRemoteDetach(pn_link_t *link, bool closed); - void doDeliveryUpdated(pn_delivery_t *delivery); -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP1_CONNECTION_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/DataReader.cpp b/qpid/cpp/src/qpid/broker/amqp/DataReader.cpp deleted file mode 100644 index f83eb03f13..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/DataReader.cpp +++ /dev/null @@ -1,193 +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 "DataReader.h" -#include "qpid/amqp/CharSequence.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/amqp/MapBuilder.h" -#include "qpid/log/Statement.h" -#include -#include - -namespace qpid { -namespace broker { -namespace amqp { -namespace { -qpid::amqp::CharSequence convert(pn_bytes_t in) -{ - qpid::amqp::CharSequence out; - out.data = in.start; - out.size = in.size; - return out; -} - -qpid::amqp::CharSequence convert(pn_uuid_t in) -{ - qpid::amqp::CharSequence out; - out.data = in.bytes; - out.size = 16; - return out; -} -} - -DataReader::DataReader(qpid::amqp::Reader& r) : reader(r) {} - -void DataReader::read(pn_data_t* data) -{ - do { - readOne(data); - } while (pn_data_next(data)); -} -void DataReader::readOne(pn_data_t* data) -{ - qpid::amqp::Descriptor descriptor(0); - bool described = pn_data_is_described(data); - if (described) { - pn_data_enter(data); - pn_data_next(data); - if (pn_data_type(data) == PN_ULONG) { - descriptor = qpid::amqp::Descriptor(pn_data_get_ulong(data)); - } else if (pn_data_type(data) == PN_SYMBOL) { - descriptor = qpid::amqp::Descriptor(convert(pn_data_get_symbol(data))); - } else { - QPID_LOG(notice, "Ignoring descriptor of type " << pn_data_type(data)); - } - pn_data_next(data); - } - switch (pn_data_type(data)) { - case PN_NULL: - reader.onNull(described ? &descriptor : 0); - break; - case PN_BOOL: - reader.onBoolean(pn_data_get_bool(data), described ? &descriptor : 0); - break; - case PN_UBYTE: - reader.onUByte(pn_data_get_ubyte(data), described ? &descriptor : 0); - break; - case PN_BYTE: - reader.onByte(pn_data_get_byte(data), described ? &descriptor : 0); - break; - case PN_USHORT: - reader.onUShort(pn_data_get_ushort(data), described ? &descriptor : 0); - break; - case PN_SHORT: - reader.onShort(pn_data_get_short(data), described ? &descriptor : 0); - break; - case PN_UINT: - reader.onUInt(pn_data_get_uint(data), described ? &descriptor : 0); - break; - case PN_INT: - reader.onInt(pn_data_get_int(data), described ? &descriptor : 0); - break; - case PN_CHAR: - pn_data_get_char(data); - break; - case PN_ULONG: - reader.onULong(pn_data_get_ulong(data), described ? &descriptor : 0); - break; - case PN_LONG: - reader.onLong(pn_data_get_long(data), described ? &descriptor : 0); - break; - case PN_TIMESTAMP: - reader.onTimestamp(pn_data_get_timestamp(data), described ? &descriptor : 0); - break; - case PN_FLOAT: - reader.onFloat(pn_data_get_float(data), described ? &descriptor : 0); - break; - case PN_DOUBLE: - reader.onDouble(pn_data_get_double(data), described ? &descriptor : 0); - break; - case PN_DECIMAL32: - pn_data_get_decimal32(data); - break; - case PN_DECIMAL64: - pn_data_get_decimal64(data); - break; - case PN_DECIMAL128: - pn_data_get_decimal128(data); - break; - case PN_UUID: - reader.onUuid(convert(pn_data_get_uuid(data)), described ? &descriptor : 0); - break; - case PN_BINARY: - reader.onBinary(convert(pn_data_get_binary(data)), described ? &descriptor : 0); - break; - case PN_STRING: - reader.onString(convert(pn_data_get_string(data)), described ? &descriptor : 0); - break; - case PN_SYMBOL: - reader.onSymbol(convert(pn_data_get_symbol(data)), described ? &descriptor : 0); - break; - case PN_DESCRIBED: - break; - case PN_ARRAY: - readArray(data, described ? &descriptor : 0); - break; - case PN_LIST: - readList(data, described ? &descriptor : 0); - break; - case PN_MAP: - readMap(data, described ? &descriptor : 0); - break; - default: - break; - } - if (described) pn_data_exit(data); -} - -void DataReader::readArray(pn_data_t* /*data*/, const qpid::amqp::Descriptor* /*descriptor*/) -{ - //not yet implemented -} - -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(), qpid::amqp::CharSequence(), descriptor); - if (!skip) { - pn_data_enter(data); - for (size_t i = 0; i < count && pn_data_next(data); ++i) { - read(data); - } - pn_data_exit(data); - reader.onEndList(count, descriptor); - } -} - -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(), qpid::amqp::CharSequence(), descriptor); - pn_data_enter(data); - for (size_t i = 0; i < count && pn_data_next(data); ++i) { - read(data); - } - pn_data_exit(data); - reader.onEndMap(count, descriptor); -} - -void DataReader::read(pn_data_t* data, std::map& out) -{ - qpid::amqp::MapBuilder builder; - DataReader reader(builder); - reader.read(data); - out = builder.getMap(); -} -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/DataReader.h b/qpid/cpp/src/qpid/broker/amqp/DataReader.h deleted file mode 100644 index 99ff77b3dd..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/DataReader.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_BROKER_AMQP_DATAREADER_H -#define QPID_BROKER_AMQP_DATAREADER_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/amqp/Reader.h" -#include -#include - -struct pn_data_t; - -namespace qpid { -namespace types { -class Variant; -} -namespace amqp { -struct Descriptor; -} -namespace broker { -namespace amqp { - -/** - * Allows use of Reader interface to read pn_data_t* data. - */ -class DataReader -{ - public: - DataReader(qpid::amqp::Reader& reader); - void read(pn_data_t*); - static void read(pn_data_t*, std::map&); - private: - qpid::amqp::Reader& reader; - - void readOne(pn_data_t*); - void readMap(pn_data_t*, const qpid::amqp::Descriptor*); - void readList(pn_data_t*, const qpid::amqp::Descriptor*); - void readArray(pn_data_t*, const qpid::amqp::Descriptor*); -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_DATAREADER_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Domain.cpp b/qpid/cpp/src/qpid/broker/amqp/Domain.cpp deleted file mode 100644 index b2cd9ae21d..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Domain.cpp +++ /dev/null @@ -1,307 +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 "Domain.h" -#include "Interconnect.h" -#include "Interconnects.h" -#include "SaslClient.h" -#include "qpid/broker/Broker.h" -#include "qpid/Exception.h" -#include "qpid/SaslFactory.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include -#include -#include - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { -namespace amqp { - -namespace { -const std::string NONE("NONE"); -const std::string SOURCE("source"); -const std::string TARGET("target"); -const std::string URL("url"); -const std::string USERNAME("username"); -const std::string PASSWORD("password"); -const std::string SASL_MECHANISMS("sasl_mechanisms"); -const std::string SASL_SERVICE("sasl_service"); -const std::string MIN_SSF("min_ssf"); -const std::string MAX_SSF("max_ssf"); -const std::string DURABLE("durable"); -const std::string AMQP_SASL_SERVICENAME("amqp"); - -class Wrapper : public qpid::sys::ConnectionCodec -{ - public: - Wrapper(boost::shared_ptr c) : connection(c) {} - ~Wrapper() - { - QPID_LOG(debug, "Wrapper for non-SASL based interconnect has been deleted"); - connection->transportDeleted(); - } - - std::size_t decode(const char* buffer, std::size_t size) - { - return connection->decode(buffer, size); - } - std::size_t encode(char* buffer, std::size_t size) - { - return connection->encode(buffer, size); - } - bool canEncode() - { - return connection->canEncode(); - } - void closed() - { - connection->closed(); - } - bool isClosed() const - { - QPID_LOG(debug, "Wrapper for non_SASL based interconnect " << (connection->isClosed() ? " IS " : " IS NOT ") << " closed"); - return connection->isClosed(); - } - qpid::framing::ProtocolVersion getVersion() const - { - return connection->getVersion(); - } - private: - boost::shared_ptr connection; -}; - -bool get(std::string& result, const std::string& key, const qpid::types::Variant::Map& map) -{ - qpid::types::Variant::Map::const_iterator i = map.find(key); - if (i != map.end()) { - result = i->second.asString(); - return true; - } else { - return false; - } -} -bool get(int& result, const std::string& key, const qpid::types::Variant::Map& map) -{ - qpid::types::Variant::Map::const_iterator i = map.find(key); - if (i != map.end()) { - result = i->second; - return true; - } else { - return false; - } -} -bool get(qpid::Url& url, const std::string& key, const qpid::types::Variant::Map& map) -{ - qpid::types::Variant::Map::const_iterator i = map.find(key); - if (i != map.end()) { - url = qpid::Url(i->second.asString()); - return true; - } else { - return false; - } -} -bool get(const std::string& key, const qpid::types::Variant::Map& map) -{ - qpid::types::Variant::Map::const_iterator i = map.find(key); - if (i != map.end()) { - return i->second.asBool(); - } else { - return false; - } -} -} - -class InterconnectFactory : public BrokerContext, public qpid::sys::ConnectionCodec::Factory, public boost::enable_shared_from_this -{ - public: - InterconnectFactory(bool incoming, const std::string& name, const qpid::types::Variant::Map& properties, - boost::shared_ptr, BrokerContext&); - InterconnectFactory(bool incoming, const std::string& name, const std::string& source, const std::string& target, - boost::shared_ptr, BrokerContext&, boost::shared_ptr); - qpid::sys::ConnectionCodec* create(const framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&); - qpid::sys::ConnectionCodec* create(qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&); - qpid::framing::ProtocolVersion supportedVersion() const - { - return qpid::framing::ProtocolVersion(1, 0); - } - bool connect(); - void failed(int, std::string); - private: - bool incoming; - std::string name; - std::string source; - std::string target; - qpid::Url url; - qpid::Url::iterator next; - std::string hostname; - boost::shared_ptr domain; - qpid::Address address; - boost::shared_ptr relay; -}; - -InterconnectFactory::InterconnectFactory(bool i, const std::string& n, const qpid::types::Variant::Map& properties, boost::shared_ptr d, BrokerContext& c) - : BrokerContext(c), incoming(i), name(n), url(d->getUrl()), domain(d) -{ - get(source, SOURCE, properties); - get(target, TARGET, properties); - next = url.begin(); -} - -InterconnectFactory::InterconnectFactory(bool i, const std::string& n, const std::string& source_, const std::string& target_, - boost::shared_ptr d, BrokerContext& c, boost::shared_ptr relay_) - : BrokerContext(c), incoming(i), name(n), source(source_), target(target_), url(d->getUrl()), domain(d), relay(relay_) -{ - next = url.begin(); -} - -qpid::sys::ConnectionCodec* InterconnectFactory::create(const qpid::framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&) -{ - throw qpid::Exception("Not implemented!"); -} -qpid::sys::ConnectionCodec* InterconnectFactory::create(qpid::sys::OutputControl& out, const std::string& id, const qpid::sys::SecuritySettings& t) -{ - bool useSasl = domain->getMechanisms() != NONE; - boost::shared_ptr connection(new Interconnect(out, id, *this, useSasl, incoming, name, source, target, domain->getName())); - if (!relay) getInterconnects().add(name, connection); - else connection->setRelay(relay); - - std::auto_ptr codec; - if (useSasl) { - QPID_LOG(info, "Using AMQP 1.0 (with SASL layer) on connect"); - codec = std::auto_ptr(new qpid::broker::amqp::SaslClient(out, id, connection, domain->sasl(hostname), hostname, domain->getMechanisms(), t)); - } else { - QPID_LOG(info, "Using AMQP 1.0 (no SASL layer) on connect"); - codec = std::auto_ptr(new Wrapper(connection)); - } - domain->removePending(shared_from_this());//(TODO: add support for retry on connection failure) - return codec.release(); -} - -bool InterconnectFactory::connect() -{ - if (next == url.end()) return false; - address = *next; - next++; - hostname = address.host; - QPID_LOG (info, "Inter-broker connection initiated (" << address << ")"); - std::stringstream identifier; - identifier << name << "@" << domain->getName(); - getBroker().connect(identifier.str(), address.host, boost::lexical_cast(address.port), address.protocol, this, boost::bind(&InterconnectFactory::failed, this, _1, _2)); - return true; -} - -void InterconnectFactory::failed(int, std::string text) -{ - QPID_LOG (info, "Inter-broker connection failed (" << address << "): " << text); - if (!connect()) { - domain->removePending(shared_from_this());//give up (TODO: add support for periodic retry) - } -} - -Domain::Domain(const std::string& n, const qpid::types::Variant::Map& properties, Broker& b) - : PersistableObject(n, "domain", properties), name(n), durable(get(DURABLE, properties)), - broker(b), mechanisms("ANONYMOUS"), service(AMQP_SASL_SERVICENAME), minSsf(0), maxSsf(0), - agent(b.getManagementAgent()) -{ - if (!get(url, URL, properties)) { - QPID_LOG(error, "No URL specified for domain " << name << "!"); - throw qpid::Exception("A url is required for a domain!"); - } else { - QPID_LOG(notice, "Created domain " << name << " with url " << url << " from " << properties); - } - get(username, USERNAME, properties); - get(password, PASSWORD, properties); - get(mechanisms, SASL_MECHANISMS, properties); - get(service, SASL_SERVICE, properties); - get(minSsf, MIN_SSF, properties); - get(maxSsf, MAX_SSF, properties); - if (agent != 0) { - domain = _qmf::Domain::shared_ptr(new _qmf::Domain(agent, this, name, durable)); - domain->set_url(url.str()); - domain->set_username(username); - domain->set_password(password); - domain->set_mechanisms(mechanisms); - agent->addObject(domain); - } -} - -Domain::~Domain() -{ - if (domain != 0) domain->resourceDestroy(); -} - -boost::shared_ptr Domain::GetManagementObject() const -{ - return domain; -} - -const std::string& Domain::getMechanisms() const -{ - return mechanisms; -} - -qpid::Url Domain::getUrl() const -{ - return url; -} - -bool Domain::isDurable() const -{ - return durable; -} - -std::auto_ptr Domain::sasl(const std::string& hostname) -{ - return qpid::SaslFactory::getInstance().create(username, password, service, hostname, minSsf, maxSsf, false); -} - -void Domain::connect(bool incoming, const std::string& name, const qpid::types::Variant::Map& properties, BrokerContext& context) -{ - boost::shared_ptr factory(new InterconnectFactory(incoming, name, properties, shared_from_this(), context)); - factory->connect(); - addPending(factory); -} - -void Domain::connect(bool incoming, const std::string& name, const std::string& source, const std::string& target, BrokerContext& context, boost::shared_ptr relay) -{ - boost::shared_ptr factory(new InterconnectFactory(incoming, name, source, target, shared_from_this(), context, relay)); - factory->connect(); - addPending(factory); -} - -void Domain::addPending(boost::shared_ptr f) -{ - qpid::sys::ScopedLock l(lock); - pending.insert(f); -} - -void Domain::removePending(boost::shared_ptr f) -{ - qpid::sys::ScopedLock l(lock); - pending.erase(f); -} - - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Domain.h b/qpid/cpp/src/qpid/broker/amqp/Domain.h deleted file mode 100644 index 7ee8572c8a..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Domain.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef QPID_BROKER_AMQP_DOMAIN_H -#define QPID_BROKER_AMQP_DOMAIN_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/ConnectionCodec.h" -#include "qpid/types/Variant.h" -#include "qpid/Url.h" -#include "qpid/Version.h" -#include "qpid/broker/PersistableObject.h" -#include "qpid/management/Manageable.h" -#include "qpid/sys/Mutex.h" -#include "qmf/org/apache/qpid/broker/Domain.h" -#include -#include -#include -#include - -namespace qpid { -class Sasl; -namespace management { -class ManagementAgent; -class ManagementObject; -} -namespace broker { -class Broker; -namespace amqp { -class InterconnectFactory; -class BrokerContext; -class Relay; - -class Domain : public PersistableObject, public qpid::management::Manageable, public boost::enable_shared_from_this -{ - public: - Domain(const std::string& name, const qpid::types::Variant::Map& properties, Broker&); - ~Domain(); - void connect(bool incoming, const std::string& name, const qpid::types::Variant::Map& properties, BrokerContext&); - void connect(bool incoming, const std::string& name, const std::string& source, const std::string& target, BrokerContext&, boost::shared_ptr); - std::auto_ptr sasl(const std::string& hostname); - const std::string& getMechanisms() const; - qpid::Url getUrl() const; - bool isDurable() const; - void addPending(boost::shared_ptr); - void removePending(boost::shared_ptr); - boost::shared_ptr GetManagementObject() const; - private: - std::string name; - bool durable; - Broker& broker; - qpid::Url url; - std::string username; - std::string password; - std::string mechanisms; - std::string service; - int minSsf; - int maxSsf; - boost::shared_ptr domain; - qpid::management::ManagementAgent* agent; - std::set< boost::shared_ptr > pending; - qpid::sys::Mutex lock; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_DOMAIN_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Exception.cpp b/qpid/cpp/src/qpid/broker/amqp/Exception.cpp deleted file mode 100644 index 6b874aa272..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Exception.cpp +++ /dev/null @@ -1,30 +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 "Exception.h" - -namespace qpid { -namespace broker { -namespace amqp { -Exception::Exception(const std::string& n, const std::string& d) : name(n), description(d) {} -Exception::~Exception() throw() {} -const char* Exception::what() const throw() { return description.c_str(); } -const char* Exception::symbol() const throw() { return name.c_str(); } -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Exception.h b/qpid/cpp/src/qpid/broker/amqp/Exception.h deleted file mode 100644 index a129dffe1f..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Exception.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef QPID_BROKER_AMQP_EXCEPTION_H -#define QPID_BROKER_AMQP_EXCEPTION_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 -#include - -namespace qpid { -namespace broker { -namespace amqp { -/** - * Exception to signal various AMQP 1.0 defined conditions - */ -class Exception : public qpid::Exception -{ - public: - Exception(const std::string& name, const std::string& description); - virtual ~Exception() throw(); - const char* what() const throw(); - const char* symbol() const throw(); - private: - std::string name; - std::string description; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_EXCEPTION_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Filter.cpp b/qpid/cpp/src/qpid/broker/amqp/Filter.cpp deleted file mode 100644 index ab456f4355..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Filter.cpp +++ /dev/null @@ -1,417 +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/broker/amqp/Filter.h" -#include "qpid/broker/amqp/Authorise.h" -#include "qpid/broker/amqp/DataReader.h" -#include "qpid/broker/amqp/Outgoing.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/log/Statement.h" -extern "C" { -#include -} - -namespace qpid { -namespace broker { -namespace amqp { -namespace { -const std::string XQUERY("xquery"); -const std::string XML("xml"); -const std::string DEFAULT_SUBJECT_FILTER("default-subject-filter"); -const std::string DEFAULT_HEADERS_FILTER("default-headers-filter"); -const std::string XMATCH("x-match"); -const std::string ALL("all"); -const std::string DEFAULT_XQUERY_FILTER("default-xquery-filter"); -const std::string DEFAULT_XQUERY_VALUE("true()"); -const std::string WILDCARD("#"); -} -Filter::Filter() : inHeadersMap(false), nolocal(false) {} - -void Filter::read(pn_data_t* data) -{ - try { - DataReader reader(*this); - reader.read(data); - } catch (const std::exception& e) { - QPID_LOG(warning, "Error parsing filter: " << e.what()); - } -} - -void Filter::write(pn_data_t* data) -{ - if (!active.empty()) { - pn_data_put_map(data); - pn_data_enter(data); - for (std::vector::const_iterator i = active.begin(); i != active.end(); ++i) { - (*i)->write(data); - } - pn_data_exit(data); - } -} - -void Filter::onStringValue(const qpid::amqp::CharSequence& key, const qpid::amqp::CharSequence& value, const qpid::amqp::Descriptor* descriptor) -{ - if (inHeadersMap) { - headersFilter.value[std::string(key.data, key.size)] = std::string(value.data, value.size); - } else { - StringFilter filter; - filter.key = std::string(key.data, key.size); - filter.value = std::string(value.data, value.size); - if (descriptor) { - filter.described = true; - filter.descriptor = *descriptor; - if (descriptor->match(qpid::amqp::filters::LEGACY_TOPIC_FILTER_SYMBOL, qpid::amqp::filters::LEGACY_TOPIC_FILTER_CODE) - || descriptor->match(qpid::amqp::filters::LEGACY_DIRECT_FILTER_SYMBOL, qpid::amqp::filters::LEGACY_DIRECT_FILTER_CODE)) { - setFilter(subjectFilter, filter); - } else if (descriptor->match(qpid::amqp::filters::SELECTOR_FILTER_SYMBOL, qpid::amqp::filters::SELECTOR_FILTER_CODE)) { - setFilter(selectorFilter, filter); - } else if (descriptor->match(qpid::amqp::filters::XQUERY_FILTER_SYMBOL, qpid::amqp::filters::XQUERY_FILTER_CODE)) { - setFilter(xqueryFilter, filter); - } else if (descriptor && descriptor->match(qpid::amqp::filters::NO_LOCAL_FILTER_SYMBOL, qpid::amqp::filters::NO_LOCAL_FILTER_CODE)) { - //though the no-local-filter is define to be a list, the JMS client sends it as a string - nolocal = true; - } else { - QPID_LOG(notice, "Skipping unrecognised string filter with key " << filter.key << " and descriptor " << filter.descriptor); - } - } else { - setFilter(subjectFilter, filter); - } - } -} -void Filter::onNullValue(const qpid::amqp::CharSequence& key, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = qpid::types::Variant(); -} -void Filter::onBooleanValue(const qpid::amqp::CharSequence& key, bool value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onUByteValue(const qpid::amqp::CharSequence& key, uint8_t value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onUShortValue(const qpid::amqp::CharSequence& key, uint16_t value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onUIntValue(const qpid::amqp::CharSequence& key, uint32_t value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onULongValue(const qpid::amqp::CharSequence& key, uint64_t value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onByteValue(const qpid::amqp::CharSequence& key, int8_t value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onShortValue(const qpid::amqp::CharSequence& key, int16_t value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onIntValue(const qpid::amqp::CharSequence& key, int32_t value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onLongValue(const qpid::amqp::CharSequence& key, int64_t value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onFloatValue(const qpid::amqp::CharSequence& key, float value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -void Filter::onDoubleValue(const qpid::amqp::CharSequence& key, double value, const qpid::amqp::Descriptor*) -{ - headersFilter.value[std::string(key.data, key.size)] = value; -} - -bool Filter::onStartListValue(const qpid::amqp::CharSequence& /*key*/, uint32_t /*count*/, const qpid::amqp::Descriptor* descriptor) -{ - if (descriptor && descriptor->match(qpid::amqp::filters::NO_LOCAL_FILTER_SYMBOL, qpid::amqp::filters::NO_LOCAL_FILTER_CODE)) { - nolocal = true; - } - return false; -} - -bool Filter::onStartMapValue(const qpid::amqp::CharSequence& key, uint32_t /*count*/, const qpid::amqp::Descriptor* descriptor) -{ - if (inHeadersMap) { - QPID_LOG(warning, "Skipping illegal nested map data in headers filter"); - return false; - } else if (descriptor && descriptor->match(qpid::amqp::filters::LEGACY_HEADERS_FILTER_SYMBOL, qpid::amqp::filters::LEGACY_HEADERS_FILTER_CODE)) { - inHeadersMap = true; - setAllowedKeyType(STRING_KEY); - headersFilter.requested = true; - headersFilter.described = true; - headersFilter.descriptor = *descriptor; - headersFilter.key = std::string(key.data, key.size); - return true; - } else { - if (descriptor) { - QPID_LOG(info, "Skipping unrecognised map data in filter: " << *descriptor); - } else { - QPID_LOG(info, "Skipping undescribed map data in filter"); - } - return false; - } -} -void Filter::onEndMapValue(const qpid::amqp::CharSequence&, uint32_t, const qpid::amqp::Descriptor*) -{ - if (inHeadersMap) { - inHeadersMap = false; - setAllowedKeyType(SYMBOL_KEY); - } -} - -bool Filter::hasSubjectFilter() const -{ - return !subjectFilter.value.empty(); -} - -std::string Filter::getSubjectFilter() const -{ - return subjectFilter.value; -} - - -bool Filter::hasSelectorFilter() const -{ - return !selectorFilter.value.empty(); -} - -std::string Filter::getSelectorFilter() const -{ - return selectorFilter.value; -} - -void Filter::setFilter(StringFilter& lhs, const StringFilter& rhs) -{ - if (!lhs.value.empty()) { - QPID_LOG(notice, "Skipping filter with key " << rhs.key << "; value provided for " << lhs.key << " already"); - } else { - lhs = rhs; - lhs.requested = true; - } -} - -void Filter::apply(boost::shared_ptr queue) -{ - if (hasSubjectFilter()) { - queue->setSubjectFilter(getSubjectFilter()); - active.push_back(&subjectFilter); - } - if (hasSelectorFilter()) { - queue->setSelectorFilter(getSelectorFilter()); - active.push_back(&selectorFilter); - } -} - -void Filter::configure(QueueSettings& settings) -{ - if (hasSelectorFilter()) { - settings.filter = getSelectorFilter(); - active.push_back(&selectorFilter); - } - if (nolocal) { - settings.noLocal = true; - QPID_LOG(notice, "No local filter set"); - } -} - -std::string Filter::getBindingKey(boost::shared_ptr exchange) const -{ - if (subjectFilter.value.empty() && exchange->getType() == TopicExchange::typeName) { - return WILDCARD; - } else { - return subjectFilter.value; - } -} - -void Filter::bind(boost::shared_ptr exchange, boost::shared_ptr queue) -{ - qpid::framing::FieldTable bindingArgs; - if (exchange->getType() == TopicExchange::typeName) { - setDefaultSubjectFilter(true); - active.push_back(&subjectFilter); - } else if (exchange->getType() == DirectExchange::typeName) { - if (!setDefaultSubjectFilter() && adjustDirectFilter()) { - QPID_LOG(info, "Using legacy topic filter as a direct matching filter for " << exchange->getName()); - } - active.push_back(&subjectFilter); - } else if (exchange->getType() == HeadersExchange::typeName) { - setDefaultHeadersFilter(); - qpid::amqp_0_10::translate(headersFilter.value, bindingArgs); - active.push_back(&headersFilter); - } else if (exchange->getType() == XML) { - setDefaultXQueryFilter(); - if (!setDefaultSubjectFilter() && adjustDirectFilter()) { - QPID_LOG(info, "Using legacy topic filter as a direct matching filter for " << exchange->getName()); - } - bindingArgs.setString(XQUERY, xqueryFilter.value); - active.push_back(&subjectFilter); - active.push_back(&xqueryFilter); - } - queue->bind(exchange, subjectFilter.value, bindingArgs); -} - -void Filter::setDefaultXQueryFilter() -{ - if (!xqueryFilter.requested) { - xqueryFilter.key = DEFAULT_XQUERY_FILTER; - xqueryFilter.value = DEFAULT_XQUERY_VALUE; - xqueryFilter.setDescriptor(qpid::amqp::Descriptor(qpid::amqp::filters::XQUERY_FILTER_CODE)); - } -} -void Filter::setDefaultHeadersFilter() -{ - if (!headersFilter.requested) { - headersFilter.key = DEFAULT_HEADERS_FILTER; - headersFilter.value[XMATCH] = ALL; - headersFilter.setDescriptor(qpid::amqp::Descriptor(qpid::amqp::filters::LEGACY_HEADERS_FILTER_CODE)); - } -} - -bool Filter::setDefaultSubjectFilter(const qpid::amqp::Descriptor& d, const std::string& value) -{ - if (!subjectFilter.requested) { - subjectFilter.key = DEFAULT_SUBJECT_FILTER; - subjectFilter.value = value; - subjectFilter.setDescriptor(d); - return true; - } else { - return false; - } -} - -bool Filter::setDefaultSubjectFilter(bool wildcards) -{ - if (wildcards) { - return setDefaultSubjectFilter(qpid::amqp::Descriptor(qpid::amqp::filters::LEGACY_TOPIC_FILTER_CODE), WILDCARD); - } else { - return setDefaultSubjectFilter(qpid::amqp::Descriptor(qpid::amqp::filters::LEGACY_DIRECT_FILTER_CODE)); - } -} - -Filter::FilterBase::FilterBase() : described(false), requested(false), descriptor(0) {} -Filter::FilterBase::~FilterBase() {} -void Filter::FilterBase::setDescriptor(const qpid::amqp::Descriptor& d) -{ - described = true; - descriptor = d; -} -namespace { -pn_bytes_t convert(const std::string& in) -{ - pn_bytes_t out; - out.start = const_cast(in.data()); - out.size = in.size(); - return out; -} -pn_bytes_t convert(const qpid::amqp::CharSequence& in) -{ - pn_bytes_t out; - out.start = const_cast(in.data); - out.size = in.size; - return out; -} -qpid::amqp::Descriptor symbolicDescriptor(const std::string& symbol) -{ - qpid::amqp::CharSequence cs; - cs.data = symbol.data(); - cs.size = symbol.size(); - return qpid::amqp::Descriptor(cs); -} -} - -bool Filter::adjustDirectFilter() -{ - if (subjectFilter.descriptor.match(qpid::amqp::filters::LEGACY_TOPIC_FILTER_SYMBOL, qpid::amqp::filters::LEGACY_TOPIC_FILTER_CODE)) { - if (subjectFilter.descriptor.type == qpid::amqp::Descriptor::NUMERIC) { - subjectFilter.descriptor = qpid::amqp::Descriptor(qpid::amqp::filters::LEGACY_DIRECT_FILTER_CODE); - } else { - subjectFilter.descriptor = symbolicDescriptor(qpid::amqp::filters::LEGACY_DIRECT_FILTER_SYMBOL); - } - return true; - } else { - return false; - } -} - -void Filter::FilterBase::write(pn_data_t* data) -{ - pn_data_put_symbol(data, convert(key)); - if (described) { - pn_data_put_described(data); - pn_data_enter(data); - switch (descriptor.type) { - case qpid::amqp::Descriptor::NUMERIC: - pn_data_put_ulong(data, descriptor.value.code); - break; - case qpid::amqp::Descriptor::SYMBOLIC: - pn_data_put_symbol(data, convert(descriptor.value.symbol)); - break; - } - writeValue(data); - pn_data_exit(data); - } else { - writeValue(data); - } -} -void Filter::StringFilter::writeValue(pn_data_t* data) -{ - pn_data_put_string(data, convert(value)); -} - -void Filter::MapFilter::writeValue(pn_data_t* data) -{ - pn_data_put_map(data); - pn_data_enter(data); - for (ValueType::const_iterator i = value.begin(); i != value.end(); ++i) { - pn_data_put_string(data, convert(i->first)); - pn_data_put_string(data, convert(i->second));//TODO: other types? - } - pn_data_exit(data); -} - -void Filter::write(std::map source, pn_data_t* target) -{ - MapFilter dummy; - dummy.value = source; - dummy.writeValue(target); -} - - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Filter.h b/qpid/cpp/src/qpid/broker/amqp/Filter.h deleted file mode 100644 index af942535ef..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Filter.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef QPID_BROKER_AMQP_FILTER_H -#define QPID_BROKER_AMQP_FILTER_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/amqp/MapReader.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/types/Variant.h" -#include -#include -#include - -struct pn_data_t; -namespace qpid { -namespace broker { -class Exchange; -class Queue; -struct QueueSettings; -namespace amqp { -class Outgoing; - -class Filter : private qpid::amqp::MapReader -{ - public: - Filter(); - void read(pn_data_t*); - void write(pn_data_t*); - std::string getBindingKey(boost::shared_ptr exchange) const; - - /** - * Apply filters where source is a queue - */ - void apply(boost::shared_ptr queue); - - /** - * Configure subscription queue for case where source is an exchange - */ - void configure(QueueSettings&); - /** - * Bind subscription queue for case where source is an exchange - */ - void bind(boost::shared_ptr exchange, boost::shared_ptr queue); - - /** - * Not really the ideal place for this, but the logic is already implemented here... - */ - static void write(std::map source, pn_data_t* target); - private: - struct FilterBase - { - bool described; - bool requested; - qpid::amqp::Descriptor descriptor; - std::string key; - FilterBase(); - virtual ~FilterBase(); - void write(pn_data_t*); - virtual void writeValue(pn_data_t*) = 0; - void setDescriptor(const qpid::amqp::Descriptor&); - }; - struct StringFilter : FilterBase - { - std::string value; - void writeValue(pn_data_t*); - }; - struct MapFilter : FilterBase - { - typedef std::map ValueType; - ValueType value; - void writeValue(pn_data_t*); - }; - - void onStringValue(const qpid::amqp::CharSequence& key, const qpid::amqp::CharSequence& value, const qpid::amqp::Descriptor* descriptor); - void onNullValue(const qpid::amqp::CharSequence&, const qpid::amqp::Descriptor*); - void onBooleanValue(const qpid::amqp::CharSequence&, bool, const qpid::amqp::Descriptor*); - void onUByteValue(const qpid::amqp::CharSequence&, uint8_t, const qpid::amqp::Descriptor*); - void onUShortValue(const qpid::amqp::CharSequence&, uint16_t, const qpid::amqp::Descriptor*); - void onUIntValue(const qpid::amqp::CharSequence&, uint32_t, const qpid::amqp::Descriptor*); - void onULongValue(const qpid::amqp::CharSequence&, uint64_t, const qpid::amqp::Descriptor*); - void onByteValue(const qpid::amqp::CharSequence&, int8_t, const qpid::amqp::Descriptor*); - void onShortValue(const qpid::amqp::CharSequence&, int16_t, const qpid::amqp::Descriptor*); - void onIntValue(const qpid::amqp::CharSequence&, int32_t, const qpid::amqp::Descriptor*); - void onLongValue(const qpid::amqp::CharSequence&, int64_t, const qpid::amqp::Descriptor*); - void onFloatValue(const qpid::amqp::CharSequence&, float, const qpid::amqp::Descriptor*); - void onDoubleValue(const qpid::amqp::CharSequence&, double, const qpid::amqp::Descriptor*); - bool onStartListValue(const qpid::amqp::CharSequence& key, uint32_t count, const qpid::amqp::Descriptor* descriptor); - bool onStartMapValue(const qpid::amqp::CharSequence& key, uint32_t count, const qpid::amqp::Descriptor* descriptor); - void onEndMapValue(const qpid::amqp::CharSequence& key, uint32_t count, const qpid::amqp::Descriptor* descriptor); - void setFilter(StringFilter&, const StringFilter&); - bool hasSubjectFilter() const; - std::string getSubjectFilter() const; - bool hasSelectorFilter() const; - std::string getSelectorFilter() const; - bool setDefaultSubjectFilter(bool wildcards=false); - bool setDefaultSubjectFilter(const qpid::amqp::Descriptor& descriptor, const std::string& value=std::string()); - bool adjustDirectFilter(); - void setDefaultHeadersFilter(); - void setDefaultXQueryFilter(); - - StringFilter subjectFilter; - StringFilter selectorFilter; - StringFilter xqueryFilter; - MapFilter headersFilter; - std::vector active; - bool inHeadersMap; - bool nolocal; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_FILTER_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Header.cpp b/qpid/cpp/src/qpid/broker/amqp/Header.cpp deleted file mode 100644 index e1b3d22553..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Header.cpp +++ /dev/null @@ -1,65 +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/broker/amqp/Header.h" -#include "qpid/broker/Message.h" - -namespace qpid { -namespace broker { -namespace amqp { - -bool Header::isDurable() const -{ - return message.isPersistent(); -} - -uint8_t Header::getPriority() const -{ - return message.getPriority(); -} - -bool Header::hasTtl() const -{ - uint64_t dummy(0); - return message.getTtl(dummy); -} - -uint32_t Header::getTtl() const -{ - uint64_t ttl(0); - message.getTtl(ttl); - if (ttl > std::numeric_limits::max()) return std::numeric_limits::max(); - else return (uint32_t) ttl; -} - -bool Header::isFirstAcquirer() const -{ - return (!message.hasBeenAcquired()); -} - -uint32_t Header::getDeliveryCount() const -{ - return message.isRedelivered() ? message.getDeliveryCount() : 0; -} - -Header::Header(const qpid::broker::Message& m) : message(m) {} - - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Header.h b/qpid/cpp/src/qpid/broker/amqp/Header.h deleted file mode 100644 index 6e4f763028..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Header.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_BROKER_AMQP_HEADER_H -#define QPID_BROKER_AMQP_HEADER_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/amqp/MessageEncoder.h" - -namespace qpid { -namespace broker { -class Message; -namespace amqp { - -/** - * Adapts the broker current message abstraction to provide that - * required by the AMQP 1.0 message encoder. - */ -class Header : public qpid::amqp::MessageEncoder::Header -{ - public: - Header(const qpid::broker::Message&); - bool isDurable() const; - uint8_t getPriority() const; - bool hasTtl() const; - uint32_t getTtl() const; - bool isFirstAcquirer() const; - uint32_t getDeliveryCount() const; - private: - const qpid::broker::Message& message; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_HEADER_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp b/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp deleted file mode 100644 index fd3319eca1..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp +++ /dev/null @@ -1,156 +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 "Incoming.h" -#include "Exception.h" -#include "ManagedConnection.h" -#include "Message.h" -#include "Session.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/broker/AsyncCompletion.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { -namespace amqp { -Incoming::Incoming(pn_link_t* l, Broker& broker, Session& parent, const std::string& source, const std::string& target, const std::string& name) - : ManagedIncomingLink(broker, parent, source, target, name), credit(500), window(0), link(l), session(parent) {} - - -Incoming::~Incoming() {} -bool Incoming::doWork() -{ - uint32_t c = getCredit(); - bool issue = window < c; - if (issue) { - pn_link_flow(link, c - window); - window = c; - } - return issue; -} -bool Incoming::haveWork() -{ - return window <= (getCredit()/2); -} - -uint32_t Incoming::getCredit() -{ - return credit;//TODO: proper flow control -} - -void Incoming::detached(bool /*closed*/) -{ -} - -void Incoming::wakeup() -{ - session.wakeup(); -} - -void Incoming::verify(const std::string& u, const std::string& r) -{ - userid.init(u, r); -} - -Incoming::UserId::UserId() : inDefaultRealm(false) {} -void Incoming::UserId::init(const std::string& u, const std::string& defaultRealm) -{ - userid = u; - size_t at = userid.find('@'); - if (at != std::string::npos) { - unqualified = userid.substr(0, at); - inDefaultRealm = defaultRealm == userid.substr(at+1); - } -} -void Incoming::UserId::verify(const std::string& claimed) -{ - if(!userid.empty() && !claimed.empty() && userid != claimed && !(inDefaultRealm && claimed == unqualified)) { - throw Exception(qpid::amqp::error_conditions::NOT_ALLOWED, QPID_MSG("Authenticated user id is " << userid << " but user id in message declared as " << claimed)); - } -} - - -namespace { - class Transfer : public qpid::broker::AsyncCompletion::Callback - { - public: - Transfer(pn_delivery_t* d, boost::shared_ptr s) : delivery(d), session(s) {} - void completed(bool sync) { session->accepted(delivery, sync); } - boost::intrusive_ptr clone() - { - boost::intrusive_ptr copy(new Transfer(delivery, session)); - return copy; - } - - private: - pn_delivery_t* delivery; - boost::shared_ptr session; - }; -} - -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), sessionPtr(parent.shared_from_this()) {} -DecodingIncoming::~DecodingIncoming() {} - -void DecodingIncoming::readable(pn_delivery_t* delivery) -{ - size_t pending = pn_delivery_pending(delivery); - size_t offset = partial ? partial->getSize() : 0; - boost::intrusive_ptr received(new Message(offset + pending)); - if (partial) { - ::memcpy(received->getData(), partial->getData(), offset); - partial = boost::intrusive_ptr(); - } - assert(received->getSize() == pending + offset); - pn_link_recv(link, received->getData() + offset, pending); - - if (pn_delivery_partial(delivery)) { - QPID_LOG(debug, "Message incomplete: received " << pending << " bytes, now have " << received->getSize()); - partial = received; - } else { - incomingMessageReceived(); - if (offset) { - QPID_LOG(debug, "Message complete: received " << pending << " bytes, " << received->getSize() << " in total"); - } else { - QPID_LOG(debug, "Message received: " << received->getSize() << " bytes"); - } - - received->scan(); - pn_link_advance(link); - received->setPublisher(&session.getParent()); - received->computeExpiration(); - --window; - deliver(received, delivery); - } -} - -void DecodingIncoming::deliver(boost::intrusive_ptr received, pn_delivery_t* delivery) -{ - qpid::broker::Message message(received, received); - userid.verify(message.getUserId()); - received->begin(); - handle(message, session.getTransaction(delivery)); - Transfer t(delivery, sessionPtr); - sessionPtr->pending_accept(delivery); - received->end(t); -} -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Incoming.h b/qpid/cpp/src/qpid/broker/amqp/Incoming.h deleted file mode 100644 index ccf999a256..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Incoming.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef QPID_BROKER_AMQP_INCOMING_H -#define QPID_BROKER_AMQP_INCOMING_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 "Message.h" -#include "ManagedIncomingLink.h" -extern "C" { -#include -} -#include -namespace qpid { -namespace broker { -class Broker; -class Message; -class TxBuffer; -namespace amqp { -class Session; - -class Incoming : public ManagedIncomingLink -{ - public: - Incoming(pn_link_t*, Broker& broker, Session& parent, const std::string& source, const std::string& target, const std::string& name); - virtual ~Incoming(); - virtual bool doWork();//do anything that requires output - virtual bool haveWork();//called when handling input to see whether any output work is needed - virtual void detached(bool closed); - virtual void readable(pn_delivery_t* delivery) = 0; - void verify(const std::string& userid, const std::string& defaultRealm); - void wakeup(); - protected: - class UserId - { - public: - UserId(); - void init(const std::string& userid, const std::string& defaultRealm); - void verify(const std::string& claimed); - private: - std::string userid; - bool inDefaultRealm; - std::string unqualified; - }; - - const uint32_t credit; - uint32_t window; - - - pn_link_t* link; - Session& session; - UserId userid; - virtual uint32_t getCredit(); -}; - -class DecodingIncoming : public Incoming -{ - public: - DecodingIncoming(pn_link_t*, Broker& broker, Session& parent, const std::string& source, const std::string& target, const std::string& name); - virtual ~DecodingIncoming(); - void readable(pn_delivery_t* delivery); - virtual void deliver(boost::intrusive_ptr received, pn_delivery_t* delivery); - virtual void handle(qpid::broker::Message&, qpid::broker::TxBuffer*) = 0; - private: - boost::shared_ptr sessionPtr; - boost::intrusive_ptr partial; -}; - -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_INCOMING_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Interconnect.cpp b/qpid/cpp/src/qpid/broker/amqp/Interconnect.cpp deleted file mode 100644 index 41d22d39cc..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Interconnect.cpp +++ /dev/null @@ -1,163 +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 "Interconnect.h" -#include "Interconnects.h" -#include "Connection.h" -#include "SaslClient.h" -#include "Session.h" -#include "qpid/broker/Broker.h" -#include "qpid/Exception.h" -#include "qpid/SaslFactory.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/log/Statement.h" -#include -extern "C" { -#include -#include -} - -namespace qpid { -namespace broker { -namespace amqp { - -Interconnect::Interconnect(qpid::sys::OutputControl& out, const std::string& id, BrokerContext& broker, bool saslInUse, - bool i, const std::string& n, const std::string& s, const std::string& t, const std::string& d) - : Connection(out, id, broker, true, true), incoming(i), name(n), source(s), target(t), domain(d), headerDiscarded(saslInUse), - isOpened(false), closeRequested(false), isTransportDeleted(false) -{} - -Interconnect::~Interconnect() -{ - QPID_LOG(notice, "Interconnect deleted"); -} - -namespace { -const pn_state_t UNINIT = PN_LOCAL_UNINIT | PN_REMOTE_UNINIT; -const size_t PROTOCOL_HEADER_LENGTH(8); -} - -size_t Interconnect::encode(char* buffer, size_t size) -{ - if (headerDiscarded) { - return Connection::encode(buffer, size); - } else { - //The IO 'layer' will write in a protocol header when an - //'outgoing' connection is established. However the proton - //protocol engine will also emit one. One needs to be - //discarded, here we discard the one the engine emits for - //interconnects. - headerDiscarded = true; - size_t encoded = Connection::encode(buffer, size); - assert(encoded >= PROTOCOL_HEADER_LENGTH);//we never encode part of protocol header - //discard first eight bytes - ::memmove(buffer, buffer + PROTOCOL_HEADER_LENGTH, encoded - PROTOCOL_HEADER_LENGTH); - return encoded - PROTOCOL_HEADER_LENGTH; - } -} - -namespace { -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -pn_bytes_t convert(const std::string& s) -{ - pn_bytes_t result; - result.start = const_cast(s.data()); - result.size = s.size(); - return result; -} -void setProperties(pn_connection_t* connection) -{ - pn_data_t* data = pn_connection_properties(connection); - pn_data_put_map(data); - pn_data_enter(data); - - pn_data_put_symbol(data, convert(CLIENT_PROCESS_NAME)); - std::string processName = sys::SystemInfo::getProcessName(); - pn_data_put_string(data, convert(processName)); - - pn_data_put_symbol(data, convert(CLIENT_PID)); - pn_data_put_int(data, sys::SystemInfo::getProcessId()); - pn_data_exit(data); -} -} - -void Interconnect::process() -{ - QPID_LOG(trace, id << " processing interconnect"); - if (closeRequested) { - close(); - } else { - if ((pn_connection_state(connection) & UNINIT) == UNINIT) { - QPID_LOG_CAT(debug, model, id << " interconnect open initiated"); - pn_connection_set_container(connection, getBroker().getFederationTag().c_str()); - setProperties(connection); - pn_connection_open(connection); - out.connectionEstablished(); - setInterconnectDomain(domain); - } - if (!isOpened && (pn_connection_state(connection) & PN_REMOTE_ACTIVE)) { - QPID_LOG_CAT(debug, model, id << " interconnect open completed, attaching link"); - isOpened = true; - readPeerProperties(); - const char* containerid(pn_connection_remote_container(connection)); - if (containerid) { - setContainerId(std::string(containerid)); - } - opened(); - getBroker().getConnectionObservers().opened(*this); - pn_session_t* s = pn_session(connection); - pn_session_open(s); - boost::shared_ptr ssn(new Session(s, *this, out)); - sessions[s] = ssn; - - pn_link_t* l = incoming ? pn_receiver(s, name.c_str()) : pn_sender(s, name.c_str()); - pn_link_open(l); - ssn->attach(l, source, target, relay); - } - Connection::process(); - } -} - -void Interconnect::setRelay(boost::shared_ptr r) -{ - relay = r; -} - -void Interconnect::deletedFromRegistry() -{ - closeRequested = true; - if (!isTransportDeleted) out.activateOutput(); -} - -void Interconnect::transportDeleted() -{ - isTransportDeleted = true; - getInterconnects().remove(name); -} - -bool Interconnect::isLink() const -{ - return true; -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Interconnect.h b/qpid/cpp/src/qpid/broker/amqp/Interconnect.h deleted file mode 100644 index d8eb457be2..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Interconnect.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef QPID_BROKER_AMQP_INTERCONNECT_H -#define QPID_BROKER_AMQP_INTERCONNECT_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 "Connection.h" - -namespace qpid { -struct Address; -namespace broker { -namespace amqp { -class Domain; -class Interconnects; -class Relay; - -/** - * - */ -class Interconnect : public Connection -{ - public: - Interconnect(qpid::sys::OutputControl& out, const std::string& id, BrokerContext& broker, bool saslInUse, - bool incoming, const std::string& name, - const std::string& source, const std::string& target, const std::string& domain); - void setRelay(boost::shared_ptr); - ~Interconnect(); - size_t encode(char* buffer, size_t size); - void deletedFromRegistry(); - void transportDeleted(); - bool isLink() const; - private: - bool incoming; - std::string name; - std::string source; - std::string target; - std::string domain; - bool headerDiscarded; - boost::shared_ptr relay; - bool isOpened; - bool closeRequested; - bool isTransportDeleted; - - void process(); -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_INTERCONNECT_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Interconnects.cpp b/qpid/cpp/src/qpid/broker/amqp/Interconnects.cpp deleted file mode 100644 index 912b244bf9..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Interconnects.cpp +++ /dev/null @@ -1,176 +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 "Interconnects.h" -#include "Interconnect.h" -#include "Connection.h" -#include "Domain.h" -#include "SaslClient.h" -#include "qpid/broker/Broker.h" -#include "qpid/Exception.h" -#include "qpid/SaslFactory.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/log/Statement.h" -#include -#include - -namespace qpid { -namespace broker { -namespace amqp { - -namespace { -const std::string INCOMING_TYPE("incoming"); -const std::string OUTGOING_TYPE("outgoing"); -const std::string DOMAIN_TYPE("domain"); -} - -bool Interconnects::createObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& /*userId*/, const std::string& /*connectionId*/) -{ - if (type == DOMAIN_TYPE) { - qpid::sys::ScopedLock l(lock); - DomainMap::iterator i = domains.find(name); - if (i == domains.end()) { - boost::shared_ptr domain(new Domain(name, properties, broker)); - domains[name] = domain; - if (domain->isDurable()) broker.getStore().create(*domain); - return true; - } else { - throw qpid::Exception(QPID_MSG("A domain named " << name << " already exists")); - } - } else if (type == INCOMING_TYPE || type == OUTGOING_TYPE) { - QPID_LOG(notice, "Creating interconnect " << name << ", " << properties); - boost::shared_ptr domain; - { - qpid::sys::ScopedLock l(lock); - qpid::types::Variant::Map::const_iterator p = properties.find(DOMAIN_TYPE); - if (p != properties.end()) { - std::string domainName = p->second; - DomainMap::iterator i = domains.find(domainName); - if (i != domains.end()) { - domain = i->second; - } else { - throw qpid::Exception(QPID_MSG("No such domain: " << domainName)); - } - } else { - throw qpid::Exception(QPID_MSG("Domain must be specified")); - } - } - domain->connect(type == INCOMING_TYPE, name, properties, *context); - return true; - } else { - return false; - } -} -bool Interconnects::deleteObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& /*properties*/, - const std::string& /*userId*/, const std::string& /*connectionId*/) -{ - if (type == DOMAIN_TYPE) { - boost::shared_ptr domain; - qpid::sys::ScopedLock l(lock); - DomainMap::iterator i = domains.find(name); - if (i != domains.end()) { - domain = i->second; - domains.erase(i); - if (domain->isDurable()) broker.getStore().destroy(*domain); - return true; - } else { - throw qpid::Exception(QPID_MSG("No such domain: " << name)); - } - } else if (type == INCOMING_TYPE || type == OUTGOING_TYPE) { - boost::shared_ptr interconnect; - { - qpid::sys::ScopedLock l(lock); - InterconnectMap::iterator i = interconnects.find(name); - if (i != interconnects.end()) { - interconnect = i->second; - interconnects.erase(i); - } else { - throw qpid::Exception(QPID_MSG("No such interconnection: " << name)); - } - } - if (interconnect) interconnect->deletedFromRegistry(); - return true; - } else { - return false; - } -} - -bool Interconnects::recoverObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - uint64_t persistenceId) -{ - if (type == DOMAIN_TYPE) { - boost::shared_ptr domain(new Domain(name, properties, broker)); - domain->setPersistenceId(persistenceId); - qpid::sys::ScopedLock l(lock); - domains[name] = domain; - return true; - } else { - return false; - } -} - - -bool Interconnects::add(const std::string& name, boost::shared_ptr connection) -{ - qpid::sys::ScopedLock l(lock); - InterconnectMap::iterator i = interconnects.find(name); - if (i == interconnects.end()) { - interconnects[name] = connection; - return true; - } else return false; -} -boost::shared_ptr Interconnects::get(const std::string& name) -{ - qpid::sys::ScopedLock l(lock); - InterconnectMap::const_iterator i = interconnects.find(name); - if (i != interconnects.end()) return i->second; - else return boost::shared_ptr(); -} -bool Interconnects::remove(const std::string& name) -{ - qpid::sys::ScopedLock l(lock); - InterconnectMap::iterator i = interconnects.find(name); - if (i != interconnects.end()) { - interconnects.erase(i); - return true; - } else return false; -} - -boost::shared_ptr Interconnects::findDomain(const std::string& name) -{ - qpid::sys::ScopedLock l(lock); - DomainMap::iterator i = domains.find(name); - if (i == domains.end()) { - return boost::shared_ptr(); - } else { - return i->second; - } -} -void Interconnects::setContext(BrokerContext& c) -{ - context = &c; - assert(&(context->getInterconnects()) == this); -} - -Interconnects::Interconnects() : context(0) {} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Interconnects.h b/qpid/cpp/src/qpid/broker/amqp/Interconnects.h deleted file mode 100644 index 030d6d6446..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Interconnects.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef QPID_BROKER_AMQP_INTERCONNECTS_H -#define QPID_BROKER_AMQP_INTERCONNECTS_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/ObjectFactory.h" -#include "qpid/sys/Mutex.h" -#include -#include -#include - -namespace qpid { -namespace broker { -namespace amqp { -class BrokerContext; -class Domain; -class Interconnect; -/** - * - */ -class Interconnects : public ObjectFactory -{ - public: - bool createObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId); - bool deleteObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId); - bool recoverObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - uint64_t persistenceId); - - bool add(const std::string&, boost::shared_ptr); - boost::shared_ptr get(const std::string&); - bool remove(const std::string&); - - boost::shared_ptr findDomain(const std::string&); - void setContext(BrokerContext&); - Interconnects(); - private: - typedef std::map > InterconnectMap; - typedef std::map > DomainMap; - InterconnectMap interconnects; - DomainMap domains; - qpid::sys::Mutex lock; - BrokerContext* context; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_INTERCONNECTS_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/ManagedConnection.cpp b/qpid/cpp/src/qpid/broker/amqp/ManagedConnection.cpp deleted file mode 100644 index 2c4824bc51..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ManagedConnection.cpp +++ /dev/null @@ -1,214 +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/broker/amqp/ManagedConnection.h" -#include "qpid/broker/amqp/Exception.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/log/Statement.h" -#include "qpid/types/Variant.h" -#include "qmf/org/apache/qpid/broker/EventClientConnect.h" -#include "qmf/org/apache/qpid/broker/EventClientDisconnect.h" - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { -namespace amqp { -namespace { -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); -template T getProperty(const std::string& key, const qpid::types::Variant::Map& props, T defaultValue) -{ - qpid::types::Variant::Map::const_iterator i = props.find(key); - if (i != props.end()) { - return i->second; - } else { - return defaultValue; - } -} -} -ManagedConnection::ManagedConnection(Broker& broker, const std::string i, bool brokerInitiated) : id(i), agent(0) -{ - //management integration: - agent = broker.getManagementAgent(); - if (agent != 0) { - qpid::management::Manageable* parent = broker.GetVhostObject(); - connection = _qmf::Connection::shared_ptr(new _qmf::Connection(agent, this, parent, id, !brokerInitiated, false, "AMQP 1.0")); - agent->addObject(connection); - } -} - -ManagedConnection::~ManagedConnection() -{ - if (agent && connection) { - agent->raiseEvent(_qmf::EventClientDisconnect(id, userid, connection->get_remoteProperties())); - connection->resourceDestroy(); - } - QPID_LOG_CAT(debug, model, "Delete connection. user:" << userid << " rhost:" << id); -} - -void ManagedConnection::setUserId(const std::string& uid) -{ - userid = uid; - if (connection) { - connection->set_authIdentity(userid); - } -} - -void ManagedConnection::opened() -{ - if (agent) { - agent->raiseEvent(_qmf::EventClientConnect(id, userid, connection->get_remoteProperties())); - } - QPID_LOG_CAT(debug, model, "Create connection. user:" << userid << " rhost:" << id ); -} - -void ManagedConnection::setSaslMechanism(const std::string& mechanism) -{ - if (connection) { - connection->set_saslMechanism(mechanism); - } -} - -void ManagedConnection::setSaslSsf(int ssf) -{ - if (connection) { - connection->set_saslSsf(ssf); - } -} - -void ManagedConnection::setPeerProperties(std::map& p) -{ - peerProperties = p; - if (connection) { - connection->set_remoteProperties(peerProperties); - - std::string procName = getProperty(CLIENT_PROCESS_NAME, peerProperties, std::string()); - uint32_t pid = getProperty(CLIENT_PID, peerProperties, 0); - uint32_t ppid = getProperty(CLIENT_PPID, peerProperties, 0); - - if (!procName.empty()) - connection->set_remoteProcessName(procName); - if (pid != 0) - connection->set_remotePid(pid); - if (ppid != 0) - connection->set_remoteParentPid(ppid); - - } -} - -void ManagedConnection::setContainerId(const std::string& container) -{ - containerid = container; - peerProperties["container-id"] = containerid; - if (connection) { - connection->set_remoteProperties(peerProperties); - } -} -const std::string& ManagedConnection::getContainerId() const -{ - return containerid; -} - -void ManagedConnection::setInterconnectDomain(const std::string& d) -{ - domain = d; -} -const std::string& ManagedConnection::getInterconnectDomain() const -{ - return domain; -} - -qpid::management::ManagementObject::shared_ptr ManagedConnection::GetManagementObject() const -{ - return connection; -} - -std::string ManagedConnection::getId() const { return id; } - -const management::ObjectId ManagedConnection::getObjectId() const -{ - return GetManagementObject()->getObjectId(); -} -const std::string& ManagedConnection::getUserId() const -{ - return userid; -} -const std::string& ManagedConnection::getMgmtId() const -{ - return id; -} -const std::map& ManagedConnection::getClientProperties() const -{ - return connection->get_remoteProperties(); -} -bool ManagedConnection::isLink() const -{ - return false; -} - -bool ManagedConnection::isLocal(const OwnershipToken* t) const -{ - return this == t; -} -void ManagedConnection::outgoingMessageSent() -{ - if (connection) connection->inc_msgsToClient(); -} - -void ManagedConnection::incomingMessageReceived() -{ - if (connection) connection->inc_msgsFromClient(); -} - -void ManagedConnection::closedByManagement() -{ - throw Exception(qpid::amqp::error_conditions::NOT_IMPLEMENTED, QPID_MSG(id << "Connection close requested, but not implemented")); -} - -qpid::management::Manageable::status_t ManagedConnection::ManagementMethod(uint32_t methodId, qpid::management::Args&, std::string& error) -{ - qpid::management::Manageable::status_t status = qpid::management::Manageable::STATUS_UNKNOWN_METHOD; - - try { - switch (methodId) - { - case _qmf::Connection::METHOD_CLOSE : - closedByManagement(); - if (connection) connection->set_closing(true); - status = qpid::management::Manageable::STATUS_OK; - break; - } - } catch (const Exception& e) { - if (e.symbol() == qpid::amqp::error_conditions::NOT_IMPLEMENTED) { - status = qpid::management::Manageable::STATUS_NOT_IMPLEMENTED; - } else { - error = e.what(); - status = qpid::management::Manageable::STATUS_EXCEPTION; - } - } - - return status; -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/ManagedConnection.h b/qpid/cpp/src/qpid/broker/amqp/ManagedConnection.h deleted file mode 100644 index 77483b5630..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ManagedConnection.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef QPID_BROKER_AMQP_MANAGEDCONNECTION_H -#define QPID_BROKER_AMQP_MANAGEDCONNECTION_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/management/Manageable.h" -#include "qpid/broker/Connection.h" -#include "qpid/types/Variant.h" -#include "qmf/org/apache/qpid/broker/Connection.h" - -namespace qpid { -namespace management { -class ManagementAgent; -class ManagementObject; -} -namespace broker { -class Broker; -namespace amqp { - -class ManagedConnection : public qpid::management::Manageable, public qpid::broker::Connection -{ - public: - ManagedConnection(Broker& broker, const std::string id, bool brokerInitiated); - virtual ~ManagedConnection(); - virtual void setUserId(const std::string&); - std::string getId() const; - void setSaslMechanism(const std::string&); - void setSaslSsf(int); - void setContainerId(const std::string&); - const std::string& getContainerId() const; - void setInterconnectDomain(const std::string&); - const std::string& getInterconnectDomain() const; - void setPeerProperties(std::map&); - qpid::management::ManagementObject::shared_ptr GetManagementObject() const; - bool isLocal(const OwnershipToken* t) const; - void incomingMessageReceived(); - void outgoingMessageSent(); - - //ConnectionIdentity - const management::ObjectId getObjectId() const; - const std::string& getUserId() const; - const std::string& getMgmtId() const; - const std::map& getClientProperties() const; - virtual bool isLink() const; - void opened(); - - qpid::management::Manageable::status_t ManagementMethod(uint32_t methodId, qpid::management::Args&, std::string&); - - protected: - virtual void closedByManagement(); - private: - const std::string id; - std::string userid; - std::string containerid; - std::string domain; - qmf::org::apache::qpid::broker::Connection::shared_ptr connection; - qpid::management::ManagementAgent* agent; - std::map peerProperties; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_MANAGEDCONNECTION_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/ManagedIncomingLink.cpp b/qpid/cpp/src/qpid/broker/amqp/ManagedIncomingLink.cpp deleted file mode 100644 index a30349d50e..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ManagedIncomingLink.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "ManagedIncomingLink.h" -#include "qpid/broker/amqp/ManagedConnection.h" -#include "qpid/broker/amqp/ManagedSession.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/log/Statement.h" - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { -namespace amqp { - -ManagedIncomingLink::ManagedIncomingLink(Broker& broker, ManagedSession& p, const std::string& source, const std::string& target, const std::string& _name) - : parent(p), name(_name) -{ - qpid::management::ManagementAgent* agent = broker.getManagementAgent(); - if (agent) { - incoming = _qmf::Incoming::shared_ptr(new _qmf::Incoming(agent, this, &parent, parent.getParent().getContainerId(), _name, source, target, - parent.getParent().getInterconnectDomain())); - agent->addObject(incoming); - } -} -ManagedIncomingLink::~ManagedIncomingLink() -{ - if (incoming != 0) incoming->resourceDestroy(); -} - -qpid::management::ManagementObject::shared_ptr ManagedIncomingLink::GetManagementObject() const -{ - return incoming; -} - -void ManagedIncomingLink::incomingMessageReceived() -{ - if (incoming) { incoming->inc_transfers(); } -} -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/ManagedIncomingLink.h b/qpid/cpp/src/qpid/broker/amqp/ManagedIncomingLink.h deleted file mode 100644 index 5d4b1409d4..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ManagedIncomingLink.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_BROKER_AMQP_MANAGEDINCOMINGLINK_H -#define QPID_BROKER_AMQP_MANAGEDINCOMINGLINK_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/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Incoming.h" - -namespace qpid { -namespace management { -class ManagementObject; -} -namespace broker { -class Broker; -namespace amqp { -class ManagedSession; - -class ManagedIncomingLink : public qpid::management::Manageable -{ - public: - ManagedIncomingLink(Broker& broker, ManagedSession& parent, const std::string& source, const std::string& target, const std::string& name); - virtual ~ManagedIncomingLink(); - qpid::management::ManagementObject::shared_ptr GetManagementObject() const; - void incomingMessageReceived(); - private: - ManagedSession& parent; - const std::string name; - qmf::org::apache::qpid::broker::Incoming::shared_ptr incoming; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_MANAGEDINCOMINGLINK_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/ManagedOutgoingLink.cpp b/qpid/cpp/src/qpid/broker/amqp/ManagedOutgoingLink.cpp deleted file mode 100644 index 9c538f864c..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ManagedOutgoingLink.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "ManagedOutgoingLink.h" -#include "qpid/broker/amqp/ManagedConnection.h" -#include "qpid/broker/amqp/ManagedSession.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/log/Statement.h" - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { -namespace amqp { - -ManagedOutgoingLink::ManagedOutgoingLink(Broker& broker, ManagedSession& p, const std::string& source, const std::string& target, const std::string& _name) - : parent(p), name(_name) -{ - qpid::management::ManagementAgent* agent = broker.getManagementAgent(); - if (agent) { - outgoing = _qmf::Outgoing::shared_ptr(new _qmf::Outgoing(agent, this, &parent, parent.getParent().getContainerId(), _name, source, target, - parent.getParent().getInterconnectDomain())); - agent->addObject(outgoing); - } -} -ManagedOutgoingLink::~ManagedOutgoingLink() -{ - if (outgoing != 0) outgoing->resourceDestroy(); -} - -qpid::management::ManagementObject::shared_ptr ManagedOutgoingLink::GetManagementObject() const -{ - return outgoing; -} - -void ManagedOutgoingLink::outgoingMessageSent() -{ - if (outgoing) { outgoing->inc_transfers(); } - parent.outgoingMessageSent(); -} -void ManagedOutgoingLink::outgoingMessageAccepted() -{ - parent.outgoingMessageAccepted(); -} -void ManagedOutgoingLink::outgoingMessageRejected() -{ - parent.outgoingMessageRejected(); -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/ManagedOutgoingLink.h b/qpid/cpp/src/qpid/broker/amqp/ManagedOutgoingLink.h deleted file mode 100644 index f6415bff38..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ManagedOutgoingLink.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_BROKER_AMQP_MANAGEDOUTGOINGLINK_H -#define QPID_BROKER_AMQP_MANAGEDOUTGOINGLINK_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/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Outgoing.h" - -namespace qpid { -namespace management { -class ManagementObject; -} -namespace broker { -class Broker; -namespace amqp { -class ManagedSession; - -class ManagedOutgoingLink : public qpid::management::Manageable -{ - public: - ManagedOutgoingLink(Broker& broker, ManagedSession& parent, const std::string& source, const std::string& target, const std::string& name); - virtual ~ManagedOutgoingLink(); - qpid::management::ManagementObject::shared_ptr GetManagementObject() const; - void outgoingMessageSent(); - void outgoingMessageAccepted(); - void outgoingMessageRejected(); - private: - ManagedSession& parent; - const std::string name; - qmf::org::apache::qpid::broker::Outgoing::shared_ptr outgoing; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_MANAGEDOUTGOINGLINK_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/ManagedSession.cpp b/qpid/cpp/src/qpid/broker/amqp/ManagedSession.cpp deleted file mode 100644 index 3bf9cf90db..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ManagedSession.cpp +++ /dev/null @@ -1,158 +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/broker/amqp/ManagedSession.h" -#include "qpid/broker/amqp/ManagedConnection.h" -#include "qpid/broker/amqp/Exception.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/log/Statement.h" - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { -namespace amqp { - -ManagedSession::ManagedSession(Broker& broker, ManagedConnection& p, const std::string i) : parent(p), id(i), unacked(0) -{ - qpid::management::ManagementAgent* agent = broker.getManagementAgent(); - if (agent != 0) { - std::string name(id); - std::string fullName(name); - if (name.length() >= std::numeric_limits::max()) - name.resize(std::numeric_limits::max()-1); - session = _qmf::Session::shared_ptr(new _qmf::Session(agent, this, broker.GetVhostObject(), name)); - session->set_fullName(fullName); - session->set_attached(true); - session->clr_expireTime(); - session->set_connectionRef(parent.GetManagementObject()->getObjectId()); - agent->addObject(session); - } -} - -ManagedSession::~ManagedSession() -{ - if (session) session->resourceDestroy(); -} - -qpid::management::ManagementObject::shared_ptr ManagedSession::GetManagementObject() const -{ - return session; -} - -bool ManagedSession::isLocal(const OwnershipToken* t) const -{ - return &parent == t; -} - -void ManagedSession::outgoingMessageSent() -{ - if (session) session->set_unackedMessages(++unacked); - parent.outgoingMessageSent(); -} -void ManagedSession::outgoingMessageAccepted() -{ - if (session) session->set_unackedMessages(--unacked); -} -void ManagedSession::outgoingMessageRejected() -{ - if (session) session->set_unackedMessages(--unacked); -} - -void ManagedSession::incomingMessageReceived() -{ - parent.incomingMessageReceived(); -} -void ManagedSession::incomingMessageAccepted() -{ - -} -void ManagedSession::incomingMessageRejected() -{ - -} -void ManagedSession::txStarted() -{ - if (session) { - session->inc_TxnStarts(); - } -} - -void ManagedSession::txCommitted() -{ - if (session) { - session->inc_TxnCommits(); - session->inc_TxnCount(); - } -} - -void ManagedSession::txAborted() -{ - if (session) { - session->inc_TxnRejects(); - session->inc_TxnCount(); - } -} - -ManagedConnection& ManagedSession::getParent() -{ - return parent; -} - -void ManagedSession::detachedByManagement() -{ - throw Exception(qpid::amqp::error_conditions::NOT_IMPLEMENTED, QPID_MSG(id << "Session detach requested, but not implemented")); -} - -qpid::management::Manageable::status_t ManagedSession::ManagementMethod (uint32_t methodId, - qpid::management::Args& /*args*/, - std::string& error) -{ - qpid::management::Manageable::status_t status = qpid::management::Manageable::STATUS_UNKNOWN_METHOD; - - try { - switch (methodId) - { - case _qmf::Session::METHOD_DETACH : - detachedByManagement(); - status = qpid::management::Manageable::STATUS_OK; - break; - - case _qmf::Session::METHOD_CLOSE : - case _qmf::Session::METHOD_SOLICITACK : - case _qmf::Session::METHOD_RESETLIFESPAN : - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } - } catch (const Exception& e) { - if (e.symbol() == qpid::amqp::error_conditions::NOT_IMPLEMENTED) { - status = qpid::management::Manageable::STATUS_NOT_IMPLEMENTED; - } else { - error = e.what(); - status = qpid::management::Manageable::STATUS_EXCEPTION; - } - } - - return status; -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/ManagedSession.h b/qpid/cpp/src/qpid/broker/amqp/ManagedSession.h deleted file mode 100644 index c35e304cfb..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ManagedSession.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef QPID_BROKER_AMQP_MANAGEDSESSION_H -#define QPID_BROKER_AMQP_MANAGEDSESSION_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/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Session.h" -#include "qpid/broker/OwnershipToken.h" - -namespace qpid { -namespace management { -class ManagementObject; -} -namespace broker { -class Broker; -namespace amqp { -class ManagedConnection; - -class ManagedSession : public qpid::management::Manageable, public OwnershipToken -{ - public: - ManagedSession(Broker& broker, ManagedConnection& parent, const std::string id); - virtual ~ManagedSession(); - qpid::management::ManagementObject::shared_ptr GetManagementObject() const; - bool isLocal(const OwnershipToken* t) const; - void incomingMessageReceived(); - void incomingMessageAccepted(); - void incomingMessageRejected(); - void outgoingMessageSent(); - void outgoingMessageAccepted(); - void outgoingMessageRejected(); - void txStarted(); - void txCommitted(); - void txAborted(); - ManagedConnection& getParent(); - - qpid::management::Manageable::status_t ManagementMethod (uint32_t, qpid::management::Args&, std::string&); - protected: - virtual void detachedByManagement(); - private: - ManagedConnection& parent; - const std::string id; - qmf::org::apache::qpid::broker::Session::shared_ptr session; - size_t unacked; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_MANAGEDSESSION_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Message.cpp b/qpid/cpp/src/qpid/broker/amqp/Message.cpp deleted file mode 100644 index 2e19c9a9ad..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Message.cpp +++ /dev/null @@ -1,569 +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 "Message.h" -#include "qpid/amqp/Decoder.h" -#include "qpid/amqp/descriptors.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 -#include - -namespace qpid { -namespace broker { -namespace amqp { - -using qpid::amqp::CharSequence; -using qpid::amqp::Constructor; -using qpid::amqp::Descriptor; -using qpid::amqp::MapHandler; -using qpid::amqp::Reader; - -namespace { -std::string empty; -} - -std::string Message::getRoutingKey() const -{ - std::string v; - v.assign(subject.data, subject.size); - return v; -} -std::string Message::getUserId() const -{ - std::string v; - v.assign(userId.data, userId.size); - return v; -} - -uint64_t Message::getTimestamp() const -{ - //creation time is in milliseconds, timestamp (from the 0-10 spec) is in seconds - return !creationTime ? 0 : creationTime.get()/1000; -} - -bool Message::isPersistent() const -{ - return durable && durable.get(); -} -bool Message::getTtl(uint64_t& t) const -{ - if (!ttl) { - return false; - } else { - t = ttl.get(); - return true; - } -} - -uint8_t Message::getPriority() const -{ - if (!priority) return 4; - else return priority.get(); -} - -std::string Message::getTo() const -{ - std::string v; - if (to.data) v.assign(to.data, to.size); - return v; -} -std::string Message::getSubject() const -{ - std::string v; - if (subject.data) v.assign(subject.data, subject.size); - return v; -} -std::string Message::getReplyTo() const -{ - std::string v; - if (replyTo.data) v.assign(replyTo.data, replyTo.size); - return v; -} - -namespace { -class StringRetriever : public MapHandler -{ - public: - StringRetriever(const std::string& k) : key(k) {} - void handleBool(const qpid::amqp::CharSequence& actualKey, bool actualValue) { process(actualKey, actualValue); } - void handleUint8(const qpid::amqp::CharSequence& actualKey, uint8_t actualValue) { process(actualKey, actualValue); } - void handleUint16(const qpid::amqp::CharSequence& actualKey, uint16_t actualValue) { process(actualKey, actualValue); } - void handleUint32(const qpid::amqp::CharSequence& actualKey, uint32_t actualValue) { process(actualKey, actualValue); } - void handleUint64(const qpid::amqp::CharSequence& actualKey, uint64_t actualValue) { process(actualKey, actualValue); } - void handleInt8(const qpid::amqp::CharSequence& actualKey, int8_t actualValue) { process(actualKey, actualValue); } - void handleInt16(const qpid::amqp::CharSequence& actualKey, int16_t actualValue) { process(actualKey, actualValue); } - void handleInt32(const qpid::amqp::CharSequence& actualKey, int32_t actualValue) { process(actualKey, actualValue); } - void handleInt64(const qpid::amqp::CharSequence& actualKey, int64_t actualValue) { process(actualKey, actualValue); } - void handleFloat(const qpid::amqp::CharSequence& actualKey, float actualValue) { process(actualKey, actualValue); } - void handleDouble(const qpid::amqp::CharSequence& actualKey, double actualValue) { process(actualKey, actualValue); } - void handleVoid(const qpid::amqp::CharSequence&) { /*nothing to do*/ } - void handleString(const qpid::amqp::CharSequence& actualKey, const qpid::amqp::CharSequence& actualValue, const qpid::amqp::CharSequence& /*encoding*/) - { - if (isRequestedKey(actualKey)) value = std::string(actualValue.data, actualValue.size); - } - std::string getValue() const { return value; } - private: - const std::string key; - std::string value; - - template void process(const qpid::amqp::CharSequence& actualKey, T actualValue) - { - if (isRequestedKey(actualKey)) value = boost::lexical_cast(actualValue); - } - - bool isRequestedKey(const qpid::amqp::CharSequence& actualKey) - { - //TODO: avoid allocating new string by just iterating over chars - return key == std::string(actualKey.data, actualKey.size); - } -}; -} - -std::string Message::getPropertyAsString(const std::string& key) const -{ - StringRetriever sr(key); - processProperties(sr); - return sr.getValue(); -} - -namespace { -class PropertyPrinter : public MapHandler -{ - public: - std::stringstream out; - - PropertyPrinter() : first(true) {} - void handleVoid(const CharSequence&) {} - void handleBool(const CharSequence& key, bool value) { handle(key, value); } - void handleUint8(const CharSequence& key, uint8_t value) { handle(key, value); } - void handleUint16(const CharSequence& key, uint16_t value) { handle(key, value); } - void handleUint32(const CharSequence& key, uint32_t value) { handle(key, value); } - void handleUint64(const CharSequence& key, uint64_t value) { handle(key, value); } - void handleInt8(const CharSequence& key, int8_t value) { handle(key, value); } - void handleInt16(const CharSequence& key, int16_t value) { handle(key, value); } - void handleInt32(const CharSequence& key, int32_t value) { handle(key, value); } - void handleInt64(const CharSequence& key, int64_t value) { handle(key, value); } - void handleFloat(const CharSequence& key, float value) { handle(key, value); } - void handleDouble(const CharSequence& key, double value) { handle(key, value); } - void handleString(const CharSequence& key, const CharSequence& value, const CharSequence& /*encoding*/) - { - handle(key, value.str()); - } - std::string str() { return out.str(); } - bool print(const std::string& key, const std::string& value, bool prependComma) { - if (prependComma) out << ", "; - if (!value.empty()) { - out << key << "=" << value; - return true; - } else { - return false; - } - } - template bool print_(const std::string& key, T value, bool prependComma) { - if (prependComma) out << ", "; - if (value) { - out << key << "=" << value; - return true; - } else { - return false; - } - } - - private: - bool first; - - template void handle(const CharSequence& key, T value) - { - if (first) { - first = false; - } else { - out << ", "; - } - out << key.str() << "=" << value; - } -}; -} - -std::string Message::printProperties() const -{ - PropertyPrinter r; - bool comma = false; - comma = r.print("subject", getSubject(), comma); - comma = r.print("message-id", getMessageId().str(), comma); - comma = r.print("correlation-id", getCorrelationId().str(), comma); - comma = r.print("user-id", getUserId(), comma); - comma = r.print("to", getTo(), comma); - comma = r.print("reply-to", getReplyTo(), comma); - comma = r.print_("priority", (uint32_t) getPriority(), comma); - comma = r.print_("durable", isPersistent(), comma); - uint64_t ttl(0); - getTtl(ttl); - comma = r.print_("ttl", ttl, comma); - r.out << ", application-properties={"; - processProperties(r); - r.out << "}"; - return r.str(); -} - -namespace { - class PropertyAdapter : public Reader { - MapHandler& handler; - CharSequence key; - enum { - KEY, - VALUE - } state; - - void checkValue() { - if ( state==VALUE ) state = KEY; - else { - // TODO: Would throwing an exception make more sense here? - QPID_LOG(error, "Received non string property key"); - key = CharSequence(); - state = KEY; - } - } - - void onNull(const Descriptor*) {checkValue(); handler.handleVoid(key);} - void onBoolean(bool b, const Descriptor*) {checkValue(); handler.handleBool(key, b);} - void onUByte(uint8_t i, const Descriptor*) {checkValue(); handler.handleUint8(key, i);} - void onUShort(uint16_t i, const Descriptor*) {checkValue(); handler.handleUint16(key, i);} - void onUInt(uint32_t i, const Descriptor*) {checkValue(); handler.handleUint32(key, i);} - void onULong(uint64_t i, const Descriptor*) {checkValue(); handler.handleUint64(key, i);} - void onByte(int8_t i, const Descriptor*) {checkValue(); handler.handleInt8(key, i);} - void onShort(int16_t i, const Descriptor*) {checkValue(); handler.handleInt16(key, i);} - void onInt(int32_t i, const Descriptor*) {checkValue(); handler.handleInt32(key, i);} - void onLong(int64_t i, const Descriptor*) {checkValue(); handler.handleInt64(key, i);} - void onFloat(float x, const Descriptor*) {checkValue(); handler.handleFloat(key, x);} - void onDouble(double x, const Descriptor*) {checkValue(); handler.handleDouble(key, x);} - void onTimestamp(int64_t i, const Descriptor*) {checkValue(); handler.handleInt64(key, i);} - - void onString(const CharSequence& s, const Descriptor*) { - if ( state==KEY ) { - state = VALUE; - key = s; - } else { - state = KEY; - handler.handleString(key, s, CharSequence()); - } - } - - 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: - PropertyAdapter(MapHandler& mh) : - handler(mh), - state(KEY) - {} - }; - -void processMapData(const CharSequence& source, MapHandler& handler) -{ - qpid::amqp::Decoder d(source.data, source.size); - PropertyAdapter adapter(handler); - d.read(adapter); - -} -} - -void Message::processProperties(MapHandler& mh) const { - processMapData(applicationProperties, mh); -} - -std::string Message::getAnnotationAsString(const std::string& key) const -{ - StringRetriever sr(key); - processMapData(messageAnnotations, sr); - if (sr.getValue().empty()) processMapData(deliveryAnnotations, sr); - return sr.getValue(); - -} - -uint64_t Message::getMessageSize() const { return data.size(); } -//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), bodyDescriptor(0) -{ - deliveryAnnotations.init(); - messageAnnotations.init(); - bareMessage.init(); - - userId.init(); - to.init(); - subject.init(); - replyTo.init(); - contentType.init(); - contentEncoding.init(); - - applicationProperties.init(); - body.init(); - footer.init(); -} -char* Message::getData() { return &data[0]; } -const char* Message::getData() const { return &data[0]; } -size_t Message::getSize() const { return data.size(); } - -qpid::amqp::MessageId Message::getMessageId() const -{ - return messageId; -} -qpid::amqp::CharSequence Message::getReplyToAsCharSequence() const -{ - return replyTo; -} -qpid::amqp::MessageId Message::getCorrelationId() const -{ - return correlationId; -} -qpid::amqp::CharSequence Message::getContentType() const -{ - return contentType; -} -qpid::amqp::CharSequence Message::getContentEncoding() const -{ - return contentEncoding; -} - -qpid::amqp::CharSequence Message::getDeliveryAnnotations() const -{ - return deliveryAnnotations; -} -qpid::amqp::CharSequence Message::getMessageAnnotations() const -{ - return messageAnnotations; -} -qpid::amqp::CharSequence Message::getApplicationProperties() const -{ - return applicationProperties; -} -qpid::amqp::CharSequence Message::getBareMessage() const -{ - return bareMessage; -} -qpid::amqp::CharSequence Message::getBody() const -{ - return body; -} -qpid::amqp::CharSequence Message::getFooter() const -{ - return footer; -} - -void Message::scan() -{ - qpid::amqp::Decoder decoder(getData(), getSize()); - decoder.read(*this); - bareMessage = qpid::amqp::MessageReader::getBareMessage(); - if (bareMessage.data && !bareMessage.size) { - bareMessage.size = getSize() - (bareMessage.data - getData()); - } -} - -const Message& Message::get(const qpid::broker::Message& message) -{ - const Message* m = dynamic_cast(&message.getEncoding()); - if (!m) throw qpid::Exception("Translation not yet implemented!!"); - return *m; -} - -void Message::onDurable(bool b) { durable = b; } -void Message::onPriority(uint8_t i) { priority = i; } -void Message::onTtl(uint32_t i) { ttl = i; } -void Message::onFirstAcquirer(bool b) { firstAcquirer = b; } -void Message::onDeliveryCount(uint32_t i) { deliveryCount = i; } - -void Message::onMessageId(uint64_t v) { messageId.set(v); } -void Message::onMessageId(const qpid::amqp::CharSequence& v, qpid::types::VariantType t) { messageId.set(v, t); } -void Message::onUserId(const qpid::amqp::CharSequence& v) { userId = v; } -void Message::onTo(const qpid::amqp::CharSequence& v) { to = v; } -void Message::onSubject(const qpid::amqp::CharSequence& v) { subject = v; } -void Message::onReplyTo(const qpid::amqp::CharSequence& v) { replyTo = v; } -void Message::onCorrelationId(uint64_t v) { correlationId.set(v); } -void Message::onCorrelationId(const qpid::amqp::CharSequence& v, qpid::types::VariantType t) { correlationId.set(v, t);} -void Message::onContentType(const qpid::amqp::CharSequence& v) { contentType = v; } -void Message::onContentEncoding(const qpid::amqp::CharSequence& v) { contentEncoding = v; } -void Message::onAbsoluteExpiryTime(int64_t) {} -void Message::onCreationTime(int64_t v) { creationTime = v; } -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, 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, const qpid::amqp::Descriptor* d) -{ - 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; - } - if (d) { - bodyDescriptor = *d; - } -} -void Message::onAmqpValue(const qpid::types::Variant& v, const qpid::amqp::Descriptor* d) -{ - typedBody = v; - if (d) { - bodyDescriptor = *d; - } -} - -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; - } -} - -const qpid::amqp::Descriptor& Message::getBodyDescriptor() const -{ - return bodyDescriptor; -} - -//PersistableMessage interface: -void Message::encode(framing::Buffer& buffer) const -{ - buffer.putLong(0);//4-byte format indicator - buffer.putRawData((const uint8_t*) getData(), getSize()); - QPID_LOG(debug, "Encoded 1.0 message of " << getSize() << " bytes, including " << bareMessage.size << " bytes of 'bare message'"); -} -uint32_t Message::encodedSize() const -{ - return 4/*format indicator*/ + data.size(); -} -//in 1.0 the binary header/content makes less sense and in any case -//the functionality that split originally supported (i.e. lazy-loaded -//messages) is no longer in use; for 1.0 we therefore treat the whole -//content as 'header' and load it in the first stage. -uint32_t Message::encodedHeaderSize() const -{ - return encodedSize(); -} -void Message::decodeHeader(framing::Buffer& buffer) -{ - if (buffer.available() != getSize()) { - QPID_LOG(warning, "1.0 Message buffer was " << data.size() << " bytes, but " << buffer.available() << " bytes are available. Resizing."); - data.resize(buffer.available()); - } - buffer.getRawData((uint8_t*) getData(), getSize()); - scan(); - QPID_LOG(debug, "Decoded 1.0 message of " << getSize() << " bytes, including " << bareMessage.size << " bytes of 'bare message'"); -} -void Message::decodeContent(framing::Buffer& /*buffer*/) {} - -boost::intrusive_ptr Message::merge(const std::map& added) const -{ - //message- or delivery- annotations? would have to determine that from the name, for now assume always message-annotations - std::map combined; - const std::map* annotations(0); - if (messageAnnotations) { - //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::const_iterator i = added.begin(); i != added.end(); ++i) { - combined[i->first] = i->second; - } - annotations = &combined; - } else { - //additions form a whole new section - annotations = &added; - } - size_t annotationsSize = qpid::amqp::MessageEncoder::getEncodedSize(*annotations, true) + 3/*descriptor*/; - - boost::intrusive_ptr copy(new Message(bareMessage.size+footer.size+deliveryAnnotations.size+annotationsSize)); - size_t position(0); - if (deliveryAnnotations.size) { - ::memcpy(©->data[position], deliveryAnnotations.data, deliveryAnnotations.size); - position += deliveryAnnotations.size; - } - - qpid::amqp::Encoder encoder(©->data[position], annotationsSize); - encoder.writeMap(*annotations, &qpid::amqp::message::MESSAGE_ANNOTATIONS, true); - position += encoder.getPosition(); - - if (bareMessage) { - ::memcpy(©->data[position], bareMessage.data, bareMessage.size); - position += bareMessage.size; - } - if (footer) { - ::memcpy(©->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(); - assert(copy->messageAnnotations); - assert(copy->bareMessage.size == bareMessage.size); - assert(copy->footer.size == footer.size); - assert(copy->deliveryAnnotations.size == deliveryAnnotations.size); - return copy; -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Message.h b/qpid/cpp/src/qpid/broker/amqp/Message.h deleted file mode 100644 index 67b99a6866..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Message.h +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef QPID_BROKER_AMQP_MESSAGE_H -#define QPID_BROKER_AMQP_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/broker/Message.h" -#include "qpid/amqp/CharSequence.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/amqp/MessageId.h" -#include "qpid/amqp/MessageReader.h" -#include - -namespace qpid { -namespace framing { -class Buffer; -} -namespace broker { -namespace amqp { - -/** - * Represents an AMQP 1.0 format message - */ -class Message : public qpid::broker::Message::SharedStateImpl, private qpid::amqp::MessageReader, public qpid::broker::PersistableMessage -{ - public: - //Encoding interface: - std::string getRoutingKey() const; - bool isPersistent() const; - uint8_t getPriority() const; - uint64_t getMessageSize() const; - std::string getPropertyAsString(const std::string& key) const; - std::string getAnnotationAsString(const std::string& key) const; - bool getTtl(uint64_t&) const; - std::string getContent() const; - void processProperties(qpid::amqp::MapHandler&) const; - std::string printProperties() const; - std::string getUserId() const; - uint64_t getTimestamp() const; - std::string getTo() const; - std::string getSubject() const; - std::string getReplyTo() const; - qpid::amqp::MessageId getMessageId() const; - qpid::amqp::MessageId getCorrelationId() const; - - qpid::amqp::CharSequence getReplyToAsCharSequence() const; - qpid::amqp::CharSequence getContentType() const; - qpid::amqp::CharSequence getContentEncoding() const; - - qpid::amqp::CharSequence getDeliveryAnnotations() const; - qpid::amqp::CharSequence getMessageAnnotations() const; - qpid::amqp::CharSequence getApplicationProperties() const; - qpid::amqp::CharSequence getBareMessage() const; - qpid::amqp::CharSequence getBody() const; - qpid::amqp::CharSequence getFooter() const; - bool isTypedBody() const; - qpid::types::Variant getTypedBody() const; - const qpid::amqp::Descriptor& getBodyDescriptor() const; - - Message(size_t size); - char* getData(); - const char* getData() const; - size_t getSize() const; - void scan(); - - //PersistableMessage interface: - void encode(framing::Buffer& buffer) const; - uint32_t encodedSize() const; - void decodeHeader(framing::Buffer& buffer); - void decodeContent(framing::Buffer& buffer); - uint32_t encodedHeaderSize() const; - boost::intrusive_ptr merge(const std::map& annotations) const; - - static const Message& get(const qpid::broker::Message&); - private: - std::vector data; - - //header: - boost::optional durable; - boost::optional priority; - boost::optional ttl; - boost::optional firstAcquirer; - boost::optional deliveryCount; - //annotations: - qpid::amqp::CharSequence deliveryAnnotations; - qpid::amqp::CharSequence messageAnnotations; - - qpid::amqp::CharSequence bareMessage;//properties, application-properties and content - //properties: - qpid::amqp::MessageId messageId; - qpid::amqp::CharSequence userId; - qpid::amqp::CharSequence to; - qpid::amqp::CharSequence subject; - qpid::amqp::CharSequence replyTo; - qpid::amqp::MessageId correlationId; - qpid::amqp::CharSequence contentType; - qpid::amqp::CharSequence contentEncoding; - boost::optional creationTime; - - //application-properties: - qpid::amqp::CharSequence applicationProperties; - - //body: - qpid::amqp::CharSequence body; - qpid::types::Variant typedBody; - std::string bodyType; - qpid::amqp::Descriptor bodyDescriptor; - - //footer: - qpid::amqp::CharSequence footer; - - //header: - void onDurable(bool b); - void onPriority(uint8_t i); - void onTtl(uint32_t i); - void onFirstAcquirer(bool b); - void onDeliveryCount(uint32_t i); - //properties: - void onMessageId(uint64_t); - void onMessageId(const qpid::amqp::CharSequence&, qpid::types::VariantType); - void onUserId(const qpid::amqp::CharSequence& v); - void onTo(const qpid::amqp::CharSequence& v); - void onSubject(const qpid::amqp::CharSequence& v); - void onReplyTo(const qpid::amqp::CharSequence& v); - void onCorrelationId(uint64_t); - void onCorrelationId(const qpid::amqp::CharSequence&, qpid::types::VariantType); - void onContentType(const qpid::amqp::CharSequence& v); - void onContentEncoding(const qpid::amqp::CharSequence& v); - void onAbsoluteExpiryTime(int64_t i); - void onCreationTime(int64_t); - void onGroupId(const qpid::amqp::CharSequence&); - void onGroupSequence(uint32_t); - void onReplyToGroupId(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, const qpid::amqp::Descriptor*); - void onAmqpValue(const qpid::types::Variant&, const qpid::amqp::Descriptor*); - - void onFooter(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&); -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_MESSAGE_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/NodePolicy.cpp b/qpid/cpp/src/qpid/broker/amqp/NodePolicy.cpp deleted file mode 100644 index 69b41dafa2..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/NodePolicy.cpp +++ /dev/null @@ -1,326 +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/broker/amqp/NodePolicy.h" -#include "qpid/broker/amqp/Connection.h" -#include "qpid/broker/amqp/Topic.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Exchange.h" -#include "qpid/types/Exception.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { -namespace amqp { -namespace { -const std::string DURABLE("durable"); -const std::string AUTO_DELETE("auto-delete"); -const std::string LIFETIME_POLICY("qpid.lifetime-policy"); -const std::string MANUAL("manual"); -const std::string UNUSED("delete-if-unused"); -const std::string UNUSED_AND_EMPTY("delete-if-unused-and-empty"); -const std::string QUEUE_POLICY("QueuePolicy"); -const std::string TOPIC_POLICY("TopicPolicy"); -const std::string QUEUE("queue"); -const std::string TOPIC("topic"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string EXCHANGE_TYPE("exchange-type"); -const std::string QPID_MSG_SEQUENCE("qpid.msg_sequence"); -const std::string QPID_IVE("qpid.ive"); -const std::string EMPTY; - -template -T get(const std::string& k, const qpid::types::Variant::Map& m, T defaultValue) -{ - qpid::types::Variant::Map::const_iterator i = m.find(k); - if (i == m.end()) return defaultValue; - else return i->second; -} - -std::string getProperty(const std::string& k, const qpid::types::Variant::Map& m) -{ - return get(k, m, EMPTY); -} - -bool testProperty(const std::string& k, const qpid::types::Variant::Map& m) -{ - return get(k, m, false); -} - -qpid::types::Variant::Map filterForQueue(const qpid::types::Variant::Map& properties) -{ - qpid::types::Variant::Map filtered = properties; - filtered.erase(DURABLE); - filtered.erase(AUTO_DELETE); - filtered.erase(ALTERNATE_EXCHANGE); - return filtered; -} -qpid::types::Variant::Map filterForTopic(const qpid::types::Variant::Map& properties) -{ - qpid::types::Variant::Map filtered = properties; - filtered.erase(DURABLE); - filtered.erase(EXCHANGE_TYPE); - filtered.erase(AUTO_DELETE); - filtered.erase(QPID_IVE); - filtered.erase(QPID_MSG_SEQUENCE); - return filtered; -} -void copy(const std::string& key, const qpid::types::Variant::Map& from, qpid::types::Variant::Map& to) -{ - qpid::types::Variant::Map::const_iterator i = from.find(key); - if (i != from.end()) to.insert(*i); -} - -} -NodePolicy::NodePolicy(const std::string& type, const std::string& ptrn, const qpid::types::Variant::Map& props) - : PersistableObject(ptrn, type, props), pattern(ptrn), - durable(testProperty(DURABLE, props)), - alternateExchange(getProperty(ALTERNATE_EXCHANGE, props)), - compiled(pattern) {} - -NodePolicy::~NodePolicy() {} - -const std::string& NodePolicy::getPattern() const -{ - return pattern; -} - -bool NodePolicy::isDurable() const -{ - return durable; -} - -bool NodePolicy::match(const std::string& name) const -{ - return qpid::sys::regex_match(name, compiled); -} - -QueuePolicy::QueuePolicy(Broker& broker, const std::string& pattern, const qpid::types::Variant::Map& props) - : NodePolicy(QUEUE_POLICY, pattern, props), - queueSettings(durable, testProperty(AUTO_DELETE, props)) -{ - qpid::types::Variant::Map unused; - qpid::types::Variant::Map filtered = filterForQueue(props); - //if queue is not durable and neither lifetime policy nor - //autodelete were explicitly specified, clean it up when not - //needed by default: - if (!queueSettings.durable && props.find(LIFETIME_POLICY) == props.end() && props.find(AUTO_DELETE) == props.end()) { - filtered[LIFETIME_POLICY] = UNUSED_AND_EMPTY; - } - queueSettings.populate(filtered, unused); - qpid::amqp_0_10::translate(filtered, queueSettings.storeSettings); - - qpid::management::ManagementAgent* agent = broker.getManagementAgent(); - if (agent != 0) { - policy = _qmf::QueuePolicy::shared_ptr(new _qmf::QueuePolicy(agent, this, pattern)); - policy->set_properties(props); - agent->addObject(policy); - } -} -QueuePolicy::~QueuePolicy() -{ - if (policy != 0) policy->resourceDestroy(); -} - - -std::pair, boost::shared_ptr > QueuePolicy::create(const std::string& name, Connection& connection) -{ - std::pair, boost::shared_ptr > result; - result.first = connection.getBroker().createQueue(name, queueSettings, 0/*not exclusive*/, alternateExchange, connection.getUserId(), connection.getId()).first; - return result; -} - -boost::shared_ptr QueuePolicy::GetManagementObject() const -{ - return policy; -} - -TopicPolicy::TopicPolicy(Broker& broker, const std::string& pattern, const qpid::types::Variant::Map& props) - : NodePolicy(TOPIC_POLICY, pattern, props), exchangeType(getProperty(EXCHANGE_TYPE, props)), - autodelete(get(AUTO_DELETE, props, !durable)) -{ - if (exchangeType.empty()) exchangeType = TOPIC; - broker.getExchanges().checkType(exchangeType); - qpid::types::Variant::Map::const_iterator i = props.find(LIFETIME_POLICY); - if (i != props.end()) { - if (i->second == MANUAL) { - autodelete = false; - } else if (i->second == UNUSED || i->second == UNUSED_AND_EMPTY/*though empty doesn't mean much for an exchange*/) { - autodelete = true; - } else { - QPID_LOG(warning, "Did not recognise lifetime policy " << i->second << " in topic policy for " << pattern); - } - } - topicSettings = filterForTopic(props); - copy(QPID_IVE, props, exchangeSettings); - copy(QPID_MSG_SEQUENCE, props, exchangeSettings); - - qpid::management::ManagementAgent* agent = broker.getManagementAgent(); - if (agent != 0) { - policy = _qmf::TopicPolicy::shared_ptr(new _qmf::TopicPolicy(agent, this, pattern)); - policy->set_properties(props); - agent->addObject(policy); - } -} - -TopicPolicy::~TopicPolicy() -{ - if (policy != 0) policy->resourceDestroy(); -} - -std::pair, boost::shared_ptr > TopicPolicy::create(const std::string& name, Connection& connection) -{ - std::pair, boost::shared_ptr > result; - qpid::framing::FieldTable args; - qpid::amqp_0_10::translate(exchangeSettings, args); - boost::shared_ptr exchange = connection.getBroker().createExchange(name, exchangeType, isDurable(), autodelete, alternateExchange, - args, connection.getUserId(), connection.getId()).first; - result.second = connection.getTopics().declare(connection.getBroker(), name, exchange, topicSettings); - return result; -} - -boost::shared_ptr TopicPolicy::GetManagementObject() const -{ - return policy; -} - -boost::shared_ptr NodePolicyRegistry::createQueuePolicy(Broker& broker, const std::string& name, const qpid::types::Variant::Map& properties) -{ - boost::shared_ptr nodePolicy(new QueuePolicy(broker, name, properties)); - add(nodePolicy); - return nodePolicy; -} - -boost::shared_ptr NodePolicyRegistry::createTopicPolicy(Broker& broker, const std::string& name, const qpid::types::Variant::Map& properties) -{ - boost::shared_ptr nodePolicy(new TopicPolicy(broker, name, properties)); - add(nodePolicy); - return nodePolicy; -} - -boost::shared_ptr NodePolicyRegistry::createNodePolicy(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties) -{ - if (type == QUEUE_POLICY) { - return createQueuePolicy(broker, name, properties); - } else if (type == TOPIC_POLICY) { - return createTopicPolicy(broker, name, properties); - } else { - return boost::shared_ptr(); - } -} - -bool NodePolicyRegistry::createObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& /*userId*/, const std::string& /*connectionId*/) -{ - boost::shared_ptr nodePolicy = createNodePolicy(broker, type, name, properties); - if (nodePolicy) { - if (nodePolicy->isDurable()) broker.getStore().create(*nodePolicy); - return true; - } else { - return false; - } -} -bool NodePolicyRegistry::deleteObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map&, - const std::string& /*userId*/, const std::string& /*connectionId*/) -{ - if (type == QUEUE_POLICY || type == TOPIC_POLICY) { - boost::shared_ptr nodePolicy = remove(name, type); - if (nodePolicy) { - if (nodePolicy->isDurable()) broker.getStore().destroy(*nodePolicy); - return true; - } else { - return false; - } - } else { - return false; - } -} -bool NodePolicyRegistry::recoverObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - uint64_t persistenceId) -{ - - boost::shared_ptr nodePolicy = createNodePolicy(broker, type, name, properties); - if (nodePolicy) { - nodePolicy->setPersistenceId(persistenceId); - return true; - } else { - return false; - } -} - -void NodePolicyRegistry::add(boost::shared_ptr nodePolicy) -{ - qpid::sys::Mutex::ScopedLock l(lock); - NodePolicies::const_iterator i = nodePolicies.find(nodePolicy->getName()); - if (i == nodePolicies.end()) { - nodePolicies.insert(NodePolicies::value_type(nodePolicy->getName(), nodePolicy)); - } else { - if (i->second->getType() != nodePolicy->getType()) { - throw qpid::types::Exception(QPID_MSG("Cannot create object of type " << nodePolicy->getType() << " with key " - << nodePolicy->getName() << " as an object of type " << i->second->getType() << " already exists with the same key")); - } else { - throw qpid::types::Exception(QPID_MSG("An object of type " << nodePolicy->getType() << " with key " << nodePolicy->getName() << " already exists")); - } - } -} -boost::shared_ptr NodePolicyRegistry::remove(const std::string& pattern, const std::string& type) -{ - boost::shared_ptr result; - qpid::sys::Mutex::ScopedLock l(lock); - NodePolicies::iterator i = nodePolicies.find(pattern); - if (i != nodePolicies.end()) { - if (i->second->getType() != type) { - throw qpid::types::Exception(QPID_MSG("Object with key " << i->first << " is of type " << i->second->getType() << " not " << type)); - } - result = i->second; - nodePolicies.erase(i); - } - return result; -} -boost::shared_ptr NodePolicyRegistry::get(const std::string& pattern) -{ - qpid::sys::Mutex::ScopedLock l(lock); - NodePolicies::const_iterator i = nodePolicies.find(pattern); - if (i == nodePolicies.end()) { - return boost::shared_ptr(); - } else { - return i->second; - } -} - -boost::shared_ptr NodePolicyRegistry::match(const std::string& name) -{ - qpid::sys::Mutex::ScopedLock l(lock); - boost::shared_ptr best; - for (NodePolicies::const_iterator i = nodePolicies.begin(); i != nodePolicies.end(); ++i) { - //where multiple policies match, pick the one with the longest - //pattern as a crude guesstimate of the more specific one - if (i->second->match(name) && (!best || i->first.size() > best->getPattern().size())) { - best = i->second; - } - } - return best; -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/NodePolicy.h b/qpid/cpp/src/qpid/broker/amqp/NodePolicy.h deleted file mode 100644 index d6e987d85f..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/NodePolicy.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef QPID_BROKER_AMQP_NODEPOLICY_H -#define QPID_BROKER_AMQP_NODEPOLICY_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/ObjectFactory.h" -#include "qpid/broker/PersistableObject.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/regex.h" -#include "qpid/types/Variant.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/QueuePolicy.h" -#include "qmf/org/apache/qpid/broker/TopicPolicy.h" -#include - -namespace qpid { -namespace broker { -class Broker; -class Queue; -namespace amqp { -class Connection; -class Topic; - -/** - * Policy for creation of nodes 'on-demand' - */ -class NodePolicy : public PersistableObject, public management::Manageable -{ - public: - NodePolicy(const std::string& type, const std::string& ptrn, const qpid::types::Variant::Map& props); - virtual ~NodePolicy(); - const std::string& getPattern() const; - bool match(const std::string&) const; - bool isDurable() const; - virtual std::pair, boost::shared_ptr > create(const std::string&, Connection&) = 0; - virtual boost::shared_ptr GetManagementObject() const = 0; - protected: - NodePolicy(Broker&, const std::string& type, const std::string& pattern, const qpid::types::Variant::Map& properties); - const std::string pattern; - bool durable; - std::string alternateExchange; - qpid::sys::regex compiled; -}; - -class QueuePolicy : public NodePolicy -{ - public: - QueuePolicy(Broker&, const std::string& pattern, const qpid::types::Variant::Map& properties); - ~QueuePolicy(); - std::pair, boost::shared_ptr > create(const std::string&, Connection&); - boost::shared_ptr GetManagementObject() const; - private: - qpid::broker::QueueSettings queueSettings; - qmf::org::apache::qpid::broker::QueuePolicy::shared_ptr policy; -}; - -class TopicPolicy : public NodePolicy -{ - public: - TopicPolicy(Broker&, const std::string& pattern, const qpid::types::Variant::Map& properties); - ~TopicPolicy(); - std::pair, boost::shared_ptr > create(const std::string&, Connection&); - boost::shared_ptr GetManagementObject() const; - private: - qpid::types::Variant::Map topicSettings; - std::string exchangeType; - bool autodelete; - qpid::types::Variant::Map exchangeSettings; - qmf::org::apache::qpid::broker::TopicPolicy::shared_ptr policy; -}; - -class NodePolicyRegistry : public ObjectFactory -{ - public: - bool createObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId); - bool deleteObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId); - bool recoverObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - uint64_t persistenceId); - - boost::shared_ptr match(const std::string& name); - boost::shared_ptr createQueuePolicy(Broker&, const std::string& name, const qpid::types::Variant::Map& properties); - boost::shared_ptr createTopicPolicy(Broker&, const std::string& name, const qpid::types::Variant::Map& properties); - private: - typedef std::map > NodePolicies; - qpid::sys::Mutex lock; - NodePolicies nodePolicies; - - boost::shared_ptr createNodePolicy(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties); - void add(boost::shared_ptr nodePolicy); - boost::shared_ptr remove(const std::string& pattern, const std::string& type); - boost::shared_ptr get(const std::string& pattern); -}; - -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_NODEPOLICY_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/NodeProperties.cpp b/qpid/cpp/src/qpid/broker/amqp/NodeProperties.cpp deleted file mode 100644 index 500a0c042d..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/NodeProperties.cpp +++ /dev/null @@ -1,388 +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/broker/amqp/NodeProperties.h" -#include "qpid/broker/amqp/DataReader.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/amqp/CharSequence.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/types/encodings.h" -#include "qpid/types/Variant.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/log/Statement.h" -extern "C" { -#include -} - -using qpid::amqp::CharSequence; -using qpid::amqp::Descriptor; - -namespace qpid { -namespace broker { -namespace amqp { -namespace { -//distribution modes: -const std::string MOVE("move"); -const std::string COPY("copy"); -const std::string SUPPORTED_DIST_MODES("supported-dist-modes"); -const std::string LIFETIME_POLICY("lifetime-policy"); - -//AMQP 0-10 standard parameters: -const std::string DURABLE("durable"); -const std::string EXCLUSIVE("exclusive"); -const std::string AUTO_DELETE("auto-delete"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string EXCHANGE_TYPE("exchange-type"); -const std::string EMPTY; - -pn_bytes_t convert(const std::string& s) -{ - pn_bytes_t result; - result.start = const_cast(s.data()); - result.size = s.size(); - return result; -} - -bool getLifetimePolicy(const Descriptor& d, QueueSettings::LifetimePolicy& policy) -{ - if (d.match(qpid::amqp::lifetime_policy::DELETE_ON_CLOSE_SYMBOL, qpid::amqp::lifetime_policy::DELETE_ON_CLOSE_CODE)) { - policy = QueueSettings::DELETE_ON_CLOSE; - return true; - } else if (d.match(qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_SYMBOL, qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_CODE)) { - policy = QueueSettings::DELETE_IF_UNUSED; - return true; - } else if (d.match(qpid::amqp::lifetime_policy::DELETE_ON_NO_MESSAGES_SYMBOL, qpid::amqp::lifetime_policy::DELETE_ON_NO_MESSAGES_CODE)) { - policy = QueueSettings::DELETE_IF_EMPTY; - return true; - } else if (d.match(qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_SYMBOL, qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_CODE)) { - policy = QueueSettings::DELETE_IF_UNUSED_AND_EMPTY; - return true; - } else { - return false; - } -} - -bool getLifetimeDescriptorSymbol(QueueSettings::LifetimePolicy policy, pn_bytes_t& out) -{ - switch (policy) { - case QueueSettings::DELETE_ON_CLOSE: - out = convert(qpid::amqp::lifetime_policy::DELETE_ON_CLOSE_SYMBOL); - return true; - case QueueSettings::DELETE_IF_UNUSED: - out = convert(qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_SYMBOL); - return true; - case QueueSettings::DELETE_IF_EMPTY: - out = convert(qpid::amqp::lifetime_policy::DELETE_ON_NO_MESSAGES_SYMBOL); - return true; - case QueueSettings::DELETE_IF_UNUSED_AND_EMPTY: - out = convert(qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_SYMBOL); - return true; - default: - return false; - } -} - -} - -NodeProperties::NodeProperties(bool isDynamic) : received(false), queue(true), durable(false), autoDelete(false), exclusive(false), - dynamic(isDynamic), exchangeType("topic"), lifetime(QueueSettings::DELETE_IF_UNUSED) {} - -void NodeProperties::read(pn_data_t* data) -{ - DataReader reader(*this); - reader.read(data); - -} - -bool NodeProperties::wasSpecified(const std::string& key) const -{ - return specified.find(key) != specified.end(); -} - -void NodeProperties::write(pn_data_t* data, boost::shared_ptr node) -{ - if (received) { - pn_data_put_map(data); - pn_data_enter(data); - pn_data_put_symbol(data, convert(SUPPORTED_DIST_MODES)); - pn_data_put_string(data, convert(MOVE));//TODO: should really add COPY as well, since queues can be browsed - pn_bytes_t symbol; - if ((wasSpecified(AUTO_DELETE) || wasSpecified(LIFETIME_POLICY)) && node->isAutoDelete() && getLifetimeDescriptorSymbol(node->getSettings().lifetime, symbol)) { - pn_data_put_symbol(data, convert(LIFETIME_POLICY)); - pn_data_put_described(data); - pn_data_enter(data); - pn_data_put_symbol(data, symbol); - pn_data_put_list(data); - pn_data_exit(data); - } - if (wasSpecified(DURABLE) && node->isDurable()) { - pn_data_put_symbol(data, convert(DURABLE)); - pn_data_put_bool(data, true); - } - if (wasSpecified(EXCLUSIVE) && node->hasExclusiveOwner()) { - pn_data_put_symbol(data, convert(EXCLUSIVE)); - pn_data_put_bool(data, true); - } - if (!alternateExchange.empty() && node->getAlternateExchange()) { - pn_data_put_symbol(data, convert(ALTERNATE_EXCHANGE)); - pn_data_put_string(data, convert(node->getAlternateExchange()->getName())); - } - - qpid::types::Variant::Map actual = node->getSettings().asMap(); - qpid::types::Variant::Map unrecognised; - QueueSettings dummy; - dummy.populate(actual, unrecognised); - for (qpid::types::Variant::Map::const_iterator i = unrecognised.begin(); i != unrecognised.end(); ++i) { - actual.erase(i->first); - } - for (qpid::types::Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - qpid::types::Variant::Map::const_iterator j = actual.find(i->first); - if (j != actual.end()) { - pn_data_put_symbol(data, convert(j->first)); - pn_data_put_string(data, convert(j->second.asString())); - } - } - - pn_data_exit(data); - } -} -namespace { -const std::string QPID_MSG_SEQUENCE("qpid.msg_sequence"); -const std::string QPID_IVE("qpid.ive"); -} -void NodeProperties::write(pn_data_t* data, boost::shared_ptr node) -{ - if (received) { - pn_data_put_map(data); - pn_data_enter(data); - pn_data_put_symbol(data, convert(SUPPORTED_DIST_MODES)); - pn_data_put_string(data, convert(COPY)); - if (wasSpecified(DURABLE) && node->isDurable()) { - pn_data_put_symbol(data, convert(DURABLE)); - pn_data_put_bool(data, true); - } - if (!exchangeType.empty()) { - pn_data_put_symbol(data, convert(EXCHANGE_TYPE)); - pn_data_put_string(data, convert(node->getType())); - } - if (!alternateExchange.empty() && node->getAlternate()) { - pn_data_put_symbol(data, convert(ALTERNATE_EXCHANGE)); - pn_data_put_string(data, convert(node->getAlternate()->getName())); - } - if (wasSpecified(AUTO_DELETE)) { - pn_data_put_symbol(data, convert(AUTO_DELETE)); - pn_data_put_bool(data, node->isAutoDelete()); - } - - for (qpid::types::Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - if ((i->first == QPID_MSG_SEQUENCE || i->first == QPID_IVE) && node->getArgs().isSet(i->first)) { - pn_data_put_symbol(data, convert(i->first)); - pn_data_put_bool(data, true); - } - } - - pn_data_exit(data); - } -} - - -void NodeProperties::process(const std::string& key, const qpid::types::Variant& value, const Descriptor* d) -{ - received = true; - QPID_LOG(debug, "Processing node property " << key << " = " << value); - specified.insert(key); - if (key == SUPPORTED_DIST_MODES) { - if (value == MOVE) queue = true; - else if (value == COPY) queue = false; - } else if (key == LIFETIME_POLICY) { - if (d) { - if (getLifetimePolicy(*d, lifetime)) { - autoDelete = true; - } else { - QPID_LOG(warning, "Unrecognised lifetime policy: " << *d); - } - } - } else if (key == DURABLE) { - durable = value; - } else if (key == EXCLUSIVE) { - exclusive = value; - } else if (key == AUTO_DELETE) { - autoDelete = value; - } else if (key == ALTERNATE_EXCHANGE) { - alternateExchange = value.asString(); - } else if (key == EXCHANGE_TYPE) { - exchangeType = value.asString(); - } else { - properties[key] = value; - } -} - -bool NodeProperties::onStartListValue(const qpid::amqp::CharSequence& key, uint32_t count, const qpid::amqp::Descriptor* d) -{ - QPID_LOG(debug, "NodeProperties::onStartListValue(" << std::string(key.data, key.size) << ", " << count << ", " << d); - process(key.str(), qpid::types::Variant(), d); - return true; -} - -void NodeProperties::onNullValue(const CharSequence& key, const Descriptor* d) -{ - process(key.str(), qpid::types::Variant(), d); -} - -void NodeProperties::onBooleanValue(const CharSequence& key, bool value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onUByteValue(const CharSequence& key, uint8_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onUShortValue(const CharSequence& key, uint16_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onUIntValue(const CharSequence& key, uint32_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onULongValue(const CharSequence& key, uint64_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onByteValue(const CharSequence& key, int8_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onShortValue(const CharSequence& key, int16_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onIntValue(const CharSequence& key, int32_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onLongValue(const CharSequence& key, int64_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onFloatValue(const CharSequence& key, float value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onDoubleValue(const CharSequence& key, double value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -void NodeProperties::onUuidValue(const CharSequence& key, const CharSequence& value, const Descriptor* d) -{ - process(key.str(), value.str(), d); -} - -void NodeProperties::onTimestampValue(const CharSequence& key, int64_t value, const Descriptor* d) -{ - process(key.str(), value, d); -} - -namespace { -qpid::types::Variant utf8(const std::string& s) -{ - qpid::types::Variant v(s); - v.setEncoding(qpid::types::encodings::UTF8); - return v; -} -} - -void NodeProperties::onStringValue(const CharSequence& key, const CharSequence& value, const Descriptor* d) -{ - process(key.str(), utf8(value.str()), d); -} - -void NodeProperties::onSymbolValue(const CharSequence& key, const CharSequence& value, const Descriptor* d) -{ - process(key.str(), utf8(value.str()), d); -} - -QueueSettings NodeProperties::getQueueSettings() -{ - //assume autodelete for dynamic nodes unless explicitly requested - //otherwise or unless durability is requested - QueueSettings settings(durable, autoDelete || (dynamic && !wasSpecified(AUTO_DELETE) && !durable)); - qpid::types::Variant::Map unused; - settings.populate(properties, unused); - settings.lifetime = lifetime; - qpid::amqp_0_10::translate(unused, settings.storeSettings); - return settings; -} - -bool NodeProperties::isQueue() const -{ - return queue; -} -bool NodeProperties::isDurable() const -{ - return durable; -} -bool NodeProperties::isExclusive() const -{ - return exclusive; -} -bool NodeProperties::isAutodelete() const -{ - return autoDelete; -} -std::string NodeProperties::getExchangeType() const -{ - return exchangeType; -} -std::string NodeProperties::getSpecifiedExchangeType() const -{ - return wasSpecified(EXCHANGE_TYPE) ? exchangeType : EMPTY; -} -std::string NodeProperties::getAlternateExchange() const -{ - return alternateExchange; -} - -bool NodeProperties::trackControllingLink() const -{ - return lifetime == QueueSettings::DELETE_ON_CLOSE || lifetime == QueueSettings::DELETE_IF_EMPTY; -} - -const qpid::types::Variant::Map& NodeProperties::getProperties() const -{ - return properties; -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/NodeProperties.h b/qpid/cpp/src/qpid/broker/amqp/NodeProperties.h deleted file mode 100644 index 45a3533cf4..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/NodeProperties.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef QPID_BROKER_AMQP_NODEPROPERTIES_H -#define QPID_BROKER_AMQP_NODEPROPERTIES_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/amqp/MapReader.h" -#include "qpid/types/Variant.h" -#include "qpid/broker/QueueSettings.h" -#include -#include - -struct pn_data_t; -namespace qpid { -namespace broker { -class Exchange; -class Queue; -struct QueueSettings; -namespace amqp { - -class NodeProperties : public qpid::amqp::MapReader -{ - public: - NodeProperties(bool isDynamic); - void read(pn_data_t*); - void write(pn_data_t*,boost::shared_ptr); - void write(pn_data_t*,boost::shared_ptr); - void onNullValue(const qpid::amqp::CharSequence&, const qpid::amqp::Descriptor*); - void onBooleanValue(const qpid::amqp::CharSequence&, bool, const qpid::amqp::Descriptor*); - void onUByteValue(const qpid::amqp::CharSequence&, uint8_t, const qpid::amqp::Descriptor*); - void onUShortValue(const qpid::amqp::CharSequence&, uint16_t, const qpid::amqp::Descriptor*); - void onUIntValue(const qpid::amqp::CharSequence&, uint32_t, const qpid::amqp::Descriptor*); - void onULongValue(const qpid::amqp::CharSequence&, uint64_t, const qpid::amqp::Descriptor*); - void onByteValue(const qpid::amqp::CharSequence&, int8_t, const qpid::amqp::Descriptor*); - void onShortValue(const qpid::amqp::CharSequence&, int16_t, const qpid::amqp::Descriptor*); - void onIntValue(const qpid::amqp::CharSequence&, int32_t, const qpid::amqp::Descriptor*); - void onLongValue(const qpid::amqp::CharSequence&, int64_t, const qpid::amqp::Descriptor*); - void onFloatValue(const qpid::amqp::CharSequence&, float, const qpid::amqp::Descriptor*); - void onDoubleValue(const qpid::amqp::CharSequence&, double, const qpid::amqp::Descriptor*); - void onUuidValue(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&, const qpid::amqp::Descriptor*); - void onTimestampValue(const qpid::amqp::CharSequence&, int64_t, const qpid::amqp::Descriptor*); - void onStringValue(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&, const qpid::amqp::Descriptor*); - void onSymbolValue(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&, const qpid::amqp::Descriptor*); - bool onStartListValue(const qpid::amqp::CharSequence&, uint32_t count, const qpid::amqp::Descriptor*); - bool isQueue() const; - QueueSettings getQueueSettings(); - bool isDurable() const; - bool isExclusive() const; - bool isAutodelete() const; - std::string getExchangeType() const; - std::string getSpecifiedExchangeType() const; - std::string getAlternateExchange() const; - bool trackControllingLink() const; - const qpid::types::Variant::Map& getProperties() const; - private: - bool received; - bool queue; - bool durable; - bool autoDelete; - bool exclusive; - bool dynamic; - std::string exchangeType; - std::string alternateExchange; - qpid::types::Variant::Map properties; - QueueSettings::LifetimePolicy lifetime; - std::set specified; - - void process(const std::string&, const qpid::types::Variant&, const qpid::amqp::Descriptor*); - bool wasSpecified(const std::string& key) const; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_NODEPROPERTIES_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp b/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp deleted file mode 100644 index abd96a61e9..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp +++ /dev/null @@ -1,373 +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/broker/amqp/DataReader.h" -#include "qpid/broker/amqp/Outgoing.h" -#include "qpid/broker/amqp/Exception.h" -#include "qpid/broker/amqp/Header.h" -#include "qpid/broker/amqp/Session.h" -#include "qpid/broker/amqp/Translation.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Selector.h" -#include "qpid/broker/TopicKeyNode.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/amqp/MessageEncoder.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "config.h" - -namespace qpid { -namespace broker { -namespace amqp { - -Outgoing::Outgoing(Broker& broker, Session& parent, const std::string& source, const std::string& target, const std::string& name) - : ManagedOutgoingLink(broker, parent, source, target, name), session(parent) {} - -void Outgoing::wakeup() -{ - session.wakeup(); -} - -namespace { -bool requested_reliable(pn_link_t* link) -{ - return pn_link_remote_snd_settle_mode(link) == PN_SND_UNSETTLED; -} -bool requested_unreliable(pn_link_t* link) -{ - return pn_link_remote_snd_settle_mode(link) == PN_SND_SETTLED; -} -} - -OutgoingFromQueue::OutgoingFromQueue(Broker& broker, const std::string& source, const std::string& target, boost::shared_ptr 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), type, target), - exclusive(e), - isControllingUser(p), - queue(q), deliveries(5000), link(l), out(o), - current(0), - buffer(1024)/*used only for header at present*/, - //for exclusive queues, assume unreliable unless reliable is explicitly requested; otherwise assume reliable unless unreliable requested - unreliable(exclusive ? !requested_reliable(link) : requested_unreliable(link)), - cancelled(false), - trackingUndeliverableMessages(false) -{ - for (size_t i = 0 ; i < deliveries.capacity(); ++i) { - deliveries[i].init(i); - } - if (isControllingUser) queue->markInUse(true); -} - -void OutgoingFromQueue::init() -{ - queue->consume(shared_from_this(), exclusive);//may throw exception -} - -bool OutgoingFromQueue::doWork() -{ - QPID_LOG(trace, "Dispatching to " << getName() << ": " << pn_link_credit(link)); - if (canDeliver()) { - try{ - if (queue->dispatch(shared_from_this())) { - return true; - } else { - pn_link_drained(link); - QPID_LOG(trace, "No message available on " << queue->getName()); - } - } catch (const qpid::framing::ResourceDeletedException& e) { - throw Exception(qpid::amqp::error_conditions::RESOURCE_DELETED, e.what()); - } - } else { - QPID_LOG(trace, "Can't deliver to " << getName() << " from " << queue->getName() << ": " << pn_link_credit(link)); - } - return false; -} - -void OutgoingFromQueue::write(const char* data, size_t size) -{ - pn_link_send(link, data, size); -} - -void OutgoingFromQueue::mergeMessageAnnotationsIfRequired(const Record &r) -{ - pn_data_t *remoteAnnotationsRaw = - pn_disposition_annotations(pn_delivery_remote(r.delivery)); - if (remoteAnnotationsRaw == 0) { - return; - } - - qpid::types::Variant::Map remoteMessageAnnotations; - DataReader::read(remoteAnnotationsRaw, remoteMessageAnnotations); - queue->mergeMessageAnnotations(r.cursor, remoteMessageAnnotations); -} - -void OutgoingFromQueue::handle(pn_delivery_t* delivery) -{ - size_t i = Record::getIndex(pn_delivery_tag(delivery)); - Record& r = deliveries[i]; - if (r.delivery && pn_delivery_updated(delivery)) { - assert(r.delivery == delivery); - r.disposition = pn_delivery_remote_state(delivery); - - std::pair txn = session.getTransactionalState(delivery); - if (txn.first) { - r.disposition = txn.second; - } - - if (!r.disposition && pn_delivery_settled(delivery)) { - //if peer has settled without setting state, assume accepted - r.disposition = PN_ACCEPTED; - } - if (r.disposition) { - switch (r.disposition) { - case PN_ACCEPTED: - if (preAcquires()) queue->dequeue(r.cursor, txn.first); - outgoingMessageAccepted(); - break; - case PN_REJECTED: - if (preAcquires()) queue->reject(r.cursor); - outgoingMessageRejected(); - break; - case PN_RELEASED: - if (preAcquires()) queue->release(r.cursor, false);//for PN_RELEASED, delivery count should not be incremented - outgoingMessageRejected();//TODO: not quite true... - break; - case PN_MODIFIED: - if (preAcquires()) { - mergeMessageAnnotationsIfRequired(r); - if (pn_disposition_is_undeliverable(pn_delivery_remote(delivery))) { - if (!trackingUndeliverableMessages) { - // observe queue for changes to track undeliverable messages - queue->getObservers().add( - boost::dynamic_pointer_cast(shared_from_this())); - trackingUndeliverableMessages = true; - } - - undeliverableMessages.add(r.msg.getSequence()); - } - - queue->release(r.cursor, pn_disposition_is_failed(pn_delivery_remote(delivery))); - } - outgoingMessageRejected();//TODO: not quite true... - break; - default: - QPID_LOG(warning, "Unhandled disposition: " << r.disposition); - } - //TODO: only settle once any dequeue on store has completed - pn_delivery_settle(delivery); - r.reset(); - } - } -} - -bool OutgoingFromQueue::canDeliver() -{ - return deliveries[current].delivery == 0 && pn_link_credit(link); -} - -void OutgoingFromQueue::detached(bool closed) -{ - QPID_LOG(debug, "Detaching outgoing link " << getName() << " from " << queue->getName()); - - if (trackingUndeliverableMessages) { - // stop observation of the queue - queue->getObservers().remove( - boost::dynamic_pointer_cast(shared_from_this())); - } - - queue->cancel(shared_from_this()); - //TODO: release in a clearer order? - for (size_t i = 0 ; i < deliveries.capacity(); ++i) { - if (deliveries[i].msg) queue->release(deliveries[i].cursor, true); - } - if (exclusive) { - queue->releaseExclusiveOwnership(closed); - } else if (isControllingUser) { - queue->releaseFromUse(true); - } - cancelled = true; -} - -OutgoingFromQueue::~OutgoingFromQueue() -{ - if (!cancelled && isControllingUser) queue->releaseFromUse(true); -} - -//Consumer interface: -bool OutgoingFromQueue::deliver(const QueueCursor& cursor, const qpid::broker::Message& msg) -{ - Record& r = deliveries[current++]; - if (current >= deliveries.capacity()) current = 0; - r.cursor = cursor; - r.msg = msg; - r.delivery = pn_delivery(link, r.tag); - //write header - qpid::amqp::MessageEncoder encoder(&buffer[0], buffer.size()); - encoder.writeHeader(Header(r.msg)); - write(&buffer[0], encoder.getPosition()); - Translation t(r.msg); - t.write(*this); - if (pn_link_advance(link)) { - if (unreliable) pn_delivery_settle(r.delivery); - outgoingMessageSent(); - QPID_LOG(debug, "Sent message " << r.msg.getSequence() << " from " << queue->getName() << ", index=" << r.index); - } else { - QPID_LOG(error, "Failed to send message " << r.msg.getSequence() << " from " << queue->getName() << ", index=" << r.index); - } - if (unreliable) { - if (preAcquires()) queue->dequeue(0, r.cursor); - r.reset(); - } - QPID_LOG(debug, "Requested delivery of " << r.msg.getSequence() << " from " << queue->getName() << ", index=" << r.index); - return true; -} - -void OutgoingFromQueue::notify() -{ - QPID_LOG(trace, "Notification received for " << queue->getName()); - out.activateOutput(); -} - -bool OutgoingFromQueue::accept(const qpid::broker::Message&) -{ - return true; -} - -void OutgoingFromQueue::setSubjectFilter(const std::string& f) -{ - subjectFilter = f; -} - -void OutgoingFromQueue::setSelectorFilter(const std::string& f) -{ - selector.reset(new Selector(f)); -} - -namespace { - -bool match(TokenIterator& filter, TokenIterator& target) -{ - bool wild = false; - while (!filter.finished()) - { - if (filter.match1('*')) { - if (target.finished()) return false; - //else move to next word in filter target - filter.next(); - target.next(); - } else if (filter.match1('#')) { - // i.e. filter word is '#' which can match a variable number of words in the target - filter.next(); - if (filter.finished()) return true; - else if (target.finished()) return false; - wild = true; - } else { - //filter word needs to match target exactly - if (target.finished()) return false; - std::string word; - target.pop(word); - if (filter.match(word)) { - wild = false; - filter.next(); - } else if (!wild) { - return false; - } - } - } - return target.finished(); -} -bool match(const std::string& filter, const std::string& target) -{ - TokenIterator lhs(filter); - TokenIterator rhs(target); - return match(lhs, rhs); -} -} - -bool OutgoingFromQueue::filter(const qpid::broker::Message& m) -{ - if (undeliverableMessages.contains(m.getSequence())) return false; - return (subjectFilter.empty() || subjectFilter == m.getRoutingKey() || match(subjectFilter, m.getRoutingKey())) - && (!selector || selector->filter(m)); -} - -void OutgoingFromQueue::cancel() {} - -void OutgoingFromQueue::acknowledged(const qpid::broker::DeliveryRecord&) {} - -qpid::broker::OwnershipToken* OutgoingFromQueue::getSession() -{ - return 0; -} - -OutgoingFromQueue::Record::Record() : delivery(0), disposition(0), index(0) -{ -#ifdef NO_PROTON_DELIVERY_TAG_T - tag.start = tagData; -#else - tag.bytes = tagData; -#endif - tag.size = TAG_WIDTH; -} -void OutgoingFromQueue::Record::init(size_t i) -{ - index = i; - qpid::framing::Buffer buffer(tagData, tag.size); - assert(index <= std::numeric_limits::max()); - buffer.putLong(index); -} -void OutgoingFromQueue::Record::reset() -{ - cursor = QueueCursor(); - msg = qpid::broker::Message(); - delivery = 0; - disposition = 0; -} - -size_t OutgoingFromQueue::Record::getIndex(pn_delivery_tag_t t) -{ - assert(t.size == TAG_WIDTH); -#ifdef NO_PROTON_DELIVERY_TAG_T - qpid::framing::Buffer buffer(const_cast(t.start)/*won't ever be written to*/, t.size); -#else - qpid::framing::Buffer buffer(const_cast(t.bytes)/*won't ever be written to*/, t.size); -#endif - return (size_t) buffer.getLong(); -} - -boost::shared_ptr OutgoingFromQueue::getExclusiveSubscriptionQueue(Outgoing* o) -{ - OutgoingFromQueue* s = dynamic_cast(o); - if (s && s->exclusive) return s->queue; - else return boost::shared_ptr(); -} - -void OutgoingFromQueue::dequeued(const qpid::broker::Message &m) -{ - if (undeliverableMessages.contains(m.getSequence())) { - undeliverableMessages.remove(m.getSequence()); - } -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Outgoing.h b/qpid/cpp/src/qpid/broker/amqp/Outgoing.h deleted file mode 100644 index f4ca4691b3..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Outgoing.h +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef QPID_BROKER_AMQP1_OUTGOING_H -#define QPID_BROKER_AMQP1_OUTGOING_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/amqp/Message.h" -#include "qpid/broker/amqp/ManagedOutgoingLink.h" -#include "qpid/broker/Consumer.h" -#include "qpid/broker/QueueObserver.h" - -#include -#include -#include -extern "C" { -#include -} - -namespace qpid { -namespace sys { -class OutputControl; -} - -namespace framing { -class SequenceSet; -} - -namespace broker { -class Broker; -class Queue; -class Selector; - -namespace amqp { -class Session; - -template -class CircularArray -{ - public: - CircularArray(size_t l) : limit(l), data(new T[limit]) {} - T& operator[](size_t i) { return data[i]; } - size_t capacity() { return limit; } - ~CircularArray() { delete [] data; } - private: - const size_t limit; - T* const data; - size_t next; -}; - -class Outgoing : public ManagedOutgoingLink -{ - public: - Outgoing(Broker& broker, Session& parent, const std::string& source, const std::string& target, const std::string& name); - virtual void setSubjectFilter(const std::string&) = 0; - virtual void setSelectorFilter(const std::string&) = 0; - virtual void init() = 0; - /** - * Allows the link to initiate any outgoing transfers - */ - virtual bool doWork() = 0; - /** - * Signals that this link has been detached - */ - virtual void detached(bool closed) = 0; - /** - * Called when a delivery is writable - */ - virtual void handle(pn_delivery_t* delivery) = 0; - - void wakeup(); - virtual ~Outgoing() {} - protected: - Session& session; -}; - -/** - * Logic for handling an outgoing link from a queue (even if it is a - * subscription pseduo-queue created by the broker) - */ -class OutgoingFromQueue : public Outgoing, public qpid::broker::Consumer, - public boost::enable_shared_from_this, - public qpid::broker::QueueObserver -{ - public: - OutgoingFromQueue(Broker&, const std::string& source, const std::string& target, boost::shared_ptr q, pn_link_t* l, Session&, - qpid::sys::OutputControl& o, SubscriptionType type, bool exclusive, bool isControllingUser); - ~OutgoingFromQueue(); - void setSubjectFilter(const std::string&); - void setSelectorFilter(const std::string&); - void init(); - bool doWork(); - void write(const char* data, size_t size); - void handle(pn_delivery_t* delivery); - bool canDeliver(); - void detached(bool closed); - - // Consumer interface: - bool deliver(const QueueCursor& cursor, const qpid::broker::Message& msg); - void notify(); - bool accept(const qpid::broker::Message&); - bool filter(const qpid::broker::Message&); - void cancel(); - void acknowledged(const qpid::broker::DeliveryRecord&); - qpid::broker::OwnershipToken* getSession(); - static boost::shared_ptr getExclusiveSubscriptionQueue(Outgoing*); - - // QueueObserver interface - virtual void enqueued(const qpid::broker::Message&) {}; - virtual void acquired(const qpid::broker::Message&) {}; - virtual void requeued(const qpid::broker::Message&) {}; - virtual void dequeued(const qpid::broker::Message&); - virtual void consumerAdded(const qpid::broker::Consumer&) {}; - virtual void consumerRemoved(const qpid::broker::Consumer&) {}; - - private: - - struct Record - { - QueueCursor cursor; - qpid::broker::Message msg; - pn_delivery_t* delivery; - 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); - }; - - void mergeMessageAnnotationsIfRequired(const Record &r); - - const bool exclusive; - const bool isControllingUser; - boost::shared_ptr queue; - CircularArray deliveries; - pn_link_t* link; - qpid::sys::OutputControl& out; - size_t current; - std::vector buffer; - std::string subjectFilter; - boost::scoped_ptr selector; - bool unreliable; - bool cancelled; - - bool trackingUndeliverableMessages; - qpid::framing::SequenceSet undeliverableMessages; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP1_OUTGOING_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.cpp b/qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.cpp deleted file mode 100644 index 62861ab270..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/ProtocolPlugin.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/Plugin.h" - -#include "qpid/Options.h" -#include "qpid/SaslFactory.h" -#include "qpid/NullSaslServer.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Protocol.h" -#include "qpid/broker/RecoverableMessage.h" -#include "qpid/broker/RecoverableMessageImpl.h" -#include "qpid/broker/amqp/Connection.h" -#include "qpid/broker/amqp/Interconnects.h" -#include "qpid/broker/amqp/Message.h" -#include "qpid/broker/amqp/NodePolicy.h" -#include "qpid/broker/amqp/Sasl.h" -#include "qpid/broker/amqp/Topic.h" -#include "qpid/broker/amqp/Translation.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { -namespace amqp { - -const std::string AMQP_SASL_SERVICENAME("amqp"); - -struct Options : public qpid::Options { - std::string domain; - std::vector queuePatterns; - std::vector topicPatterns; - - Options() : qpid::Options("AMQP 1.0 Options") { - addOptions() - ("domain", optValue(domain, "DOMAIN"), "Domain of this broker") - ("queue-patterns", optValue(queuePatterns, "PATTERN"), "Pattern for on-demand queues") - ("topic-patterns", optValue(topicPatterns, "PATTERN"), "Pattern for on-demand topics"); - } -}; - -class ProtocolImpl : public BrokerContext, public Protocol -{ - public: - ProtocolImpl(Interconnects* interconnects, TopicRegistry* topics, NodePolicyRegistry* policies, Broker& broker, const std::string& domain) - : BrokerContext(broker, *interconnects, *topics, *policies, domain) - { - interconnects->setContext(*this); - broker.getObjectFactoryRegistry().add(interconnects);//registry deletes on shutdown - broker.getObjectFactoryRegistry().add(topics);//registry deletes on shutdown - broker.getObjectFactoryRegistry().add(policies);//registry deletes on shutdown - } - qpid::sys::ConnectionCodec* create(const qpid::framing::ProtocolVersion&, qpid::sys::OutputControl&, const std::string&, const qpid::sys::SecuritySettings&); - boost::intrusive_ptr translate(const qpid::broker::Message&); - boost::shared_ptr recover(qpid::framing::Buffer&); - qpid::framing::ProtocolVersion supportedVersion() const; - private: -}; - -struct ProtocolPlugin : public Plugin -{ - Options options; - Options* getOptions() { return &options; } - NodePolicyRegistry* policies; - - ProtocolPlugin() : policies(0) {} - - void earlyInitialize(Plugin::Target& target) - { - //need to register protocol before recovery from store - broker::Broker* broker = dynamic_cast(&target); - if (broker) { - policies = new NodePolicyRegistry(); - ProtocolImpl* impl = new ProtocolImpl(new Interconnects(), new TopicRegistry(), policies, *broker, options.domain); - broker->getProtocolRegistry().add("amqp1.0", impl);//registry deletes on shutdown - } - } - - void initialize(Plugin::Target& target) - { - broker::Broker* broker = dynamic_cast(&target); - if (broker) { - for (std::vector::const_iterator i = options.queuePatterns.begin(); i != options.queuePatterns.end(); ++i) { - policies->createQueuePolicy(*broker, *i, qpid::types::Variant::Map()); - } - for (std::vector::const_iterator i = options.topicPatterns.begin(); i != options.topicPatterns.end(); ++i) { - policies->createTopicPolicy(*broker, *i, qpid::types::Variant::Map()); - } - } - } -}; - -ProtocolPlugin instance; // Static initialization - -qpid::sys::ConnectionCodec* ProtocolImpl::create(const qpid::framing::ProtocolVersion& v, qpid::sys::OutputControl& out, const std::string& id, const qpid::sys::SecuritySettings& external) -{ - if (v == qpid::framing::ProtocolVersion(1, 0)) { - if (v.getProtocol() == qpid::framing::ProtocolVersion::SASL) { - if (getBroker().isAuthenticating()) { - QPID_LOG(info, "Using AMQP 1.0 (with SASL layer)"); - std::string serviceName = getBroker().getSaslServiceName().empty() ? AMQP_SASL_SERVICENAME : getBroker().getSaslServiceName(); - return new qpid::broker::amqp::Sasl(out, id, *this, - qpid::SaslFactory::getInstance().createServer(getBroker().getRealm(),serviceName,getBroker().requireEncrypted(), external)); - } else { - std::auto_ptr authenticator(new qpid::NullSaslServer(getBroker().getRealm())); - QPID_LOG(info, "Using AMQP 1.0 (with dummy SASL layer)"); - return new qpid::broker::amqp::Sasl(out, id, *this, authenticator); - } - } else { - if (getBroker().isAuthenticating()) { - throw qpid::Exception("SASL layer required!"); - } else { - QPID_LOG(info, "Using AMQP 1.0 (no SASL layer)"); - return new qpid::broker::amqp::Connection(out, id, *this, false, false); - } - } - } - return 0; -} - -boost::intrusive_ptr ProtocolImpl::translate(const qpid::broker::Message& m) -{ - qpid::broker::amqp::Translation t(m, &getBroker()); - return t.getTransfer(); -} - -boost::shared_ptr ProtocolImpl::recover(qpid::framing::Buffer& buffer) -{ - QPID_LOG(debug, "Recovering, checking for 1.0 message format indicator..."); - uint32_t format = buffer.getLong(); - if (format == 0) { - QPID_LOG(debug, "Recovered message IS in 1.0 format"); - //this is a 1.0 format message - boost::intrusive_ptr m(new qpid::broker::amqp::Message(buffer.available())); - m->decodeHeader(buffer); - return RecoverableMessage::shared_ptr(new RecoverableMessageImpl(qpid::broker::Message(m, m))); - } else { - QPID_LOG(debug, "Recovered message is NOT in 1.0 format"); - return RecoverableMessage::shared_ptr(); - } -} - -qpid::framing::ProtocolVersion ProtocolImpl::supportedVersion() const -{ - return qpid::framing::ProtocolVersion(1,0); -} - - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Relay.cpp b/qpid/cpp/src/qpid/broker/amqp/Relay.cpp deleted file mode 100644 index 587a11466a..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Relay.cpp +++ /dev/null @@ -1,301 +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 "Relay.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include -#include -#include "config.h" - -namespace qpid { -namespace broker { -namespace amqp { - -Relay::Relay(size_t max_) : credit(0), max(max_), head(0), tail(0), isDetached(false), out(0), in(0) {} -void Relay::check() -{ - if (isDetached) throw qpid::Exception("other end of relay has been detached"); -} -bool Relay::send(pn_link_t* link) -{ - BufferedTransfer* c(0); - { - qpid::sys::ScopedLock l(lock); - if (head < tail) { - c = &buffer[head++]; - } else { - return false; - } - } - c->initOut(link); - return true; -} - -BufferedTransfer& Relay::push() -{ - qpid::sys::ScopedLock l(lock); - buffer.push_back(BufferedTransfer()); - return buffer.back(); -} - -void Relay::received(pn_link_t* link, pn_delivery_t* delivery) -{ - BufferedTransfer& received = push(); - received.initIn(link, delivery); - { - qpid::sys::ScopedLock l(lock); - ++tail; - } - if (out) out->wakeup(); -} -size_t Relay::size() const -{ - qpid::sys::ScopedLock l(lock); - return buffer.size(); -} -BufferedTransfer& Relay::front() -{ - qpid::sys::ScopedLock l(lock); - return buffer.front(); -} -void Relay::pop() -{ - qpid::sys::ScopedLock l(lock); - buffer.pop_front(); - if (head) --head; - if (tail) --tail; -} -void Relay::setCredit(int c) -{ - credit = c; - if (in) in->wakeup(); -} - -int Relay::getCredit() const -{ - qpid::sys::ScopedLock l(lock); - return std::min(credit - size(), max); -} -void Relay::attached(Outgoing* o) -{ - out = o; -} -void Relay::attached(Incoming* i) -{ - in = i; -} -void Relay::detached(Outgoing*) -{ - out = 0; - isDetached = true; - QPID_LOG(info, "Outgoing link detached from relay [" << this << "]"); - if (in) in->wakeup(); -} -void Relay::detached(Incoming*) -{ - in = 0; - isDetached = true; - QPID_LOG(info, "Incoming link detached from relay [" << this << "]"); - if (out) out->wakeup(); -} - -OutgoingFromRelay::OutgoingFromRelay(pn_link_t* l, Broker& broker, Session& parent, const std::string& source, - const std::string& target, const std::string& name_, boost::shared_ptr r) - : Outgoing(broker, parent, source, target, name_), name(name_), link(l), relay(r) {} -/** - * Allows the link to initiate any outgoing transfers - */ -bool OutgoingFromRelay::doWork() -{ - relay->check(); - relay->setCredit(pn_link_credit(link)); - bool worked = relay->send(link); - pn_delivery_t *d = pn_link_current(link); - if (d && pn_delivery_writable(d)) { - handle(d); - return true; - } - return worked; -} -/** - * Called when a delivery is writable - */ -void OutgoingFromRelay::handle(pn_delivery_t* delivery) -{ - void* context = pn_delivery_get_context(delivery); - BufferedTransfer* transfer = reinterpret_cast(context); - assert(transfer); - if (pn_delivery_writable(delivery)) { - if (transfer->write(link)) { - outgoingMessageSent(); - QPID_LOG(debug, "Sent relayed message " << name << " [" << relay.get() << "]"); - } else { - QPID_LOG(error, "Failed to send relayed message " << name << " [" << relay.get() << "]"); - } - } - if (pn_delivery_updated(delivery)) { - uint64_t d = transfer->updated(); - switch (d) { - case PN_ACCEPTED: - outgoingMessageAccepted(); - break; - case PN_REJECTED: - case PN_RELEASED://TODO: not quite true... - case PN_MODIFIED://TODO: not quite true... - outgoingMessageRejected(); - break; - default: - QPID_LOG(warning, "Unhandled disposition: " << d); - } - } -} -/** - * Signals that this link has been detached - */ -void OutgoingFromRelay::detached(bool /*closed*/) -{ - relay->detached(this); -} -void OutgoingFromRelay::init() -{ - relay->attached(this); -} -void OutgoingFromRelay::setSubjectFilter(const std::string&) -{ - //TODO -} -void OutgoingFromRelay::setSelectorFilter(const std::string&) -{ - //TODO -} - -IncomingToRelay::IncomingToRelay(pn_link_t* link, Broker& broker, Session& parent, const std::string& source, - const std::string& target, const std::string& name, boost::shared_ptr r) - : Incoming(link, broker, parent, source, target, name), relay(r) -{ - relay->attached(this); -} -bool IncomingToRelay::settle() -{ - bool result(false); - while (relay->size() && relay->front().settle()) { - result = true; - relay->pop(); - } - return result; -} -bool IncomingToRelay::doWork() -{ - relay->check(); - bool work(false); - if (settle()) work = true; - if (Incoming::doWork()) work = true; - return work; -} -bool IncomingToRelay::haveWork() -{ - bool work(false); - if (settle()) work = true; - if (Incoming::haveWork()) work = true; - return work; -} -void IncomingToRelay::readable(pn_delivery_t* delivery) -{ - relay->received(link, delivery); - --window; -} - -uint32_t IncomingToRelay::getCredit() -{ - return relay->getCredit(); -} - -void IncomingToRelay::detached(bool /*closed*/) -{ - relay->detached(this); -} - -BufferedTransfer::BufferedTransfer() : disposition(0) {} -void BufferedTransfer::initIn(pn_link_t* link, pn_delivery_t* d) -{ - in.handle = d; - //read in data - data.resize(pn_delivery_pending(d)); - /*ssize_t read = */pn_link_recv(link, &data[0], data.size()); - pn_link_advance(link); - - //copy delivery tag - pn_delivery_tag_t dt = pn_delivery_tag(d); - tag.resize(dt.size); -#ifdef NO_PROTON_DELIVERY_TAG_T - ::memmove(&tag[0], dt.start, dt.size); -#else - ::memmove(&tag[0], dt.bytes, dt.size); -#endif - - //set context - pn_delivery_set_context(d, this); - -} - -bool BufferedTransfer::settle() -{ - if (out.settled && !in.settled) { - pn_delivery_update(in.handle, disposition); - pn_delivery_settle(in.handle); - in.settled = true; - } - return out.settled && in.settled; -} - -void BufferedTransfer::initOut(pn_link_t* link) -{ - pn_delivery_tag_t dt; -#ifdef NO_PROTON_DELIVERY_TAG_T - dt.start = &tag[0]; -#else - dt.bytes = &tag[0]; -#endif - dt.size = tag.size(); - out.handle = pn_delivery(link, dt); - //set context - pn_delivery_set_context(out.handle, this); -} - -uint64_t BufferedTransfer::updated() -{ - disposition = pn_delivery_remote_state(out.handle); - if (disposition) { - pn_delivery_settle(out.handle); - out.settled = true; - } - return disposition; -} - -bool BufferedTransfer::write(pn_link_t* link) -{ - pn_link_send(link, &data[0], data.size()); - return pn_link_advance(link); -} -Delivery::Delivery() : settled(false), handle(0) {} -Delivery::Delivery(pn_delivery_t* d) : settled(false), handle(d) {} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Relay.h b/qpid/cpp/src/qpid/broker/amqp/Relay.h deleted file mode 100644 index 32f317bfe1..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Relay.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef QPID_BROKER_AMQP_RELAY_H -#define QPID_BROKER_AMQP_RELAY_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 "Incoming.h" -#include "Outgoing.h" -#include "qpid/sys/Mutex.h" -extern "C" { -#include -} -#include - -namespace qpid { -namespace broker { -namespace amqp { - -struct Delivery -{ - bool settled; - pn_delivery_t* handle; - - Delivery(); - Delivery(pn_delivery_t* d); -}; - -class BufferedTransfer -{ - public: - BufferedTransfer(); - void initIn(pn_link_t* link, pn_delivery_t* d); - bool settle(); - void initOut(pn_link_t* link); - uint64_t updated(); - bool write(pn_link_t*); - private: - std::vector data; - Delivery in; - Delivery out; - pn_delivery_tag_t dt; - std::vector tag; - uint64_t disposition; -}; - -/** - * - */ -class Relay -{ - public: - Relay(size_t max); - void check(); - size_t size() const; - BufferedTransfer& front(); - void pop(); - bool send(pn_link_t*); - void received(pn_link_t* link, pn_delivery_t* delivery); - int getCredit() const; - void setCredit(int); - void attached(Outgoing*); - void attached(Incoming*); - void detached(Outgoing*); - void detached(Incoming*); - private: - std::deque buffer;//TODO: optimise by replacing with simple circular array - int credit;//issued by outgoing peer, decremented everytime we send a message on outgoing link - size_t max; - size_t head; - size_t tail; - bool isDetached; - Outgoing* out; - Incoming* in; - mutable qpid::sys::Mutex lock; - - BufferedTransfer& push(); -}; - -class OutgoingFromRelay : public Outgoing -{ - public: - OutgoingFromRelay(pn_link_t*, Broker&, Session&, const std::string& source, - const std::string& target, const std::string& name, boost::shared_ptr); - bool doWork(); - void handle(pn_delivery_t* delivery); - void detached(bool closed); - void init(); - void setSubjectFilter(const std::string&); - void setSelectorFilter(const std::string&); - private: - const std::string name; - pn_link_t* link; - boost::shared_ptr relay; -}; - -class IncomingToRelay : public Incoming -{ - public: - IncomingToRelay(pn_link_t*, Broker&, Session&, const std::string& source, - const std::string& target, const std::string& name, boost::shared_ptr r); - bool settle(); - bool doWork(); - bool haveWork(); - void detached(bool closed); - void readable(pn_delivery_t* delivery); - uint32_t getCredit(); - private: - boost::shared_ptr relay; -}; - -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_RELAY_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Sasl.cpp b/qpid/cpp/src/qpid/broker/amqp/Sasl.cpp deleted file mode 100644 index 890de40eb4..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Sasl.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/broker/amqp/Sasl.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/sys/SecurityLayer.h" -#include -#include - -namespace qpid { -namespace broker { -namespace amqp { - -Sasl::Sasl(qpid::sys::OutputControl& o, const std::string& id, BrokerContext& context, std::auto_ptr auth) - : qpid::amqp::SaslServer(id), out(o), connection(out, id, context, true, false), - authenticator(auth), - state(INCOMPLETE), writeHeader(true), haveOutput(true) -{ - out.activateOutput(); - mechanisms(authenticator->getMechanisms()); -} - -Sasl::~Sasl() {} - -size_t Sasl::decode(const char* buffer, size_t size) -{ - size_t total = 0; - while (total < size) { - size_t decoded = 0; - if (state == AUTHENTICATED || state == SUCCESS_PENDING) { - if (securityLayer.get()) decoded = securityLayer->decode(buffer+total, size-total); - else decoded = connection.decode(buffer+total, size-total); - } else if (state == INCOMPLETE && size) { - decoded = read(buffer+total, size-total); - QPID_LOG(trace, id << " Sasl::decode(" << size << "): " << decoded << " (" << total << ")"); - } - if (decoded) total += decoded; - else break; - } - return total; -} - -size_t Sasl::encode(char* buffer, size_t size) -{ - if (state == AUTHENTICATED) { - if (securityLayer.get()) return securityLayer->encode(buffer, size); - else return connection.encode(buffer, size); - } else { - size_t encoded = 0; - if (writeHeader) { - encoded += writeProtocolHeader(buffer, size); - if (!encoded) return 0; - writeHeader = false; - } - if (encoded < size) { - encoded += write(buffer + encoded, size - encoded); - } - if (state == SUCCESS_PENDING) { - state = AUTHENTICATED; - } else if (state == FAILURE_PENDING) { - state = FAILED; - } else { - haveOutput = (encoded == size); - } - QPID_LOG(trace, id << " Sasl::encode(" << size << "): " << encoded); - return encoded; - } -} - -bool Sasl::canEncode() -{ - if (state == AUTHENTICATED) { - if (securityLayer.get()) return securityLayer->canEncode(); - else return connection.canEncode(); - } else { - return haveOutput; - } -} - -void Sasl::closed() -{ - if (state == AUTHENTICATED) { - connection.closed(); - } else { - QPID_LOG(info, id << " Connection closed prior to authentication completing"); - state = FAILED; - } -} -bool Sasl::isClosed() const -{ - if (state == AUTHENTICATED) { - return connection.isClosed(); - } else { - return state == FAILED; - } -} - -framing::ProtocolVersion Sasl::getVersion() const -{ - return connection.getVersion(); -} -namespace { -const std::string EMPTY; -} - -void Sasl::init(const std::string& mechanism, const std::string* response, const std::string* /*hostname*/) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-INIT(" << mechanism << ", " << (response ? *response : EMPTY) << ")"); - //TODO: what should we do with hostname here? - std::string c; - respond(authenticator->start(mechanism, response, c), c); - connection.setSaslMechanism(mechanism); -} - -void Sasl::response(const std::string* r) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-RESPONSE(" << (r ? *r : EMPTY) << ")"); - std::string c; - respond(authenticator->step(r, c), c); -} - -void Sasl::respond(qpid::SaslServer::Status status, const std::string& chllnge) -{ - switch (status) { - case qpid::SaslServer::OK: - connection.setUserId(authenticator->getUserid()); - completed(true); - //can't set authenticated & failed until we have actually sent the outcome - state = SUCCESS_PENDING; - securityLayer = authenticator->getSecurityLayer(65535); - if (securityLayer.get()) { - QPID_LOG_CAT(info, security, id << " Security layer installed"); - securityLayer->init(&connection); - connection.setSaslSsf(securityLayer->getSsf()); - } - QPID_LOG_CAT(info, security, id << " Authenticated as " << authenticator->getUserid()); - break; - case qpid::SaslServer::FAIL: - completed(false); - state = FAILURE_PENDING; - QPID_LOG_CAT(info, security, id << " Failed to authenticate"); - break; - case qpid::SaslServer::CHALLENGE: - challenge(&chllnge); - QPID_LOG_CAT(info, security, id << " Challenge issued"); - break; - } - haveOutput = true; - out.activateOutput(); -} -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Sasl.h b/qpid/cpp/src/qpid/broker/amqp/Sasl.h deleted file mode 100644 index 859cfb2d34..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Sasl.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef QPID_BROKER_AMQP_SASL_H -#define QPID_BROKER_AMQP_SASL_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/amqp/Connection.h" -#include "qpid/SaslServer.h" -#include "qpid/amqp/SaslServer.h" -#include "qpid/sys/ConnectionCodec.h" -#include -namespace qpid { -namespace sys { -class SecurityLayer; -} -namespace broker { -namespace amqp { -/** - * An AMQP 1.0 SASL Security Layer for authentication and optionally - * encryption. - */ -class Sasl : public sys::ConnectionCodec, qpid::amqp::SaslServer -{ - public: - Sasl(qpid::sys::OutputControl& out, const std::string& id, BrokerContext& context, std::auto_ptr authenticator); - ~Sasl(); - - size_t decode(const char* buffer, size_t size); - size_t encode(char* buffer, size_t size); - bool canEncode(); - - void closed(); - bool isClosed() const; - - framing::ProtocolVersion getVersion() const; - private: - qpid::sys::OutputControl& out; - Connection connection; - std::auto_ptr securityLayer; - std::auto_ptr authenticator; - enum { - INCOMPLETE, SUCCESS_PENDING, FAILURE_PENDING, AUTHENTICATED, FAILED - } state; - - bool writeHeader; - bool haveOutput; - - void init(const std::string& mechanism, const std::string* response, const std::string* hostname); - void response(const std::string*); - void respond(qpid::SaslServer::Status status, const std::string& challenge); -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_SASL_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp b/qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp deleted file mode 100644 index 4317d18525..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp +++ /dev/null @@ -1,181 +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 "SaslClient.h" -#include "Interconnect.h" -#include "qpid/broker/Broker.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/log/Statement.h" -#include "qpid/Sasl.h" -#include "qpid/SaslFactory.h" -#include "qpid/StringUtils.h" -#include - -namespace qpid { -namespace broker { -namespace amqp { - -SaslClient::SaslClient(qpid::sys::OutputControl& out_, const std::string& id, boost::shared_ptr c, std::auto_ptr 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), initialised(false), state(NONE) {} - -SaslClient::~SaslClient() -{ - connection->transportDeleted(); -} - -std::size_t SaslClient::decode(const char* buffer, std::size_t size) -{ - size_t decoded = 0; - if (readHeader) { - decoded += readProtocolHeader(buffer, size); - readHeader = !decoded; - } - if (state == NONE && decoded < size) { - decoded += read(buffer + decoded, size - decoded); - } else if (state == SUCCEEDED) { - if (securityLayer.get()) decoded += securityLayer->decode(buffer + decoded, size - decoded); - else decoded += connection->decode(buffer + decoded, size - decoded); - } - QPID_LOG(trace, id << " SaslClient::decode(" << size << "): " << decoded); - return decoded; -} - -std::size_t SaslClient::encode(char* buffer, std::size_t size) -{ - size_t encoded = 0; - if (writeHeader) { - encoded += writeProtocolHeader(buffer, size); - writeHeader = !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); - } - haveOutput = (encoded == size); - QPID_LOG(trace, id << " SaslClient::encode(" << size << "): " << encoded); - return encoded; -} - -bool SaslClient::canEncode() -{ - if (state == NONE) { - QPID_LOG(trace, id << " SaslClient::canEncode(): " << writeHeader << " || " << haveOutput); - return writeHeader || haveOutput; - } else if (state == SUCCEEDED) { - if (securityLayer.get()) return securityLayer->canEncode(); - else return connection->canEncode(); - } else { - return false; - } -} - -void SaslClient::mechanisms(const std::string& offered) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-MECHANISMS(" << offered << ")"); - std::string response; - - std::string mechanisms; - if (allowedMechanisms.size()) { - std::vector allowed = split(allowedMechanisms, " "); - std::vector supported = split(offered, " "); - std::stringstream intersection; - for (std::vector::const_iterator i = allowed.begin(); i != allowed.end(); ++i) { - if (std::find(supported.begin(), supported.end(), *i) != supported.end()) { - if (!intersection.str().empty()) intersection << " "; - intersection << *i; - } - } - mechanisms = intersection.str(); - } else { - mechanisms = offered; - } - - if (sasl->start(mechanisms, response, &transport)) { - init(sasl->getMechanism(), &response, hostname.size() ? &hostname : 0); - } else { - init(sasl->getMechanism(), 0, hostname.size() ? &hostname : 0); - } - haveOutput = true; - out.activateOutput(); -} -void SaslClient::challenge(const std::string& challenge) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-CHALLENGE(" << challenge.size() << " bytes)"); - std::string r = sasl->step(challenge); - response(&r); - haveOutput = true; - out.activateOutput(); -} -namespace { -const std::string EMPTY; -} -void SaslClient::challenge() -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-CHALLENGE(null)"); - std::string r = sasl->step(EMPTY); - response(&r); -} -void SaslClient::outcome(uint8_t result, const std::string& extra) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-OUTCOME(" << result << ", " << extra << ")"); - outcome(result); -} -void SaslClient::outcome(uint8_t result) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-OUTCOME(" << result << ")"); - if (result) state = FAILED; - else state = SUCCEEDED; - - securityLayer = sasl->getSecurityLayer(65535); - if (securityLayer.get()) { - securityLayer->init(connection.get()); - } - out.activateOutput(); -} - -void SaslClient::closed() -{ - if (state == SUCCEEDED) { - connection->closed(); - } else { - QPID_LOG(info, id << " Connection closed prior to authentication completing"); - state = FAILED; - } -} - -bool SaslClient::isClosed() const -{ - if (state == FAILED) return true; - else if (state == SUCCEEDED) return connection->isClosed(); - else return false; -} -qpid::framing::ProtocolVersion SaslClient::getVersion() const -{ - return qpid::framing::ProtocolVersion(1,0,qpid::framing::ProtocolVersion::SASL); -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/SaslClient.h b/qpid/cpp/src/qpid/broker/amqp/SaslClient.h deleted file mode 100644 index fca293879e..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/SaslClient.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef QPID_BROKER_AMQP_SASLCLIENT_H -#define QPID_BROKER_AMQP_SASLCLIENT_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/ConnectionCodec.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/amqp/SaslClient.h" -#include -#include - -namespace qpid { -class Sasl; -namespace sys { -class OutputControl; -class SecurityLayer; -} -namespace broker { -class Broker; -namespace amqp { -class Interconnect; - -/** - * Implementation of SASL client role for when broker connects to - * external peers. - */ -class SaslClient : public qpid::sys::ConnectionCodec, qpid::amqp::SaslClient -{ - public: - SaslClient(qpid::sys::OutputControl& out, const std::string& id, boost::shared_ptr, std::auto_ptr, - const std::string& hostname, const std::string& allowedMechanisms, const qpid::sys::SecuritySettings&); - ~SaslClient(); - std::size_t decode(const char* buffer, std::size_t size); - std::size_t encode(char* buffer, std::size_t size); - bool canEncode(); - void closed(); - bool isClosed() const; - qpid::framing::ProtocolVersion getVersion() const; - private: - qpid::sys::OutputControl& out; - boost::shared_ptr connection; - std::auto_ptr sasl; - std::string hostname; - std::string allowedMechanisms; - qpid::sys::SecuritySettings transport; - bool readHeader; - bool writeHeader; - bool haveOutput; - bool initialised; - enum { - NONE, FAILED, SUCCEEDED - } state; - std::auto_ptr securityLayer; - - void mechanisms(const std::string&); - void challenge(const std::string&); - void challenge(); //null != empty string - void outcome(uint8_t result, const std::string&); - void outcome(uint8_t result); -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_SASLCLIENT_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Session.cpp b/qpid/cpp/src/qpid/broker/amqp/Session.cpp deleted file mode 100644 index 5573498a39..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Session.cpp +++ /dev/null @@ -1,1053 +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 "Session.h" -#include "Incoming.h" -#include "Outgoing.h" -#include "Message.h" -#include "Connection.h" -#include "DataReader.h" -#include "Domain.h" -#include "Exception.h" -#include "Interconnects.h" -#include "NodePolicy.h" -#include "Relay.h" -#include "Topic.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/DirectExchange.h" -#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" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Statement.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "config.h" -#include -#include -#include -#include -extern "C" { -#include -} - -namespace qpid { -namespace broker { -namespace amqp { - -using namespace qpid::amqp::transaction; - -namespace { -pn_bytes_t convert(const std::string& s) -{ - pn_bytes_t result; - result.start = const_cast(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"); -const std::string DURABLE("durable"); -const std::string QUEUE("queue"); -const std::string TOPIC("topic"); -const std::string DIRECT_FILTER("legacy-amqp-direct-binding"); -const std::string TOPIC_FILTER("legacy-amqp-topic-binding"); -const std::string SHARED("shared"); - -void writeCapabilities(pn_data_t* out, const std::vector& supported) -{ - 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::const_iterator i = supported.begin(); i != supported.end(); ++i) { - pn_data_put_symbol(out, convert(*i)); - } - pn_data_exit(out); - } -} - -template -void readCapabilities(pn_data_t* data, F f) -{ - 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)) { - std::string s = convert(pn_data_get_symbol(data)); - f(s); - } - pn_data_exit(data); - } else if (type == PN_SYMBOL) { - std::string s = convert(pn_data_get_symbol(data)); - f(s); - } 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 node, std::vector* 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 node, std::vector* 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 node) -{ - std::vector 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 node) -{ - std::vector supported; - readCapabilities(in, boost::bind(&collectExchangeCapabilities, node, &supported, _1)); - writeCapabilities(out, supported); -} - -} - -class IncomingToQueue : public DecodingIncoming -{ - public: - IncomingToQueue(Broker& b, Session& p, boost::shared_ptr q, pn_link_t* l, const std::string& source, bool icl) - : DecodingIncoming(l, b, p, source, q->getName(), pn_link_name(l)), queue(q), isControllingLink(icl) - { - queue->markInUse(isControllingLink); - } - ~IncomingToQueue() { queue->releaseFromUse(isControllingLink); } - void handle(qpid::broker::Message& m, qpid::broker::TxBuffer*); - private: - boost::shared_ptr queue; - bool isControllingLink; -}; - -class IncomingToExchange : public DecodingIncoming -{ - public: - IncomingToExchange(Broker& b, Session& p, boost::shared_ptr e, pn_link_t* l, const std::string& source, bool icl) - : DecodingIncoming(l, b, p, source, e->getName(), pn_link_name(l)), exchange(e), authorise(p.getAuthorise()), isControllingLink(icl) - { - exchange->incOtherUsers(); - } - ~IncomingToExchange() - { - exchange->decOtherUsers(isControllingLink); - } - void handle(qpid::broker::Message& m, qpid::broker::TxBuffer*); - private: - boost::shared_ptr exchange; - Authorise& authorise; - bool isControllingLink; -}; - -class AnonymousRelay : public DecodingIncoming -{ - public: - AnonymousRelay(Broker& b, Connection& c, Session& p, pn_link_t* l) - : DecodingIncoming(l, b, p, std::string(), "ANONYMOUS-RELAY", pn_link_name(l)), authorise(p.getAuthorise()), context(c) - {} - void handle(qpid::broker::Message& m, qpid::broker::TxBuffer*); - private: - boost::shared_ptr exchange; - Authorise& authorise; - BrokerContext& context; -}; - -class IncomingToCoordinator : public DecodingIncoming -{ - public: - IncomingToCoordinator(pn_link_t* link, Broker& broker, Session& parent) - : DecodingIncoming(link, broker, parent, std::string(), "txn-ctrl", pn_link_name(link)) {} - - ~IncomingToCoordinator() { session.abort(); } - void deliver(boost::intrusive_ptr, pn_delivery_t*); - void handle(qpid::broker::Message&, qpid::broker::TxBuffer*) {} - private: -}; - -bool Session::ResolvedNode::trackControllingLink() const -{ - return created && (properties.trackControllingLink() || (queue && queue->getSettings().lifetime == QueueSettings::DELETE_ON_CLOSE)); -} - -Session::Session(pn_session_t* s, Connection& c, qpid::sys::OutputControl& o) - : ManagedSession(c.getBroker(), c, (boost::format("%1%") % s).str()), session(s), connection(c), out(o), deleted(false), - authorise(connection.getUserId(), connection.getBroker().getAcl()), - detachRequested(), - tx(*this) -{} - - -Session::ResolvedNode Session::resolve(const std::string name, pn_terminus_t* terminus, bool incoming) -{ - bool isQueueRequested = is_capability_requested(QUEUE, pn_terminus_capabilities(terminus)); - bool isTopicRequested = is_capability_requested(TOPIC, pn_terminus_capabilities(terminus)); - if (isTopicRequested && isQueueRequested) { - //requesting both renders each request meaningless - isQueueRequested = false; - isTopicRequested = false; - } - //check whether user is even allowed access to queues/topics before resolving - authorise.access(name, isQueueRequested, isTopicRequested); - ResolvedNode node(pn_terminus_is_dynamic(terminus)); - if (isTopicRequested || !isQueueRequested) { - node.topic = connection.getTopics().get(name); - if (node.topic) node.exchange = node.topic->getExchange(); - else node.exchange = connection.getBroker().getExchanges().find(name); - } - if (isQueueRequested || !isTopicRequested) { - node.queue = connection.getBroker().getQueues().find(name); - } - bool createOnDemand = is_capability_requested(CREATE_ON_DEMAND, pn_terminus_capabilities(terminus)); - //Strictly speaking, properties should only be specified when the - //terminus is dynamic. However we will not enforce that here. If - //properties are set on the attach request, we will set them on - //our reply. This allows the 'create' and 'assert' options in the - //qpid messaging API to be implemented over 1.0. - node.properties.read(pn_terminus_properties(terminus)); - - if (node.exchange && createOnDemand && isTopicRequested) { - if (!node.properties.getSpecifiedExchangeType().empty() && node.properties.getExchangeType() != node.exchange->getType()) { - //emulate 0-10 exchange-declare behaviour - throw Exception(qpid::amqp::error_conditions::PRECONDITION_FAILED, "Exchange of different type already exists"); - } - } - bool isCreateRequested = pn_terminus_is_dynamic(terminus) || createOnDemand; - bool isCreateQueueRequested = isCreateRequested && isQueueRequested; - bool isCreateTopicRequested = isCreateRequested && isTopicRequested; - if ((!node.queue && !node.exchange) || (!node.queue && isCreateQueueRequested) || (!node.exchange && isCreateTopicRequested)) { - if (isCreateRequested) { - //is it a queue or an exchange? - if (isTopicRequested) { - if (node.queue) { - QPID_LOG_CAT(warning, model, "Node name will be ambiguous, creation of exchange named " << name << " requested when queue of the same name already exists"); - } - qpid::framing::FieldTable args; - qpid::amqp_0_10::translate(node.properties.getProperties(), args); - std::pair, bool> result - = connection.getBroker().createExchange(name, node.properties.getExchangeType(), node.properties.isDurable(), node.properties.isAutodelete(), - node.properties.getAlternateExchange(), - args, connection.getUserId(), connection.getId()); - node.exchange = result.first; - node.created = result.second; - } else { - if (node.exchange) { - QPID_LOG_CAT(warning, model, "Node name will be ambiguous, creation of queue named " << name << " requested when exchange of the same name already exists"); - } - std::pair, bool> result - = connection.getBroker().createQueue(name, node.properties.getQueueSettings(), node.properties.isExclusive() ? this:0, node.properties.getAlternateExchange(), connection.getUserId(), connection.getId()); - node.queue = result.first; - node.created = result.second; - } - } else { - boost::shared_ptr nodePolicy = connection.getNodePolicies().match(name); - if (nodePolicy) { - std::pair, boost::shared_ptr > result = nodePolicy->create(name, connection); - node.queue = result.first; - node.topic = result.second; - node.created = node.queue || node.topic; - if (node.topic) node.exchange = node.topic->getExchange(); - - if (node.queue) { - QPID_LOG(info, "Created queue " << name << " from policy with pattern " << nodePolicy->getPattern()); - } else if (node.topic) { - QPID_LOG(info, "Created topic " << name << " from policy with pattern " << nodePolicy->getPattern()); - } else { - QPID_LOG(debug, "Created neither a topic nor a queue for " << name << " from policy with pattern " << nodePolicy->getPattern()); - } - - } else { - size_t i = name.find('@'); - if (i != std::string::npos && (i+1) < name.length()) { - std::string domain = name.substr(i+1); - std::string local = name.substr(0, i); - std::string id = (boost::format("%1%-%2%") % name % qpid::types::Uuid(true).str()).str(); - //does this domain exist? - boost::shared_ptr d = connection.getInterconnects().findDomain(domain); - if (d) { - node.relay = boost::shared_ptr(new Relay(1000)); - if (incoming) { - d->connect(false, id, name, local, connection, node.relay); - } else { - d->connect(true, id, local, name, connection, node.relay); - } - } - } - } - } - } else if (node.queue && node.topic) { - if (isTopicRequested) { - QPID_LOG_CAT(info, protocol, "Ambiguous node name; " << name << " could be queue or topic, topic requested"); - node.queue.reset(); - } else if (isQueueRequested) { - QPID_LOG_CAT(info, protocol, "Ambiguous node name; " << name << " could be queue or topic, queue requested"); - node.exchange.reset(); - node.topic.reset(); - } else { - QPID_LOG_CAT(warning, protocol, "Ambiguous node name; " << name << " could be queue or topic, assuming topic"); - node.queue.reset(); - } - } else if (node.queue && node.exchange) { - if (isTopicRequested) { - QPID_LOG_CAT(info, protocol, "Ambiguous node name; " << name << " could be queue or topic, topic requested"); - node.queue.reset(); - } else if (isQueueRequested) { - QPID_LOG_CAT(info, protocol, "Ambiguous node name; " << name << " could be queue or topic, queue requested"); - node.exchange.reset(); - node.topic.reset(); - } else { - QPID_LOG_CAT(warning, protocol, "Ambiguous node name; " << name << " could be queue or exchange, assuming queue"); - node.exchange.reset(); - } - } - - if (node.properties.isExclusive() && node.queue) { - if (node.queue->setExclusiveOwner(this)) { - exclusiveQueues.insert(node.queue); - } else { - throw Exception(qpid::amqp::error_conditions::PRECONDITION_FAILED, std::string("Cannot grant exclusive access to ") + node.queue->getName()); - } - } - return node; -} - -std::string Session::generateName(pn_link_t* link) -{ - std::stringstream s; - if (connection.getContainerId().empty()) { - s << qpid::types::Uuid(true); - } else { - s << connection.getContainerId(); - } - s << "_" << pn_link_name(link); - return s.str(); -} - -std::string Session::qualifyName(const std::string& name) -{ - if (connection.getDomain().empty()) { - return name; - } else { - std::stringstream s; - s << name << "@" << connection.getDomain(); - return s.str(); - } -} - -void Session::attach(pn_link_t* link) -{ - if (pn_link_is_sender(link)) { - pn_terminus_t* source = pn_link_remote_source(link); - pn_link_set_snd_settle_mode(link, pn_link_remote_snd_settle_mode(link)); - //i.e a subscription - std::string name; - if (pn_terminus_get_type(source) == PN_UNSPECIFIED) { - pn_terminus_set_type(pn_link_source(link), PN_UNSPECIFIED); - throw Exception(qpid::amqp::error_conditions::PRECONDITION_FAILED, "No source specified!"); - } else if (pn_terminus_is_dynamic(source)) { - name = generateName(link); - QPID_LOG(debug, "Received attach request for outgoing link from " << name); - pn_terminus_set_address(pn_link_source(link), qualifyName(name).c_str()); - } else { - name = pn_terminus_get_address(source); - QPID_LOG(debug, "Received attach request for outgoing link from " << name); - pn_terminus_set_address(pn_link_source(link), name.c_str()); - } - - try { - setupOutgoing(link, source, name); - } catch (const std::exception&) { - pn_terminus_set_type(pn_link_source(link), PN_UNSPECIFIED); - throw; - } - } else { - pn_terminus_t* target = pn_link_remote_target(link); - std::string name; - if (pn_terminus_get_type(target) == PN_UNSPECIFIED) { - pn_terminus_set_type(pn_link_target(link), PN_UNSPECIFIED); - throw Exception(qpid::amqp::error_conditions::PRECONDITION_FAILED, "No target specified!"); - } else if (pn_terminus_get_type(target) == PN_COORDINATOR) { - QPID_LOG(debug, "Received attach request for incoming link to transaction coordinator on " << this); - boost::shared_ptr i(new IncomingToCoordinator(link, connection.getBroker(), *this)); - incoming[link] = i; - return; - } else if (pn_terminus_is_dynamic(target)) { - name = generateName(link); - QPID_LOG(debug, "Received attach request for incoming link to " << name); - pn_terminus_set_address(pn_link_target(link), qualifyName(name).c_str()); - } else if (pn_terminus_get_type(target) == PN_TARGET && !pn_terminus_get_address(target)) { - authorise.access("ANONYMOUS-RELAY"); - boost::shared_ptr r(new AnonymousRelay(connection.getBroker(), connection, *this, link)); - incoming[link] = r; - if (connection.getBroker().isAuthenticating() && !connection.isLink()) - r->verify(connection.getUserId(), connection.getBroker().getRealm()); - QPID_LOG(debug, "Incoming link attached for ANONYMOUS-RELAY"); - return; - } else { - name = pn_terminus_get_address(target); - QPID_LOG(debug, "Received attach request for incoming link to " << name); - pn_terminus_set_address(pn_link_target(link), name.c_str()); - } - - try { - setupIncoming(link, target, name); - } catch (const std::exception&) { - pn_terminus_set_type(pn_link_target(link), PN_UNSPECIFIED); - throw; - } - } -} - -void Session::setupIncoming(pn_link_t* link, pn_terminus_t* target, const std::string& name) -{ - ResolvedNode node = resolve(name, target, true); - //set capabilities - if (node.queue) { - setCapabilities(pn_terminus_capabilities(target), pn_terminus_capabilities(pn_link_target(link)), node.queue); - authorise.incoming(node.queue); - node.properties.write(pn_terminus_properties(pn_link_target(link)), node.queue); - } else if (node.exchange) { - setCapabilities(pn_terminus_capabilities(target), pn_terminus_capabilities(pn_link_target(link)), node.exchange); - authorise.incoming(node.exchange); - node.properties.write(pn_terminus_properties(pn_link_target(link)), node.exchange); - } - - const char* sourceAddress = pn_terminus_get_address(pn_link_remote_source(link)); - if (!sourceAddress) { - sourceAddress = pn_terminus_get_address(pn_link_source(link)); - } - std::string source; - if (sourceAddress) { - source = sourceAddress; - } - if (node.queue) { - boost::shared_ptr q(new IncomingToQueue(connection.getBroker(), *this, node.queue, link, source, node.trackControllingLink())); - incoming[link] = q; - } else if (node.exchange) { - boost::shared_ptr e(new IncomingToExchange(connection.getBroker(), *this, node.exchange, link, source, node.trackControllingLink())); - incoming[link] = e; - } else if (node.relay) { - boost::shared_ptr in(new IncomingToRelay(link, connection.getBroker(), *this, source, name, pn_link_name(link), node.relay)); - incoming[link] = in; - } else { - pn_terminus_set_type(pn_link_target(link), PN_UNSPECIFIED); - throw Exception(qpid::amqp::error_conditions::NOT_FOUND, std::string("Node not found: ") + name); - } - if (connection.getBroker().isAuthenticating() && !connection.isLink()) - incoming[link]->verify(connection.getUserId(), connection.getBroker().getRealm()); - QPID_LOG(debug, "Incoming link attached"); -} - -void Session::setupOutgoing(pn_link_t* link, pn_terminus_t* source, const std::string& name) -{ - ResolvedNode node = resolve(name, source, false); - if (node.queue) { - setCapabilities(pn_terminus_capabilities(source), pn_terminus_capabilities(pn_link_source(link)), node.queue); - node.properties.write(pn_terminus_properties(pn_link_source(link)), node.queue); - } else if (node.exchange) { - setCapabilities(pn_terminus_capabilities(source), pn_terminus_capabilities(pn_link_source(link)), node.exchange); - node.properties.write(pn_terminus_properties(pn_link_source(link)), node.exchange); - } - - Filter filter; - filter.read(pn_terminus_filter(source)); - const char* targetAddress = pn_terminus_get_address(pn_link_remote_target(link)); - if (!targetAddress) { - targetAddress = pn_terminus_get_address(pn_link_target(link)); - } - std::string target; - if (targetAddress) { - target = targetAddress; - } - - if (node.queue) { - authorise.outgoing(node.queue); - SubscriptionType type = (pn_terminus_get_distribution_mode(source) == PN_DIST_MODE_COPY) || (node.queue->isBrowseOnly()) ? BROWSER : CONSUMER; - if (type == CONSUMER && node.queue->hasExclusiveOwner() && !node.queue->isExclusiveOwner(this)) { - throw Exception(qpid::amqp::error_conditions::PRECONDITION_FAILED, std::string("Cannot consume from exclusive queue ") + node.queue->getName()); - } - boost::shared_ptr q(new OutgoingFromQueue(connection.getBroker(), name, target, node.queue, link, *this, out, type, false, node.trackControllingLink())); - q->init(); - filter.apply(q); - outgoing[link] = q; - pn_terminus_set_distribution_mode(pn_link_source(link), type == BROWSER ? PN_DIST_MODE_COPY : PN_DIST_MODE_MOVE); - } else if (node.exchange) { - authorise.access(node.exchange);//do separate access check before trying to create the queue - bool shared = is_capability_requested(SHARED, pn_terminus_capabilities(source)); - bool durable = pn_terminus_get_durability(source); - bool autodelete = !durable && pn_link_remote_snd_settle_mode(link) != PN_SND_UNSETTLED; - QueueSettings settings(durable, autodelete); - std::string altExchange; - if (node.topic) { - settings = node.topic->getPolicy(); - settings.durable = durable; - //only determine autodelete from link details if the policy did not imply autodeletion - if (!settings.autodelete) settings.autodelete = autodelete; - altExchange = node.topic->getAlternateExchange(); - } - if (settings.original.find("qpid.auto_delete_timeout") == settings.original.end()) { - //only use delay from link if policy didn't specify one - settings.autoDeleteDelay = pn_terminus_get_timeout(source); - if (settings.autoDeleteDelay) - settings.original["qpid.auto_delete_timeout"] = settings.autoDeleteDelay; - } - if (settings.autoDeleteDelay) { - settings.autodelete = true; - } - filter.configure(settings); - std::stringstream queueName; - if (shared) { - //just use link name (TODO: could allow this to be - //overridden when access to link properties is provided - //(PROTON-335)) - queueName << pn_link_name(link); - } else { - //combination of container id and link name is unique - queueName << connection.getContainerId() << "_" << pn_link_name(link); - } - boost::shared_ptr queue - = connection.getBroker().createQueue(queueName.str(), settings, this, altExchange, connection.getUserId(), connection.getId()).first; - if (!shared) queue->setExclusiveOwner(this); - authorise.outgoing(node.exchange, queue, filter); - filter.bind(node.exchange, queue); - boost::shared_ptr 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 out(new OutgoingFromRelay(link, connection.getBroker(), *this, name, target, pn_link_name(link), node.relay)); - outgoing[link] = out; - out->init(); - } else { - pn_terminus_set_type(pn_link_source(link), PN_UNSPECIFIED); - throw Exception(qpid::amqp::error_conditions::NOT_FOUND, std::string("Node not found: ") + name);/*not-found*/ - } - filter.write(pn_terminus_filter(pn_link_source(link))); - QPID_LOG(debug, "Outgoing link attached"); -} - -/** - * Called for links initiated by the broker - */ -void Session::attach(pn_link_t* link, const std::string& src, const std::string& tgt, boost::shared_ptr relay) -{ - pn_terminus_t* source = pn_link_source(link); - pn_terminus_t* target = pn_link_target(link); - pn_terminus_set_address(source, src.c_str()); - pn_terminus_set_address(target, tgt.c_str()); - - if (relay) { - if (pn_link_is_sender(link)) { - boost::shared_ptr out(new OutgoingFromRelay(link, connection.getBroker(), *this, src, tgt, pn_link_name(link), relay)); - outgoing[link] = out; - out->init(); - } else { - boost::shared_ptr in(new IncomingToRelay(link, connection.getBroker(), *this, src, tgt, pn_link_name(link), relay)); - incoming[link] = in; - } - } else { - if (pn_link_is_sender(link)) { - setupOutgoing(link, source, src); - } else { - setupIncoming(link, target, tgt); - } - } -} - -void Session::detach(pn_link_t* link, bool closed) -{ - if (pn_link_is_sender(link)) { - OutgoingLinks::iterator i = outgoing.find(link); - if (i != outgoing.end()) { - i->second->detached(closed); - boost::shared_ptr q = OutgoingFromQueue::getExclusiveSubscriptionQueue(i->second.get()); - if (q && !q->isAutoDelete() && !q->isDeleted()) { - connection.getBroker().deleteQueue(q->getName(), connection.getUserId(), connection.getMgmtId()); - } - outgoing.erase(i); - QPID_LOG(debug, "Outgoing link detached"); - } - } else { - IncomingLinks::iterator i = incoming.find(link); - if (i != incoming.end()) { - abort_pending(link); - i->second->detached(closed); - incoming.erase(i); - QPID_LOG(debug, "Incoming link detached"); - } - } -} - -void Session::pending_accept(pn_delivery_t* delivery) -{ - qpid::sys::Mutex::ScopedLock l(lock); - pending.insert(delivery); -} - -bool Session::clear_pending(pn_delivery_t* delivery) -{ - qpid::sys::Mutex::ScopedLock l(lock); - std::set::iterator i = pending.find(delivery); - if (i != pending.end()) { - pending.erase(i); - return true; - } else { - return false; - } -} - -void Session::abort_pending(pn_link_t* link) -{ - qpid::sys::Mutex::ScopedLock l(lock); - for (std::set::iterator i = pending.begin(); i != pending.end();) { - if (pn_delivery_link(*i) == link) { - pn_delivery_settle(*i); - pending.erase(i++); - } else { - ++i; - } - } -} - -void Session::accepted(pn_delivery_t* delivery, bool sync) -{ - if (sync) { - if (clear_pending(delivery)) - { - //this is on IO thread - pn_delivery_update(delivery, PN_ACCEPTED); - pn_delivery_settle(delivery);//do we need to check settlement modes/orders? - incomingMessageAccepted(); - } - } else { - //this is not on IO thread, need to delay processing until on IO thread - qpid::sys::Mutex::ScopedLock l(lock); - if (!deleted && pending.find(delivery) != pending.end()) { - completed.push_back(delivery); - out.activateOutput(); - } - } -} - -void Session::readable(pn_link_t* link, pn_delivery_t* delivery) -{ - pn_delivery_tag_t tag = pn_delivery_tag(delivery); -#ifdef NO_PROTON_DELIVERY_TAG_T - QPID_LOG(debug, "received delivery: " << std::string(tag.start, tag.size)); -#else - QPID_LOG(debug, "received delivery: " << std::string(tag.bytes, tag.size)); -#endif - incomingMessageReceived(); - IncomingLinks::iterator target = incoming.find(link); - if (target == incoming.end()) { - QPID_LOG(error, "Received message on unknown link"); - pn_delivery_update(delivery, PN_REJECTED); - pn_delivery_settle(delivery);//do we need to check settlement modes/orders? - incomingMessageRejected(); - } else { - target->second->readable(delivery); - if (target->second->haveWork()) out.activateOutput(); - } -} - -void Session::writable(pn_link_t* link, pn_delivery_t* delivery) -{ - OutgoingLinks::iterator sender = outgoing.find(link); - if (sender == outgoing.end()) { - QPID_LOG(error, "Delivery returned for unknown link " << pn_link_name(link)); - } else { - sender->second->handle(delivery); - } -} - -bool Session::dispatch() -{ - bool output(false); - if (tx.commitPending.boolCompareAndSwap(true, false)) { - committed(true); - } - for (OutgoingLinks::iterator s = outgoing.begin(); s != outgoing.end();) { - try { - if (s->second->doWork()) output = true; - ++s; - } catch (const Exception& e) { - pn_condition_t* error = pn_link_condition(s->first); - pn_condition_set_name(error, e.symbol()); - pn_condition_set_description(error, e.what()); - pn_link_close(s->first); - s->second->detached(true); - outgoing.erase(s++); - output = true; - } - } - if (completed.size()) { - output = true; - std::deque copy; - { - qpid::sys::Mutex::ScopedLock l(lock); - completed.swap(copy); - } - for (std::deque::iterator i = copy.begin(); i != copy.end(); ++i) { - accepted(*i, true); - } - } - for (IncomingLinks::iterator i = incoming.begin(); i != incoming.end();) { - try { - if (i->second->doWork()) output = true; - ++i; - } catch (const Exception& e) { - pn_condition_t* error = pn_link_condition(i->first); - pn_condition_set_name(error, e.symbol()); - pn_condition_set_description(error, e.what()); - pn_link_close(i->first); - i->second->detached(true); - incoming.erase(i++); - output = true; - } - } - - return output; -} - -void Session::close() -{ - for (OutgoingLinks::iterator i = outgoing.begin(); i != outgoing.end(); ++i) { - i->second->detached(false); - } - for (IncomingLinks::iterator i = incoming.begin(); i != incoming.end(); ++i) { - i->second->detached(false); - } - outgoing.clear(); - incoming.clear(); - QPID_LOG(debug, "Session " << session << " closed, all links detached."); - for (std::set< boost::shared_ptr >::const_iterator i = exclusiveQueues.begin(); i != exclusiveQueues.end(); ++i) { - (*i)->releaseExclusiveOwnership(); - } - exclusiveQueues.clear(); - qpid::sys::Mutex::ScopedLock l(lock); - deleted = true; -} - -void Session::wakeup() -{ - out.activateOutput(); -} - -Authorise& Session::getAuthorise() -{ - return authorise; -} - -bool Session::endedByManagement() const -{ - return detachRequested; -} - -void Session::detachedByManagement() -{ - detachRequested = true; - wakeup(); -} - -TxBuffer* Session::getTransaction(const std::string& id) -{ - return (tx.buffer.get() && id == tx.id) ? tx.buffer.get() : 0; -} - -TxBuffer* Session::getTransaction(pn_delivery_t* delivery) -{ - return getTransactionalState(delivery).first; -} - -std::pair Session::getTransactionalState(pn_delivery_t* delivery) -{ - std::pair result((TxBuffer*)0, 0); - if (pn_delivery_remote_state(delivery) == TRANSACTIONAL_STATE_CODE) { - pn_data_t* data = pn_disposition_data(pn_delivery_remote(delivery)); - pn_data_rewind(data); - size_t count = 0; - if (data && pn_data_next(data) && (count = pn_data_get_list(data)) > 0) { - pn_data_enter(data); - pn_data_next(data); - std::string id = convert(pn_data_get_binary(data)); - result.first = getTransaction(id); - if (!result.first) { - QPID_LOG(error, "Transaction not found for id: " << id); - } - if (count > 1 && pn_data_next(data)) { - pn_data_enter(data); - pn_data_next(data); - result.second = pn_data_get_ulong(data); - } - } - else - QPID_LOG(error, "Transactional delivery " << delivery << " appears to have no data"); - } - return result; -} - -std::string Session::declare() -{ - if (tx.buffer.get()) { - //not sure what the error code should be; none in spec really fit well. - throw Exception(qpid::amqp::error_conditions::transaction::ROLLBACK, - "Session only supports one transaction active at a time"); - } - tx.buffer = boost::intrusive_ptr(new TxBuffer()); - connection.getBroker().getBrokerObservers().startTx(tx.buffer); - txStarted(); - return tx.id; -} - -namespace { - class AsyncCommit : public qpid::broker::AsyncCompletion::Callback - { - public: - AsyncCommit(boost::shared_ptr s) : session(s) {} - void completed(bool sync) { session->committed(sync); } - boost::intrusive_ptr clone() - { - boost::intrusive_ptr copy(new AsyncCommit(session)); - return copy; - } - - private: - boost::shared_ptr session; - }; -} - -void Session::discharge(const std::string& id, bool failed, pn_delivery_t* delivery) -{ - QPID_LOG(debug, "Coordinator " << (failed ? " rollback" : " commit") - << " transaction " << id); - if (!tx.buffer.get() || id != tx.id) { - throw Exception(qpid::amqp::error_conditions::transaction::UNKNOWN_ID, - Msg() << "Cannot discharge transaction " << id - << (tx.buffer.get() ? Msg() << ", current transaction is " << tx.id : - Msg() << ", no current transaction")); - } - tx.discharge = delivery; - if (failed) { - abort(); - } else { - tx.buffer->begin(); - tx.buffer->startCommit(&connection.getBroker().getStore()); - AsyncCommit callback(shared_from_this()); - tx.buffer->end(callback); - } -} - -void Session::abort() -{ - if (tx.buffer) { - tx.dischargeComplete(); - tx.buffer->rollback(); - txAborted(); - tx.buffer = boost::intrusive_ptr(); - QPID_LOG(debug, "Transaction " << tx.id << " rolled back"); - } -} - -void Session::committed(bool sync) -{ - if (sync) { - //this is on IO thread - tx.dischargeComplete(); - if (tx.buffer.get()) { - tx.buffer->endCommit(&connection.getBroker().getStore()); - txCommitted(); - tx.buffer = boost::intrusive_ptr(); - QPID_LOG(debug, "Transaction " << tx.id << " comitted"); - } else { - throw Exception(qpid::amqp::error_conditions::transaction::ROLLBACK, "tranaction vanished during async commit"); - } - } else { - //this is not on IO thread, need to delay processing until on IO thread - if (tx.commitPending.boolCompareAndSwap(false, true)) { - qpid::sys::Mutex::ScopedLock l(lock); - if (!deleted) { - out.activateOutput(); - } - } - } -} - -void IncomingToQueue::handle(qpid::broker::Message& message, qpid::broker::TxBuffer* transaction) -{ - if (queue->isDeleted()) { - std::stringstream msg; - msg << " Queue " << queue->getName() << " has been deleted"; - throw Exception(qpid::amqp::error_conditions::RESOURCE_DELETED, msg.str()); - } - try { - queue->deliver(message, transaction); - } catch (const qpid::SessionException& e) { - throw Exception(qpid::amqp::error_conditions::PRECONDITION_FAILED, e.what()); - } -} - -void IncomingToExchange::handle(qpid::broker::Message& message, qpid::broker::TxBuffer* transaction) -{ - if (exchange->isDestroyed()) - throw qpid::framing::ResourceDeletedException(QPID_MSG("Exchange " << exchange->getName() << " has been deleted.")); - authorise.route(exchange, message); - DeliverableMessage deliverable(message, transaction); - exchange->route(deliverable); - if (!deliverable.delivered) { - if (exchange->getAlternate()) { - exchange->getAlternate()->route(deliverable); - } - } -} - -void AnonymousRelay::handle(qpid::broker::Message& message, qpid::broker::TxBuffer* transaction) -{ - // need to retrieve AMQP 1.0 'to' field and resolve it to a queue or exchange - std::string dest = message.getTo(); - authorise.access(dest, false, false); - QPID_LOG(debug, "AnonymousRelay received message for " << dest); - boost::shared_ptr exchange; - boost::shared_ptr queue; - boost::shared_ptr topic; - - queue = context.getBroker().getQueues().find(dest); - if (!queue) { - topic = context.getTopics().get(dest); - if (topic) { - exchange = topic->getExchange(); - } else { - exchange = context.getBroker().getExchanges().find(dest); - } - } - - try { - if (queue) { - authorise.incoming(queue); - queue->deliver(message, transaction); - } else if (exchange) { - authorise.route(exchange, message); - DeliverableMessage deliverable(message, transaction); - exchange->route(deliverable); - } else { - QPID_LOG(info, "AnonymousRelay dropping message for " << dest); - } - } catch (const qpid::SessionException& e) { - throw Exception(qpid::amqp::error_conditions::PRECONDITION_FAILED, e.what()); - } - -} - -void IncomingToCoordinator::deliver(boost::intrusive_ptr message, pn_delivery_t* delivery) -{ - if (message && message->isTypedBody()) { - QPID_LOG(debug, "Coordinator got message: @" << message->getBodyDescriptor() << " " << message->getTypedBody()); - if (message->getBodyDescriptor().match(DECLARE_SYMBOL, DECLARE_CODE)) { - std::string id = session.declare(); - //encode the txn id in a 'declared' list on the disposition - pn_data_t* data = pn_disposition_data(pn_delivery_local(delivery)); - pn_data_put_list(data); - pn_data_enter(data); - pn_data_put_binary(data, convert(id)); - pn_data_exit(data); - pn_data_exit(data); - pn_delivery_update(delivery, DECLARED_CODE); - pn_delivery_settle(delivery); - session.incomingMessageAccepted(); - QPID_LOG(debug, "Coordinator declared transaction " << id); - } else if (message->getBodyDescriptor().match(DISCHARGE_SYMBOL, DISCHARGE_CODE)) { - if (message->getTypedBody().getType() == qpid::types::VAR_LIST) { - qpid::types::Variant::List args = message->getTypedBody().asList(); - qpid::types::Variant::List::const_iterator i = args.begin(); - if (i != args.end()) { - std::string id = *i; - bool failed = ++i != args.end() ? i->asBool() : false; - session.pending_accept(delivery); - session.discharge(id, failed, delivery); - } - - } else { - throw framing::IllegalArgumentException( - Msg() << "Coordinator unknown message: @" << - message->getBodyDescriptor() << " " << message->getTypedBody()); - } - } - } -} - -Session::Transaction::Transaction(Session& s) : - session(s), id((boost::format("%1%") % &s).str()), discharge(0) {} - -// Called in IO thread to signal completion of dischage by settling discharge message. -void Session::Transaction::dischargeComplete() { - if (buffer.get() && discharge) { - session.accepted(discharge, false); // Queue up accept and activate output. - discharge = 0; - } -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Session.h b/qpid/cpp/src/qpid/broker/amqp/Session.h deleted file mode 100644 index e48d563f27..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Session.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef QPID_BROKER_AMQP1_SESSION_H -#define QPID_BROKER_AMQP1_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/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/broker/amqp/Authorise.h" -#include "qpid/broker/amqp/ManagedSession.h" -#include "qpid/broker/amqp/NodeProperties.h" -#include -#include -#include -#include -#include -#include - -struct pn_delivery_t; -struct pn_link_t; -struct pn_session_t; -struct pn_terminus_t; - -namespace qpid { -namespace broker { - -class Broker; -class Exchange; -class Queue; -class TxBuffer; - -namespace amqp { - -class Connection; -class Incoming; -class Outgoing; -class Relay; -class Topic; -/** - * - */ -class Session : public ManagedSession, public boost::enable_shared_from_this -{ - public: - Session(pn_session_t*, Connection&, qpid::sys::OutputControl&); - /** - * called for links initiated by the peer - */ - void attach(pn_link_t*); - void detach(pn_link_t*, bool closed); - void readable(pn_link_t*, pn_delivery_t*); - void writable(pn_link_t*, pn_delivery_t*); - bool dispatch(); - bool endedByManagement() const; - void close(); - - /** - * called for links initiated by the broker - */ - void attach(pn_link_t* link, const std::string& src, const std::string& tgt, boost::shared_ptr); - - //called when a transfer is completely processed (e.g.including stored on disk) - void accepted(pn_delivery_t*, bool sync); - //called to indicate that the delivery will be accepted asynchronously - void pending_accept(pn_delivery_t*); - //called when async transaction completes - void committed(bool sync); - - void wakeup(); - - Authorise& getAuthorise(); - - TxBuffer* getTransaction(const std::string&); - TxBuffer* getTransaction(pn_delivery_t*); - std::pair getTransactionalState(pn_delivery_t*); - //transaction coordination: - std::string declare(); - void discharge(const std::string& id, bool failed, pn_delivery_t*); - void abort(); - protected: - void detachedByManagement(); - private: - typedef std::map > OutgoingLinks; - typedef std::map > IncomingLinks; - pn_session_t* session; - Connection& connection; - qpid::sys::OutputControl& out; - IncomingLinks incoming; - OutgoingLinks outgoing; - std::deque completed; - std::set pending; - bool deleted; - qpid::sys::Mutex lock; - std::set< boost::shared_ptr > exclusiveQueues; - Authorise authorise; - bool detachRequested; - - struct Transaction { - Transaction(Session&); - void dischargeComplete(); - - Session& session; - boost::intrusive_ptr buffer; - std::string id; - qpid::sys::AtomicValue commitPending; - pn_delivery_t* discharge; - }; - Transaction tx; - - struct ResolvedNode - { - boost::shared_ptr exchange; - boost::shared_ptr queue; - boost::shared_ptr topic; - boost::shared_ptr relay; - NodeProperties properties; - bool created; - ResolvedNode(bool isDynamic) : properties(isDynamic), created(false) {} - bool trackControllingLink() const; - }; - - ResolvedNode resolve(const std::string name, pn_terminus_t* terminus, bool incoming); - void setupOutgoing(pn_link_t* link, pn_terminus_t* source, const std::string& name); - void setupIncoming(pn_link_t* link, pn_terminus_t* target, const std::string& name); - std::string generateName(pn_link_t*); - std::string qualifyName(const std::string&); - bool clear_pending(pn_delivery_t*);//tests and clears pending status for delivery - void abort_pending(pn_link_t*);//removes pending status for all deliveries associated with link -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP1_SESSION_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Topic.cpp b/qpid/cpp/src/qpid/broker/amqp/Topic.cpp deleted file mode 100644 index 93f4b83f08..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Topic.cpp +++ /dev/null @@ -1,209 +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/broker/amqp/Topic.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { -namespace amqp { -namespace { -const std::string TOPIC("topic"); -const std::string EXCHANGE("exchange"); -const std::string DURABLE("durable"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string EMPTY; - -std::string getProperty(const std::string& k, const qpid::types::Variant::Map& m) -{ - qpid::types::Variant::Map::const_iterator i = m.find(k); - if (i == m.end()) return EMPTY; - else return i->second; -} - -bool testProperty(const std::string& k, const qpid::types::Variant::Map& m) -{ - qpid::types::Variant::Map::const_iterator i = m.find(k); - if (i == m.end()) return false; - else return i->second; -} - -qpid::types::Variant::Map filter(const qpid::types::Variant::Map& properties, bool queue) -{ - qpid::types::Variant::Map filtered = properties; - filtered.erase(DURABLE); - filtered.erase(EXCHANGE); - if (queue) filtered.erase(ALTERNATE_EXCHANGE); - return filtered; -} -} - -Topic::Topic(Broker& broker, const std::string& n, boost::shared_ptr e, const qpid::types::Variant::Map& properties) - : PersistableObject(n, TOPIC, properties), name(n), durable(testProperty(DURABLE, properties)), exchange(e), - alternateExchange(getProperty(ALTERNATE_EXCHANGE, properties)) -{ - if (exchange->getName().empty()) throw qpid::Exception("Exchange must be specified."); - if (durable && !exchange->isDurable()) throw qpid::Exception("Durable topic must be backed by durable exchange"); - - qpid::types::Variant::Map unused; - qpid::types::Variant::Map filtered = filter(properties, true); - policy.populate(filtered, unused); - - 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(filter(properties, false)); - agent->addObject(topic); - } -} - -bool Topic::isDurable() const -{ - return durable; -} - -Topic::~Topic() -{ - if (topic != 0) topic->resourceDestroy(); -} - -boost::shared_ptr Topic::GetManagementObject() const -{ - return topic; -} - -const QueueSettings& Topic::getPolicy() const -{ - return policy; -} -boost::shared_ptr Topic::getExchange() -{ - return exchange; -} -const std::string& Topic::getName() const -{ - return name; -} -const std::string& Topic::getAlternateExchange() const -{ - return alternateExchange; -} -boost::shared_ptr TopicRegistry::createTopic(Broker& broker, const std::string& name, boost::shared_ptr exchange, const qpid::types::Variant::Map& properties) -{ - boost::shared_ptr topic(new Topic(broker, name, exchange, properties)); - add(topic); - topic->getExchange()->setDeletionListener(name, boost::bind(&TopicRegistry::remove, this, name)); - return topic; -} - -boost::shared_ptr TopicRegistry::declare(Broker& broker, const std::string& name, boost::shared_ptr exchange, const qpid::types::Variant::Map& properties) -{ - qpid::sys::Mutex::ScopedLock l(lock); - Topics::const_iterator i = topics.find(name); - if (i == topics.end()) { - boost::shared_ptr topic(new Topic(broker, name, exchange, properties)); - topics.insert(Topics::value_type(name, topic)); - topic->getExchange()->setDeletionListener(name, boost::bind(&TopicRegistry::remove, this, name)); - return topic; - } else { - return i->second; - } -} - -bool TopicRegistry::createObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& props, - const std::string& /*userId*/, const std::string& /*connectionId*/) -{ - if (type == TOPIC) { - boost::shared_ptr topic = createTopic(broker, name, broker.getExchanges().get(getProperty(EXCHANGE, props)), props); - if (topic->isDurable()) broker.getStore().create(*topic); - return true; - } else { - return false; - } -} - -bool TopicRegistry::deleteObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& /*properties*/, - const std::string& /*userId*/, const std::string& /*connectionId*/) -{ - if (type == TOPIC) { - boost::shared_ptr topic = remove(name); - if (topic) { - if (topic->isDurable()) broker.getStore().destroy(*topic); - return true; - } else { - return false; - } - } else { - return false; - } -} - -bool TopicRegistry::recoverObject(Broker& broker, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - uint64_t persistenceId) -{ - if (type == TOPIC) { - boost::shared_ptr topic = createTopic(broker, name, broker.getExchanges().get(getProperty(EXCHANGE, properties)), properties); - topic->setPersistenceId(persistenceId); - return true; - } else { - return false; - } -} - -bool TopicRegistry::add(boost::shared_ptr topic) -{ - qpid::sys::Mutex::ScopedLock l(lock); - Topics::const_iterator i = topics.find(topic->getName()); - if (i == topics.end()) { - topics.insert(Topics::value_type(topic->getName(), topic)); - return true; - } else { - throw qpid::types::Exception(QPID_MSG("A topic named " << topic->getName() << " already exists")); - } - -} -boost::shared_ptr TopicRegistry::remove(const std::string& name) -{ - boost::shared_ptr result; - qpid::sys::Mutex::ScopedLock l(lock); - Topics::iterator i = topics.find(name); - if (i != topics.end()) { - result = i->second; - topics.erase(i); - result->getExchange()->unsetDeletionListener(name); - } - return result; -} - -boost::shared_ptr TopicRegistry::get(const std::string& name) -{ - qpid::sys::Mutex::ScopedLock l(lock); - Topics::const_iterator i = topics.find(name); - if (i == topics.end()) { - return boost::shared_ptr(); - } else { - return i->second; - } -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Topic.h b/qpid/cpp/src/qpid/broker/amqp/Topic.h deleted file mode 100644 index 457b8cfced..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Topic.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef QPID_BROKER_AMQP_TOPIC_H -#define QPID_BROKER_AMQP_TOPIC_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/ObjectFactory.h" -#include "qpid/broker/PersistableObject.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/sys/Mutex.h" -#include "qpid/types/Variant.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Exchange.h" -#include "qmf/org/apache/qpid/broker/Topic.h" -#include - -namespace qpid { -namespace broker { -class Broker; -class Exchange; -class QueueDepth; - -namespace amqp { - -/** - * A topic is a node supporting a pub-sub style. It is at present - * implemented by an exchange with an additional policy for handling - * subscription queues. - */ -class Topic : public PersistableObject, public management::Manageable -{ - public: - Topic(Broker&, const std::string& name, boost::shared_ptr, const qpid::types::Variant::Map& properties); - ~Topic(); - const std::string& getName() const; - const QueueSettings& getPolicy() const; - const std::string& getAlternateExchange() const; - boost::shared_ptr getExchange(); - bool isDurable() const; - boost::shared_ptr GetManagementObject() const; - private: - std::string name; - bool durable; - boost::shared_ptr exchange; - QueueSettings policy; - std::string alternateExchange; - qmf::org::apache::qpid::broker::Topic::shared_ptr topic; -}; - -class TopicRegistry : public ObjectFactory -{ - public: - bool createObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId); - bool deleteObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - const std::string& userId, const std::string& connectionId); - bool recoverObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, - uint64_t persistenceId); - - bool add(boost::shared_ptr topic); - boost::shared_ptr remove(const std::string& name); - boost::shared_ptr get(const std::string& name); - boost::shared_ptr createTopic(Broker&, const std::string& name, boost::shared_ptr exchange, const qpid::types::Variant::Map& properties); - boost::shared_ptr declare(Broker&, const std::string& name, boost::shared_ptr exchange, const qpid::types::Variant::Map& properties); - private: - typedef std::map > Topics; - qpid::sys::Mutex lock; - Topics topics; - -}; - -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_TOPIC_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp/Translation.cpp b/qpid/cpp/src/qpid/broker/amqp/Translation.cpp deleted file mode 100644 index d4b3f555b2..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Translation.cpp +++ /dev/null @@ -1,343 +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/broker/amqp/Translation.h" -#include "qpid/broker/amqp/Outgoing.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/broker/Broker.h" -#include "qpid/amqp/Decoder.h" -#include "qpid/amqp/descriptors.h" -#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 - -namespace qpid { -namespace broker { -namespace amqp { -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) -{ - size_t i = address.find(FORWARD_SLASH); - if (i == std::string::npos) { - //is it a queue or an exchange? - if (broker && broker->getQueues().find(address)) { - return qpid::framing::ReplyTo(EMPTY, address); - } else if (broker && broker->getExchanges().find(address)) { - return qpid::framing::ReplyTo(address, EMPTY); - } else { - return qpid::framing::ReplyTo(); - } - } else { - return qpid::framing::ReplyTo(i > 0 ? address.substr(0, i) : EMPTY, (i+1) < address.size() ? address.substr(i+1) : EMPTY); - } -} -std::string translate(const qpid::framing::ReplyTo r) -{ - if (r.getExchange().size()) { - if (r.getRoutingKey().size()) return r.getExchange() + FORWARD_SLASH + r.getRoutingKey(); - else return r.getExchange(); - } else return r.getRoutingKey(); -} -std::string translate(const qpid::amqp::CharSequence& chars) -{ - if (chars.data && chars.size) return std::string(chars.data, chars.size); - else return EMPTY; -} -bool setMessageId(qpid::framing::MessageProperties& m, const qpid::amqp::CharSequence& chars) -{ - if (chars.data && chars.size) { - if (chars.size == 16) { - m.setMessageId(qpid::framing::Uuid(chars.data)); - return true; - } else { - std::istringstream in(translate(chars)); - qpid::framing::Uuid uuid; - in >> uuid; - if (!in.fail()) { - m.setMessageId(uuid); - return true; - } - } - } - return false; -} -class Properties_0_10 : public qpid::amqp::MessageEncoder::Properties -{ - public: - bool hasMessageId() const { return messageProperties && messageProperties->hasMessageId(); } - std::string getMessageId() const { return messageProperties ? messageProperties->getMessageId().str() : EMPTY; } - bool hasUserId() const { return messageProperties && messageProperties->hasUserId(); } - 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 - { - 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(); } - std::string getCorrelationId() const { return messageProperties ? messageProperties->getCorrelationId() : EMPTY; } - bool hasContentType() const { return messageProperties && messageProperties->hasContentType(); } - std::string getContentType() const { return messageProperties ? messageProperties->getContentType() : EMPTY; } - bool hasContentEncoding() const { return messageProperties && messageProperties->hasContentEncoding(); } - std::string getContentEncoding() const { return messageProperties ? messageProperties->getContentEncoding() : EMPTY; } - bool hasAbsoluteExpiryTime() const { return deliveryProperties && deliveryProperties->hasExpiration(); } - int64_t getAbsoluteExpiryTime() const { return deliveryProperties ? deliveryProperties->getExpiration() : 0; } - bool hasCreationTime() const { return false; } - int64_t getCreationTime() const { return 0; } - bool hasGroupId() const {return false; } - std::string getGroupId() const { return EMPTY; } - bool hasGroupSequence() const { return false; } - uint32_t getGroupSequence() const { return 0; } - bool hasReplyToGroupId() const { return false; } - std::string getReplyToGroupId() const { return EMPTY; } - - 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()), - deliveryProperties(transfer.getProperties()) - {} - private: - const qpid::broker::amqp_0_10::MessageTransfer& transfer; - const qpid::framing::MessageProperties* messageProperties; - const qpid::framing::DeliveryProperties* deliveryProperties; - - std::string getDestination() const - { - return transfer.getMethod()->getDestination(); - } -}; -} - -Translation::Translation(const qpid::broker::Message& m, Broker* b) : original(m), broker(b) {} - -boost::intrusive_ptr Translation::getTransfer() -{ - boost::intrusive_ptr t = - boost::intrusive_ptr(dynamic_cast(&original.getEncoding())); - if (t) { - return t;//no translation required - } else { - const Message* message = dynamic_cast(&original.getEncoding()); - if (message) { - //translate 1.0 message into 0-10 - boost::intrusive_ptr transfer(new qpid::broker::amqp_0_10::MessageTransfer()); - qpid::framing::AMQFrame method((qpid::framing::MessageTransferBody(qpid::framing::ProtocolVersion(), EMPTY, 0, 0))); - qpid::framing::AMQFrame header((qpid::framing::AMQHeaderBody())); - qpid::framing::AMQFrame content((qpid::framing::AMQContentBody())); - method.setEof(false); - header.setBof(false); - header.setEof(false); - content.setBof(false); - - transfer->getFrames().append(method); - transfer->getFrames().append(header); - - qpid::framing::MessageProperties* props = - transfer->getFrames().getHeaders()->get(true); - - if (message->isTypedBody()) { - qpid::types::Variant body = message->getTypedBody(); - std::string& data = content.castBody()->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()->getData().assign(body.data, body.size); - transfer->getFrames().append(content); - - props->setContentLength(body.size); - } - - qpid::amqp::MessageId mid = message->getMessageId(); - qpid::framing::Uuid uuid; - switch (mid.type) { - case qpid::amqp::MessageId::NONE: - break; - case qpid::amqp::MessageId::UUID: - case qpid::amqp::MessageId::BYTES: - if (mid.value.bytes.size == 0) break; - if (setMessageId(*props, mid.value.bytes)) break; - case qpid::amqp::MessageId::ULONG: - QPID_LOG(info, "Skipping message id in translation from 1.0 to 0-10 as it is not a UUID"); - break; - } - - qpid::amqp::MessageId cid = message->getCorrelationId(); - switch (cid.type) { - case qpid::amqp::MessageId::NONE: - break; - case qpid::amqp::MessageId::UUID: - assert(cid.value.bytes.size = 16); - props->setCorrelationId(qpid::framing::Uuid(cid.value.bytes.data).str()); - break; - case qpid::amqp::MessageId::BYTES: - if (cid.value.bytes.size) { - props->setCorrelationId(translate(cid.value.bytes)); - } - break; - case qpid::amqp::MessageId::ULONG: - props->setCorrelationId(boost::lexical_cast(cid.value.ulong)); - break; - } - if (message->getReplyToAsCharSequence()) props->setReplyTo(translate(message->getReplyTo(), broker)); - if (message->getContentType()) props->setContentType(translate(message->getContentType())); - if (message->getContentEncoding()) props->setContentEncoding(translate(message->getContentEncoding())); - props->setUserId(message->getUserId()); - // TODO: FieldTable applicationHeaders; - qpid::amqp::CharSequence ap = message->getApplicationProperties(); - 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(true); - dp->setPriority(message->getPriority()); - if (message->isPersistent()) dp->setDeliveryMode(2); - if (message->getRoutingKey().size()) { - if (message->getRoutingKey().size() > std::numeric_limits::max()) { - //have to truncate routing key as it is specified to be a str8 - dp->setRoutingKey(message->getRoutingKey().substr(0,std::numeric_limits::max())); - } else { - dp->setRoutingKey(message->getRoutingKey()); - } - props->getApplicationHeaders().setString(SUBJECT_KEY, message->getRoutingKey()); - } - - return transfer.get(); - } else { - throw qpid::Exception("Could not write message data in AMQP 0-10 format"); - } - } -} - -void Translation::write(OutgoingFromQueue& out) -{ - const Message* message = dynamic_cast(original.getPersistentContext().get()); - //persistent context will contain any newly added annotations - if (!message) message = dynamic_cast(&original.getEncoding()); - if (message) { - //write annotations - qpid::amqp::CharSequence deliveryAnnotations = message->getDeliveryAnnotations(); - qpid::amqp::CharSequence messageAnnotations = message->getMessageAnnotations(); - if (deliveryAnnotations.size) out.write(deliveryAnnotations.data, deliveryAnnotations.size); - if (messageAnnotations.size) out.write(messageAnnotations.data, messageAnnotations.size); - //write bare message - qpid::amqp::CharSequence bareMessage = message->getBareMessage(); - if (bareMessage.size) out.write(bareMessage.data, bareMessage.size); - //write footer: - qpid::amqp::CharSequence footer = message->getFooter(); - if (footer.size) out.write(footer.data, footer.size); - } else { - const qpid::broker::amqp_0_10::MessageTransfer* transfer = dynamic_cast(&original.getEncoding()); - if (transfer) { - Properties_0_10 properties(*transfer); - qpid::types::Variant::Map applicationProperties; - qpid::amqp_0_10::translate(properties.getApplicationProperties(), applicationProperties); - 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 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 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 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"); - } - } -} - -}}} // namespace qpid::broker::amqp diff --git a/qpid/cpp/src/qpid/broker/amqp/Translation.h b/qpid/cpp/src/qpid/broker/amqp/Translation.h deleted file mode 100644 index 47cb69d0ba..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp/Translation.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_BROKER_AMQP_TRANSLATION_H -#define QPID_BROKER_AMQP_TRANSLATION_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 - -namespace qpid { -namespace broker { -class Broker; -class Message; -namespace amqp_0_10 { -class MessageTransfer; -} -namespace amqp { - -class OutgoingFromQueue; -/** - * - */ -class Translation -{ - public: - Translation(const qpid::broker::Message& message, Broker* broker = 0); - - /** - * @returns a pointer to an AMQP 0-10 message transfer suitable - * for sending on an 0-10 session, translating from 1.0 as - * necessary - */ - boost::intrusive_ptr getTransfer(); - /** - * Writes the AMQP 1.0 bare message and any annotations, translating from 0-10 if necessary - */ - void write(OutgoingFromQueue&); - private: - const qpid::broker::Message& original; - Broker* broker; -}; -}}} // namespace qpid::broker::amqp - -#endif /*!QPID_BROKER_AMQP_TRANSLATION_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp b/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp deleted file mode 100644 index 4682c1f917..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp +++ /dev/null @@ -1,549 +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/broker/amqp_0_10/Connection.h" - -#include "qpid/broker/ConnectionObserver.h" -#include "qpid/broker/SessionOutputException.h" -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/Timer.h" - -#include "qpid/log/Statement.h" -#include "qpid/ptr_map.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qmf/org/apache/qpid/broker/EventClientConnect.h" -#include "qmf/org/apache/qpid/broker/EventClientDisconnect.h" - -#include -#include - -#include -#include -#include - -using std::string; - -using namespace qpid::sys; -using namespace qpid::framing; -using qpid::ptr_map_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { -namespace amqp_0_10 { - -struct ConnectionTimeoutTask : public sys::TimerTask { - sys::Timer& timer; - Connection& connection; - - ConnectionTimeoutTask(uint16_t hb, sys::Timer& t, Connection& c) : - TimerTask(Duration(hb*2*TIME_SEC),"ConnectionTimeout"), - timer(t), - connection(c) - {} - - void touch() { - restart(); - } - - void fire() { - // If we get here then we've not received any traffic in the timeout period - // Schedule closing the connection for the io thread - QPID_LOG(error, "Connection " << connection.getMgmtId() - << " timed out: closing"); - connection.abort(); - } -}; -/** - * A ConnectionOutputHandler that delegates to another - * ConnectionOutputHandler. Allows you to inspect outputting frames - */ -class FrameInspector : public sys::ConnectionOutputHandler -{ -public: - FrameInspector(ConnectionOutputHandler* p, framing::FrameHandler* i) : - next(p), - intercepter(i) - { - assert(next); - assert(intercepter); - } - - void close() { next->close(); } - void abort() { next->abort(); } - void connectionEstablished() { next->connectionEstablished(); } - void activateOutput() { next->activateOutput(); } - void handle(framing::AMQFrame& f) { intercepter->handle(f); next->handle(f); } - -private: - ConnectionOutputHandler* next; - framing::FrameHandler* intercepter; -}; - -/** - * Chained ConnectionOutputHandler that allows outgoing frames to be - * tracked (for updating mgmt stats). - */ -class OutboundFrameTracker : public framing::FrameHandler -{ -public: - OutboundFrameTracker(Connection& _con) : con(_con) {} - void handle(framing::AMQFrame& f) - { - con.sent(f); - } -private: - Connection& con; -}; - -Connection::Connection(ConnectionOutputHandler* out_, - Broker& broker_, const - std::string& mgmtId_, - const qpid::sys::SecuritySettings& external, - bool link_, - uint64_t objectId_ -) : - outboundTracker(new OutboundFrameTracker(*this)), - out(new FrameInspector(out_, outboundTracker.get())), - broker(broker_), - framemax(65535), - heartbeat(0), - heartbeatmax(120), - isDefaultRealm(false), - securitySettings(external), - link(link_), - adapter(*this, link), - mgmtClosing(false), - mgmtId(mgmtId_), - links(broker_.getLinks()), - agent(0), - timer(broker_.getTimer()), - objectId(objectId_) -{ - broker.getConnectionObservers().connection(*this); - assert(agent == 0); - assert(mgmtObject == 0); - Manageable* parent = broker.GetVhostObject(); - if (parent != 0) { - agent = broker.getManagementAgent(); - if (agent != 0) { - // TODO set last bool true if system connection - mgmtObject = _qmf::Connection::shared_ptr(new _qmf::Connection(agent, this, parent, mgmtId, !link, false, "AMQP 0-10")); - agent->addObject(mgmtObject, objectId); - } - } -} - -void Connection::requestIOProcessing(boost::function0 callback) -{ - ScopedLock l(ioCallbackLock); - ioCallbacks.push(callback); - if (isOpen()) out->activateOutput(); -} - -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() - << " rhost:" << mgmtId ); - mgmtObject->resourceDestroy(); - } - broker.getConnectionObservers().closed(*this); - - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - if (linkHeartbeatTimer) { - linkHeartbeatTimer->cancel(); - } -} - -void Connection::received(framing::AMQFrame& frame) { - // Received frame on connection so delay timeout - restartTimeout(); - bool wasOpen = isOpen(); - adapter.handle(frame); - if (link) //i.e. we are acting as the client to another broker - recordFromServer(frame); - else - recordFromClient(frame); - if (!wasOpen && isOpen()) { - doIoCallbacks(); // Do any callbacks registered before we opened. - broker.getConnectionObservers().opened(*this); - } -} - -void Connection::sent(const framing::AMQFrame& frame) -{ - if (link) //i.e. we are acting as the client to another broker - recordFromClient(frame); - else - recordFromServer(frame); -} - -bool isMessage(const AMQMethodBody* method) -{ - return method && method->isA(); -} - -void Connection::recordFromServer(const framing::AMQFrame& frame) -{ - if (mgmtObject != 0) - { - qmf::org::apache::qpid::broker::Connection::PerThreadStats *cStats = mgmtObject->getStatistics(); - cStats->framesToClient += 1; - cStats->bytesToClient += frame.encodedSize(); - if (isMessage(frame.getMethod())) { - cStats->msgsToClient += 1; - } - mgmtObject->statisticsUpdated(); - } -} - -void Connection::recordFromClient(const framing::AMQFrame& frame) -{ - if (mgmtObject != 0) - { - qmf::org::apache::qpid::broker::Connection::PerThreadStats *cStats = mgmtObject->getStatistics(); - cStats->framesFromClient += 1; - cStats->bytesFromClient += frame.encodedSize(); - if (isMessage(frame.getMethod())) { - cStats->msgsFromClient += 1; - } - mgmtObject->statisticsUpdated(); - } -} - -string Connection::getAuthMechanism() -{ - if (!link) - return string("ANONYMOUS"); - - return links.getAuthMechanism(mgmtId); -} - -string Connection::getUsername ( ) -{ - if (!link) - return string("anonymous"); - - return links.getUsername(mgmtId); -} - -string Connection::getPassword ( ) -{ - if (!link) - return string(""); - - return links.getPassword(mgmtId); -} - -string Connection::getHost ( ) -{ - if (!link) - return string(""); - - return links.getHost(mgmtId); -} - -uint16_t Connection::getPort ( ) -{ - if (!link) - return 0; - - return links.getPort(mgmtId); -} - -string Connection::getAuthCredentials() -{ - if (!link) - return string(); - - if (mgmtObject != 0) - { - if (links.getAuthMechanism(mgmtId) == "ANONYMOUS") - mgmtObject->set_authIdentity("anonymous"); - else - mgmtObject->set_authIdentity(links.getAuthIdentity(mgmtId)); - } - - return links.getAuthCredentials(mgmtId); -} - -void Connection::notifyConnectionForced(const string& text) -{ - broker.getConnectionObservers().forced(*this, text); -} - -void Connection::setUserId(const string& uid) -{ - userId = uid; - size_t at = userId.find('@'); - userName = userId.substr(0, at); - isDefaultRealm = ( - at!= std::string::npos && - getBroker().getRealm() == userId.substr(at+1,userId.size())); - raiseConnectEvent(); -} - -void Connection::raiseConnectEvent() { - if (mgmtObject != 0) { - mgmtObject->set_authIdentity(userId); - agent->raiseEvent(_qmf::EventClientConnect(mgmtId, userId, mgmtObject->get_remoteProperties())); - } - - QPID_LOG_CAT(debug, model, "Create connection. user:" << userId - << " rhost:" << mgmtId ); -} - -void Connection::close(connection::CloseCode code, const string& text) -{ - QPID_LOG_IF(error, code != connection::CLOSE_CODE_NORMAL, "Connection " << mgmtId << " closed by error: " << text << "(" << code << ")"); - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - if (linkHeartbeatTimer) { - linkHeartbeatTimer->cancel(); - } - adapter.close(code, text); - //make sure we delete dangling pointers from outputTasks before deleting sessions - outputTasks.removeAll(); - channels.clear(); - out->close(); -} - -void Connection::activateOutput() -{ - out->activateOutput(); -} - -void Connection::addOutputTask(OutputTask* t) -{ - outputTasks.addOutputTask(t); -} - -void Connection::removeOutputTask(OutputTask* t) -{ - outputTasks.removeOutputTask(t); -} - -void Connection::closed(){ // Physically closed, suspend open sessions. - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - if (linkHeartbeatTimer) { - linkHeartbeatTimer->cancel(); - } - try { - while (!channels.empty()) - ptr_map_ptr(channels.begin())->handleDetach(); - } catch(std::exception& e) { - QPID_LOG(error, QPID_MSG("While closing connection: " << e.what())); - assert(0); - } -} - -void Connection::doIoCallbacks() { - if (!isOpen()) return; // Don't process IO callbacks until we are open. - ScopedLock l(ioCallbackLock); - while (!ioCallbacks.empty()) { - boost::function0 cb = ioCallbacks.front(); - ioCallbacks.pop(); - ScopedUnlock ul(ioCallbackLock); - cb(); // Lend the IO thread for management processing - } -} - -bool Connection::doOutput() { - try { - doIoCallbacks(); - if (mgmtClosing) { - closed(); - close(connection::CLOSE_CODE_CONNECTION_FORCED, "Closed by Management Request"); - } else { - //then do other output as needed: - return outputTasks.doOutput(); - } - }catch(const SessionOutputException& e){ - getChannel(e.channel).handleException(e); - return true; - }catch(ConnectionException& e){ - close(e.code, e.getMessage()); - }catch(std::exception& e){ - close(connection::CLOSE_CODE_CONNECTION_FORCED, e.what()); - } - return false; -} - -void Connection::sendHeartbeat() { - requestIOProcessing(boost::bind(&ConnectionHandler::heartbeat, &adapter)); -} - -void Connection::closeChannel(uint16_t id) { - ChannelMap::iterator i = channels.find(id); - if (i != channels.end()) channels.erase(i); -} - -SessionHandler& Connection::getChannel(ChannelId id) { - ChannelMap::iterator i=channels.find(id); - if (i == channels.end()) { - i = channels.insert(id, new SessionHandler(*this, id)).first; - } - return *ptr_map_ptr(i); -} - -ManagementObject::shared_ptr Connection::GetManagementObject(void) const -{ - return mgmtObject; -} - -Manageable::status_t Connection::ManagementMethod(uint32_t methodId, Args&, string&) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - QPID_LOG(debug, "Connection::ManagementMethod [id=" << methodId << "]"); - - switch (methodId) - { - case _qmf::Connection::METHOD_CLOSE : - mgmtClosing = true; - if (mgmtObject != 0) mgmtObject->set_closing(1); - out->activateOutput(); - status = Manageable::STATUS_OK; - break; - } - - return status; -} - -void Connection::setSecureConnection(SecureConnection* s) -{ - adapter.setSecureConnection(s); -} - -struct ConnectionHeartbeatTask : public sys::TimerTask { - sys::Timer& timer; - Connection& connection; - ConnectionHeartbeatTask(uint16_t hb, sys::Timer& t, Connection& c) : - TimerTask(Duration(hb*TIME_SEC), "ConnectionHeartbeat"), - timer(t), - connection(c) - {} - - void fire() { - // Setup next firing - setupNextFire(); - timer.add(this); - - // Send Heartbeat - connection.sendHeartbeat(); - } -}; - -class LinkHeartbeatTask : public qpid::sys::TimerTask { - sys::Timer& timer; - Connection& connection; - bool heartbeatSeen; - - void fire() { - if (!heartbeatSeen) { - QPID_LOG(error, "Federation link connection " << connection.getMgmtId() << " missed 2 heartbeats - closing connection"); - connection.abort(); - } else { - heartbeatSeen = false; - // Setup next firing - setupNextFire(); - timer.add(this); - } - } - -public: - LinkHeartbeatTask(sys::Timer& t, qpid::sys::Duration period, Connection& c) : - TimerTask(period, "LinkHeartbeatTask"), timer(t), connection(c), heartbeatSeen(false) {} - - void heartbeatReceived() { heartbeatSeen = true; } -}; - - -void Connection::abort() -{ - // Make sure that we don't try to send a heartbeat as we're - // aborting the connection - if (heartbeatTimer) - heartbeatTimer->cancel(); - - out->abort(); -} - -void Connection::setHeartbeatInterval(uint16_t heartbeat) -{ - setHeartbeat(heartbeat); - if (heartbeat > 0) { - if (!heartbeatTimer) { - heartbeatTimer = new ConnectionHeartbeatTask(heartbeat, timer, *this); - timer.add(heartbeatTimer); - } - if (!timeoutTimer) { - timeoutTimer = new ConnectionTimeoutTask(heartbeat, timer, *this); - timer.add(timeoutTimer); - } - } - out->connectionEstablished(); -} - -void Connection::startLinkHeartbeatTimeoutTask() { - if (!linkHeartbeatTimer && heartbeat > 0) { - linkHeartbeatTimer = new LinkHeartbeatTask(timer, 2 * heartbeat * TIME_SEC, *this); - timer.add(linkHeartbeatTimer); - } - out->connectionEstablished(); -} - -void Connection::restartTimeout() -{ - if (timeoutTimer) - timeoutTimer->touch(); - - if (linkHeartbeatTimer) { - static_cast(linkHeartbeatTimer.get())->heartbeatReceived(); - } -} - -bool Connection::isOpen() { return adapter.isOpen(); } - -}}} diff --git a/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.h b/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.h deleted file mode 100644 index 8fff5206ea..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.h +++ /dev/null @@ -1,250 +0,0 @@ -#ifndef QPID_BROKER_AMQP_0_10_CONNECTION_H -#define QPID_BROKER_AMQP_0_10_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 -#include -#include -#include - -#include "qpid/broker/BrokerImportExport.h" - -#include "qpid/broker/ConnectionHandler.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/management/Manageable.h" -#include "qpid/sys/AggregateOutput.h" -#include "qpid/sys/ConnectionInputHandler.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/Mutex.h" -#include "qpid/types/Variant.h" -#include "qpid/RefCounted.h" -#include "qpid/Url.h" -#include "qpid/ptr_map.h" - -#include "qmf/org/apache/qpid/broker/Connection.h" - -#include -#include - -#include - -namespace qpid { -namespace sys { -class ConnectionOutputHandler; -class Timer; -class TimerTask; -} -namespace broker { - -class Broker; -class LinkRegistry; -class Queue; -class SecureConnection; -class SessionHandler; - -namespace amqp_0_10 { -struct ConnectionTimeoutTask; - -class Connection : public sys::ConnectionInputHandler, public qpid::broker::Connection, - public management::Manageable, - public RefCounted -{ - public: - uint32_t getFrameMax() const { return framemax; } - uint16_t getHeartbeat() const { return heartbeat; } - uint16_t getHeartbeatMax() const { return heartbeatmax; } - - void setFrameMax(uint32_t fm) { framemax = std::max(fm, (uint32_t) 4096); } - void setHeartbeat(uint16_t hb) { heartbeat = hb; } - void setHeartbeatMax(uint16_t hbm) { heartbeatmax = hbm; } - - - const management::ObjectId getObjectId() const { return GetManagementObject()->getObjectId(); }; - const std::string& getUserId() const { return userId; } - - bool isFederationLink() const { return federationPeerTag.size() > 0; } - void setFederationPeerTag(const std::string& tag) { federationPeerTag = std::string(tag); } - const std::string& getFederationPeerTag() const { return federationPeerTag; } - std::vector& getKnownHosts() { return knownHosts; } - - /**@return true if user is the authenticated user on this connection. - * If id has the default realm will also compare plain username. - */ - bool isAuthenticatedUser(const std::string& id) const { - return (id == userId || (isDefaultRealm && id == userName)); - } - - Broker& getBroker() { return broker; } - - sys::ConnectionOutputHandler& getOutput() { return *out; } - void activateOutput(); - void addOutputTask(OutputTask*); - void removeOutputTask(OutputTask*); - framing::ProtocolVersion getVersion() const { return version; } - - Connection(sys::ConnectionOutputHandler* out, - Broker& broker, - const std::string& mgmtId, - const qpid::sys::SecuritySettings&, - bool isLink = false, - uint64_t objectId = 0); - - ~Connection (); - - /** Get the SessionHandler for channel. Create if it does not already exist */ - SessionHandler& getChannel(framing::ChannelId channel); - - /** Close the connection. Waits for the client to respond with close-ok - * before actually destroying the connection. - */ - QPID_BROKER_EXTERN void close( - framing::connection::CloseCode code, const std::string& text); - - /** Abort the connection. Close abruptly and immediately. */ - QPID_BROKER_EXTERN void abort(); - - // ConnectionInputHandler methods - void received(framing::AMQFrame& frame); - bool doOutput(); - void closed(); - - void closeChannel(framing::ChannelId channel); - - // Manageable entry points - management::ManagementObject::shared_ptr GetManagementObject(void) const; - management::Manageable::status_t - ManagementMethod (uint32_t methodId, management::Args& args, std::string&); - - void requestIOProcessing (boost::function0); - void recordFromServer (const framing::AMQFrame& frame); - void recordFromClient (const framing::AMQFrame& frame); - - // gets for configured federation links - std::string getAuthMechanism(); - std::string getAuthCredentials(); - std::string getUsername(); - std::string getPassword(); - std::string getHost(); - uint16_t getPort(); - - void notifyConnectionForced(const std::string& text); - void setUserId(const std::string& uid); - - // credentials for connected client - const std::string& getMgmtId() const { return mgmtId; } - management::ManagementAgent* getAgent() const { return agent; } - - void setHeartbeatInterval(uint16_t heartbeat); - void sendHeartbeat(); - void restartTimeout(); - - void setSecureConnection(SecureConnection* secured); - - const qpid::sys::SecuritySettings& getExternalSecuritySettings() const - { - return securitySettings; - } - - /** @return true if the initial connection negotiation is complete. */ - bool isOpen(); - - bool isLink() const { return link; } - void startLinkHeartbeatTimeoutTask(); - - void setClientProperties(const types::Variant::Map& cp) { clientProperties = cp; } - const types::Variant::Map& getClientProperties() const { return clientProperties; } - - private: - // Management object is used in the constructor so must be early - qmf::org::apache::qpid::broker::Connection::shared_ptr mgmtObject; - - //contained output tasks - sys::AggregateOutput outputTasks; - - boost::scoped_ptr outboundTracker; - boost::scoped_ptr out; - - Broker& broker; - - framing::ProtocolVersion version; - uint32_t framemax; - uint16_t heartbeat; - uint16_t heartbeatmax; - std::string userId; - std::string federationPeerTag; - std::vector knownHosts; - std::string userName; - bool isDefaultRealm; - - typedef boost::ptr_map ChannelMap; - - ChannelMap channels; - qpid::sys::SecuritySettings securitySettings; - const bool link; - ConnectionHandler adapter; - bool mgmtClosing; - const std::string mgmtId; - sys::Mutex ioCallbackLock; - std::queue > ioCallbacks; - LinkRegistry& links; - management::ManagementAgent* agent; - sys::Timer& timer; - boost::intrusive_ptr heartbeatTimer, linkHeartbeatTimer; - boost::intrusive_ptr timeoutTimer; - uint64_t objectId; - types::Variant::Map clientProperties; - - void raiseConnectEvent(); - -friend class OutboundFrameTracker; - - void sent(const framing::AMQFrame& f); - void doIoCallbacks(); - - public: - - qmf::org::apache::qpid::broker::Connection::shared_ptr getMgmtObject() { return mgmtObject; } -}; -} - -// See weakCallback below. -template void callIfValid(boost::function1 f, boost::weak_ptr wp) { - boost::shared_ptr sp = wp.lock(); - if (sp) f(sp.get()); -} - -// Memory safety helper for requestIOProcessing with boost::shared_ptr. -// -// Makes a function that calls f(p) only if p is still valid. The returned -// function is bound to a weak_ptr, and only calls f(p) if the weak pointer is -// still valid. Note this does not prevent the object being deleted before the -// IO callback, instead it skips the callback if the object is already deleted. -template -boost::function0 weakCallback(boost::function1 f, T* p) { - return boost::bind(&callIfValid, f, p->shared_from_this()); -} - -}} - -#endif /*!QPID_BROKER_AMQP_0_10_CONNECTION_H*/ diff --git a/qpid/cpp/src/qpid/broker/amqp_0_10/MessageTransfer.cpp b/qpid/cpp/src/qpid/broker/amqp_0_10/MessageTransfer.cpp deleted file mode 100644 index 7b64226bdf..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp_0_10/MessageTransfer.cpp +++ /dev/null @@ -1,477 +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 "MessageTransfer.h" - -#include "qpid/amqp/CharSequence.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/amqp/MapHandler.h" -#include "qpid/amqp/MessageId.h" -#include "qpid/broker/Message.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/frame_functors.h" -#include "qpid/framing/TypeFilter.h" -#include "qpid/framing/SendContent.h" -#include "qpid/log/Statement.h" -#include "boost/lexical_cast.hpp" - -using namespace qpid::framing; - -namespace qpid { -namespace broker { -namespace amqp_0_10 { -namespace { -const std::string DELIMITER("/"); -const std::string EMPTY; -const std::string QMF2("qmf2"); -const std::string PARTIAL("partial"); -const std::string SUBJECT_KEY("qpid.subject"); -} -MessageTransfer::MessageTransfer() : frames(framing::SequenceNumber()), requiredCredit(0), cachedRequiredCredit(false) {} -MessageTransfer::MessageTransfer(const framing::SequenceNumber& id) : frames(id), requiredCredit(0), cachedRequiredCredit(false) {} - -uint64_t MessageTransfer::getContentSize() const -{ - return frames.getContentSize(); -} - -uint64_t MessageTransfer::getMessageSize() const -{ - return getRequiredCredit(); -} - -std::string MessageTransfer::getAnnotationAsString(const std::string& key) const -{ - const qpid::framing::MessageProperties* mp = getProperties(); - if (mp && mp->hasApplicationHeaders()) { - FieldTable::ValuePtr value = mp->getApplicationHeaders().get(key); - if (value) { - if (value->convertsTo()) return value->get(); - else if (value->convertsTo()) return boost::lexical_cast(value->get()); - } - return std::string(); - } else { - return std::string(); - } -} -std::string MessageTransfer::getPropertyAsString(const std::string& key) const { return getAnnotationAsString(key); } - -amqp::MessageId MessageTransfer::getMessageId() const -{ - const qpid::framing::MessageProperties* mp = getProperties(); - - amqp::MessageId r; - if (mp->hasMessageId()) { - r.set(amqp::CharSequence::create(mp->getMessageId().data(),16), types::VAR_UUID); - } - return r; -} - -amqp::MessageId MessageTransfer::getCorrelationId() const -{ - const qpid::framing::MessageProperties* mp = getProperties(); - - amqp::MessageId r; - if (mp->hasCorrelationId()) { - r.set(amqp::CharSequence::create(mp->getCorrelationId()), types::VAR_STRING); - } - return r; -} - -bool MessageTransfer::getTtl(uint64_t& result) const -{ - const qpid::framing::DeliveryProperties* dp = getProperties(); - if (dp && dp->hasTtl()) { - result = dp->getTtl(); - return true; - } else { - return false; - } -} -bool MessageTransfer::hasExpiration() const -{ - const qpid::framing::DeliveryProperties* dp = getProperties(); - if (dp && dp->hasExpiration()) { - return true; - } else { - return false; - } -} - -uint8_t MessageTransfer::getPriority() const -{ - const qpid::framing::DeliveryProperties* dp = getProperties(); - if (dp && dp->hasPriority()) { - return dp->getPriority(); - } else { - return 0; - } -} - -std::string MessageTransfer::getExchangeName() const -{ - return getFrames().as()->getDestination(); -} - -void MessageTransfer::setTimestamp() -{ - DeliveryProperties* props = getFrames().getHeaders()->get(true); - time_t now = ::time(0); - props->setTimestamp(now); -} - -uint64_t MessageTransfer::getTimestamp() const -{ - const DeliveryProperties* props = getProperties(); - return props ? props->getTimestamp() : 0; -} - -std::string MessageTransfer::getTo() const -{ - const DeliveryProperties* props = getProperties(); - if (props) { - //if message was sent to 'nameless exchange' then the routing key is the queue - return props->getExchange().empty() ? props->getRoutingKey() : props->getExchange(); - } else { - return EMPTY; - } -} -std::string MessageTransfer::getSubject() const -{ - const DeliveryProperties* props = getProperties(); - if (props) { - //if message was sent to 'nameless exchange' then the routing key is the queue name, not the subject - return props->getExchange().empty() ? getPropertyAsString(SUBJECT_KEY) : props->getRoutingKey(); - } else { - return EMPTY; - } -} -std::string MessageTransfer::getReplyTo() const -{ - const MessageProperties* props = getProperties(); - if (props && props->hasReplyTo()) { - const qpid::framing::ReplyTo& replyto = props->getReplyTo(); - if (replyto.hasExchange() && replyto.hasRoutingKey()) - return replyto.getExchange() + DELIMITER + replyto.getRoutingKey(); - else if (replyto.hasExchange()) return replyto.getExchange(); - else if (replyto.hasRoutingKey()) return replyto.getRoutingKey(); - else return EMPTY; - } else { - return EMPTY; - } -} - -bool MessageTransfer::requiresAccept() const -{ - const framing::MessageTransferBody* b = getFrames().as(); - return b && b->getAcceptMode() == 0/*EXPLICIT == 0*/; -} -uint32_t MessageTransfer::getRequiredCredit() const -{ - if (cachedRequiredCredit) { - return requiredCredit; - } else { - // TODO -- remove this code and replace it with a QPID_ASSERT(cachedRequiredCredit), - // then fix whatever breaks. compute should always be called before get. - uint32_t sum = 0; - for(FrameSet::Frames::const_iterator i = frames.begin(); i != frames.end(); ++i ) { - uint8_t type = (*i).getBody()->type(); - if ((type == qpid::framing::HEADER_BODY ) || (type == qpid::framing::CONTENT_BODY )) - sum += (*i).getBody()->encodedSize(); - } - return sum; - } -} -void MessageTransfer::computeRequiredCredit() -{ - //add up payload for all header and content frames in the frameset - uint32_t sum = 0; - for(FrameSet::Frames::const_iterator i = frames.begin(); i != frames.end(); ++i ) { - uint8_t type = (*i).getBody()->type(); - if ((type == qpid::framing::HEADER_BODY ) || (type == qpid::framing::CONTENT_BODY )) - sum += (*i).getBody()->encodedSize(); - } - requiredCredit = sum; - cachedRequiredCredit = true; -} - -qpid::framing::FrameSet& MessageTransfer::getFrames() -{ - return frames; -} -const qpid::framing::FrameSet& MessageTransfer::getFrames() const -{ - return frames; -} -void MessageTransfer::sendContent(framing::FrameHandler& out, uint16_t maxFrameSize) const -{ - qpid::framing::Count c; - frames.map_if(c, qpid::framing::TypeFilter()); - - qpid::framing::SendContent f(out, maxFrameSize, c.getCount()); - frames.map_if(f, qpid::framing::TypeFilter()); -} - -class SendHeader -{ - public: - SendHeader(FrameHandler& h, bool r, uint64_t t, const qpid::types::Variant::Map& a) : handler(h), redelivered(r), ttl(t), annotations(a) {} - void operator()(const AMQFrame& f) - { - AMQFrame copy = f; - if (redelivered || ttl || annotations.size()) { - copy.cloneBody(); - if (annotations.size()) { - MessageProperties* props = - copy.castBody()->get(true); - for (qpid::types::Variant::Map::const_iterator i = annotations.begin(); - i != annotations.end(); ++i) { - props->getApplicationHeaders().set(i->first, qpid::amqp_0_10::translate(i->second)); - } - } - if (redelivered || ttl) { - DeliveryProperties* dp = - copy.castBody()->get(true); - if (ttl) dp->setTtl(ttl); - if (redelivered) dp->setRedelivered(redelivered); - } - } - handler.handle(copy); - } - private: - FrameHandler& handler; - bool redelivered; - uint64_t ttl; - const qpid::types::Variant::Map& annotations; -}; - -void MessageTransfer::sendHeader(framing::FrameHandler& out, uint16_t /*maxFrameSize*/, - bool redelivered, uint64_t ttl, - const qpid::types::Variant::Map& annotations) const -{ - SendHeader f(out, redelivered, ttl, annotations); - frames.map_if(f, TypeFilter()); -} -bool MessageTransfer::isImmediateDeliveryRequired(const qpid::broker::Message& /*message*/) -{ - return false;//TODO -} - -const framing::SequenceNumber& MessageTransfer::getCommandId() const { return frames.getId(); } - -std::string MessageTransfer::getRoutingKey() const -{ - const qpid::framing::DeliveryProperties* dp = getProperties(); - if (dp && dp->hasRoutingKey()) { - return dp->getRoutingKey(); - } else { - return std::string(); - } -} -bool MessageTransfer::isPersistent() const -{ - const qpid::framing::DeliveryProperties* dp = getProperties(); - if (dp && dp->hasDeliveryMode()) { - return dp->getDeliveryMode() == 2; - } else { - return false; - } -} - -std::string MessageTransfer::getContent() const -{ - return frames.getContent(); -} - -void MessageTransfer::decodeHeader(framing::Buffer& buffer) -{ - AMQFrame method; - method.decode(buffer); - frames.append(method); - - AMQFrame header; - header.decode(buffer); - frames.append(header); -} -void MessageTransfer::decodeContent(framing::Buffer& buffer) -{ - decodeContent(buffer, buffer.available()); -} - -void MessageTransfer::decodeContent(framing::Buffer& buffer, size_t size) -{ - if (size) { - //get the data as a string and set that as the content - //body on a frame then add that frame to the frameset - AMQFrame frame((AMQContentBody())); - frame.castBody()->decode(buffer, size); - frame.setFirstSegment(false); - frames.append(frame); - } else { - //adjust header flags - MarkLastSegment f; - frames.map_if(f, TypeFilter()); - } -} - -void MessageTransfer::encode(framing::Buffer& buffer) const -{ - //encode method and header frames - EncodeFrame f1(buffer); - frames.map_if(f1, TypeFilter2()); - - //then encode the payload of each content frame - framing::EncodeBody f2(buffer); - frames.map_if(f2, TypeFilter()); -} - -void MessageTransfer::encodeContent(framing::Buffer& buffer) const -{ - //encode the payload of each content frame - EncodeBody f2(buffer); - frames.map_if(f2, TypeFilter()); -} - -uint32_t MessageTransfer::encodedSize() const -{ - return encodedHeaderSize() + encodedContentSize(); -} - -uint32_t MessageTransfer::encodedContentSize() const -{ - return frames.getContentSize(); -} - -uint32_t MessageTransfer::encodedHeaderSize() const -{ - //add up the size for all method and header frames in the frameset - SumFrameSize sum; - frames.map_if(sum, TypeFilter2()); - return sum.getSize(); -} - -bool MessageTransfer::isQMFv2() const -{ - const framing::MessageProperties* props = getProperties(); - return props && props->getAppId() == QMF2 && props->hasApplicationHeaders(); -} - -bool MessageTransfer::isQMFv2(const qpid::broker::Message& message) -{ - const MessageTransfer* transfer = dynamic_cast(&message.getEncoding()); - return transfer && transfer->isQMFv2(); -} - -bool MessageTransfer::isLastQMFResponse(const std::string correlation) const -{ - const framing::MessageProperties* props = getProperties(); - return props && props->getCorrelationId() == correlation - && props->hasApplicationHeaders() && !props->getApplicationHeaders().isSet(PARTIAL); -} - -bool MessageTransfer::isLastQMFResponse(const qpid::broker::Message& message, const std::string correlation) -{ - const MessageTransfer* transfer = dynamic_cast(&message.getEncoding()); - return transfer && transfer->isLastQMFResponse(correlation); -} - -std::string MessageTransfer::printProperties() const -{ - std::stringstream out; - const qpid::framing::MessageProperties* mp = getProperties(); - if (mp) { - out << *mp; - } - return out.str(); -} - -void MessageTransfer::processProperties(qpid::amqp::MapHandler& handler) const -{ - const qpid::framing::MessageProperties* mp = getProperties(); - if (mp && mp->hasApplicationHeaders()) { - const FieldTable ft = mp->getApplicationHeaders(); - for (FieldTable::const_iterator i = ft.begin(); i != ft.end(); ++i) { - qpid::types::Variant v; - qpid::amqp_0_10::translate(i->second, v); - qpid::amqp::CharSequence key = {i->first.data(), i->first.size()}; - switch (v.getType()) { - case qpid::types::VAR_VOID: - handler.handleVoid(key); break; - case qpid::types::VAR_BOOL: - handler.handleBool(key, v); break; - case qpid::types::VAR_UINT8: - handler.handleUint8(key, v); break; - case qpid::types::VAR_UINT16: - handler.handleUint16(key, v); break; - case qpid::types::VAR_UINT32: - handler.handleUint32(key, v); break; - case qpid::types::VAR_UINT64: - handler.handleUint64(key, v); break; - case qpid::types::VAR_INT8: - handler.handleInt8(key, v); break; - case qpid::types::VAR_INT16: - handler.handleInt16(key, v); break; - case qpid::types::VAR_INT32: - handler.handleInt32(key, v); break; - case qpid::types::VAR_INT64: - handler.handleInt64(key, v); break; - case qpid::types::VAR_FLOAT: - handler.handleFloat(key, v); break; - case qpid::types::VAR_DOUBLE: - handler.handleDouble(key, v); break; - case qpid::types::VAR_STRING: { - std::string s(v); - qpid::amqp::CharSequence value = {s.data(), s.size()}; - qpid::amqp::CharSequence encoding = {0, 0}; - handler.handleString(key, value, encoding); - break; - } - case qpid::types::VAR_MAP: - case qpid::types::VAR_LIST: - case qpid::types::VAR_UUID: - QPID_LOG(debug, "Unhandled key!" << v); - break; - } - } - } -} - -std::string MessageTransfer::getUserId() const -{ - const qpid::framing::MessageProperties* mp = getProperties(); - if (mp && mp->hasUserId()) return mp->getUserId(); - else return std::string(); - -} -MessageTransfer::MessageTransfer(const qpid::framing::FrameSet& f) : frames(f), requiredCredit(0) {} - -boost::intrusive_ptr MessageTransfer::merge(const std::map& annotations) const -{ - boost::intrusive_ptr clone(new MessageTransfer(this->frames)); - qpid::framing::MessageProperties* mp = clone->frames.getHeaders()->get(true); - for (qpid::types::Variant::Map::const_iterator i = annotations.begin(); i != annotations.end(); ++i) { - mp->getApplicationHeaders().set(i->first, qpid::amqp_0_10::translate(i->second)); - } - return clone; -} -}}} // namespace qpid::broker::amqp_0_10 diff --git a/qpid/cpp/src/qpid/broker/amqp_0_10/MessageTransfer.h b/qpid/cpp/src/qpid/broker/amqp_0_10/MessageTransfer.h deleted file mode 100644 index af7dfbba74..0000000000 --- a/qpid/cpp/src/qpid/broker/amqp_0_10/MessageTransfer.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef QPID_BROKER_AMQP_0_10_MESSAGETRANSFER_H -#define QPID_BROKER_AMQP_0_10_MESSAGETRANSFER_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/BrokerImportExport.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/PersistableMessage.h" -#include "qpid/types/Variant.h" - -namespace qpid { -namespace broker { -class Queue; -namespace amqp_0_10 { - -/** - * - */ -class MessageTransfer : public qpid::broker::Message::SharedStateImpl, public qpid::broker::PersistableMessage -{ - public: - QPID_BROKER_EXTERN MessageTransfer(); - QPID_BROKER_EXTERN MessageTransfer(const qpid::framing::SequenceNumber&); - - std::string getRoutingKey() const; - bool isPersistent() const; - uint8_t getPriority() const; - uint64_t getContentSize() const; - uint64_t getMessageSize() const; - qpid::amqp::MessageId getMessageId() const; - qpid::amqp::MessageId getCorrelationId() const; - std::string getPropertyAsString(const std::string& key) const; - std::string getAnnotationAsString(const std::string& key) const; - bool getTtl(uint64_t&) const; - bool hasExpiration() const; - std::string getExchangeName() const; - void processProperties(qpid::amqp::MapHandler&) const; - std::string printProperties() const; - std::string getUserId() const; - void setTimestamp(); - uint64_t getTimestamp() const; - std::string getTo() const; - std::string getSubject() const; - std::string getReplyTo() const; - - - bool requiresAccept() const; - const qpid::framing::SequenceNumber& getCommandId() const; - QPID_BROKER_EXTERN qpid::framing::FrameSet& getFrames(); - QPID_BROKER_EXTERN const qpid::framing::FrameSet& getFrames() const; - - template const T* getProperties() const { - const qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - return p->get(); - } - - template const T* hasProperties() const { - const qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - return p->get(); - } - template const T* getMethod() const { - return frames.as(); - } - - template T* getMethod() { - return frames.as(); - } - - template bool isA() const { - return frames.isA(); - } - - template void eraseProperties() { - qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - p->erase(); - } - std::string getContent() const; - uint32_t getRequiredCredit() const; - void computeRequiredCredit(); - - void clearApplicationHeadersFlag(); - void sendContent(framing::FrameHandler& out, uint16_t maxFrameSize) const; - void sendHeader(framing::FrameHandler& out, uint16_t maxFrameSize, bool redelivered, uint64_t ttl, const qpid::types::Variant::Map& annotations) const; - - void decodeHeader(framing::Buffer& buffer); - void decodeContent(framing::Buffer& buffer); - void decodeContent(framing::Buffer& buffer, size_t size); - - void encode(framing::Buffer& buffer) const; - uint32_t encodedSize() const; - - /** - * @returns the size of the buffer needed to encode the - * 'header' of this message (not just the header frame, - * but other meta data e.g.routing key and exchange) - */ - uint32_t encodedHeaderSize() const; - boost::intrusive_ptr merge(const std::map& annotations) const; - - QPID_BROKER_EXTERN bool isQMFv2() const; - QPID_BROKER_EXTERN bool isLastQMFResponse(const std::string correlation) const; - - static bool isImmediateDeliveryRequired(const qpid::broker::Message& message); - static MessageTransfer& get(qpid::broker::Message& message) { - return *dynamic_cast(&message.getSharedState()); - } - static const MessageTransfer& get(const qpid::broker::Message& message) { - return *dynamic_cast(&message.getEncoding()); - } - QPID_BROKER_EXTERN static bool isQMFv2(const qpid::broker::Message& message); - QPID_BROKER_EXTERN static bool isLastQMFResponse(const qpid::broker::Message& message, const std::string correlation); - private: - qpid::framing::FrameSet frames; - uint32_t requiredCredit; - bool cachedRequiredCredit; - - MessageTransfer(const qpid::framing::FrameSet&); - void encodeHeader(framing::Buffer& buffer) const; - uint32_t encodedContentSize() const; - void encodeContent(framing::Buffer& buffer) const; -}; -}}} // namespace qpid::broker::amqp_0_10 - -#endif /*!QPID_BROKER_AMQP_0_10_MESSAGETRANSFER_H*/ diff --git a/qpid/cpp/src/qpid/broker/management-schema.xml b/qpid/cpp/src/qpid/broker/management-schema.xml deleted file mode 100644 index debc1a4af2..0000000000 --- a/qpid/cpp/src/qpid/broker/management-schema.xml +++ /dev/null @@ -1,624 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This class represents an inter-broker connection. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp b/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp deleted file mode 100644 index e3cfa66b02..0000000000 --- a/qpid/cpp/src/qpid/broker/posix/BrokerDefaults.cpp +++ /dev/null @@ -1,42 +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/broker/Broker.h" -#include "qpid/broker/BrokerOptions.h" -#include - -namespace qpid { -namespace broker { - -const std::string BrokerOptions::DEFAULT_DATA_DIR_LOCATION("/tmp"); -const std::string BrokerOptions::DEFAULT_DATA_DIR_NAME("/.qpidd"); -const std::string BrokerOptions::DEFAULT_PAGED_QUEUE_DIR("/pq"); - -std::string -BrokerOptions::getHome() { - std::string home; - char *home_c = ::getenv("HOME"); - if (home_c != 0) - home += home_c; - return home; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/posix/SocketFDPlugin.cpp b/qpid/cpp/src/qpid/broker/posix/SocketFDPlugin.cpp deleted file mode 100644 index d73c5713ea..0000000000 --- a/qpid/cpp/src/qpid/broker/posix/SocketFDPlugin.cpp +++ /dev/null @@ -1,93 +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/sys/TransportFactory.h" - -#include "qpid/Options.h" -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/posix/BSDSocket.h" -#include "qpid/sys/SocketTransport.h" - -#include - -#include - -namespace qpid { -namespace sys { - -struct SocketOptions : public Options { - std::vector socketFds; - - SocketOptions() : - socketFds(0) - { - addOptions() - ("socket-fd", optValue(socketFds, "FD"), "File descriptor for tcp listening socket"); - } -}; - -bool isSocket(int fd) -{ - if (fd < 0 ) return false; - - struct ::stat st_fd; - if (::fstat(fd, &st_fd) < 0) return false; - - return S_ISSOCK(st_fd.st_mode); -} - -// Static instance to initialise plugin -static class SocketFDPlugin : public Plugin { - SocketOptions options; - - Options* getOptions() { return &options; } - - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - broker::Broker* broker = dynamic_cast(&target); - // Only provide to a Broker - if (broker) { - if (!options.socketFds.empty()) { - SocketAcceptor* sa = new SocketAcceptor(broker->getTcpNoDelay(), false, broker->getMaxNegotiateTime(), broker->getTimer()); - for (unsigned i = 0; iaddListener(s); - QPID_LOG(notice, "Listening on imported socket: " << s->getLocalAddress()); - } - broker->registerTransport("socket", TransportAcceptor::shared_ptr(sa), TransportConnector::shared_ptr(), 0); - } else { - QPID_LOG(debug, "No Socket fd specified"); - } - } - } -} socketFdPlugin; - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp b/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp deleted file mode 100644 index 6184e0450f..0000000000 --- a/qpid/cpp/src/qpid/broker/windows/BrokerDefaults.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerOptions.h" -#include -#include - -namespace qpid { -namespace broker { - -const std::string BrokerOptions::DEFAULT_DATA_DIR_LOCATION("\\TEMP"); -const std::string BrokerOptions::DEFAULT_DATA_DIR_NAME("\\QPIDD.DATA"); -const std::string BrokerOptions::DEFAULT_PAGED_QUEUE_DIR("\\PQ"); - -std::string -BrokerOptions::getHome() { - std::string home; -#ifdef _MSC_VER - char home_c[MAX_PATH+1]; - size_t unused; - if (0 == getenv_s (&unused, home_c, sizeof(home_c), "HOME")) - home += home_c; -#else - char *home_c = getenv("HOME"); - if (home_c) - home += home_c; -#endif - return home; -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp b/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp deleted file mode 100644 index 19941c7909..0000000000 --- a/qpid/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp +++ /dev/null @@ -1,209 +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. - * - */ - -// This source is only used on Windows; SSPI is the Windows mechanism for -// accessing authentication mechanisms, analogous to Cyrus SASL. - -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/sys/ConnectionOutputHandler.h" - -#include - -using namespace qpid::framing; -using qpid::sys::SecurityLayer; - -using std::string; - -namespace qpid { -namespace broker { - -class NullAuthenticator : public SaslAuthenticator -{ - qpid::broker::amqp_0_10::Connection& connection; - framing::AMQP_ClientProxy::Connection client; - string realm; -public: - NullAuthenticator(qpid::broker::amqp_0_10::Connection& connection); - ~NullAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string* response); - void step(const std::string&) {} - std::auto_ptr getSecurityLayer(uint16_t maxFrameSize); -}; - -class SspiAuthenticator : public SaslAuthenticator -{ - HANDLE userToken; - qpid::broker::amqp_0_10::Connection& connection; - framing::AMQP_ClientProxy::Connection client; - -public: - SspiAuthenticator(qpid::broker::amqp_0_10::Connection& connection); - ~SspiAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string* response); - void step(const std::string& response); - std::auto_ptr getSecurityLayer(uint16_t maxFrameSize); -}; - -bool SaslAuthenticator::available(void) -{ - return true; -} - -// Initialize the SASL mechanism; throw if it fails. -void SaslAuthenticator::init(const std::string& /*saslName*/, const std::string& /*saslConfig*/) -{ - return; -} - -void SaslAuthenticator::fini(void) -{ - return; -} - -std::auto_ptr SaslAuthenticator::createAuthenticator(qpid::broker::amqp_0_10::Connection& c) -{ - if (c.getBroker().isAuthenticating()) { - return std::auto_ptr(new SspiAuthenticator(c)); - } else { - return std::auto_ptr(new NullAuthenticator(c)); - } -} - -NullAuthenticator::NullAuthenticator(qpid::broker::amqp_0_10::Connection& c) : - connection(c), client(c.getOutput()), realm("@"+c.getBroker().getRealm()) {} -NullAuthenticator::~NullAuthenticator() {} - -void NullAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr(new Str16Value("ANONYMOUS"))); - mechanisms.add(boost::shared_ptr(new Str16Value("PLAIN"))); -} - -namespace { -bool endsWith(const std::string& str, const std::string& ending) { - return (ending.size() <= str.size()) && - (str.compare(str.size() - ending.size(), ending.size(), ending) == 0); -} -} - -void NullAuthenticator::start(const string& mechanism, const string* response) -{ - QPID_LOG(warning, "SASL: No Authentication Performed"); - if (mechanism == "PLAIN") { // Old behavior - if (response && response->size() > 0 && (*response).c_str()[0] == (char) 0) { - string temp = response->substr(1); - string::size_type i = temp.find((char)0); - string uid = temp.substr(0, i); - string pwd = temp.substr(i + 1); - if (!endsWith(uid, realm)) uid += realm; - connection.setUserId(uid); - } - } else { - connection.setUserId("anonymous"); - } - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); -} - -std::auto_ptr NullAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr securityLayer; - return securityLayer; -} - - -SspiAuthenticator::SspiAuthenticator(qpid::broker::amqp_0_10::Connection& c) : userToken(INVALID_HANDLE_VALUE), connection(c), client(c.getOutput()) -{ -} - -SspiAuthenticator::~SspiAuthenticator() -{ - if (INVALID_HANDLE_VALUE != userToken) { - CloseHandle(userToken); - userToken = INVALID_HANDLE_VALUE; - } -} - -void SspiAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr(new Str16Value(string("ANONYMOUS")))); - mechanisms.add(boost::shared_ptr(new Str16Value(string("PLAIN")))); - QPID_LOG(info, "SASL: Mechanism list: ANONYMOUS PLAIN"); -} - -void SspiAuthenticator::start(const string& mechanism, const string* response) -{ - QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism); - if (mechanism == "ANONYMOUS") { - connection.setUserId("anonymous"); - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); - return; - } - if (mechanism != "PLAIN") - throw ConnectionForcedException("Unsupported mechanism"); - - // PLAIN's response is composed of 3 strings separated by 0 bytes: - // authorization id, authentication id (user), clear-text password. - if (!response || response->size() == 0) - throw ConnectionForcedException("Authentication failed"); - - string::size_type i = response->find((char)0); - string auth = response->substr(0, i); - string::size_type j = response->find((char)0, i+1); - string uid = response->substr(i+1, j-1); - string pwd = response->substr(j+1); - string dot("."); - int error = 0; - if (!LogonUser(const_cast(uid.c_str()), - const_cast(dot.c_str()), - const_cast(pwd.c_str()), - LOGON32_LOGON_NETWORK, - LOGON32_PROVIDER_DEFAULT, - &userToken)) - error = GetLastError(); - pwd.replace(0, string::npos, 1, (char)0); - if (error != 0) { - QPID_LOG(info, - "SASL: Auth failed [" << error << "]: " << qpid::sys::strError(error)); - throw ConnectionForcedException("Authentication failed"); - } - - connection.setUserId(uid); - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); -} - -void SspiAuthenticator::step(const string& /*response*/) -{ - QPID_LOG(info, "SASL: Need another step!!!"); -} - -std::auto_ptr SspiAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr securityLayer; - return securityLayer; -} - -}} diff --git a/qpid/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp b/qpid/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp deleted file mode 100644 index 0ae4d8356d..0000000000 --- a/qpid/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp +++ /dev/null @@ -1,312 +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/sys/TransportFactory.h" -#include "qpid/sys/SocketTransport.h" - -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/AsynchIOHandler.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/windows/SslAsynchIO.h" - -#include -#include -#include - -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include -#include -#undef SECURITY_WIN32 - - -namespace qpid { -namespace sys { - -class Timer; - -namespace windows { - -struct SslServerOptions : qpid::Options -{ - std::string certStore; - std::string certStoreLocation; - std::string certName; - uint16_t port; - bool clientAuth; - - SslServerOptions() : qpid::Options("SSL Options"), - certStore("My"), - certStoreLocation("CurrentUser"), - certName("localhost"), - port(5671), - clientAuth(false) - { - qpid::Address me; - if (qpid::sys::SystemInfo::getLocalHostname(me)) - certName = me.host; - - addOptions() - ("ssl-cert-store", optValue(certStore, "NAME"), "Local store name from which to obtain certificate") - ("ssl-cert-store-location", optValue(certStoreLocation, "NAME"), - "Local store name location for certificates ( CurrentUser | LocalMachine | CurrentService )") - ("ssl-cert-name", optValue(certName, "NAME"), "Name of the certificate to use") - ("ssl-port", optValue(port, "PORT"), "Port on which to listen for SSL connections") - ("ssl-require-client-authentication", optValue(clientAuth), - "Forces clients to authenticate in order to establish an SSL connection"); - } -}; - -class SslProtocolFactory : public qpid::sys::SocketAcceptor, public qpid::sys::TransportConnector { - Timer& brokerTimer; - uint32_t maxNegotiateTime; - const bool tcpNoDelay; - std::string brokerHost; - const bool clientAuthSelected; - std::auto_ptr acceptor; - ConnectFailedCallback connectFailedCallback; - CredHandle credHandle; - - public: - SslProtocolFactory(const qpid::broker::Broker& broker, const SslServerOptions&, Timer& timer); - ~SslProtocolFactory(); - - void connect(sys::Poller::shared_ptr, const std::string& name, const std::string& host, const std::string& port, - sys::ConnectionCodec::Factory*, - ConnectFailedCallback failed); - - private: - void connectFailed(const qpid::sys::Socket&, - int err, - const std::string& msg); - void establishedIncoming(sys::Poller::shared_ptr, const qpid::sys::Socket&, sys::ConnectionCodec::Factory*); - void establishedOutgoing(sys::Poller::shared_ptr, const qpid::sys::Socket&, sys::ConnectionCodec::Factory*, std::string& ); - void establishedCommon(sys::Poller::shared_ptr, sys::AsynchIOHandler*, sys::AsynchIO*, const qpid::sys::Socket&); -}; - -// Static instance to initialise plugin -static struct SslPlugin : public Plugin { - SslServerOptions options; - - Options* getOptions() { return &options; } - - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - broker::Broker* broker = dynamic_cast(&target); - // Only provide to a Broker - if (broker) { - try { - boost::shared_ptr protocol(new SslProtocolFactory(*broker, options, broker->getTimer())); - uint16_t port = - protocol->listen(broker->getListenInterfaces(), - options.port, broker->getConnectionBacklog(), - &createSocket); - QPID_LOG(notice, "Listening for SSL connections on TCP port " << port); - broker->registerTransport("ssl", protocol, protocol, port); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL listener: " << e.what()); - } - } - } -} sslPlugin; - -SslProtocolFactory::SslProtocolFactory(const qpid::broker::Broker& broker, const SslServerOptions& options, Timer& timer) - : SocketAcceptor(broker.getTcpNoDelay(), false, broker.getMaxNegotiateTime(), timer, - boost::bind(&SslProtocolFactory::establishedIncoming, this, _1, _2, _3)), - brokerTimer(timer), - maxNegotiateTime(broker.getMaxNegotiateTime()), - tcpNoDelay(broker.getTcpNoDelay()), - clientAuthSelected(options.clientAuth) { - - // Make sure that certificate store is good before listening to sockets - // to avoid having open and listening sockets when there is no cert store - SecInvalidateHandle(&credHandle); - - // Get the certificate for this server. - DWORD flags = 0; - std::string certStoreLocation = options.certStoreLocation; - std::transform(certStoreLocation.begin(), certStoreLocation.end(), certStoreLocation.begin(), ::tolower); - if (certStoreLocation == "currentuser") { - flags = CERT_SYSTEM_STORE_CURRENT_USER; - } else if (certStoreLocation == "localmachine") { - flags = CERT_SYSTEM_STORE_LOCAL_MACHINE; - } else if (certStoreLocation == "currentservice") { - flags = CERT_SYSTEM_STORE_CURRENT_SERVICE; - } else { - QPID_LOG(error, "Unrecognised SSL certificate store location: " << options.certStoreLocation - << " - Using default location"); - } - HCERTSTORE certStoreHandle; - certStoreHandle = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, - X509_ASN_ENCODING, - 0, - flags | - CERT_STORE_READONLY_FLAG, - options.certStore.c_str()); - if (!certStoreHandle) - throw qpid::Exception(QPID_MSG("Opening store " << options.certStore << " " << qpid::sys::strError(GetLastError()))); - - PCCERT_CONTEXT certContext; - certContext = ::CertFindCertificateInStore(certStoreHandle, - X509_ASN_ENCODING, - 0, - CERT_FIND_SUBJECT_STR_A, - options.certName.c_str(), - NULL); - if (certContext == NULL) { - int err = ::GetLastError(); - ::CertCloseStore(certStoreHandle, 0); - throw qpid::Exception(QPID_MSG("Locating certificate " << options.certName << " in store " << options.certStore << " " << qpid::sys::strError(GetLastError()))); - throw QPID_WINDOWS_ERROR(err); - } - - SCHANNEL_CRED cred; - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - cred.cCreds = 1; - cred.paCred = &certContext; - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_INBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - NULL); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - ::CertFreeCertificateContext(certContext); - ::CertCloseStore(certStoreHandle, 0); -} - -SslProtocolFactory::~SslProtocolFactory() { - ::FreeCredentialsHandle(&credHandle); -} - -void SslProtocolFactory::connectFailed(const qpid::sys::Socket&, - int err, - const std::string& msg) { - if (connectFailedCallback) - connectFailedCallback(err, msg); -} - -void SslProtocolFactory::establishedIncoming(sys::Poller::shared_ptr poller, - const qpid::sys::Socket& s, - sys::ConnectionCodec::Factory* f) { - sys::AsynchIOHandler* async = new sys::AsynchIOHandler(s.getFullAddress(), f, false, false); - - sys::AsynchIO *aio = - new qpid::sys::windows::ServerSslAsynchIO( - clientAuthSelected, - s, - credHandle, - boost::bind(&AsynchIOHandler::readbuff, async, _1, _2), - boost::bind(&AsynchIOHandler::eof, async, _1), - boost::bind(&AsynchIOHandler::disconnect, async, _1), - boost::bind(&AsynchIOHandler::closedSocket, async, _1, _2), - boost::bind(&AsynchIOHandler::nobuffs, async, _1), - boost::bind(&AsynchIOHandler::idle, async, _1)); - - establishedCommon(poller, async, aio, s); -} - -void SslProtocolFactory::establishedOutgoing(sys::Poller::shared_ptr poller, - const qpid::sys::Socket& s, - sys::ConnectionCodec::Factory* f, - std::string& name) { - sys::AsynchIOHandler* async = new sys::AsynchIOHandler(name, f, true, false); - - sys::AsynchIO *aio = - new qpid::sys::windows::ClientSslAsynchIO( - brokerHost, - s, - credHandle, - boost::bind(&AsynchIOHandler::readbuff, async, _1, _2), - boost::bind(&AsynchIOHandler::eof, async, _1), - boost::bind(&AsynchIOHandler::disconnect, async, _1), - boost::bind(&AsynchIOHandler::closedSocket, async, _1, _2), - boost::bind(&AsynchIOHandler::nobuffs, async, _1), - boost::bind(&AsynchIOHandler::idle, async, _1)); - - establishedCommon(poller, async, aio, s); -} - -void SslProtocolFactory::establishedCommon(sys::Poller::shared_ptr poller, - sys::AsynchIOHandler* async, - sys::AsynchIO* aio, - const qpid::sys::Socket& s) { - if (tcpNoDelay) { - s.setTcpNoDelay(); - QPID_LOG(debug, "Set TCP_NODELAY on connection to " << s.getPeerAddress()); - } - - async->init(aio, brokerTimer, maxNegotiateTime); - aio->start(poller); -} - -void SslProtocolFactory::connect(sys::Poller::shared_ptr poller, - const std::string& name, - const std::string& host, - const std::string& port, - sys::ConnectionCodec::Factory* fact, - ConnectFailedCallback failed) -{ - SCHANNEL_CRED cred; - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_OUTBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - NULL); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - - brokerHost = host; - // Note that the following logic does not cause a memory leak. - // The allocated Socket is freed either by the AsynchConnector - // upon connection failure or by the AsynchIO upon connection - // shutdown. The allocated AsynchConnector frees itself when it - // is no longer needed. - qpid::sys::Socket* socket = createSocket(); - connectFailedCallback = failed; - AsynchConnector::create(*socket, - host, - port, - boost::bind(&SslProtocolFactory::establishedOutgoing, - this, poller, _1, fact, name), - boost::bind(&SslProtocolFactory::connectFailed, - this, _1, _2, _3)); -} - -}}} diff --git a/qpid/cpp/src/qpid/client/AsyncSession.h b/qpid/cpp/src/qpid/client/AsyncSession.h deleted file mode 100644 index d91efeb4f1..0000000000 --- a/qpid/cpp/src/qpid/client/AsyncSession.h +++ /dev/null @@ -1,38 +0,0 @@ -#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/Bounds.cpp b/qpid/cpp/src/qpid/client/Bounds.cpp deleted file mode 100644 index cc2577d5fc..0000000000 --- a/qpid/cpp/src/qpid/client/Bounds.cpp +++ /dev/null @@ -1,71 +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/client/Bounds.h" - -#include "qpid/log/Statement.h" -#include "qpid/sys/Waitable.h" - -namespace qpid { -namespace client { - -using sys::Waitable; - -Bounds::Bounds(size_t maxSize) : max(maxSize), current(0) {} - -bool Bounds::expand(size_t sizeRequired, bool block) { - if (!max) return true; - Waitable::ScopedLock l(lock); - if (block) { - Waitable::ScopedWait w(lock); - while (current + sizeRequired > max) - lock.wait(); - } - current += sizeRequired; - return current <= max; -} - -void Bounds::reduce(size_t size) { - if (!max || size == 0) return; - Waitable::ScopedLock l(lock); - assert(current >= size); - current -= std::min(size, current); - if (current < max && lock.hasWaiters()) { - lock.notifyAll(); - } -} - -size_t Bounds::getCurrentSize() { - Waitable::ScopedLock l(lock); - return current; -} - -std::ostream& operator<<(std::ostream& out, const Bounds& bounds) { - out << "current=" << bounds.current << ", max=" << bounds.max << " [" << &bounds << "]"; - return out; -} - -void Bounds::setException(const sys::ExceptionHolder& e) { - Waitable::ScopedLock l(lock); - lock.setException(e); - lock.waitWaiters(); // Wait for waiting threads to exit. -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/Bounds.h b/qpid/cpp/src/qpid/client/Bounds.h deleted file mode 100644 index 838fcb8368..0000000000 --- a/qpid/cpp/src/qpid/client/Bounds.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef QPID_CLIENT_BOUNDSCHECKING_H -#define QPID_CLIENT_BOUNDSCHECKING_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/Waitable.h" - -namespace qpid{ -namespace client{ - -class Bounds -{ - public: - Bounds(size_t maxSize); - bool expand(size_t, bool block); - void reduce(size_t); - size_t getCurrentSize(); - void setException(const sys::ExceptionHolder&); - - private: - friend std::ostream& operator<<(std::ostream&, const Bounds&); - sys::Waitable lock; - const size_t max; - size_t current; -}; - -std::ostream& operator<<(std::ostream&, const Bounds&); - - -}} - -#endif diff --git a/qpid/cpp/src/qpid/client/ChainableFrameHandler.h b/qpid/cpp/src/qpid/client/ChainableFrameHandler.h deleted file mode 100644 index 29e16d53dc..0000000000 --- a/qpid/cpp/src/qpid/client/ChainableFrameHandler.h +++ /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. - * - */ - -#ifndef _ChainableFrameHandler_ -#define _ChainableFrameHandler_ - -#include -#include "qpid/framing/AMQFrame.h" - -namespace qpid { -namespace client { - -struct ChainableFrameHandler -{ - typedef boost::function FrameDelegate; - - FrameDelegate in; - FrameDelegate out; - - ChainableFrameHandler() {} - ChainableFrameHandler(FrameDelegate i, FrameDelegate o): in(i), out(o) {} - virtual ~ChainableFrameHandler() {} -}; - -}} - - - -#endif diff --git a/qpid/cpp/src/qpid/client/ClientImportExport.h b/qpid/cpp/src/qpid/client/ClientImportExport.h deleted file mode 100644 index 2a3a5a52e9..0000000000 --- a/qpid/cpp/src/qpid/client/ClientImportExport.h +++ /dev/null @@ -1,35 +0,0 @@ -#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.cpp b/qpid/cpp/src/qpid/client/Completion.cpp deleted file mode 100644 index fc6737d96f..0000000000 --- a/qpid/cpp/src/qpid/client/Completion.cpp +++ /dev/null @@ -1,43 +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/client/Completion.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/PrivateImplRef.h" - -namespace qpid { -namespace client { - -// Explicitly instantiate Handle superclass -template class Handle; - -typedef PrivateImplRef PI; -Completion::Completion(CompletionImpl* p) { PI::ctor(*this, p); } -Completion::Completion(const Completion& c) : Handle() { PI::copy(*this, c); } -Completion::~Completion() { PI::dtor(*this); } -Completion& Completion::operator=(const Completion& c) { return PI::assign(*this, c); } - - -void Completion::wait() { impl->wait(); } -bool Completion::isComplete() { return impl->isComplete(); } -std::string Completion::getResult() { return impl->getResult(); } - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/Completion.h b/qpid/cpp/src/qpid/client/Completion.h deleted file mode 100644 index 9546db9258..0000000000 --- a/qpid/cpp/src/qpid/client/Completion.h +++ /dev/null @@ -1,71 +0,0 @@ -#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 - -namespace qpid { -namespace client { - -class CompletionImpl; -template 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 -{ -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; -}; - -}} - - -#endif /*!QPID_CLIENT_COMPLETION_H*/ diff --git a/qpid/cpp/src/qpid/client/CompletionImpl.cpp b/qpid/cpp/src/qpid/client/CompletionImpl.cpp deleted file mode 100644 index cf2cfc6138..0000000000 --- a/qpid/cpp/src/qpid/client/CompletionImpl.cpp +++ /dev/null @@ -1,34 +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/client/CompletionImpl.h" -#include "qpid/client/Handle.h" -#include "qpid/client/PrivateImplRef.h" - -namespace qpid { -namespace client { - -CompletionImpl::CompletionImpl() {} - -CompletionImpl::CompletionImpl(Future f, boost::shared_ptr s) : - future(f), session(s) {} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/CompletionImpl.h b/qpid/cpp/src/qpid/client/CompletionImpl.h deleted file mode 100644 index b8243511ef..0000000000 --- a/qpid/cpp/src/qpid/client/CompletionImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_CLIENT_COMPLETIONIMPL_H -#define QPID_CLIENT_COMPLETIONIMPL_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/RefCounted.h" -#include "qpid/client/Future.h" -#include "qpid/client/ClientImportExport.h" -#include - -namespace qpid { -namespace client { - -///@internal -class QPID_CLIENT_CLASS_EXTERN CompletionImpl : public RefCounted -{ -public: - QPID_CLIENT_EXTERN CompletionImpl(); - QPID_CLIENT_EXTERN CompletionImpl(Future f, boost::shared_ptr s); - - QPID_CLIENT_EXTERN bool isComplete() { return future.isComplete(*session); } - QPID_CLIENT_EXTERN void wait() { future.wait(*session); } - QPID_CLIENT_EXTERN std::string getResult() { return future.getResult(*session); } - -protected: - Future future; - boost::shared_ptr session; -}; - -}} // namespace qpid::client - - -#endif /*!QPID_CLIENT_COMPLETIONIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/Connection.cpp b/qpid/cpp/src/qpid/client/Connection.cpp deleted file mode 100644 index f7d6341128..0000000000 --- a/qpid/cpp/src/qpid/client/Connection.cpp +++ /dev/null @@ -1,161 +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/client/Connection.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/Message.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/Url.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/AMQP_HighestVersion.h" - -#include -#include -#include -#include -#include -#include -#include - -using namespace qpid::framing; -using namespace qpid::sys; - - -namespace qpid { -namespace client { - -Connection::Connection() : version(framing::ProtocolVersion(0, 10)) -{ - ConnectionImpl::init(); -} - -Connection::~Connection() {} - -void Connection::open( - const Url& url, - const std::string& uid, const std::string& pwd, - const std::string& vhost, - uint16_t maxFrameSize) -{ - ConnectionSettings settings; - settings.username = uid; - settings.password = pwd; - settings.virtualhost = vhost; - settings.maxFrameSize = maxFrameSize; - open(url, settings); -} - -void Connection::open(const Url& url, const ConnectionSettings& settings) { - if (url.empty()) - throw Exception(QPID_MSG("Attempt to open URL with no addresses.")); - Url::const_iterator i = url.begin(); - do { - const Address& addr = *i; - i++; - try { - ConnectionSettings cs(settings); - if (addr.protocol.size()) cs.protocol = addr.protocol; - cs.host = addr.host; - cs.port = addr.port; - open(cs); - break; - } - catch (const Exception& /*e*/) { - if (i == url.end()) throw; - } - } while (i != url.end()); -} - -void Connection::open( - const std::string& host, int port, - const std::string& uid, const std::string& pwd, - const std::string& vhost, - uint16_t maxFrameSize) -{ - ConnectionSettings settings; - settings.host = host; - settings.port = port; - settings.username = uid; - settings.password = pwd; - settings.virtualhost = vhost; - settings.maxFrameSize = maxFrameSize; - open(settings); -} - -bool Connection::isOpen() const { - return impl && impl->isOpen(); -} - -void -Connection::registerFailureCallback ( boost::function fn ) { - failureCallback = fn; - if ( impl ) - impl->registerFailureCallback ( fn ); -} - - - -void Connection::open(const ConnectionSettings& settings) -{ - if (isOpen()) - throw Exception(QPID_MSG("Connection::open() was already called")); - - impl = ConnectionImpl::create(version, settings); - impl->open(); - if ( failureCallback ) - impl->registerFailureCallback ( failureCallback ); -} - -const ConnectionSettings& Connection::getNegotiatedSettings() const -{ - if (!isOpen()) - throw Exception(QPID_MSG("Connection is not open.")); - return impl->getNegotiatedSettings(); -} - -Session Connection::newSession(const std::string& name, uint32_t timeout) { - if (!isOpen()) - throw TransportFailure("Can't create session, connection is not open"); - Session s; - SessionBase_0_10Access(s).set(impl->newSession(name, timeout)); - return s; -} - -void Connection::resume(Session& session) { - if (!isOpen()) - throw Exception(QPID_MSG("Connection is not open.")); - impl->addSession(session.impl); - session.impl->resume(impl); -} - -void Connection::close() { - if ( impl ) - impl->close(); -} - -std::vector Connection::getInitialBrokers() { - return impl ? impl->getInitialBrokers() : std::vector(); -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/Connection.h b/qpid/cpp/src/qpid/client/Connection.h deleted file mode 100644 index 8c8a106c36..0000000000 --- a/qpid/cpp/src/qpid/client/Connection.h +++ /dev/null @@ -1,227 +0,0 @@ -#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 -#include -#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 = - * port = number]]> - * - */ - -class QPID_CLIENT_CLASS_EXTERN Connection -{ - framing::ProtocolVersion version; - - boost::function failureCallback; - - - protected: - boost::shared_ptr 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 - * 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 getInitialBrokers(); - - QPID_CLIENT_EXTERN void registerFailureCallback ( boost::function 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/ConnectionAccess.h b/qpid/cpp/src/qpid/client/ConnectionAccess.h deleted file mode 100644 index 3a763f692f..0000000000 --- a/qpid/cpp/src/qpid/client/ConnectionAccess.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLIENT_CONNECTIONACCESS_H -#define QPID_CLIENT_CONNECTIONACCESS_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/Connection.h" - -/**@file @internal Internal use only */ - -namespace qpid { -namespace client { - - - -struct ConnectionAccess { - static void setVersion(Connection& c, const framing::ProtocolVersion& v) { c.version = v; } - static boost::shared_ptr getImpl(Connection& c) { return c.impl; } - static void setImpl(Connection& c, boost::shared_ptr i) { c.impl = i; } -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_CONNECTIONACCESS_H*/ diff --git a/qpid/cpp/src/qpid/client/ConnectionHandler.cpp b/qpid/cpp/src/qpid/client/ConnectionHandler.cpp deleted file mode 100644 index 77d43f191d..0000000000 --- a/qpid/cpp/src/qpid/client/ConnectionHandler.cpp +++ /dev/null @@ -1,392 +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/client/ConnectionHandler.h" - -#include "qpid/SaslFactory.h" -#include "qpid/StringUtils.h" -#include "qpid/client/Bounds.h" -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/ClientInvoker.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/log/Helpers.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SystemInfo.h" - -#include - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::framing::connection; -using qpid::sys::SecurityLayer; -using qpid::sys::Duration; -using qpid::sys::TimerTask; -using qpid::sys::Timer; -using qpid::sys::AbsTime; -using qpid::sys::TIME_SEC; -using qpid::sys::ScopedLock; -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"); -const std::string INVALID_STATE_TUNE("tune received in invalid state"); -const std::string INVALID_STATE_OPEN_OK("open-ok received in invalid state"); -const std::string INVALID_STATE_CLOSE_OK("close-ok received in invalid state"); - -const std::string SESSION_FLOW_CONTROL("qpid.session_flow"); -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); -const int SESSION_FLOW_CONTROL_VER = 1; -} - -CloseCode ConnectionHandler::convert(uint16_t replyCode) -{ - switch (replyCode) { - case 200: return CLOSE_CODE_NORMAL; - case 320: return CLOSE_CODE_CONNECTION_FORCED; - case 402: return CLOSE_CODE_INVALID_PATH; - case 501: default: - return CLOSE_CODE_FRAMING_ERROR; - } -} - -ConnectionHandler::Adapter::Adapter(ConnectionHandler& h, Bounds& b) : handler(h), bounds(b) {} -void ConnectionHandler::Adapter::handle(qpid::framing::AMQFrame& f) -{ - bounds.expand(f.encodedSize(), false); - handler.out(f); -} - -ConnectionHandler::ConnectionHandler( - const ConnectionSettings& s, ProtocolVersion& v, Bounds& b) - : StateManager(NOT_STARTED), ConnectionSettings(s), - outHandler(*this, b), proxy(outHandler), errorCode(CLOSE_CODE_NORMAL), version(v), - properties(s.clientProperties) -{ - insist = true; - - ESTABLISHED.insert(FAILED); - ESTABLISHED.insert(CLOSED); - ESTABLISHED.insert(OPEN); - - FINISHED.insert(FAILED); - FINISHED.insert(CLOSED); - - properties.setInt(SESSION_FLOW_CONTROL, SESSION_FLOW_CONTROL_VER); - properties.setString(CLIENT_PROCESS_NAME, sys::SystemInfo::getProcessName()); - properties.setInt(CLIENT_PID, sys::SystemInfo::getProcessId()); - properties.setInt(CLIENT_PPID, sys::SystemInfo::getParentProcessId()); -} - -void ConnectionHandler::incoming(AMQFrame& frame) -{ - if (getState() == CLOSED) { - throw Exception("Received frame on closed connection"); - } - - if (rcvTimeoutTask) { - // Received frame on connection so delay timeout - rcvTimeoutTask->restart(); - } - - AMQBody* body = frame.getBody(); - try { - if (frame.getChannel() != 0 || !invoke(static_cast(*this), *body)) { - switch(getState()) { - case OPEN: - in(frame); - break; - case CLOSING: - QPID_LOG(warning, "Ignoring frame while closing connection: " << frame); - break; - default: - throw Exception("Cannot receive frames on non-zero channel until connection is established."); - } - } - }catch(std::exception& e){ - QPID_LOG(warning, "Closing connection due to " << e.what()); - setState(CLOSING); - errorCode = CLOSE_CODE_FRAMING_ERROR; - errorText = e.what(); - proxy.close(501, e.what()); - } -} - -void ConnectionHandler::outgoing(AMQFrame& frame) -{ - if (getState() == OPEN) - out(frame); - else - throw TransportFailure(errorText.empty() ? "Connection is not open." : errorText); -} - -void ConnectionHandler::waitForOpen() -{ - waitFor(ESTABLISHED); - if (getState() == FAILED) { - throw TransportFailure(errorText); - } else if (getState() == CLOSED) { - throw ConnectionException(errorCode, errorText); - } -} - -void ConnectionHandler::close() -{ - switch (getState()) { - case NEGOTIATING: - case OPENING: - fail("Connection closed before it was established"); - break; - case OPEN: - if (setState(CLOSING, OPEN)) { - proxy.close(200, OK); - if (ConnectionSettings::heartbeat) { - //heartbeat timer is turned off at this stage, so don't wait indefinately - if (!waitFor(FINISHED, qpid::sys::Duration(ConnectionSettings::heartbeat * qpid::sys::TIME_SEC))) { - QPID_LOG(warning, "Connection close timed out"); - } - } else { - waitFor(FINISHED);//FINISHED = CLOSED or FAILED - } - } - //else, state was changed from open after we checked, can only - //change to failed or closed, so nothing to do - break; - - // Nothing to do if already CLOSING, CLOSED, FAILED or if NOT_STARTED - } -} - -void ConnectionHandler::heartbeat() -{ - // Do nothing - the purpose of heartbeats is just to make sure that there is some - // traffic on the connection within the heart beat interval, we check for the - // traffic and don't need to do anything in response to heartbeats - - // Although the above is still true we're now using a received heartbeat as a trigger - // to send out our own heartbeat - proxy.heartbeat(); -} - -void ConnectionHandler::checkState(STATES s, const std::string& msg) -{ - if (getState() != s) { - throw CommandInvalidException(msg); - } -} - -void ConnectionHandler::fail(const std::string& message) -{ - errorCode = CLOSE_CODE_FRAMING_ERROR; - errorText = message; - QPID_LOG(debug, message); - setState(FAILED); -} - -namespace { -std::string SPACE(" "); - -std::string join(const std::vector& in) -{ - std::string result; - for (std::vector::const_iterator i = in.begin(); i != in.end(); ++i) { - if (result.size()) result += SPACE; - result += *i; - } - return result; -} - -void intersection(const std::vector& a, const std::vector& b, std::vector& results) -{ - for (std::vector::const_iterator i = a.begin(); i != a.end(); ++i) { - if (std::find(b.begin(), b.end(), *i) != b.end()) results.push_back(*i); - } -} - -} - -void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& mechanisms, const Array& /*locales*/) -{ - checkState(NOT_STARTED, INVALID_STATE_START); - setState(NEGOTIATING); - sasl = SaslFactory::getInstance().create( username, - password, - service, - host, - minSsf, - maxSsf - ); - - std::vector 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); - } else { - //mechlist is the intersection of those indicated by user and - //those supported by server, in the order listed by user - std::vector allowed = split(mechanism, " "); - std::vector supported(mechanisms.size()); - std::transform(mechanisms.begin(), mechanisms.end(), std::back_inserter(supported), Array::get); - intersection(allowed, supported, mechlist); - if (mechlist.empty()) { - throw Exception(QPID_MSG("Desired mechanism(s) not valid: " << mechanism << " (supported: " << join(supported) << ")")); - } - } - - if (sasl.get()) { - std::string response; - if (sasl->start(join(mechlist), response, getSecuritySettings ? getSecuritySettings() : 0)) { - proxy.startOk(properties, sasl->getMechanism(), response, locale); - } else { - //response was null - ConnectionStartOkBody body; - body.setClientProperties(properties); - body.setMechanism(sasl->getMechanism()); - //Don't set response, as none was given - body.setLocale(locale); - proxy.send(body); - } - } else { - bool haveAnonymous(false); - bool havePlain(false); - for (std::vector::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))); - } - } -} - -void ConnectionHandler::secure(const std::string& challenge) -{ - if (sasl.get()) { - std::string response = sasl->step(challenge); - proxy.secureOk(response); - } else { - throw NotImplementedException("Challenge-response cycle not yet implemented in client"); - } -} - -void ConnectionHandler::tune(uint16_t maxChannelsProposed, uint16_t maxFrameSizeProposed, - uint16_t heartbeatMin, uint16_t heartbeatMax) -{ - checkState(NEGOTIATING, INVALID_STATE_TUNE); - maxChannels = std::min(maxChannels, maxChannelsProposed); - maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed); - // Clip the requested heartbeat to the maximum/minimum offered - uint16_t heartbeat = ConnectionSettings::heartbeat; - heartbeat = heartbeat < heartbeatMin ? heartbeatMin : - heartbeat > heartbeatMax ? heartbeatMax : - heartbeat; - ConnectionSettings::heartbeat = heartbeat; - proxy.tuneOk(maxChannels, maxFrameSize, heartbeat); - setState(OPENING); - proxy.open(virtualhost, capabilities, insist); -} - -void ConnectionHandler::openOk ( const Array& knownBrokers ) -{ - checkState(OPENING, INVALID_STATE_OPEN_OK); - knownBrokersUrls.clear(); - framing::Array::ValueVector::const_iterator i; - for ( i = knownBrokers.begin(); i != knownBrokers.end(); ++i ) - knownBrokersUrls.push_back(Url((*i)->get())); - if (sasl.get()) { - securityLayer = sasl->getSecurityLayer(maxFrameSize); - operUserId = sasl->getUserId(); - } - setState(OPEN); - QPID_LOG(debug, "Known-brokers for connection: " << log::formatList(knownBrokersUrls)); -} - - -void ConnectionHandler::redirect(const std::string& /*host*/, const Array& /*knownHosts*/) -{ - throw NotImplementedException("Redirection received from broker; not yet implemented in client"); -} - -void ConnectionHandler::close(uint16_t replyCode, const std::string& replyText) -{ - proxy.closeOk(); - errorCode = convert(replyCode); - errorText = replyText; - setState(CLOSED); - QPID_LOG(warning, "Broker closed connection: " << replyCode << ", " << replyText); - if (onError) { - onError(replyCode, replyText); - } -} - -void ConnectionHandler::closeOk() -{ - checkState(CLOSING, INVALID_STATE_CLOSE_OK); - if (onError && errorCode != CLOSE_CODE_NORMAL) { - onError(errorCode, errorText); - } else if (onClose) { - onClose(); - } - setState(CLOSED); -} - -bool ConnectionHandler::isOpen() const -{ - return getState() == OPEN; -} - -bool ConnectionHandler::isClosed() const -{ - int s = getState(); - return s == CLOSED || s == FAILED; -} - -bool ConnectionHandler::isClosing() const { return getState() == CLOSING; } - -std::auto_ptr ConnectionHandler::getSecurityLayer() -{ - return securityLayer; -} - -void ConnectionHandler::setRcvTimeoutTask(boost::intrusive_ptr t) -{ - rcvTimeoutTask = t; -} diff --git a/qpid/cpp/src/qpid/client/ConnectionHandler.h b/qpid/cpp/src/qpid/client/ConnectionHandler.h deleted file mode 100644 index 6af2e987fb..0000000000 --- a/qpid/cpp/src/qpid/client/ConnectionHandler.h +++ /dev/null @@ -1,139 +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. - * - */ -#ifndef _ConnectionHandler_ -#define _ConnectionHandler_ - -#include "qpid/client/ChainableFrameHandler.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Sasl.h" -#include "qpid/client/StateManager.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/AMQP_ClientOperations.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/InputHandler.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/Timer.h" -#include "qpid/Url.h" -#include - -namespace qpid { - -namespace sys { -struct SecuritySettings; -} - -namespace client { - -class Bounds; - -class ConnectionHandler : private StateManager, - public ConnectionSettings, - public ChainableFrameHandler, - public framing::InputHandler, - private framing::AMQP_ClientOperations::ConnectionHandler -{ - typedef framing::AMQP_ClientOperations::ConnectionHandler ConnectionOperations; - enum STATES {NOT_STARTED, NEGOTIATING, OPENING, OPEN, CLOSING, CLOSED, FAILED}; - std::set ESTABLISHED, FINISHED; - - class Adapter : public framing::FrameHandler - { - ConnectionHandler& handler; - Bounds& bounds; - public: - Adapter(ConnectionHandler& h, Bounds& bounds); - void handle(framing::AMQFrame& f); - }; - - Adapter outHandler; - framing::AMQP_ServerProxy::Connection proxy; - framing::connection::CloseCode errorCode; - std::string errorText; - bool insist; - framing::ProtocolVersion version; - framing::Array capabilities; - framing::FieldTable properties; - std::auto_ptr sasl; - std::auto_ptr securityLayer; - boost::intrusive_ptr rcvTimeoutTask; - std::string operUserId; - - void checkState(STATES s, const std::string& msg); - - //methods corresponding to connection controls: - void start(const framing::FieldTable& serverProperties, - const framing::Array& mechanisms, - const framing::Array& locales); - void secure(const std::string& challenge); - void tune(uint16_t channelMax, - uint16_t frameMax, - uint16_t heartbeatMin, - uint16_t heartbeatMax); - void openOk(const framing::Array& knownHosts); - void redirect(const std::string& host, - const framing::Array& knownHosts); - void close(uint16_t replyCode, const std::string& replyText); - void closeOk(); - void heartbeat(); - -public: - using InputHandler::handle; - typedef boost::function CloseListener; - typedef boost::function ErrorListener; - typedef boost::function GetSecuritySettings; - - ConnectionHandler(const ConnectionSettings&, framing::ProtocolVersion&, Bounds&); - - void received(framing::AMQFrame& f) { incoming(f); } - - void incoming(framing::AMQFrame& frame); - void outgoing(framing::AMQFrame& frame); - - void waitForOpen(); - void close(); - void fail(const std::string& message); - - // Note that open and closed aren't related by open = !closed - bool isOpen() const; - bool isClosed() const; - bool isClosing() const; - - std::auto_ptr getSecurityLayer(); - void setRcvTimeoutTask(boost::intrusive_ptr); - - CloseListener onClose; - ErrorListener onError; - - std::vector knownBrokersUrls; - - static framing::connection::CloseCode convert(uint16_t replyCode); - const std::string& getUserId() const { return operUserId; } - GetSecuritySettings getSecuritySettings; /** query the transport for its security details */ -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/client/ConnectionImpl.cpp b/qpid/cpp/src/qpid/client/ConnectionImpl.cpp deleted file mode 100644 index 4c2cbc0245..0000000000 --- a/qpid/cpp/src/qpid/client/ConnectionImpl.cpp +++ /dev/null @@ -1,455 +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/client/ConnectionImpl.h" - -#include "qpid/client/LoadPlugins.h" -#include "qpid/client/Connector.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/SessionImpl.h" - -#include "qpid/log/Statement.h" -#include "qpid/Url.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/Options.h" - -#include -#include -#include -#include - -#include -#include - -#include "config.h" - -namespace qpid { -namespace client { - -using namespace qpid::framing; -using namespace qpid::framing::connection; -using namespace qpid::sys; -using namespace qpid::framing::connection;//for connection error codes - -namespace { -// Maybe should amalgamate the singletons into a single client singleton - -// Get timer singleton -Timer& theTimer() { - static Mutex timerInitLock; - ScopedLock l(timerInitLock); - - static qpid::sys::Timer t; - return t; -} - -struct IOThreadOptions : public qpid::Options { - int maxIOThreads; - - IOThreadOptions(int c) : - Options("IO threading options"), - maxIOThreads(c) - { - addOptions() - ("max-iothreads", optValue(maxIOThreads, "N"), "Maximum number of io threads to use"); - } -}; - -// IO threads -class IOThread { - int maxIOThreads; - int ioThreads; - int connections; - Mutex threadLock; - std::vector t; - Poller::shared_ptr poller_; - -public: - void add() { - ScopedLock l(threadLock); - ++connections; - if (!poller_) - poller_.reset(new Poller); - if (ioThreads < connections && ioThreads < maxIOThreads) { - QPID_LOG(debug, "Created IO thread: " << ioThreads); - ++ioThreads; - t.push_back( Thread(poller_.get()) ); - } - } - - void sub() { - ScopedLock l(threadLock); - --connections; - } - - Poller::shared_ptr poller() const { - assert(poller_); - return poller_; - } - - // Here is where the maximum number of threads is set - IOThread(int c) : - ioThreads(0), - connections(0) - { - CommonOptions common("", "", QPIDC_CONF_FILE); - IOThreadOptions options(c); - common.parse(0, 0, common.clientConfig, true); - options.parse(0, 0, common.clientConfig, true); - maxIOThreads = (options.maxIOThreads != -1) ? - options.maxIOThreads : 1; - } - - // We can't destroy threads one-by-one as the only - // control we have is to shutdown the whole lot - // and we can't do that before we're unloaded as we can't - // restart the Poller after shutting it down - ~IOThread() { - if (SystemInfo::threadSafeShutdown()) { - std::vector threads; - { - ScopedLock l(threadLock); - if (poller_) - poller_->shutdown(); - t.swap(threads); - } - for (std::vector::iterator i = threads.begin(); i != threads.end(); ++i) { - i->join(); - } - } - } -}; - -IOThread& theIO() { - static IOThread io(SystemInfo::concurrency()); - return io; -} - -class HeartbeatTask : public TimerTask { - ConnectionImpl& timeout; - - void fire() { - // If we ever get here then we have timed out - QPID_LOG(debug, "Traffic timeout"); - timeout.timeout(); - } - -public: - HeartbeatTask(Duration p, ConnectionImpl& t) : - TimerTask(p,"Heartbeat"), - timeout(t) - {} -}; - -} - -void ConnectionImpl::init() { - // Ensure that the plugin modules have been loaded - // This will make sure that any plugin protocols are available - theModuleLoader(); - - // Ensure the IO threads exist: - // This needs to be called in the Connection constructor - // so that they will still exist at last connection destruction - (void) theIO(); -} - -boost::shared_ptr ConnectionImpl::create(framing::ProtocolVersion version, const ConnectionSettings& settings) -{ - boost::shared_ptr instance(new ConnectionImpl(version, settings), boost::bind(&ConnectionImpl::release, _1)); - return instance; -} - -ConnectionImpl::ConnectionImpl(framing::ProtocolVersion v, const ConnectionSettings& settings) - : Bounds(settings.maxFrameSize * settings.bounds), - handler(settings, v, *this), - version(v), - nextChannel(1), - shutdownComplete(false), - released(false) -{ - handler.in = boost::bind(&ConnectionImpl::incoming, this, _1); - handler.out = boost::bind(&Connector::handle, boost::ref(connector), _1); - handler.onClose = boost::bind(&ConnectionImpl::closed, this, - CLOSE_CODE_NORMAL, std::string()); - //only set error handler once open - handler.onError = boost::bind(&ConnectionImpl::closed, this, _1, _2); - handler.getSecuritySettings = boost::bind(&Connector::getSecuritySettings, boost::ref(connector)); -} - -const uint16_t ConnectionImpl::NEXT_CHANNEL = std::numeric_limits::max(); - -ConnectionImpl::~ConnectionImpl() { - if (heartbeatTask) heartbeatTask->cancel(); - theIO().sub(); -} - -void ConnectionImpl::addSession(const boost::shared_ptr& session, uint16_t channel) -{ - Mutex::ScopedLock l(lock); - for (uint16_t i = 0; i < NEXT_CHANNEL; i++) { //will at most search through channels once - uint16_t c = channel == NEXT_CHANNEL ? nextChannel++ : channel; - boost::weak_ptr& s = sessions[c]; - boost::shared_ptr ss = s.lock(); - if (!ss) { - //channel is free, we can assign it to this session - session->setChannel(c); - s = session; - return; - } else if (channel != NEXT_CHANNEL) { - //channel is taken and was requested explicitly so don't look for another - throw SessionBusyException(QPID_MSG("Channel " << ss->getChannel() << " attached to " << ss->getId())); - } //else channel is busy, but we can keep looking for a free one - } - // If we get here, we didn't find any available channel. - throw ResourceLimitExceededException("There are no channels available"); -} - -void ConnectionImpl::handle(framing::AMQFrame& frame) -{ - handler.outgoing(frame); -} - -void ConnectionImpl::incoming(framing::AMQFrame& frame) -{ - boost::shared_ptr s; - { - Mutex::ScopedLock l(lock); - s = sessions[frame.getChannel()].lock(); - } - if (!s) { - QPID_LOG(info, *this << " dropping frame received on invalid channel: " << frame); - } else { - s->in(frame); - } -} - -bool ConnectionImpl::isOpen() const -{ - return handler.isOpen(); -} - -void ConnectionImpl::open() -{ - const std::string& protocol = handler.protocol; - const std::string& host = handler.host; - int port = handler.port; - - theIO().add(); - connector.reset(Connector::create(protocol, theIO().poller(), version, handler, this)); - connector->setInputHandler(&handler); - connector->setShutdownHandler(this); - try { - std::string p = boost::lexical_cast(port); - connector->connect(host, p); - - } catch (const std::exception& e) { - QPID_LOG(debug, "Failed to connect to " << protocol << ":" << host << ":" << port << " " << e.what()); - connector.reset(); - throw TransportFailure(e.what()); - } - connector->init(); - - // Enable heartbeat if requested - uint16_t heartbeat = static_cast(handler).heartbeat; - if (heartbeat) { - // Set connection timeout to be 2x heart beat interval and setup timer - heartbeatTask = new HeartbeatTask(heartbeat * 2 * TIME_SEC, *this); - handler.setRcvTimeoutTask(heartbeatTask); - theTimer().add(heartbeatTask); - } - - // If the connect fails then the connector is cleaned up either when we try to connect again - // - in that case in connector.reset() above; - // - or when we are deleted - try { - handler.waitForOpen(); - QPID_LOG(info, *this << " connected to " << protocol << ":" << host << ":" << port); - } catch (const Exception&) { - connector->checkVersion(version); - throw; - } - - // If the SASL layer has provided an "operational" userId for the connection, - // put it in the negotiated settings. - const std::string& userId(handler.getUserId()); - if (!userId.empty()) - handler.username = userId; - - //enable security layer if one has been negotiated: - std::auto_ptr securityLayer = handler.getSecurityLayer(); - if (securityLayer.get()) { - QPID_LOG(debug, *this << " activating security layer"); - connector->activateSecurityLayer(securityLayer); - } else { - QPID_LOG(debug, *this << " no security layer in place"); - } -} - -void ConnectionImpl::timeout() -{ - connector->abort(); -} - -void ConnectionImpl::close() -{ - if (heartbeatTask) - heartbeatTask->cancel(); - // close() must be idempotent and no-throw as it will often be called in destructors. - if (handler.isOpen()) { - try { - handler.close(); - closed(CLOSE_CODE_NORMAL, "Closed by client"); - } catch (...) {} - } - assert(!handler.isOpen()); -} - - -template void ConnectionImpl::closeInternal(const F& f) { - if (heartbeatTask) { - heartbeatTask->cancel(); - } - { - Mutex::ScopedUnlock u(lock); - connector->close(); - } - //notifying sessions of failure can result in those session being - //deleted which in turn results in a call to erase(); this can - //even happen on this thread, when 's' goes out of scope - //below. Using a copy prevents the map being modified as we - //iterate through. - SessionMap copy; - sessions.swap(copy); - for (SessionMap::iterator i = copy.begin(); i != copy.end(); ++i) { - boost::shared_ptr s = i->second.lock(); - if (s) f(s); - } -} - -void ConnectionImpl::closed(uint16_t code, const std::string& text) { - Mutex::ScopedLock l(lock); - setException(new ConnectionException(ConnectionHandler::convert(code), text)); - closeInternal(boost::bind(&SessionImpl::connectionClosed, _1, code, text)); -} - -void ConnectionImpl::shutdown() { - if (!handler.isClosed()) { - failedConnection(); - } - bool canDelete; - { - Mutex::ScopedLock l(lock); - //association with IO thread is now ended - shutdownComplete = true; - //If we have already been released, we can now delete ourselves - canDelete = released; - } - if (canDelete) delete this; -} - -void ConnectionImpl::release() { - bool isActive; - { - Mutex::ScopedLock l(lock); - isActive = connector && !shutdownComplete; - } - //If we are still active - i.e. associated with an IO thread - - //then we cannot delete ourselves yet, but must wait for the - //shutdown callback which we can trigger by calling - //connector.close() - if (isActive) { - connector->close(); - bool canDelete; - { - Mutex::ScopedLock l(lock); - released = true; - canDelete = shutdownComplete; - } - if (canDelete) delete this; - } else { - delete this; - } -} - -static const std::string CONN_CLOSED("Connection closed"); - -void ConnectionImpl::failedConnection() { - if ( failureCallback ) - failureCallback(); - - if (handler.isClosed()) return; - - bool isClosing = handler.isClosing(); - bool isOpen = handler.isOpen(); - - std::ostringstream msg; - msg << *this << " closed"; - - // FIXME aconway 2008-06-06: exception use, amqp0-10 does not seem to have - // an appropriate close-code. connection-forced is not right. - handler.fail(msg.str());//ensure connection is marked as failed before notifying sessions - - // At this point if the object isn't open and isn't closing it must have failed to open - // so we can't do the rest of the cleanup - if (!isClosing && !isOpen) return; - - Mutex::ScopedLock l(lock); - closeInternal(boost::bind(&SessionImpl::connectionBroke, _1, msg.str())); - setException(new TransportFailure(msg.str())); -} - -void ConnectionImpl::erase(uint16_t ch) { - Mutex::ScopedLock l(lock); - sessions.erase(ch); -} - -const ConnectionSettings& ConnectionImpl::getNegotiatedSettings() -{ - return handler; -} - -std::vector ConnectionImpl::getInitialBrokers() { - return handler.knownBrokersUrls; -} - -boost::shared_ptr ConnectionImpl::newSession(const std::string& name, uint32_t timeout, uint16_t channel) { - boost::shared_ptr simpl(new SessionImpl(name, shared_from_this())); - addSession(simpl, channel); - simpl->open(timeout); - return simpl; -} - -std::ostream& operator<<(std::ostream& o, const ConnectionImpl& c) { - if (c.connector) - return o << "Connection " << c.connector->getIdentifier(); - else - return o << "Connection "; -} - -void shutdown() { - theIO().poller()->shutdown(); -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/ConnectionImpl.h b/qpid/cpp/src/qpid/client/ConnectionImpl.h deleted file mode 100644 index 23105bd1fd..0000000000 --- a/qpid/cpp/src/qpid/client/ConnectionImpl.h +++ /dev/null @@ -1,107 +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. - * - */ - -#ifndef _ConnectionImpl_ -#define _ConnectionImpl_ - -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionHandler.h" - -#include "qpid/framing/FrameHandler.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/ShutdownHandler.h" - -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace client { - -class Connector; -struct ConnectionSettings; -class SessionImpl; - -class ConnectionImpl : public Bounds, - public framing::FrameHandler, - public sys::ShutdownHandler, - public boost::enable_shared_from_this -{ - typedef std::map > SessionMap; - - static const uint16_t NEXT_CHANNEL; - - SessionMap sessions; - ConnectionHandler handler; - boost::scoped_ptr connector; - framing::ProtocolVersion version; - uint16_t nextChannel; - sys::Mutex lock; - bool shutdownComplete; - bool released; - - boost::intrusive_ptr heartbeatTask; - - template void closeInternal(const F&); - - void incoming(framing::AMQFrame& frame); - void closed(uint16_t, const std::string&); - void shutdown(); - void failedConnection(); - void release(); - ConnectionImpl(framing::ProtocolVersion version, const ConnectionSettings& settings); - - boost::function failureCallback; - - public: - static void init(); - static boost::shared_ptr create(framing::ProtocolVersion version, const ConnectionSettings& settings); - ~ConnectionImpl(); - - void open(); - bool isOpen() const; - - boost::shared_ptr newSession(const std::string& name, uint32_t timeout, uint16_t channel=NEXT_CHANNEL); - void addSession(const boost::shared_ptr&, uint16_t channel=NEXT_CHANNEL); - - void close(); - void timeout(); - void handle(framing::AMQFrame& frame); - void erase(uint16_t channel); - const ConnectionSettings& getNegotiatedSettings(); - - std::vector getInitialBrokers(); - void registerFailureCallback ( boost::function fn ) { failureCallback = fn; } - framing::ProtocolVersion getVersion() { return version; } - - friend std::ostream& operator<<(std::ostream&, const ConnectionImpl&); -}; - -// Shut down the poller early. Internal use only. -QPID_CLIENT_EXTERN void shutdown(); - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/client/ConnectionSettings.cpp b/qpid/cpp/src/qpid/client/ConnectionSettings.cpp deleted file mode 100644 index 3bfde0656b..0000000000 --- a/qpid/cpp/src/qpid/client/ConnectionSettings.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/ConnectionSettings.h" - -#include "qpid/log/Logger.h" -#include "qpid/sys/Socket.h" -#include "qpid/Url.h" -#include "qpid/Version.h" - -namespace qpid { -namespace client { - -ConnectionSettings::ConnectionSettings() : - protocol("tcp"), - host("localhost"), - port(5672), - locale("en_US"), - heartbeat(0), - maxChannels(32767), - maxFrameSize(65535), - bounds(2), - tcpNoDelay(true), - service(qpid::saslName), - minSsf(0), - maxSsf(256), - sslCertName(""), - sslIgnoreHostnameVerificationFailure(false) -{} - -ConnectionSettings::~ConnectionSettings() {} - -void ConnectionSettings::configureSocket(qpid::sys::Socket& socket) const -{ - if (tcpNoDelay) { - socket.setTcpNoDelay(); - QPID_LOG(debug, "Set TCP_NODELAY"); - } -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/ConnectionSettings.h b/qpid/cpp/src/qpid/client/ConnectionSettings.h deleted file mode 100644 index a4b2b59ff7..0000000000 --- a/qpid/cpp/src/qpid/client/ConnectionSettings.h +++ /dev/null @@ -1,145 +0,0 @@ -#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 - -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; - - /** - * If using SSL, connect regardless of hostname verification failure. - */ - bool sslIgnoreHostnameVerificationFailure; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_CONNECTIONSETTINGS_H*/ diff --git a/qpid/cpp/src/qpid/client/Connector.cpp b/qpid/cpp/src/qpid/client/Connector.cpp deleted file mode 100644 index afb3c8a597..0000000000 --- a/qpid/cpp/src/qpid/client/Connector.cpp +++ /dev/null @@ -1,94 +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/client/Connector.h" -#include "qpid/Url.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/framing/ProtocolInitiation.h" - -#include - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; - -namespace { - typedef std::map ProtocolRegistry; - - ProtocolRegistry& theProtocolRegistry() { - static ProtocolRegistry protocolRegistry; - - return protocolRegistry; - } -} - -Connector* Connector::create(const std::string& proto, - boost::shared_ptr p, - framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) -{ - ProtocolRegistry::const_iterator i = theProtocolRegistry().find(proto); - if (i==theProtocolRegistry().end()) { - throw Exception(QPID_MSG("Unknown protocol: " << proto)); - } - return (i->second)(p, v, s, c); -} - -void Connector::registerFactory(const std::string& proto, Factory* connectorFactory) -{ - ProtocolRegistry::const_iterator i = theProtocolRegistry().find(proto); - if (i!=theProtocolRegistry().end()) { - QPID_LOG(error, "Tried to register protocol: " << proto << " more than once"); - } - theProtocolRegistry()[proto] = connectorFactory; - Url::addProtocol(proto); -} - -void Connector::activateSecurityLayer(std::auto_ptr) -{ -} - -bool Connector::checkProtocolHeader(framing::Buffer& in, const framing::ProtocolVersion& version) -{ - if (!header) { - boost::shared_ptr protocolInit(new framing::ProtocolInitiation); - if (protocolInit->decode(in)) { - header = protocolInit; - QPID_LOG(debug, "RECV [" << getIdentifier() << "]: INIT(" << *protocolInit << ")"); - checkVersion(version); - } - } - return header.get(); -} - -void Connector::checkVersion(const framing::ProtocolVersion& version) -{ - if (header && !header->matches(version)){ - throw ProtocolVersionError(QPID_MSG("Incorrect version: " << *header - << "; expected " << version)); - } -} - - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/Connector.h b/qpid/cpp/src/qpid/client/Connector.h deleted file mode 100644 index 49fb48bdf6..0000000000 --- a/qpid/cpp/src/qpid/client/Connector.h +++ /dev/null @@ -1,89 +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. - * - */ -#ifndef _Connector_ -#define _Connector_ - - -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/ProtocolVersion.h" - -#include - -#include - -namespace qpid { - -namespace sys { -class ShutdownHandler; -class SecurityLayer; -class Poller; -struct SecuritySettings; -} - -namespace framing { -class InputHandler; -class AMQFrame; -class Buffer; -class ProtocolInitiation; -} - -namespace client { - -struct ConnectionSettings; -class ConnectionImpl; - -///@internal -class Connector : public framing::FrameHandler -{ - public: - // Protocol connector factory related stuff (it might be better to separate this code from the TCP Connector in the future) - typedef Connector* Factory(boost::shared_ptr, - framing::ProtocolVersion, const ConnectionSettings&, ConnectionImpl*); - static Connector* create(const std::string& proto, - boost::shared_ptr, - framing::ProtocolVersion, const ConnectionSettings&, ConnectionImpl*); - static void registerFactory(const std::string& proto, Factory* connectorFactory); - - virtual ~Connector() {}; - virtual void connect(const std::string& host, const std::string& port) = 0; - virtual void init() {}; - virtual void close() = 0; - virtual void handle(framing::AMQFrame& frame) = 0; - virtual void abort() = 0; - - virtual void setInputHandler(framing::InputHandler* handler) = 0; - virtual void setShutdownHandler(sys::ShutdownHandler* handler) = 0; - virtual const std::string& getIdentifier() const = 0; - - virtual void activateSecurityLayer(std::auto_ptr); - - virtual const qpid::sys::SecuritySettings* getSecuritySettings() = 0; - void checkVersion(const framing::ProtocolVersion& version); - protected: - boost::shared_ptr header; - - bool checkProtocolHeader(framing::Buffer&, const framing::ProtocolVersion& version); -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/client/Demux.cpp b/qpid/cpp/src/qpid/client/Demux.cpp deleted file mode 100644 index abc23c75df..0000000000 --- a/qpid/cpp/src/qpid/client/Demux.cpp +++ /dev/null @@ -1,132 +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/client/Demux.h" -#include "qpid/Exception.h" -#include "qpid/framing/MessageTransferBody.h" - -#include - -namespace qpid { -namespace client { - -ByTransferDest::ByTransferDest(const std::string& d) : dest(d) {} -bool ByTransferDest::operator()(const framing::FrameSet& frameset) const -{ - return frameset.isA() && - frameset.as()->getDestination() == dest; -} - -ScopedDivert::ScopedDivert(const std::string& _dest, Demux& _demuxer) : dest(_dest), demuxer(_demuxer) -{ - queue = demuxer.add(dest, ByTransferDest(dest)); -} - -ScopedDivert::~ScopedDivert() -{ - demuxer.remove(dest); -} - -Demux::Demux() : defaultQueue(new Queue()) {} - -Demux::~Demux() { close(sys::ExceptionHolder(new ClosedException())); } - -Demux::QueuePtr ScopedDivert::getQueue() -{ - return queue; -} - -void Demux::handle(framing::FrameSet::shared_ptr frameset) -{ - sys::Mutex::ScopedLock l(lock); - bool matched = false; - for (iterator i = records.begin(); i != records.end() && !matched; i++) { - if (i->condition && i->condition(*frameset)) { - matched = true; - i->queue->push(frameset); - } - } - if (!matched) { - defaultQueue->push(frameset); - } -} - -void Demux::close(const sys::ExceptionHolder& ex) -{ - sys::Mutex::ScopedLock l(lock); - for (iterator i = records.begin(); i != records.end(); i++) { - i->queue->close(ex); - } - defaultQueue->close(ex); -} - -void Demux::open() -{ - sys::Mutex::ScopedLock l(lock); - for (iterator i = records.begin(); i != records.end(); i++) { - i->queue->open(); - } - defaultQueue->open(); -} - -Demux::QueuePtr Demux::add(const std::string& name, Condition condition) -{ - sys::Mutex::ScopedLock l(lock); - iterator i = std::find_if(records.begin(), records.end(), Find(name)); - if (i == records.end()) { - Record r(name, condition); - records.push_back(r); - return r.queue; - } else { - throw Exception("Queue already exists for " + name); - } -} - -void Demux::remove(const std::string& name) -{ - sys::Mutex::ScopedLock l(lock); - records.remove_if(Find(name)); -} - -Demux::QueuePtr Demux::get(const std::string& name) -{ - sys::Mutex::ScopedLock l(lock); - iterator i = std::find_if(records.begin(), records.end(), Find(name)); - if (i == records.end()) { - throw Exception("No queue for " + name); - } - return i->queue; -} - -Demux::QueuePtr Demux::getDefault() -{ - return defaultQueue; -} - -Demux::Find::Find(const std::string& n) : name(n) {} - -bool Demux::Find::operator()(const Record& record) const -{ - return record.name == name; -} - -}} - diff --git a/qpid/cpp/src/qpid/client/Demux.h b/qpid/cpp/src/qpid/client/Demux.h deleted file mode 100644 index 31dc3f9c06..0000000000 --- a/qpid/cpp/src/qpid/client/Demux.h +++ /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 -#include -#include -#include "qpid/framing/FrameSet.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/client/ClientImportExport.h" - -#ifndef _Demux_ -#define _Demux_ - -namespace qpid { -namespace client { - -///@internal -class ByTransferDest -{ - const std::string dest; -public: - ByTransferDest(const std::string& dest); - bool operator()(const framing::FrameSet& frameset) const; -}; - -///@internal -class Demux -{ -public: - typedef boost::function Condition; - typedef sys::BlockingQueue Queue; - typedef boost::shared_ptr QueuePtr; - - QPID_CLIENT_EXTERN Demux(); - QPID_CLIENT_EXTERN ~Demux(); - - QPID_CLIENT_EXTERN void handle(framing::FrameSet::shared_ptr); - QPID_CLIENT_EXTERN void close(const sys::ExceptionHolder& ex); - QPID_CLIENT_EXTERN void open(); - - QPID_CLIENT_EXTERN QueuePtr add(const std::string& name, Condition); - QPID_CLIENT_EXTERN void remove(const std::string& name); - QPID_CLIENT_EXTERN QueuePtr get(const std::string& name); - QPID_CLIENT_EXTERN QueuePtr getDefault(); - -private: - struct Record - { - const std::string name; - Condition condition; - QueuePtr queue; - - Record(const std::string& n, Condition c) : name(n), condition(c), queue(new Queue()) {} - }; - - sys::Mutex lock; - std::list records; - QueuePtr defaultQueue; - - typedef std::list::iterator iterator; - - struct Find - { - const std::string name; - Find(const std::string& name); - bool operator()(const Record& record) const; - }; -}; - -class ScopedDivert -{ - const std::string dest; - Demux& demuxer; - Demux::QueuePtr queue; -public: - ScopedDivert(const std::string& dest, Demux& demuxer); - ~ScopedDivert(); - Demux::QueuePtr getQueue(); -}; - -}} // namespace qpid::client - - -#endif diff --git a/qpid/cpp/src/qpid/client/Dispatcher.cpp b/qpid/cpp/src/qpid/client/Dispatcher.cpp deleted file mode 100644 index a715c623bf..0000000000 --- a/qpid/cpp/src/qpid/client/Dispatcher.cpp +++ /dev/null @@ -1,151 +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/client/Dispatcher.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/SessionImpl.h" - -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/client/Message.h" -#include "qpid/client/MessageImpl.h" - -#include -#if (BOOST_VERSION >= 104000) -# include - using boost::serialization::state_saver; -#else -# include - using boost::state_saver; -#endif /* BOOST_VERSION */ - -using qpid::framing::FrameSet; -using qpid::framing::MessageTransferBody; -using qpid::sys::Mutex; -using qpid::sys::ScopedLock; -using qpid::sys::Thread; - -namespace qpid { -namespace client { - -Dispatcher::Dispatcher(const Session& s, const std::string& q) - : session(s), - running(false), - autoStop(true), - failoverHandler(0) -{ - Demux& demux = SessionBase_0_10Access(session).get()->getDemux(); - queue = q.empty() ? demux.getDefault() : demux.get(q); -} - -void Dispatcher::start() -{ - worker = Thread(this); -} - -void Dispatcher::wait() -{ - worker.join(); -} - -void Dispatcher::run() -{ - Mutex::ScopedLock l(lock); - if (running) - throw Exception("Dispatcher is already running."); - state_saver reset(running); // Reset to false on exit. - running = true; - try { - while (!queue->isClosed()) { - Mutex::ScopedUnlock u(lock); - FrameSet::shared_ptr content = queue->pop(); - if (content->isA()) { - Message msg(new MessageImpl(*content)); - boost::intrusive_ptr listener = find(msg.getDestination()); - if (!listener) { - QPID_LOG(error, "No listener found for destination " << msg.getDestination()); - } else { - assert(listener); - listener->received(msg); - } - } else { - if (handler.get()) { - handler->handle(*content); - } else { - QPID_LOG(warning, "No handler found for " << *(content->getMethod())); - } - } - } - session.sync(); // Make sure all our acks are received before returning. - } - catch (const ClosedException&) { - QPID_LOG(debug, QPID_MSG(session.getId() << ": closed by peer")); - } - catch (const TransportFailure&) { - QPID_LOG(info, QPID_MSG(session.getId() << ": transport failure")); - throw; - } - catch (const std::exception& e) { - if ( failoverHandler ) { - QPID_LOG(debug, QPID_MSG(session.getId() << " failover: " << e.what())); - failoverHandler(); - } else { - QPID_LOG(error, session.getId() << " error: " << e.what()); - throw; - } - } -} - -void Dispatcher::stop() -{ - ScopedLock l(lock); - queue->close(); // Will interrupt thread blocked in pop() -} - -void Dispatcher::setAutoStop(bool b) -{ - ScopedLock l(lock); - autoStop = b; -} - -boost::intrusive_ptr Dispatcher::find(const std::string& name) -{ - ScopedLock l(lock); - Listeners::iterator i = listeners.find(name); - if (i == listeners.end()) { - return defaultListener; - } - return i->second; -} - -void Dispatcher::listen(const boost::intrusive_ptr& subscription) { - ScopedLock l(lock); - listeners[subscription->getName()] = subscription; -} - -void Dispatcher::cancel(const std::string& destination) { - ScopedLock l(lock); - if (listeners.erase(destination) && running && autoStop && listeners.empty()) - queue->close(); -} - -}} diff --git a/qpid/cpp/src/qpid/client/Dispatcher.h b/qpid/cpp/src/qpid/client/Dispatcher.h deleted file mode 100644 index 74fdb90103..0000000000 --- a/qpid/cpp/src/qpid/client/Dispatcher.h +++ /dev/null @@ -1,87 +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. - * - */ -#ifndef _Dispatcher_ -#define _Dispatcher_ - -#include -#include -#include -#include -#include "qpid/client/Session.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/client/ClientImportExport.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/SubscriptionImpl.h" - -namespace qpid { -namespace client { - -class SubscriptionImpl; - -///@internal -typedef framing::Handler FrameSetHandler; - -///@internal -class Dispatcher : public sys::Runnable -{ - typedef std::map >Listeners; - sys::Mutex lock; - sys::Thread worker; - Session session; - Demux::QueuePtr queue; - bool running; - bool autoStop; - Listeners listeners; - boost::intrusive_ptr defaultListener; - std::auto_ptr handler; - - boost::intrusive_ptr find(const std::string& name); - bool isStopped(); - - boost::function failoverHandler; - -public: - Dispatcher(const Session& session, const std::string& queue = ""); - ~Dispatcher() {} - - void start(); - void wait(); - // As this class is marked 'internal', no extern should be made here; - // however, some test programs rely on it. - QPID_CLIENT_EXTERN void run(); - void stop(); - void setAutoStop(bool b); - - void registerFailoverHandler ( boost::function fh ) - { - failoverHandler = fh; - } - - void listen(const boost::intrusive_ptr& subscription); - void cancel(const std::string& destination); -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/client/Execution.h b/qpid/cpp/src/qpid/client/Execution.h deleted file mode 100644 index ad622af9c1..0000000000 --- a/qpid/cpp/src/qpid/client/Execution.h +++ /dev/null @@ -1,53 +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. - * - */ -#ifndef _Execution_ -#define _Execution_ - -#include "qpid/framing/SequenceNumber.h" -#include "qpid/client/Demux.h" - -namespace qpid { -namespace client { - -/**@internal - * - * Provides access to more detailed aspects of the session - * implementation. - */ -class Execution -{ -public: - virtual ~Execution() {} - /** - * Provides access to the demultiplexing function within the - * session implementation - */ - virtual Demux& getDemux() = 0; - /** - * Wait until notification has been received of completion of the - * outgoing command with the specified id. - */ - void waitForCompletion(const framing::SequenceNumber& id); -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/client/FailoverListener.cpp b/qpid/cpp/src/qpid/client/FailoverListener.cpp deleted file mode 100644 index 1a69182c90..0000000000 --- a/qpid/cpp/src/qpid/client/FailoverListener.cpp +++ /dev/null @@ -1,93 +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/client/FailoverListener.h" -#include "qpid/client/Session.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include "qpid/log/Helpers.h" -#include "qpid/UrlArray.h" - -namespace qpid { -namespace client { - -const std::string FailoverListener::AMQ_FAILOVER("amq.failover"); - -FailoverListener::FailoverListener(Connection c) : - connection(c), - session(c.newSession(AMQ_FAILOVER+"."+framing::Uuid(true).str())), - subscriptions(session) -{ init(true); } - -FailoverListener::FailoverListener(Connection c, bool useInitial) : - connection(c), - session(c.newSession(AMQ_FAILOVER+"."+framing::Uuid(true).str())), - subscriptions(session) -{ init(useInitial); } - -void FailoverListener::init(bool useInitial) { - if (useInitial) knownBrokers = connection.getInitialBrokers(); - if (session.exchangeQuery(arg::name=AMQ_FAILOVER).getNotFound()) { - session.close(); - return; - } - std::string qname=session.getId().getName(); - session.queueDeclare(arg::queue=qname, arg::exclusive=true, arg::autoDelete=true); - session.exchangeBind(arg::queue=qname, arg::exchange=AMQ_FAILOVER); - subscriptions.subscribe(*this, qname, SubscriptionSettings(FlowControl::unlimited(), - ACCEPT_MODE_NONE)); - thread = sys::Thread(*this); -} - -void FailoverListener::run() { - try { - subscriptions.run(); - } catch(...) {} -} - -FailoverListener::~FailoverListener() { - try { - subscriptions.stop(); - thread.join(); - if (connection.isOpen()) { - session.sync(); - session.close(); - } - } catch (...) {} -} - -void FailoverListener::received(Message& msg) { - sys::Mutex::ScopedLock l(lock); - knownBrokers = getKnownBrokers(msg); -} - -std::vector FailoverListener::getKnownBrokers() const { - sys::Mutex::ScopedLock l(lock); - return knownBrokers; -} - -std::vector FailoverListener::getKnownBrokers(const Message& msg) { - framing::Array urlArray; - msg.getHeaders().getArray("amq.failover", urlArray); - return urlArrayToVector(urlArray); -} - - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/FailoverListener.h b/qpid/cpp/src/qpid/client/FailoverListener.h deleted file mode 100644 index 53c7c26211..0000000000 --- a/qpid/cpp/src/qpid/client/FailoverListener.h +++ /dev/null @@ -1,88 +0,0 @@ -#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 - -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 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 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 knownBrokers; -}; -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_FAILOVERLISTENER_H*/ diff --git a/qpid/cpp/src/qpid/client/FailoverManager.cpp b/qpid/cpp/src/qpid/client/FailoverManager.cpp deleted file mode 100644 index f27aeb5b52..0000000000 --- a/qpid/cpp/src/qpid/client/FailoverManager.cpp +++ /dev/null @@ -1,133 +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/client/FailoverManager.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" - - -namespace qpid { -namespace client { - -using qpid::sys::Monitor; -using qpid::sys::AbsTime; -using qpid::sys::Duration; - -FailoverManager::FailoverManager(const ConnectionSettings& s, - ReconnectionStrategy* rs) : settings(s), strategy(rs), state(IDLE) {} - -FailoverManager::~FailoverManager() -{} - -void FailoverManager::execute(Command& c) -{ - bool retry = false; - bool completed = false; - AbsTime failed; - while (!completed) { - try { - AsyncSession session = connect().newSession(); - if (retry) { - Duration failoverTime(failed, AbsTime::now()); - QPID_LOG(info, "Failed over for " << &c << " in " << (failoverTime/qpid::sys::TIME_MSEC) << " milliseconds"); - } - c.execute(session, retry); - session.sync();//TODO: shouldn't be required - session.close(); - completed = true; - } catch(const TransportFailure&) { - retry = true; - failed = AbsTime::now(); - } - } -} - -void FailoverManager::close() -{ - Monitor::ScopedLock l(lock); - connection.close(); -} - -Connection& FailoverManager::connect(std::vector brokers) -{ - Monitor::ScopedLock l(lock); - if (state == CANT_CONNECT) { - state = IDLE;//retry - } - while (!connection.isOpen()) { - if (state == CONNECTING) { - lock.wait(); - } else if (state == CANT_CONNECT) { - throw CannotConnectException("Cannot establish a connection"); - } else { - state = CONNECTING; - Connection c; - if (brokers.empty() && failoverListener.get()) - brokers = failoverListener->getKnownBrokers(); - attempt(c, settings, brokers); - if (c.isOpen()) state = IDLE; - else state = CANT_CONNECT; - connection = c; - lock.notifyAll(); - } - } - return connection; -} - -Connection& FailoverManager::getConnection() -{ - Monitor::ScopedLock l(lock); - return connection; -} - -void FailoverManager::attempt(Connection& c, ConnectionSettings s, std::vector urls) -{ - Monitor::ScopedUnlock u(lock); - if (strategy) strategy->editUrlList(urls); - if (urls.empty()) { - attempt(c, s); - } else { - for (std::vector::const_iterator i = urls.begin(); i != urls.end() && !c.isOpen(); ++i) { - for (Url::const_iterator j = i->begin(); j != i->end() && !c.isOpen(); ++j) { - const Address& addr = *j; - s.protocol = addr.protocol; - s.host = addr.host; - s.port = addr.port; - attempt(c, s); - } - } - } -} - -void FailoverManager::attempt(Connection& c, ConnectionSettings s) -{ - try { - QPID_LOG(info, "Attempting to connect to " << s.host << " on " << s.port << "..."); - c.open(s); - failoverListener.reset(new FailoverListener(c)); - QPID_LOG(info, "Connected to " << s.host << " on " << s.port); - } catch (const Exception& e) { - QPID_LOG(info, "Could not connect to " << s.host << " on " << s.port << ": " << e.what()); - } -} - - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/FailoverManager.h b/qpid/cpp/src/qpid/client/FailoverManager.h deleted file mode 100644 index bc739fd0f5..0000000000 --- a/qpid/cpp/src/qpid/client/FailoverManager.h +++ /dev/null @@ -1,138 +0,0 @@ -#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 - -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& 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 brokers = std::vector()); - /** - * 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; - ConnectionSettings settings; - ReconnectionStrategy* strategy; - State state; - - void attempt(Connection&, ConnectionSettings settings, std::vector 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 deleted file mode 100644 index bff7071b3b..0000000000 --- a/qpid/cpp/src/qpid/client/FlowControl.h +++ /dev/null @@ -1,75 +0,0 @@ -#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 - -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.cpp b/qpid/cpp/src/qpid/client/Future.cpp deleted file mode 100644 index 740cd3df59..0000000000 --- a/qpid/cpp/src/qpid/client/Future.cpp +++ /dev/null @@ -1,46 +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/client/Future.h" -#include "qpid/client/SessionImpl.h" - -namespace qpid { -namespace client { - -void Future::wait(SessionImpl& session) -{ - if (!complete) { - session.waitForCompletion(command); - } - complete = true; -} - -bool Future::isComplete(SessionImpl& session) -{ - return complete || session.isComplete(command); -} - -void Future::setFutureResult(boost::shared_ptr r) -{ - result = r; -} - -}} diff --git a/qpid/cpp/src/qpid/client/Future.h b/qpid/cpp/src/qpid/client/Future.h deleted file mode 100644 index 630a7e03c0..0000000000 --- a/qpid/cpp/src/qpid/client/Future.h +++ /dev/null @@ -1,59 +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. - * - */ - -#ifndef _Future_ -#define _Future_ - -#include -#include -#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 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 r); -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/client/FutureCompletion.cpp b/qpid/cpp/src/qpid/client/FutureCompletion.cpp deleted file mode 100644 index ccfb073855..0000000000 --- a/qpid/cpp/src/qpid/client/FutureCompletion.cpp +++ /dev/null @@ -1,48 +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/client/FutureCompletion.h" - -using namespace qpid::client; -using namespace qpid::sys; - -FutureCompletion::FutureCompletion() : complete(false) {} - -bool FutureCompletion::isComplete() const -{ - Monitor::ScopedLock l(lock); - return complete; -} - -void FutureCompletion::completed() -{ - Monitor::ScopedLock l(lock); - complete = true; - lock.notifyAll(); -} - -void FutureCompletion::waitForCompletion() const -{ - Monitor::ScopedLock l(lock); - while (!complete) { - lock.wait(); - } -} diff --git a/qpid/cpp/src/qpid/client/FutureCompletion.h b/qpid/cpp/src/qpid/client/FutureCompletion.h deleted file mode 100644 index 0970f494b7..0000000000 --- a/qpid/cpp/src/qpid/client/FutureCompletion.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _FutureCompletion_ -#define _FutureCompletion_ - -#include "qpid/framing/amqp_framing.h" -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace client { - -///@internal -class FutureCompletion -{ -protected: - mutable sys::Monitor lock; - bool complete; - -public: - FutureCompletion(); - virtual ~FutureCompletion(){} - bool isComplete() const; - void waitForCompletion() const; - void completed(); -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/client/FutureResult.cpp b/qpid/cpp/src/qpid/client/FutureResult.cpp deleted file mode 100644 index 0237eb1464..0000000000 --- a/qpid/cpp/src/qpid/client/FutureResult.cpp +++ /dev/null @@ -1,43 +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/client/FutureResult.h" - -#include "qpid/client/SessionImpl.h" - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -const std::string& FutureResult::getResult(SessionImpl& session) const -{ - waitForCompletion(); - session.assertOpen(); - return result; -} - -void FutureResult::received(const std::string& r) -{ - Monitor::ScopedLock l(lock); - result = r; - complete = true; - lock.notifyAll(); -} diff --git a/qpid/cpp/src/qpid/client/FutureResult.h b/qpid/cpp/src/qpid/client/FutureResult.h deleted file mode 100644 index ead4929571..0000000000 --- a/qpid/cpp/src/qpid/client/FutureResult.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _FutureResult_ -#define _FutureResult_ - -#include - -#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 deleted file mode 100644 index 859dca4029..0000000000 --- a/qpid/cpp/src/qpid/client/Handle.h +++ /dev/null @@ -1,72 +0,0 @@ -#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 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 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& h) { T* t = h.impl; h.impl = impl; impl = t; } - - private: - // Not implemented,subclasses must implement. - Handle(const Handle&); - Handle& operator=(const Handle&); - - protected: - typedef T Impl; - QPID_CLIENT_INLINE_EXTERN Handle() :impl() {} - - Impl* impl; - - friend class PrivateImplRef; // FIXME aconway 2009-04-30: Specify -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_HANDLE_H*/ diff --git a/qpid/cpp/src/qpid/client/LoadPlugins.cpp b/qpid/cpp/src/qpid/client/LoadPlugins.cpp deleted file mode 100644 index 65a43c4012..0000000000 --- a/qpid/cpp/src/qpid/client/LoadPlugins.cpp +++ /dev/null @@ -1,66 +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 "LoadPlugins.h" - -#include "qpid/Modules.h" -#include "qpid/sys/Shlib.h" - -#include -#include - -#include "config.h" - -using std::vector; -using std::string; - -namespace qpid { -namespace client { - -namespace { - -struct LoadtimeInitialise { - LoadtimeInitialise() { - CommonOptions common("", "", QPIDC_CONF_FILE); - qpid::ModuleOptions moduleOptions(QPIDC_MODULE_DIR); - string defaultPath (moduleOptions.loadDir); - common.parse(0, 0, common.clientConfig, true); - moduleOptions.parse (0, 0, common.clientConfig, true); - - for (vector::iterator iter = moduleOptions.load.begin(); - iter != moduleOptions.load.end(); - iter++) - qpid::tryShlib (*iter); - - if (!moduleOptions.noLoad) { - bool isDefault = defaultPath == moduleOptions.loadDir; - qpid::loadModuleDir (moduleOptions.loadDir, isDefault); - } - } -}; - -} // namespace - -void theModuleLoader() { - static LoadtimeInitialise l; -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/LoadPlugins.h b/qpid/cpp/src/qpid/client/LoadPlugins.h deleted file mode 100644 index 0b398f6831..0000000000 --- a/qpid/cpp/src/qpid/client/LoadPlugins.h +++ /dev/null @@ -1,35 +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. - * - */ - -#ifndef _LoadPlugins_ -#define _LoadPlugins_ - -#include "qpid/client/ClientImportExport.h" - -namespace qpid { -namespace client { - -QPID_CLIENT_EXTERN void theModuleLoader(); - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/client/LocalQueue.cpp b/qpid/cpp/src/qpid/client/LocalQueue.cpp deleted file mode 100644 index 0019adabaf..0000000000 --- a/qpid/cpp/src/qpid/client/LocalQueue.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 "qpid/client/LocalQueue.h" -#include "qpid/client/LocalQueueImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/Exception.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/client/SubscriptionImpl.h" - -namespace qpid { -namespace client { - -using namespace framing; - -typedef PrivateImplRef PI; - -LocalQueue::LocalQueue() { PI::ctor(*this, new LocalQueueImpl()); } -LocalQueue::LocalQueue(const LocalQueue& x) : Handle() { PI::copy(*this, x); } -LocalQueue::~LocalQueue() { PI::dtor(*this); } -LocalQueue& LocalQueue::operator=(const LocalQueue& x) { return PI::assign(*this, x); } - -Message LocalQueue::pop(sys::Duration timeout) { return impl->pop(timeout); } - -Message LocalQueue::get(sys::Duration timeout) { return impl->get(timeout); } - -bool LocalQueue::get(Message& result, sys::Duration timeout) { return impl->get(result, timeout); } - -bool LocalQueue::empty() const { return impl->empty(); } -size_t LocalQueue::size() const { return impl->size(); } - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/LocalQueue.h b/qpid/cpp/src/qpid/client/LocalQueue.h deleted file mode 100644 index 1a19a8499d..0000000000 --- a/qpid/cpp/src/qpid/client/LocalQueue.h +++ /dev/null @@ -1,120 +0,0 @@ -#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 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 - * - *
- * LocalQueue local_queue;
- * subscriptions.subscribe(local_queue, string("message_queue"));
- * for (int i=0; i<10; i++) {
- *   Message message = local_queue.get();
- *   std::cout << message.getData() << std::endl;
- * }
- * 
- * - *

Getting Messages

- * - *
  • - *

    get()

    - *
    Message message = local_queue.get();
    - *
    // Specifying timeouts (TIME_SEC, TIME_MSEC, TIME_USEC, TIME_NSEC)
    - *#include 
    - *Message message;
    - *local_queue.get(message, 5*sys::TIME_SEC);
- * - *

Checking size

- *
  • - *

    empty()

    - *
    if (local_queue.empty()) { ... }
  • - *
  • size()

    - *
    std::cout << local_queue.size();
  • - *
- */ - -class QPID_CLIENT_CLASS_EXTERN LocalQueue : public Handle { - 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; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_LOCALQUEUE_H*/ diff --git a/qpid/cpp/src/qpid/client/LocalQueueImpl.cpp b/qpid/cpp/src/qpid/client/LocalQueueImpl.cpp deleted file mode 100644 index 8b191728f4..0000000000 --- a/qpid/cpp/src/qpid/client/LocalQueueImpl.cpp +++ /dev/null @@ -1,78 +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/client/LocalQueueImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/Exception.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/CompletionImpl.h" - -namespace qpid { -namespace client { - -using namespace framing; - -Message LocalQueueImpl::pop(sys::Duration timeout) { return get(timeout); } - -Message LocalQueueImpl::get(sys::Duration timeout) { - Message result; - bool ok = get(result, timeout); - if (!ok) throw Exception("Timed out waiting for a message"); - return result; -} - -bool LocalQueueImpl::get(Message& result, sys::Duration timeout) { - if (!queue) - throw ClosedException(); - FrameSet::shared_ptr content; - bool ok = queue->pop(content, timeout); - if (!ok) return false; - if (content->isA()) { - - *MessageImpl::get(result) = MessageImpl(*content); - boost::intrusive_ptr si = PrivateImplRef::get(subscription); - assert(si); - if (si) si->received(result); - return true; - } - else - throw CommandInvalidException( - QPID_MSG("Unexpected method: " << content->getMethod())); -} - -bool LocalQueueImpl::empty() const -{ - if (!queue) - throw ClosedException(); - return queue->empty(); -} - -size_t LocalQueueImpl::size() const -{ - if (!queue) - throw ClosedException(); - return queue->size(); -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/LocalQueueImpl.h b/qpid/cpp/src/qpid/client/LocalQueueImpl.h deleted file mode 100644 index 75b62cf203..0000000000 --- a/qpid/cpp/src/qpid/client/LocalQueueImpl.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef QPID_CLIENT_LOCALQUEUEIMPL_H -#define QPID_CLIENT_LOCALQUEUEIMPL_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/client/Subscription.h" -#include "qpid/client/Demux.h" -#include "qpid/sys/Time.h" -#include "qpid/RefCounted.h" - -namespace qpid { -namespace client { - -/** - * 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 - * - *
- * LocalQueue local_queue;
- * subscriptions.subscribe(local_queue, string("message_queue"));
- * for (int i=0; i<10; i++) {
- *   Message message = local_queue.get();
- *   std::cout << message.getData() << std::endl;
- * }
- * 
- * - *

Getting Messages

- * - *
  • - *

    get()

    - *
    Message message = local_queue.get();
    - *
    // Specifying timeouts (TIME_SEC, TIME_MSEC, TIME_USEC, TIME_NSEC)
    - *#include 
    - *Message message;
    - *local_queue.get(message, 5*sys::TIME_SEC);
- * - *

Checking size

- *
  • - *

    empty()

    - *
    if (local_queue.empty()) { ... }
  • - *
  • size()

    - *
    std::cout << local_queue.size();
  • - *
- */ - -class LocalQueueImpl : public RefCounted { - public: - /** 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. - */ - 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. - */ - Message get(sys::Duration timeout=sys::TIME_INFINITE); - - /** Synonym for get() */ - Message pop(sys::Duration timeout=sys::TIME_INFINITE); - - /** Return true if local queue is empty. */ - bool empty() const; - - /** Number of messages on the local queue */ - size_t size() const; - - private: - Demux::QueuePtr queue; - Subscription subscription; - friend class SubscriptionManagerImpl; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_LOCALQUEUEIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/Message.cpp b/qpid/cpp/src/qpid/client/Message.cpp deleted file mode 100644 index 00f911c57e..0000000000 --- a/qpid/cpp/src/qpid/client/Message.cpp +++ /dev/null @@ -1,62 +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/client/Message.h" -#include "qpid/client/MessageImpl.h" - -namespace qpid { -namespace client { - -Message::Message(MessageImpl* mi) : impl(mi) {} - -Message::Message(const std::string& data, const std::string& routingKey) - : impl(new MessageImpl(data, routingKey)) {} - -Message::Message(const Message& m) : impl(new MessageImpl(*m.impl)) {} - -Message::~Message() { delete impl; } - -Message& Message::operator=(const Message& m) { *impl = *m.impl; return *this; } - -void Message::swap(Message& m) { std::swap(impl, m.impl); } - -std::string Message::getDestination() const { return impl->getDestination(); } -bool Message::isRedelivered() const { return impl->isRedelivered(); } -void Message::setRedelivered(bool redelivered) { impl->setRedelivered(redelivered); } -framing::FieldTable& Message::getHeaders() { return impl->getHeaders(); } -const framing::FieldTable& Message::getHeaders() const { return impl->getHeaders(); } -const framing::SequenceNumber& Message::getId() const { return impl->getId(); } - -void Message::setData(const std::string& s) { impl->setData(s); } -const std::string& Message::getData() const { return impl->getData(); } -std::string& Message::getData() { return impl->getData(); } - -void Message::appendData(const std::string& s) { impl->appendData(s); } - -bool Message::hasMessageProperties() const { return impl->hasMessageProperties(); } -framing::MessageProperties& Message::getMessageProperties() { return impl->getMessageProperties(); } -const framing::MessageProperties& Message::getMessageProperties() const { return impl->getMessageProperties(); } - -bool Message::hasDeliveryProperties() const { return impl->hasDeliveryProperties(); } -framing::DeliveryProperties& Message::getDeliveryProperties() { return impl->getDeliveryProperties(); } -const framing::DeliveryProperties& Message::getDeliveryProperties() const { return impl->getDeliveryProperties(); } - -}} diff --git a/qpid/cpp/src/qpid/client/Message.h b/qpid/cpp/src/qpid/client/Message.h deleted file mode 100644 index ba50dda9ba..0000000000 --- a/qpid/cpp/src/qpid/client/Message.h +++ /dev/null @@ -1,175 +0,0 @@ -#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 - -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 - * - *

Getting and setting message contents

- * - *
    - *
  • - *

    getData()

    - *
    std::cout << "Response: " << message.getData() << std::endl;
    - *
  • - *
  • - *

    setData()

    - *
    message.setData("That's all, folks!");
  • - *
  • - *

    appendData()

    - *
    message.appendData(" ... let's add a bit more ...");
  • - *
- * - *

Getting and Setting Delivery Properties

- * - *
    - *
  • - *

    getDeliveryProperties()

    - *
    message.getDeliveryProperties().setRoutingKey("control");
    - *
    message.getDeliveryProperties().setDeliveryMode(PERSISTENT);
    - *
    message.getDeliveryProperties().setPriority(9);
    - *
    message.getDeliveryProperties().setTtl(100);
  • - * - *
  • - *

    hasDeliveryProperties()

    - *
    if (! message.hasDeliveryProperties()) {
    - *  ...
    - *}
  • - *
- * - *

Getting and Setting Message Properties

- * - *
    - *
  • - *

    getMessageProperties()

    - *
    - *request.getMessageProperties().setReplyTo(ReplyTo("amq.direct", response_queue.str()));
    - * 
    - *
    - *routingKey = request.getMessageProperties().getReplyTo().getRoutingKey();
    - *exchange = request.getMessageProperties().getReplyTo().getExchange();
    - * 
    - *
    message.getMessageProperties().setContentType("text/plain");
    - *
    message.getMessageProperties().setContentEncoding("text/plain");
    - *
  • - *
  • - *

    hasMessageProperties()

    - *
    request.getMessageProperties().hasReplyTo();
    - *
  • - *
- * - *

Getting and Setting Application Headers

- * - *
    - *
  • - *

    getHeaders()

    - *
    - *message.getHeaders().getString("control");
    - * 
    - *
    - *message.getHeaders().setString("control","continue");
    - * 
  • - *
- * - * - */ -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/MessageImpl.cpp b/qpid/cpp/src/qpid/client/MessageImpl.cpp deleted file mode 100644 index 865c462b15..0000000000 --- a/qpid/cpp/src/qpid/client/MessageImpl.cpp +++ /dev/null @@ -1,71 +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/client/MessageImpl.h" - -namespace qpid { -namespace client { - -MessageImpl::MessageImpl(const std::string& data, const std::string& routingKey) : TransferContent(data, routingKey) {} - -std::string MessageImpl::getDestination() const -{ - return method.getDestination(); -} - -bool MessageImpl::isRedelivered() const -{ - return hasDeliveryProperties() && getDeliveryProperties().getRedelivered(); -} - -void MessageImpl::setRedelivered(bool redelivered) -{ - getDeliveryProperties().setRedelivered(redelivered); -} - -framing::FieldTable& MessageImpl::getHeaders() -{ - return getMessageProperties().getApplicationHeaders(); -} - -const framing::FieldTable& MessageImpl::getHeaders() const -{ - return getMessageProperties().getApplicationHeaders(); -} - -const framing::MessageTransferBody& MessageImpl::getMethod() const -{ - return method; -} - -const framing::SequenceNumber& MessageImpl::getId() const -{ - return id; -} - -/**@internal for incoming messages */ -MessageImpl::MessageImpl(const framing::FrameSet& frameset) : - method(*frameset.as()), id(frameset.getId()) -{ - populate(frameset); -} - -}} diff --git a/qpid/cpp/src/qpid/client/MessageImpl.h b/qpid/cpp/src/qpid/client/MessageImpl.h deleted file mode 100644 index a64ddd20d8..0000000000 --- a/qpid/cpp/src/qpid/client/MessageImpl.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef QPID_CLIENT_MESSAGEIMPL_H -#define QPID_CLIENT_MESSAGEIMPL_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/Message.h" -#include "qpid/client/Session.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/TransferContent.h" -#include - -namespace qpid { -namespace client { - -class MessageImpl : public framing::TransferContent -{ -public: - /** Create a Message. - *@param data Data for the message body. - *@param routingKey Passed to the exchange that routes the message. - */ - MessageImpl(const std::string& data=std::string(), - const std::string& routingKey=std::string()); - - /** 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.) - */ - std::string getDestination() const; - - /** Check the redelivered flag. */ - bool isRedelivered() const; - /** Set the redelivered flag. */ - void setRedelivered(bool redelivered); - - /** Get a modifyable reference to the message headers. */ - framing::FieldTable& getHeaders(); - - /** Get a non-modifyable reference to the message headers. */ - const framing::FieldTable& getHeaders() const; - - ///@internal - const framing::MessageTransferBody& getMethod() const; - ///@internal - const framing::SequenceNumber& getId() const; - - /**@internal for incoming messages */ - MessageImpl(const framing::FrameSet& frameset); - - static MessageImpl* get(Message& m) { return m.impl; } - static const MessageImpl* get(const Message& m) { return m.impl; } - -private: - //method and id are only set for received messages: - framing::MessageTransferBody method; - framing::SequenceNumber id; -}; - -}} - -#endif /*!QPID_CLIENT_MESSAGEIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/MessageListener.cpp b/qpid/cpp/src/qpid/client/MessageListener.cpp deleted file mode 100644 index 0f2a71287c..0000000000 --- a/qpid/cpp/src/qpid/client/MessageListener.cpp +++ /dev/null @@ -1,24 +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/client/MessageListener.h" - -qpid::client::MessageListener::~MessageListener() {} diff --git a/qpid/cpp/src/qpid/client/MessageListener.h b/qpid/cpp/src/qpid/client/MessageListener.h deleted file mode 100644 index 3ca2fa964a..0000000000 --- a/qpid/cpp/src/qpid/client/MessageListener.h +++ /dev/null @@ -1,101 +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 -#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 - * - *

Using a MessageListener

- * - *
    - *
  • - *

    The received() function is called when a message arrives:

    - *
    virtual void received(Message& message)=0;
    - *
  • - *
  • - *

    Derive your own listener, implement the received() function:

    - *
    -     * class Listener : public MessageListener {
    -     *  private:
    -     *    SubscriptionManager& subscriptions;
    -     *  public:
    -     *    Listener(SubscriptionManager& subscriptions);
    -     *    virtual void received(Message& message);
    -     * };
    -     *
    -     * Listener::Listener(SubscriptionManager& subs) : subscriptions(subs)
    -     * {}
    -     *
    -     * void Listener::received(Message& message) {
    -     *   std::cout << "Message: " << message.getData() << std::endl;
    -     *   if (message.getData() == "That's all, folks!") {
    -     *       std::cout << "Shutting down listener for " << message.getDestination()
    -     *                << std::endl;
    -     *       subscriptions.cancel(message.getDestination());
    -     *   }
    -     * }
    -     *
    - *
    -     * 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();
    -     * 
    - *
  • - *
- * - */ - - 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.cpp b/qpid/cpp/src/qpid/client/MessageReplayTracker.cpp deleted file mode 100644 index 3afaae74e8..0000000000 --- a/qpid/cpp/src/qpid/client/MessageReplayTracker.cpp +++ /dev/null @@ -1,78 +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/client/MessageReplayTracker.h" -#include - -namespace qpid { -namespace client { - -MessageReplayTracker::MessageReplayTracker(uint f) : flushInterval(f), count(0) {} - -void MessageReplayTracker::send(const Message& message, const std::string& destination) -{ - buffer.push_back(ReplayRecord(message, destination)); - buffer.back().send(*this); - if (flushInterval && (++count % flushInterval == 0)) { - checkCompletion(); - if (!buffer.empty()) session.flush(); - } -} -void MessageReplayTracker::init(AsyncSession s) -{ - session = s; -} - -void MessageReplayTracker::replay(AsyncSession s) -{ - session = s; - std::for_each(buffer.begin(), buffer.end(), boost::bind(&ReplayRecord::send, _1, boost::ref(*this))); - session.flush(); - count = 0; -} - -void MessageReplayTracker::setFlushInterval(uint f) -{ - flushInterval = f; -} - -uint MessageReplayTracker::getFlushInterval() -{ - return flushInterval; -} - -void MessageReplayTracker::checkCompletion() -{ - buffer.remove_if(boost::bind(&ReplayRecord::isComplete, _1)); -} - -MessageReplayTracker::ReplayRecord::ReplayRecord(const Message& m, const std::string& d) : message(m), destination(d) {} - -void MessageReplayTracker::ReplayRecord::send(MessageReplayTracker& tracker) -{ - status = tracker.session.messageTransfer(arg::destination=destination, arg::content=message); -} - -bool MessageReplayTracker::ReplayRecord::isComplete() -{ - return status.isComplete(); -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/MessageReplayTracker.h b/qpid/cpp/src/qpid/client/MessageReplayTracker.h deleted file mode 100644 index 06a3f29c7d..0000000000 --- a/qpid/cpp/src/qpid/client/MessageReplayTracker.h +++ /dev/null @@ -1,73 +0,0 @@ -#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 -#include - -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 void foreach(F& f) { - for (std::list::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 buffer; -}; -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_MESSAGEREPLAYTRACKER_H*/ diff --git a/qpid/cpp/src/qpid/client/PrivateImplRef.h b/qpid/cpp/src/qpid/client/PrivateImplRef.h deleted file mode 100644 index fa89b1bfa0..0000000000 --- a/qpid/cpp/src/qpid/client/PrivateImplRef.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef QPID_CLIENT_PRIVATEIMPL_H -#define QPID_CLIENT_PRIVATEIMPL_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 -#include "qpid/RefCounted.h" - -namespace qpid { -namespace client { - -// FIXME aconway 2009-04-24: details! -/** @file - * - * Helper class to implement a class with a private, reference counted - * implementation and reference semantics. - * - * Such classes are used in the public API to hide implementation, they - * should. Example of use: - * - * === Foo.h - * - * template PrivateImplRef; - * class FooImpl; - * - * Foo : public Handle { - * public: - * Foo(FooImpl* = 0); - * Foo(const Foo&); - * ~Foo(); - * Foo& operator=(const Foo&); - * - * int fooDo(); // and other Foo functions... - * - * private: - * typedef FooImpl Impl; - * Impl* impl; - * friend class PrivateImplRef; - * - * === Foo.cpp - * - * typedef PrivateImplRef PI; - * Foo::Foo(FooImpl* p) { PI::ctor(*this, p); } - * Foo::Foo(const Foo& c) : Handle() { PI::copy(*this, c); } - * Foo::~Foo() { PI::dtor(*this); } - * Foo& Foo::operator=(const Foo& c) { return PI::assign(*this, c); } - * - * int foo::fooDo() { return impl->fooDo(); } - * - */ -template class PrivateImplRef { - public: - typedef typename T::Impl Impl; - typedef boost::intrusive_ptr intrusive_ptr; - - static intrusive_ptr get(const T& t) { return intrusive_ptr(t.impl); } - - static void set(T& t, const intrusive_ptr& p) { - if (t.impl == p) return; - if (t.impl) intrusive_ptr_release(t.impl); - t.impl = p.get(); - if (t.impl) intrusive_ptr_add_ref(t.impl); - } - - // Helper functions to implement the ctor, dtor, copy, assign - static void ctor(T& t, Impl* p) { t.impl = p; if (p) intrusive_ptr_add_ref(p); } - static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); } - static void dtor(T& t) { if(t.impl) intrusive_ptr_release(t.impl); } - static T& assign(T& t, const T& x) { set(t, get(x)); return t;} -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_PRIVATEIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/QueueOptions.cpp b/qpid/cpp/src/qpid/client/QueueOptions.cpp deleted file mode 100644 index f7705afeb0..0000000000 --- a/qpid/cpp/src/qpid/client/QueueOptions.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/QueueOptions.h" - -namespace qpid { -namespace client { - -enum QueueEventGeneration {ENQUEUE_ONLY=1, ENQUEUE_AND_DEQUEUE=2}; - - -QueueOptions::QueueOptions() -{} - -const std::string QueueOptions::strMaxCountKey("qpid.max_count"); -const std::string QueueOptions::strMaxSizeKey("qpid.max_size"); -const std::string QueueOptions::strTypeKey("qpid.policy_type"); -const std::string QueueOptions::strREJECT("reject"); -const std::string QueueOptions::strFLOW_TO_DISK("flow_to_disk"); -const std::string QueueOptions::strRING("ring"); -const std::string QueueOptions::strRING_STRICT("ring_strict"); -const std::string QueueOptions::strLastValueQueue("qpid.last_value_queue"); -const std::string QueueOptions::strLVQMatchProperty("qpid.LVQ_key"); -const std::string QueueOptions::strLastValueQueueNoBrowse("qpid.last_value_queue_no_browse"); - -QueueOptions::~QueueOptions() -{} - -void QueueOptions::setSizePolicy(QueueSizePolicy sp, uint64_t maxSize, uint32_t maxCount) -{ - if (maxCount) setUInt64(strMaxCountKey, maxCount); - if (maxSize) setUInt64(strMaxSizeKey, maxSize); - if (maxSize || maxCount){ - switch (sp) - { - case REJECT: - setString(strTypeKey, strREJECT); - break; - case FLOW_TO_DISK: - setString(strTypeKey, strFLOW_TO_DISK); - break; - case RING: - setString(strTypeKey, strRING); - break; - case RING_STRICT: - setString(strTypeKey, strRING_STRICT); - break; - case NONE: - clearSizePolicy(); - break; - } - } -} - - -void QueueOptions::setOrdering(QueueOrderingPolicy op) -{ - if (op == LVQ){ - setInt(strLastValueQueue, 1); - }else if (op == LVQ_NO_BROWSE){ - setInt(strLastValueQueueNoBrowse, 1); - }else { - clearOrdering(); - } -} - -void QueueOptions::getLVQKey(std::string& key) -{ - key.assign(strLVQMatchProperty); -} - -void QueueOptions::clearSizePolicy() -{ - erase(strMaxCountKey); - erase(strMaxSizeKey); - erase(strTypeKey); -} - -void QueueOptions::clearOrdering() -{ - erase(strLastValueQueue); -} - -} -} - - diff --git a/qpid/cpp/src/qpid/client/QueueOptions.h b/qpid/cpp/src/qpid/client/QueueOptions.h deleted file mode 100644 index f7ace15ff9..0000000000 --- a/qpid/cpp/src/qpid/client/QueueOptions.h +++ /dev/null @@ -1,95 +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/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 ); - - /** - * 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(); - - /** - * 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(); - - 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 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/RdmaConnector.cpp b/qpid/cpp/src/qpid/client/RdmaConnector.cpp deleted file mode 100644 index 77762343e2..0000000000 --- a/qpid/cpp/src/qpid/client/RdmaConnector.cpp +++ /dev/null @@ -1,420 +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/client/Connector.h" - -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/Msg.h" - -#include -#include -#include -#include - -// This stuff needs to abstracted out of here to a platform specific file -#include - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; -using boost::format; -using boost::str; - -class RdmaConnector : public Connector, public sys::Codec -{ - typedef std::deque Frames; - - const uint16_t maxFrameSize; - sys::Mutex lock; - Frames frames; - size_t lastEof; // Position after last EOF in frames - uint64_t currentSize; - Bounds* bounds; - - framing::ProtocolVersion version; - bool initiated; - - sys::Mutex dataConnectedLock; - bool dataConnected; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - framing::InitiationHandler* initialiser; - framing::FrameHandler* output; - - Rdma::AsynchIO* aio; - Rdma::Connector* acon; - sys::Poller::shared_ptr poller; - std::auto_ptr securityLayer; - - ~RdmaConnector(); - - // Callbacks - void connected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&); - void connectionError(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, Rdma::ErrorType); - void disconnected(); - void rejected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&); - - void readbuff(Rdma::AsynchIO&, Rdma::Buffer*); - void writebuff(Rdma::AsynchIO&); - void writeDataBlock(const framing::AMQDataBlock& data); - void dataError(Rdma::AsynchIO&); - void drained(); - void connectionStopped(Rdma::Connector* acon, Rdma::AsynchIO* aio); - void dataStopped(Rdma::AsynchIO* aio); - - std::string identifier; - - void connect(const std::string& host, const std::string& port); - void close(); - void handle(framing::AMQFrame& frame); - void abort() {} // TODO: need to fix this for heartbeat timeouts to work - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - const std::string& getIdentifier() const; - void activateSecurityLayer(std::auto_ptr); - const qpid::sys::SecuritySettings* getSecuritySettings() { return 0; } - - size_t decode(const char* buffer, size_t size); - size_t encode(char* buffer, size_t size); - bool canEncode(); - -public: - RdmaConnector(Poller::shared_ptr, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - return new RdmaConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - Connector::registerFactory("rdma", &create); - Connector::registerFactory("ib", &create); - }; - } init; -} - - -RdmaConnector::RdmaConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - lastEof(0), - currentSize(0), - bounds(cimpl), - version(ver), - initiated(false), - dataConnected(false), - shutdownHandler(0), - aio(0), - acon(0), - poller(p) -{ - QPID_LOG(debug, "RdmaConnector created for " << version); -} - -namespace { - void deleteAsynchIO(Rdma::AsynchIO& aio) { - delete &aio; - } - - void deleteConnector(Rdma::ConnectionManager& con) { - delete &con; - } -} - -RdmaConnector::~RdmaConnector() { - QPID_LOG(debug, "~RdmaConnector " << identifier); - if (aio) { - aio->stop(deleteAsynchIO); - } - if (acon) { - acon->stop(deleteConnector); - } -} - -void RdmaConnector::connect(const std::string& host, const std::string& port){ - Mutex::ScopedLock l(dataConnectedLock); - assert(!dataConnected); - - acon = new Rdma::Connector( - Rdma::ConnectionParams(maxFrameSize, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&RdmaConnector::connected, this, poller, _1, _2), - boost::bind(&RdmaConnector::connectionError, this, poller, _1, _2), - boost::bind(&RdmaConnector::disconnected, this), - boost::bind(&RdmaConnector::rejected, this, poller, _1, _2)); - - SocketAddress sa(host, port); - acon->start(poller, sa); -} - -// The following only gets run when connected -void RdmaConnector::connected(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr ci, const Rdma::ConnectionParams& cp) { - try { - Mutex::ScopedLock l(dataConnectedLock); - assert(!dataConnected); - Rdma::QueuePair::intrusive_ptr q = ci->getQueuePair(); - - aio = new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit , Rdma::DEFAULT_WR_ENTRIES, - boost::bind(&RdmaConnector::readbuff, this, _1, _2), - boost::bind(&RdmaConnector::writebuff, this, _1), - 0, // write buffers full - boost::bind(&RdmaConnector::dataError, this, _1)); - - identifier = str(format("[%1% %2%]") % ci->getLocalName() % ci->getPeerName()); - ProtocolInitiation init(version); - writeDataBlock(init); - - aio->start(poller); - - dataConnected = true; - - return; - } catch (const Rdma::Exception& e) { - QPID_LOG(error, "Rdma: Cannot create new connection (Rdma exception): " << e.what()); - } catch (const std::exception& e) { - QPID_LOG(error, "Rdma: Cannot create new connection (unknown exception): " << e.what()); - } - dataConnected = false; - connectionStopped(acon, aio); -} - -void RdmaConnector::connectionError(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, Rdma::ErrorType) { - QPID_LOG(debug, "Connection Error " << identifier); - connectionStopped(acon, aio); -} - -// Bizarrely we seem to get rejected events *after* we've already got a connected event for some peer disconnects -// so we need to check whether the data connection is started or not in here -void RdmaConnector::rejected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams& cp) { - QPID_LOG(debug, "Connection Rejected " << identifier << ": " << cp.maxRecvBufferSize); - if (dataConnected) { - disconnected(); - } else { - connectionStopped(acon, aio); - } -} - -void RdmaConnector::disconnected() { - QPID_LOG(debug, "Connection disconnected " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - // If we're closed already then we'll get to drained() anyway - if (!dataConnected) return; - dataConnected = false; - } - // Make sure that all the disconnected actions take place on the data "thread" - aio->requestCallback(boost::bind(&RdmaConnector::drained, this)); -} - -void RdmaConnector::dataError(Rdma::AsynchIO&) { - QPID_LOG(debug, "Data Error " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - // If we're closed already then we'll get to drained() anyway - if (!dataConnected) return; - dataConnected = false; - } - drained(); -} - -void RdmaConnector::close() { - QPID_LOG(debug, "RdmaConnector::close " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) return; - dataConnected = false; - } - aio->drainWriteQueue(boost::bind(&RdmaConnector::drained, this)); -} - -void RdmaConnector::drained() { - QPID_LOG(debug, "RdmaConnector::drained " << identifier); - assert(!dataConnected); - assert(aio); - Rdma::AsynchIO* a = aio; - aio = 0; - a->stop(boost::bind(&RdmaConnector::dataStopped, this, a)); -} - -void RdmaConnector::dataStopped(Rdma::AsynchIO* a) { - QPID_LOG(debug, "RdmaConnector::dataStopped " << identifier); - assert(!dataConnected); - assert(acon); - Rdma::Connector* c = acon; - acon = 0; - c->stop(boost::bind(&RdmaConnector::connectionStopped, this, c, a)); -} - -void RdmaConnector::connectionStopped(Rdma::Connector* c, Rdma::AsynchIO* a) { - QPID_LOG(debug, "RdmaConnector::connectionStopped " << identifier); - assert(!dataConnected); - aio = 0; - acon = 0; - delete a; - delete c; - if (shutdownHandler) { - ShutdownHandler* s = shutdownHandler; - shutdownHandler = 0; - s->shutdown(); - } -} - -void RdmaConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void RdmaConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -const std::string& RdmaConnector::getIdentifier() const { - return identifier; -} - -void RdmaConnector::handle(AMQFrame& frame) { - // It is possible that we are called to write after we are already shutting down - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) return; - - bool notifyWrite = false; - { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - //only ask to write if this is the end of a frameset or if we - //already have a buffers worth of data - currentSize += frame.encodedSize(); - if (frame.getEof()) { - lastEof = frames.size(); - notifyWrite = true; - } else { - notifyWrite = (currentSize >= maxFrameSize); - } - } - if (notifyWrite) aio->notifyPendingWrite(); -} - -// Called in IO thread. (write idle routine) -// This is NOT only called in response to previously calling notifyPendingWrite -void RdmaConnector::writebuff(Rdma::AsynchIO&) { - // It's possible to be disconnected and be writable - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) { - return; - } - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - if (!codec->canEncode()) { - return; - } - Rdma::Buffer* buffer = aio->getSendBuffer(); - if (buffer) { - size_t encoded = codec->encode(buffer->bytes(), buffer->byteCount()); - buffer->dataCount(encoded); - aio->queueWrite(buffer); - } -} - -bool RdmaConnector::canEncode() -{ - Mutex::ScopedLock l(lock); - //have at least one full frameset or a whole buffers worth of data - return aio->writable() && (lastEof || currentSize >= maxFrameSize); -} - -size_t RdmaConnector::encode(char* buffer, size_t size) -{ - framing::Buffer out(buffer, size); - size_t bytesWritten(0); - { - Mutex::ScopedLock l(lock); - while (!frames.empty() && out.available() >= frames.front().encodedSize() ) { - frames.front().encode(out); - QPID_LOG(trace, "SENT [" << identifier << "]: " << frames.front()); - frames.pop_front(); - if (lastEof) --lastEof; - } - bytesWritten = size - out.available(); - currentSize -= bytesWritten; - } - if (bounds) bounds->reduce(bytesWritten); - return bytesWritten; -} - -void RdmaConnector::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) { - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - codec->decode(buff->bytes(), buff->dataCount()); -} - -size_t RdmaConnector::decode(const char* buffer, size_t size) -{ - framing::Buffer in(const_cast(buffer), size); - try { - if (checkProtocolHeader(in, version)) { - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV [" << identifier << "]: " << frame); - input->received(frame); - } - } - } catch (const ProtocolVersionError& e) { - QPID_LOG(info, "Closing connection due to " << e.what()); - close(); - } - return size - in.available(); -} - -void RdmaConnector::writeDataBlock(const AMQDataBlock& data) { - Rdma::Buffer* buff = aio->getSendBuffer(); - framing::Buffer out(buff->bytes(), buff->byteCount()); - data.encode(out); - buff->dataCount(data.encodedSize()); - aio->queueWrite(buff); -} - -void RdmaConnector::activateSecurityLayer(std::auto_ptr sl) -{ - securityLayer = sl; - securityLayer->init(this); -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/Results.cpp b/qpid/cpp/src/qpid/client/Results.cpp deleted file mode 100644 index 0de3e8bd04..0000000000 --- a/qpid/cpp/src/qpid/client/Results.cpp +++ /dev/null @@ -1,75 +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/client/Results.h" -#include "qpid/client/FutureResult.h" -#include "qpid/framing/SequenceSet.h" - -using namespace qpid::framing; - -namespace qpid { -namespace client { - -Results::Results() {} - -Results::~Results() { - try { close(); } catch (const std::exception& /*e*/) { assert(0); } -} - -void Results::close() -{ - for (Listeners::iterator i = listeners.begin(); i != listeners.end(); i++) { - i->second->completed(); - } - listeners.clear(); -} - -void Results::completed(const SequenceSet& set) -{ - //call complete on those listeners whose ids fall within the set - Listeners::iterator i = listeners.begin(); - while (i != listeners.end()) { - if (set.contains(i->first)) { - i->second->completed(); - listeners.erase(i++); - } else { - i++; - } - } -} - -void Results::received(const SequenceNumber& id, const std::string& result) -{ - Listeners::iterator i = listeners.find(id); - if (i != listeners.end()) { - i->second->received(result); - listeners.erase(i); - } -} - -Results::FutureResultPtr Results::listenForResult(const SequenceNumber& id) -{ - FutureResultPtr l(new FutureResult()); - listeners[id] = l; - return l; -} - -}} diff --git a/qpid/cpp/src/qpid/client/Results.h b/qpid/cpp/src/qpid/client/Results.h deleted file mode 100644 index 4c49f6b05b..0000000000 --- a/qpid/cpp/src/qpid/client/Results.h +++ /dev/null @@ -1,56 +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/framing/SequenceNumber.h" -#include -#include - -#ifndef _Results_ -#define _Results_ - -namespace qpid { -namespace client { - -class FutureResult; - -///@internal -class Results -{ -public: - typedef boost::shared_ptr FutureResultPtr; - - Results(); - ~Results(); - void completed(const framing::SequenceSet& set); - void received(const framing::SequenceNumber& id, const std::string& result); - FutureResultPtr listenForResult(const framing::SequenceNumber& point); - void close(); - -private: - typedef std::map Listeners; - Listeners listeners; -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/client/Session.h b/qpid/cpp/src/qpid/client/Session.h deleted file mode 100644 index c40549bbc5..0000000000 --- a/qpid/cpp/src/qpid/client/Session.h +++ /dev/null @@ -1,39 +0,0 @@ -#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.cpp b/qpid/cpp/src/qpid/client/SessionBase_0_10.cpp deleted file mode 100644 index 2de6c601a1..0000000000 --- a/qpid/cpp/src/qpid/client/SessionBase_0_10.cpp +++ /dev/null @@ -1,85 +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/client/SessionBase_0_10.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionAccess.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/Future.h" -#include "qpid/framing/all_method_bodies.h" - -namespace qpid { -namespace client { - -using namespace framing; - -SessionBase_0_10::SessionBase_0_10() {} -SessionBase_0_10::~SessionBase_0_10() {} - -void SessionBase_0_10::close() -{ - if (impl) impl->close(); -} - -void SessionBase_0_10::flush() -{ - impl->sendFlush(); -} - -void SessionBase_0_10::sync() -{ - ExecutionSyncBody b; - b.setSync(true); - impl->send(b).wait(*impl); -} - -void SessionBase_0_10::markCompleted(const framing::SequenceSet& ids, bool notifyPeer) -{ - impl->markCompleted(ids, notifyPeer); -} - -void SessionBase_0_10::markCompleted(const framing::SequenceNumber& id, bool cumulative, bool notifyPeer) -{ - impl->markCompleted(id, cumulative, notifyPeer); -} - -void SessionBase_0_10::sendCompletion() -{ - impl->sendCompletion(); -} - -uint16_t SessionBase_0_10::getChannel() const { return impl->getChannel(); } - -void SessionBase_0_10::suspend() { impl->suspend(); } -void SessionBase_0_10::resume(Connection c) { impl->resume(c.impl); } -uint32_t SessionBase_0_10::timeout(uint32_t seconds) { return impl->setTimeout(seconds); } - -SessionId SessionBase_0_10::getId() const { return impl->getId(); } - -bool SessionBase_0_10::isValid() const { return !!impl; } - -Connection SessionBase_0_10::getConnection() -{ - Connection c; - ConnectionAccess::setImpl(c, impl->getConnection()); - return c; -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/SessionBase_0_10.h b/qpid/cpp/src/qpid/client/SessionBase_0_10.h deleted file mode 100644 index 630987c11d..0000000000 --- a/qpid/cpp/src/qpid/client/SessionBase_0_10.h +++ /dev/null @@ -1,109 +0,0 @@ -#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 - -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 impl; - friend class SessionBase_0_10Access; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SESSIONBASE_H*/ diff --git a/qpid/cpp/src/qpid/client/SessionBase_0_10Access.h b/qpid/cpp/src/qpid/client/SessionBase_0_10Access.h deleted file mode 100644 index 4d08a7ceaf..0000000000 --- a/qpid/cpp/src/qpid/client/SessionBase_0_10Access.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLIENT_SESSIONBASEACCESS_H -#define QPID_CLIENT_SESSIONBASEACCESS_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/SessionBase_0_10.h" - -/**@file @internal Internal use only */ - -namespace qpid { -namespace client { - -class SessionBase_0_10Access { - public: - SessionBase_0_10Access(SessionBase_0_10& sb_) : sb(sb_) {} - void set(const boost::shared_ptr& si) { sb.impl = si; } - boost::shared_ptr get() const { return sb.impl; } - private: - SessionBase_0_10& sb; -}; -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SESSIONBASEACCESS_H*/ diff --git a/qpid/cpp/src/qpid/client/SessionImpl.cpp b/qpid/cpp/src/qpid/client/SessionImpl.cpp deleted file mode 100644 index 397067b37a..0000000000 --- a/qpid/cpp/src/qpid/client/SessionImpl.cpp +++ /dev/null @@ -1,714 +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/client/SessionImpl.h" - -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/Future.h" - -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/ClientInvoker.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MethodContent.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/IntegerTypes.h" - -#include -#include - -namespace { const std::string EMPTY; } - -namespace qpid { -namespace client { - -using namespace qpid::framing; -using namespace qpid::framing::session; //for detach codes - -typedef sys::Monitor::ScopedLock Lock; -typedef sys::Monitor::ScopedUnlock UnLock; -typedef sys::ScopedLock Acquire; - - -SessionImpl::SessionImpl(const std::string& name, boost::shared_ptr conn) - : state(INACTIVE), - detachedLifetime(0), - maxFrameSize(conn->getNegotiatedSettings().maxFrameSize), - id(conn->getNegotiatedSettings().username, name.empty() ? Uuid(true).str() : name), - connection(conn), - ioHandler(*this), - proxy(ioHandler), - nextIn(0), - nextOut(0) -{ - channel.next = connection.get(); -} - -SessionImpl::~SessionImpl() { - { - Lock l(state); - if (state != DETACHED && state != DETACHING) { - QPID_LOG(warning, "Session was not closed cleanly: " << id); - // Inform broker but don't wait for detached as that deadlocks. - // The detached will be ignored as the channel will be invalid. - try { detach(); } catch (...) {} // ignore errors. - setState(DETACHED); - handleClosed(); - state.waitWaiters(); - } - } - connection->erase(channel); -} - - -FrameSet::shared_ptr SessionImpl::get() // user thread -{ - // No lock here: pop does a blocking wait. - return demux.getDefault()->pop(); -} - -const SessionId SessionImpl::getId() const //user thread -{ - return id; //id is immutable -} - -void SessionImpl::open(uint32_t timeout) // user thread -{ - Lock l(state); - if (state == INACTIVE) { - setState(ATTACHING); - proxy.attach(id.getName(), false); - waitFor(ATTACHED); - //TODO: timeout will not be set locally until get response to - //confirm, should we wait for that? - setTimeout(timeout); - proxy.commandPoint(nextOut, 0); - } else { - throw Exception("Open already called for this session"); - } -} - -void SessionImpl::close() //user thread -{ - Lock l(state); - // close() must be idempotent and no-throw as it will often be called in destructors. - if (state != DETACHED && state != DETACHING) { - try { - if (detachedLifetime) setTimeout(0); - detach(); - waitFor(DETACHED); - } catch (...) {} - setState(DETACHED); - } -} - -void SessionImpl::resume(boost::shared_ptr) // user thread -{ - throw NotImplementedException("Resume not yet implemented by client!"); -} - -void SessionImpl::suspend() //user thread -{ - Lock l(state); - detach(); -} - -void SessionImpl::detach() //call with lock held -{ - if (state == ATTACHED) { - setState(DETACHING); - proxy.detach(id.getName()); - } -} - - -uint16_t SessionImpl::getChannel() const // user thread -{ - return channel; -} - -void SessionImpl::setChannel(uint16_t c) // user thread -{ - //channel will only ever be set when session is detached (and - //about to be resumed) - channel = c; -} - -Demux& SessionImpl::getDemux() -{ - return demux; -} - -void SessionImpl::waitForCompletion(const SequenceNumber& id) -{ - Lock l(state); - sys::Waitable::ScopedWait w(state); - waitForCompletionImpl(id); -} - -void SessionImpl::waitForCompletionImpl(const SequenceNumber& id) //call with lock held -{ - while (incompleteOut.contains(id)) { - checkOpen(); - state.wait(); - } -} - -bool SessionImpl::isComplete(const SequenceNumber& id) -{ - Lock l(state); - return !incompleteOut.contains(id); -} - -struct IsCompleteUpTo -{ - const SequenceNumber& id; - bool result; - - IsCompleteUpTo(const SequenceNumber& _id) : id(_id), result(true) {} - void operator()(const SequenceNumber& start, const SequenceNumber&) - { - if (start <= id) result = false; - } - -}; - -bool SessionImpl::isCompleteUpTo(const SequenceNumber& id) -{ - Lock l(state); - //return false if incompleteOut contains anything less than id, - //true otherwise - IsCompleteUpTo f(id); - incompleteIn.for_each(f); - return f.result; -} - -framing::SequenceNumber SessionImpl::getCompleteUpTo() -{ - SequenceNumber firstIncomplete; - { - Lock l(state); - firstIncomplete = incompleteIn.front(); - } - return --firstIncomplete; -} - -struct MarkCompleted -{ - const SequenceNumber& id; - SequenceSet& completedIn; - - MarkCompleted(const SequenceNumber& _id, SequenceSet& set) : id(_id), completedIn(set) {} - - void operator()(const SequenceNumber& start, const SequenceNumber& end) - { - if (id >= end) { - completedIn.add(start, end); - } else if (id >= start) { - completedIn.add(start, id); - } - } - -}; - -void SessionImpl::markCompleted(const SequenceSet& ids, bool notifyPeer) -{ - Lock l(state); - incompleteIn.remove(ids); - completedIn.add(ids); - if (notifyPeer) { - sendCompletion(); - } -} - -void SessionImpl::markCompleted(const SequenceNumber& id, bool cumulative, bool notifyPeer) -{ - Lock l(state); - if (cumulative) { - //everything in incompleteIn less than or equal to id is now complete - MarkCompleted f(id, completedIn); - incompleteIn.for_each(f); - //make sure id itself is in - completedIn.add(id); - //then remove anything thats completed from the incomplete set - incompleteIn.remove(completedIn); - } else if (incompleteIn.contains(id)) { - incompleteIn.remove(id); - completedIn.add(id); - } - if (notifyPeer) { - sendCompletion(); - } -} - -void SessionImpl::setException(const sys::ExceptionHolder& ex) { - Lock l(state); - setExceptionLH(ex); -} - -void SessionImpl::setExceptionLH(const sys::ExceptionHolder& ex) { // Call with lock held. - exceptionHolder = ex; - setState(DETACHED); -} - -/** - * Called by ConnectionImpl to notify active sessions when connection - * is explictly closed - */ -void SessionImpl::connectionClosed(uint16_t code, const std::string& text) { - setException(createConnectionException(code, text)); - handleClosed(); -} - -/** - * Called by ConnectionImpl to notify active sessions when connection - * is disconnected - */ -void SessionImpl::connectionBroke(const std::string& _text) { - setException(sys::ExceptionHolder(new TransportFailure(_text))); - handleClosed(); -} - -Future SessionImpl::send(const AMQBody& command) -{ - return sendCommand(command); -} - -Future SessionImpl::send(const AMQBody& command, const MethodContent& content) -{ - return sendCommand(command, &content); -} - -namespace { -// Functor for FrameSet::map to send header + content frames but, not method frames. -struct SendContentFn { - FrameHandler& handler; - void operator()(const AMQFrame& f) { - if (!f.getMethod()) - handler(const_cast(f)); - } - SendContentFn(FrameHandler& h) : handler(h) {} -}; - -} - -Future SessionImpl::send(const AMQBody& command, const FrameSet& content) { - Acquire a(sendLock); - SequenceNumber id = nextOut++; - { - Lock l(state); - checkOpen(); - incompleteOut.add(id); - } - Future f(id); - if (command.getMethod()->resultExpected()) { - Lock l(state); - //result listener must be set before the command is sent - f.setFutureResult(results.listenForResult(id)); - } - AMQFrame frame(command); - frame.setEof(false); - handleOut(frame); - SendContentFn send(out); - content.map(send); - return f; -} - -void SessionImpl::sendRawFrame(AMQFrame& frame) { - Acquire a(sendLock); - handleOut(frame); -} - -Future SessionImpl::sendCommand(const AMQBody& command, const MethodContent* content) -{ - Acquire a(sendLock); - SequenceNumber id = nextOut++; - { - Lock l(state); - checkOpen(); - incompleteOut.add(id); - } - Future f(id); - if (command.getMethod()->resultExpected()) { - Lock l(state); - //result listener must be set before the command is sent - f.setFutureResult(results.listenForResult(id)); - } - AMQFrame frame(command); - if (content) { - frame.setEof(false); - } - handleOut(frame); - if (content) { - sendContent(*content); - } - return f; -} - -void SessionImpl::sendContent(const MethodContent& content) -{ - AMQFrame header(content.getHeader()); - - header.setFirstSegment(false); - uint64_t data_length = content.getData().length(); - if(data_length > 0){ - header.setLastSegment(false); - handleOut(header); - /*Note: end of frame marker included in overhead but not in size*/ - const uint32_t frag_size = maxFrameSize - AMQFrame::frameOverhead(); - - if(data_length < frag_size){ - AMQFrame frame((AMQContentBody(content.getData()))); - frame.setFirstSegment(false); - handleOut(frame); - }else{ - uint32_t offset = 0; - uint32_t remaining = data_length - offset; - while (remaining > 0) { - uint32_t length = remaining > frag_size ? frag_size : remaining; - std::string frag(content.getData().substr(offset, length)); - AMQFrame frame((AMQContentBody(frag))); - frame.setFirstSegment(false); - frame.setLastSegment(true); - if (offset > 0) { - frame.setFirstFrame(false); - } - offset += length; - remaining = data_length - offset; - if (remaining) { - frame.setLastFrame(false); - } - handleOut(frame); - } - } - } else { - handleOut(header); - } -} - - -bool isMessageMethod(AMQMethodBody* method) -{ - return method->isA(); -} - -bool isMessageMethod(AMQBody* body) -{ - AMQMethodBody* method=body->getMethod(); - return method && isMessageMethod(method); -} - -bool isContentFrame(AMQFrame& frame) -{ - AMQBody* body = frame.getBody(); - uint8_t type = body->type(); - return type == HEADER_BODY || type == CONTENT_BODY || isMessageMethod(body); -} - -void SessionImpl::handleIn(AMQFrame& frame) // network thread -{ - try { - if (invoke(static_cast(*this), *frame.getBody())) { - ; - } else if (invoke(static_cast(*this), *frame.getBody())) { - //make sure the command id sequence and completion - //tracking takes account of execution commands - Lock l(state); - completedIn.add(nextIn++); - } else { - //if not handled by this class, its for the application: - deliver(frame); - } - } - catch (const SessionException& e) { - setException(createSessionException(e.code, e.getMessage())); - } - catch (const ChannelException& e) { - setException(createChannelException(e.code, e.getMessage())); - } -} - -void SessionImpl::handleOut(AMQFrame& frame) // user thread -{ - sendFrame(frame, true); -} - -void SessionImpl::proxyOut(AMQFrame& frame) // network thread -{ - //Note: this case is treated slightly differently that command - //frames sent by application; session controls should not be - //blocked by bounds checking on the outgoing frame queue. - sendFrame(frame, false); -} - -void SessionImpl::sendFrame(AMQFrame& frame, bool canBlock) -{ - connection->expand(frame.encodedSize(), canBlock); - channel.handle(frame); -} - -void SessionImpl::deliver(AMQFrame& frame) // network thread -{ - if (!arriving) { - arriving = FrameSet::shared_ptr(new FrameSet(nextIn++)); - } - arriving->append(frame); - if (arriving->isComplete()) { - //message.transfers will be marked completed only when 'acked' - //as completion affects flow control; other commands will be - //considered completed as soon as processed here - if (arriving->isA()) { - arriving->setReceived(); - Lock l(state); - incompleteIn.add(arriving->getId()); - } else { - Lock l(state); - completedIn.add(arriving->getId()); - } - demux.handle(arriving); - arriving.reset(); - } -} - -//control handler methods (called by network thread when controls are -//received from peer): - -void SessionImpl::attach(const std::string& /*name*/, bool /*force*/) -{ - throw NotImplementedException("Client does not support attach"); -} - -void SessionImpl::attached(const std::string& _name) -{ - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(ATTACHED); -} - -void SessionImpl::detach(const std::string& _name) -{ - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(DETACHED); - QPID_LOG(info, "Session detached by peer: " << id); - proxy.detached(_name, DETACH_CODE_NORMAL); - handleClosed(); -} - -void SessionImpl::detached(const std::string& _name, uint8_t _code) { - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(DETACHED); - if (_code) { - //TODO: make sure this works with execution.exception - don't - //want to overwrite the code from that - setExceptionLH(createChannelException(_code, "Session detached by peer")); - QPID_LOG(error, exceptionHolder.what()); - } - if (detachedLifetime == 0) { - handleClosed(); -} -} - -void SessionImpl::requestTimeout(uint32_t t) -{ - Lock l(state); - detachedLifetime = t; - proxy.timeout(t); -} - -void SessionImpl::timeout(uint32_t t) -{ - Lock l(state); - detachedLifetime = t; -} - -void SessionImpl::commandPoint(const framing::SequenceNumber& id, uint64_t offset) -{ - if (offset) throw NotImplementedException("Non-zero byte offset not yet supported for command-point"); - - Lock l(state); - nextIn = id; -} - -void SessionImpl::expected(const framing::SequenceSet& commands, const framing::Array& fragments) -{ - if (!commands.empty() || fragments.encodedSize()) { - throw NotImplementedException("Session resumption not yet supported"); - } -} - -void SessionImpl::confirmed(const framing::SequenceSet& /*commands*/, const framing::Array& /*fragments*/) -{ - //don't really care too much about this yet -} - -void SessionImpl::completed(const framing::SequenceSet& commands, bool timelyReply) -{ - Lock l(state); - incompleteOut.remove(commands); - state.notifyAll();//notify any waiters of completion - completedOut.add(commands); - //notify any waiting results of completion - results.completed(commands); - - if (timelyReply) { - proxy.knownCompleted(completedOut); - completedOut.clear(); - } -} - -void SessionImpl::knownCompleted(const framing::SequenceSet& commands) -{ - Lock l(state); - completedIn.remove(commands); -} - -void SessionImpl::flush(bool expected, bool confirmed, bool completed) -{ - Lock l(state); - if (expected) { - proxy.expected(SequenceSet(nextIn), Array()); - } - if (confirmed) { - proxy.confirmed(completedIn, Array()); - } - if (completed) { - proxy.completed(completedIn, true); - } -} - -void SessionImpl::sendCompletion() -{ - Lock l(state); - sendCompletionImpl(); -} - -void SessionImpl::sendFlush() -{ - Lock l(state); - proxy.flush(false, false, true); -} - -void SessionImpl::sendCompletionImpl() -{ - proxy.completed(completedIn, completedIn.span() > 1000); -} - -void SessionImpl::gap(const framing::SequenceSet& /*commands*/) -{ - throw NotImplementedException("gap not yet supported"); -} - -void SessionImpl::sync() {} - -void SessionImpl::result(const framing::SequenceNumber& commandId, const std::string& value) -{ - Lock l(state); - results.received(commandId, value); -} - -void SessionImpl::exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t /*fieldIndex*/, - const std::string& description, - const framing::FieldTable& /*errorInfo*/) -{ - Lock l(state); - setExceptionLH(createSessionException(errorCode, description)); - QPID_LOG(warning, "Exception received from broker: " << exceptionHolder.what() - << " [caused by " << commandId << " " << classCode << ":" << commandCode << "]"); - - if (detachedLifetime) - setTimeout(0); -} - -//private utility methods: - -inline void SessionImpl::setState(State s) //call with lock held -{ - state = s; -} - -inline void SessionImpl::waitFor(State s) //call with lock held -{ - // We can be DETACHED at any time - if (s == DETACHED) state.waitFor(DETACHED); - else state.waitFor(States(s, DETACHED)); - check(); -} - -void SessionImpl::check() const //call with lock held. -{ - exceptionHolder.raise(); -} - -void SessionImpl::checkOpen() const //call with lock held. -{ - check(); - if (state != ATTACHED) { - throw NotAttachedException(QPID_MSG("Session " << getId() << " isn't attached")); - } -} - -void SessionImpl::assertOpen() const -{ - Lock l(state); - checkOpen(); -} - -bool SessionImpl::hasError() const -{ - Lock l(state); - return !exceptionHolder.empty(); -} - -void SessionImpl::handleClosed() -{ - demux.close(exceptionHolder.empty() ? - sys::ExceptionHolder(new ClosedException()) : exceptionHolder); - results.close(); -} - -uint32_t SessionImpl::setTimeout(uint32_t seconds) { - proxy.requestTimeout(seconds); - // FIXME aconway 2008-10-07: wait for timeout response from broker - // and use value retured by broker. - detachedLifetime = seconds; - return detachedLifetime; -} - -uint32_t SessionImpl::getTimeout() const { - return detachedLifetime; -} - -boost::shared_ptr SessionImpl::getConnection() -{ - return connection; -} - -}} diff --git a/qpid/cpp/src/qpid/client/SessionImpl.h b/qpid/cpp/src/qpid/client/SessionImpl.h deleted file mode 100644 index 752d587a39..0000000000 --- a/qpid/cpp/src/qpid/client/SessionImpl.h +++ /dev/null @@ -1,220 +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. - * - */ - -#ifndef _SessionImpl_ -#define _SessionImpl_ - -#include "qpid/client/Demux.h" -#include "qpid/client/Execution.h" -#include "qpid/client/Results.h" -#include "qpid/client/ClientImportExport.h" - -#include "qpid/SessionId.h" -#include "qpid/SessionState.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/ChannelHandler.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/AMQP_ClientOperations.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/sys/Semaphore.h" -#include "qpid/sys/StateMonitor.h" -#include "qpid/sys/ExceptionHolder.h" - -#include -#include -#include - -namespace qpid { - -namespace framing { - -class FrameSet; -class MethodContent; -class SequenceSet; - -} - -namespace client { - -class Future; -class ConnectionImpl; -class SessionHandler; - -///@internal -class SessionImpl : public framing::FrameHandler::InOutHandler, - public Execution, - private framing::AMQP_ClientOperations::SessionHandler, - private framing::AMQP_ClientOperations::ExecutionHandler -{ -public: - SessionImpl(const std::string& name, boost::shared_ptr); - ~SessionImpl(); - - - //NOTE: Public functions called in user thread. - framing::FrameSet::shared_ptr get(); - - const SessionId getId() const; - - uint16_t getChannel() const; - void setChannel(uint16_t channel); - - void open(uint32_t detachedLifetime); - void close(); - void resume(boost::shared_ptr); - void suspend(); - - QPID_CLIENT_EXTERN void assertOpen() const; - QPID_CLIENT_EXTERN bool hasError() const; - - Future send(const framing::AMQBody& command); - Future send(const framing::AMQBody& command, const framing::MethodContent& content); - QPID_CLIENT_EXTERN Future send(const framing::AMQBody& command, const framing::FrameSet& content); - void sendRawFrame(framing::AMQFrame& frame); - - Demux& getDemux(); - void markCompleted(const framing::SequenceNumber& id, bool cumulative, bool notifyPeer); - void markCompleted(const framing::SequenceSet& ids, bool notifyPeer); - bool isComplete(const framing::SequenceNumber& id); - bool isCompleteUpTo(const framing::SequenceNumber& id); - framing::SequenceNumber getCompleteUpTo(); - void waitForCompletion(const framing::SequenceNumber& id); - void sendCompletion(); - void sendFlush(); - - QPID_CLIENT_EXTERN void setException(const sys::ExceptionHolder&); - - //NOTE: these are called by the network thread when the connection is closed or dies - void connectionClosed(uint16_t code, const std::string& text); - void connectionBroke(const std::string& text); - - /** Set timeout in seconds, returns actual timeout allowed by broker */ - uint32_t setTimeout(uint32_t requestedSeconds); - - /** Get timeout in seconds. */ - uint32_t getTimeout() const; - - /** - * get the Connection associated with this connection - */ - boost::shared_ptr getConnection(); - -private: - enum State { - INACTIVE, - ATTACHING, - ATTACHED, - DETACHING, - DETACHED - }; - typedef framing::AMQP_ClientOperations::SessionHandler SessionHandler; - typedef framing::AMQP_ClientOperations::ExecutionHandler ExecutionHandler; - typedef sys::StateMonitor StateMonitor; - typedef StateMonitor::Set States; - - inline void setState(State s); - inline void waitFor(State); - - void setExceptionLH(const sys::ExceptionHolder&); // LH = lock held when called. - void detach(); - - void check() const; - void checkOpen() const; - void handleClosed(); - - void handleIn(framing::AMQFrame& frame); - void handleOut(framing::AMQFrame& frame); - /** - * Sends session controls. This case is treated slightly - * differently than command frames sent by the application via - * handleOut(); session controlsare not subject to bounds checking - * on the outgoing frame queue. - */ - void proxyOut(framing::AMQFrame& frame); - void sendFrame(framing::AMQFrame& frame, bool canBlock); - void deliver(framing::AMQFrame& frame); - - Future sendCommand(const framing::AMQBody&, const framing::MethodContent* = 0); - void sendContent(const framing::MethodContent&); - void waitForCompletionImpl(const framing::SequenceNumber& id); - - void sendCompletionImpl(); - - // Note: Following methods are called by network thread in - // response to session controls from the broker - void attach(const std::string& name, bool force); - void attached(const std::string& name); - void detach(const std::string& name); - void detached(const std::string& name, uint8_t detachCode); - void requestTimeout(uint32_t timeout); - void timeout(uint32_t timeout); - void commandPoint(const framing::SequenceNumber& commandId, uint64_t commandOffset); - void expected(const framing::SequenceSet& commands, const framing::Array& fragments); - void confirmed(const framing::SequenceSet& commands, const framing::Array& fragments); - void completed(const framing::SequenceSet& commands, bool timelyReply); - void knownCompleted(const framing::SequenceSet& commands); - void flush(bool expected, bool confirmed, bool completed); - void gap(const framing::SequenceSet& commands); - - // Note: Following methods are called by network thread in - // response to execution commands from the broker - void sync(); - void result(const framing::SequenceNumber& commandId, const std::string& value); - void exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t fieldIndex, - const std::string& description, - const framing::FieldTable& errorInfo); - - sys::ExceptionHolder exceptionHolder; - mutable StateMonitor state; - mutable sys::Semaphore sendLock; - uint32_t detachedLifetime; - const uint64_t maxFrameSize; - const SessionId id; - - boost::shared_ptr connection; - - framing::FrameHandler::MemFunRef ioHandler; - framing::ChannelHandler channel; - framing::AMQP_ServerProxy::Session proxy; - - Results results; - Demux demux; - framing::FrameSet::shared_ptr arriving; - - framing::SequenceSet incompleteIn;//incoming commands that are as yet incomplete - framing::SequenceSet completedIn;//incoming commands that are have completed - framing::SequenceSet incompleteOut;//outgoing commands not yet known to be complete - framing::SequenceSet completedOut;//outgoing commands that we know to be completed - framing::SequenceNumber nextIn; - framing::SequenceNumber nextOut; - - SessionState sessionState; - - friend class client::SessionHandler; -}; - -}} // namespace qpid::client - -#endif diff --git a/qpid/cpp/src/qpid/client/SslConnector.cpp b/qpid/cpp/src/qpid/client/SslConnector.cpp deleted file mode 100644 index aa6020e272..0000000000 --- a/qpid/cpp/src/qpid/client/SslConnector.cpp +++ /dev/null @@ -1,428 +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/client/Connector.h" - -#include "config.h" -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/ssl/util.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/ssl/SslSocket.h" -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/Msg.h" -#include "qpid/types/Exception.h" - -#include -#include -#include - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::sys::ssl; -using namespace qpid::framing; -using boost::format; -using boost::str; - - -class SslConnector : public Connector -{ - typedef std::deque Frames; - - const uint16_t maxFrameSize; - - sys::Mutex lock; - Frames frames; - size_t lastEof; // Position after last EOF in frames - uint64_t currentSize; - Bounds* bounds; - - framing::ProtocolVersion version; - bool initiated; - bool closed; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - - sys::ssl::SslSocket socket; - - sys::AsynchConnector* connector; - sys::AsynchIO* aio; - std::string identifier; - Poller::shared_ptr poller; - SecuritySettings securitySettings; - - ~SslConnector(); - - void readbuff(AsynchIO&, AsynchIOBufferBase*); - void writebuff(AsynchIO&); - void writeDataBlock(const framing::AMQDataBlock& data); - void eof(AsynchIO&); - void disconnected(AsynchIO&); - - void connect(const std::string& host, const std::string& port); - void connected(const sys::Socket&); - void connectFailed(const std::string& msg); - - void close(); - void handle(framing::AMQFrame& frame); - void abort(); - void connectAborted(); - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - const std::string& getIdentifier() const; - const SecuritySettings* getSecuritySettings(); - void socketClosed(AsynchIO&, const Socket&); - - size_t decode(const char* buffer, size_t size); - size_t encode(char* buffer, size_t size); - bool canEncode(); - -public: - SslConnector(Poller::shared_ptr p, framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c); - - struct StaticInit { - static bool initialised; - - StaticInit() { - Connector::registerFactory("ssl", &create); - }; - ~StaticInit() { - if (initialised) shutdownNSS(); - } - - void checkInitialised() { - static qpid::sys::Mutex lock; - qpid::sys::Mutex::ScopedLock l(lock); - if (!initialised) { - CommonOptions common("", "", QPIDC_CONF_FILE); - SslOptions options; - try { - common.parse(0, 0, common.clientConfig, true); - options.parse (0, 0, common.clientConfig, true); - } catch (const std::exception& e) { - throw qpid::types::Exception(QPID_MSG("Failed to parse options while initialising SSL connector: " << e.what())); - } - if (options.certDbPath.empty()) { - throw qpid::types::Exception(QPID_MSG("SSL connector not enabled, you must set QPID_SSL_CERT_DB to enable it.")); - } else { - try { - initNSS(options); - initialised = true; - } catch (const std::exception& e) { - throw qpid::types::Exception(QPID_MSG("Failed to initialise SSL: " << e.what())); - } - } - } - } - - } init; - bool StaticInit::initialised = false; - - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - init.checkInitialised(); - return new SslConnector(p, v, s, c); - } -} - -void initialiseSSL() -{ - init.checkInitialised(); -} - -void shutdownSSL() -{ - if (StaticInit::initialised) shutdownNSS(); -} - -SslConnector::SslConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - lastEof(0), - currentSize(0), - bounds(cimpl), - version(ver), - initiated(false), - closed(true), - shutdownHandler(0), - input(0), - aio(0), - poller(p) -{ - QPID_LOG(debug, "SslConnector created for " << version.toString()); - - if (settings.sslCertName != "") { - QPID_LOG(debug, "ssl-cert-name = " << settings.sslCertName); - socket.setCertName(settings.sslCertName); - } - if (settings.sslIgnoreHostnameVerificationFailure) { - socket.ignoreHostnameVerificationFailure(); - } -} - -SslConnector::~SslConnector() { - close(); -} - -void SslConnector::connect(const std::string& host, const std::string& port) { - Mutex::ScopedLock l(lock); - assert(closed); - connector = AsynchConnector::create( - socket, - host, port, - boost::bind(&SslConnector::connected, this, _1), - boost::bind(&SslConnector::connectFailed, this, _3)); - closed = false; - - connector->start(poller); -} - -void SslConnector::connected(const Socket&) { - connector = 0; - aio = AsynchIO::create(socket, - boost::bind(&SslConnector::readbuff, this, _1, _2), - boost::bind(&SslConnector::eof, this, _1), - boost::bind(&SslConnector::disconnected, this, _1), - boost::bind(&SslConnector::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&SslConnector::writebuff, this, _1)); - - aio->createBuffers(maxFrameSize); - identifier = str(format("[%1%]") % socket.getFullAddress()); - ProtocolInitiation init(version); - writeDataBlock(init); - aio->start(poller); -} - -void SslConnector::connectFailed(const std::string& msg) { - connector = 0; - QPID_LOG(warning, "Connect failed: " << msg); - socket.close(); - if (!closed) - closed = true; - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void SslConnector::close() { - Mutex::ScopedLock l(lock); - if (!closed) { - closed = true; - if (aio) - aio->queueWriteClose(); - } -} - -void SslConnector::socketClosed(AsynchIO&, const Socket&) { - if (aio) - aio->queueForDeletion(); - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void SslConnector::connectAborted() { - connector->stop(); - connectFailed("Connection timedout"); -} - -void SslConnector::abort() { - // Can't abort a closed connection - if (!closed) { - if (aio) { - // Established connection - aio->requestCallback(boost::bind(&SslConnector::eof, this, _1)); - } else if (connector) { - // We're still connecting - connector->requestCallback(boost::bind(&SslConnector::connectAborted, this)); - } - } -} - -void SslConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void SslConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -const std::string& SslConnector::getIdentifier() const { - return identifier; -} - -void SslConnector::handle(AMQFrame& frame) { - bool notifyWrite = false; - { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - //only ask to write if this is the end of a frameset or if we - //already have a buffers worth of data - currentSize += frame.encodedSize(); - if (frame.getEof()) { - lastEof = frames.size(); - notifyWrite = true; - } else { - notifyWrite = (currentSize >= maxFrameSize); - } - /* - NOTE: Moving the following line into this mutex block - is a workaround for BZ 570168, in which the test - testConcurrentSenders causes a hang about 1.5% - of the time. ( To see the hang much more frequently - leave this line out of the mutex block, and put a - small usleep just before it.) - - TODO mgoulish - fix the underlying cause and then - move this call back outside the mutex. - */ - if (notifyWrite && !closed) aio->notifyPendingWrite(); - } -} - -void SslConnector::writebuff(AsynchIO& /*aio*/) -{ - // It's possible to be disconnected and be writable - if (closed) - return; - - if (!canEncode()) { - return; - } - - AsynchIOBufferBase* buffer = aio->getQueuedBuffer(); - if (buffer) { - - size_t encoded = encode(buffer->bytes, buffer->byteCount); - - buffer->dataStart = 0; - buffer->dataCount = encoded; - aio->queueWrite(buffer); - } -} - -// Called in IO thread. -bool SslConnector::canEncode() -{ - Mutex::ScopedLock l(lock); - //have at least one full frameset or a whole buffers worth of data - return lastEof || currentSize >= maxFrameSize; -} - -// Called in IO thread. -size_t SslConnector::encode(char* buffer, size_t size) -{ - framing::Buffer out(buffer, size); - size_t bytesWritten(0); - { - Mutex::ScopedLock l(lock); - while (!frames.empty() && out.available() >= frames.front().encodedSize() ) { - frames.front().encode(out); - QPID_LOG(trace, "SENT [" << identifier << "]: " << frames.front()); - frames.pop_front(); - if (lastEof) --lastEof; - } - bytesWritten = size - out.available(); - currentSize -= bytesWritten; - } - if (bounds) bounds->reduce(bytesWritten); - return bytesWritten; -} - -void SslConnector::readbuff(AsynchIO& aio, AsynchIOBufferBase* buff) -{ - int32_t decoded = decode(buff->bytes+buff->dataStart, buff->dataCount); - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (decoded < buff->dataCount) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += decoded; - buff->dataCount -= decoded; - aio.unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio.queueReadBuffer(buff); - } -} - -size_t SslConnector::decode(const char* buffer, size_t size) -{ - framing::Buffer in(const_cast(buffer), size); - try { - if (checkProtocolHeader(in, version)) { - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV [" << identifier << "]: " << frame); - input->received(frame); - } - } - } catch (const ProtocolVersionError& e) { - QPID_LOG(info, "Closing connection due to " << e.what()); - close(); - } - return size - in.available(); -} - -void SslConnector::writeDataBlock(const AMQDataBlock& data) { - AsynchIOBufferBase* buff = aio->getQueuedBuffer(); - assert(buff); - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void SslConnector::eof(AsynchIO&) { - close(); -} - -void SslConnector::disconnected(AsynchIO&) { - close(); - socketClosed(*aio, socket); -} - -const SecuritySettings* SslConnector::getSecuritySettings() -{ - securitySettings.ssf = socket.getKeyLen(); - securitySettings.authid = socket.getLocalAuthId(); - return &securitySettings; -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/StateManager.cpp b/qpid/cpp/src/qpid/client/StateManager.cpp deleted file mode 100644 index 839d92abdc..0000000000 --- a/qpid/cpp/src/qpid/client/StateManager.cpp +++ /dev/null @@ -1,100 +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/client/StateManager.h" -#include "qpid/framing/amqp_framing.h" - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -StateManager::StateManager(int s) : state(s) {} - -void StateManager::waitForStateChange(int current) -{ - Monitor::ScopedLock l(stateLock); - while (state == current) { - stateLock.wait(); - } -} - -void StateManager::waitFor(int desired) -{ - Monitor::ScopedLock l(stateLock); - while (state != desired) { - stateLock.wait(); - } -} - -void StateManager::waitFor(std::set desired) -{ - Monitor::ScopedLock l(stateLock); - while (desired.find(state) == desired.end()) { - stateLock.wait(); - } -} - -bool StateManager::waitFor(int desired, qpid::sys::Duration timeout) -{ - AbsTime end(now(), timeout); - Monitor::ScopedLock l(stateLock); - while (state != desired && now() < end) { - stateLock.wait(end); - } - return state == desired; -} - -bool StateManager::waitFor(std::set desired, qpid::sys::Duration timeout) -{ - AbsTime end(now(), timeout); - Monitor::ScopedLock l(stateLock); - while (desired.find(state) == desired.end() && now() < end) { - stateLock.wait(end); - } - return desired.find(state) != desired.end(); -} - - -void StateManager::setState(int s) -{ - Monitor::ScopedLock l(stateLock); - state = s; - stateLock.notifyAll(); -} - -bool StateManager::setState(int s, int expected) -{ - Monitor::ScopedLock l(stateLock); - if (state == expected) { - state = s; - stateLock.notifyAll(); - return true; - } else { - return false; - } -} - -int StateManager::getState() const -{ - Monitor::ScopedLock l(stateLock); - return state; -} - diff --git a/qpid/cpp/src/qpid/client/StateManager.h b/qpid/cpp/src/qpid/client/StateManager.h deleted file mode 100644 index f06dbc493c..0000000000 --- a/qpid/cpp/src/qpid/client/StateManager.h +++ /dev/null @@ -1,50 +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. - * - */ -#ifndef _StateManager_ -#define _StateManager_ - -#include -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace client { - -///@internal -class StateManager -{ - int state; - mutable sys::Monitor stateLock; - -public: - StateManager(int initial); - void setState(int state); - bool setState(int state, int expected); - int getState() const ; - void waitForStateChange(int current); - void waitFor(std::set states); - void waitFor(int state); - bool waitFor(std::set states, qpid::sys::Duration); - bool waitFor(int state, qpid::sys::Duration); -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/client/Subscription.cpp b/qpid/cpp/src/qpid/client/Subscription.cpp deleted file mode 100644 index 988f372604..0000000000 --- a/qpid/cpp/src/qpid/client/Subscription.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Subscription.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/framing/enum.h" - -namespace qpid { -namespace client { - -typedef PrivateImplRef PI; -Subscription::Subscription(SubscriptionImpl* p) { PI::ctor(*this, p); } -Subscription::~Subscription() { PI::dtor(*this); } -Subscription::Subscription(const Subscription& c) : Handle() { PI::copy(*this, c); } -Subscription& Subscription::operator=(const Subscription& c) { return PI::assign(*this, c); } - - -std::string Subscription::getName() const { return impl->getName(); } -std::string Subscription::getQueue() const { return impl->getQueue(); } -const SubscriptionSettings& Subscription::getSettings() const { return impl->getSettings(); } -void Subscription::setFlowControl(const FlowControl& f) { impl->setFlowControl(f); } -void Subscription::setAutoAck(unsigned int n) { impl->setAutoAck(n); } -SequenceSet Subscription::getUnacquired() const { return impl->getUnacquired(); } -SequenceSet Subscription::getUnaccepted() const { return impl->getUnaccepted(); } -void Subscription::acquire(const SequenceSet& messageIds) { impl->acquire(messageIds); } -void Subscription::accept(const SequenceSet& messageIds) { impl->accept(messageIds); } -void Subscription::release(const SequenceSet& messageIds) { impl->release(messageIds); } -Session Subscription::getSession() const { return impl->getSession(); } -SubscriptionManager Subscription::getSubscriptionManager() { return impl->getSubscriptionManager(); } -void Subscription::cancel() { impl->cancel(); } -void Subscription::grantMessageCredit(uint32_t value) { impl->grantCredit(framing::message::CREDIT_UNIT_MESSAGE, value); } -void Subscription::grantByteCredit(uint32_t value) { impl->grantCredit(framing::message::CREDIT_UNIT_BYTE, value); } -}} // namespace qpid::client - - diff --git a/qpid/cpp/src/qpid/client/Subscription.h b/qpid/cpp/src/qpid/client/Subscription.h deleted file mode 100644 index bb9b98e8ff..0000000000 --- a/qpid/cpp/src/qpid/client/Subscription.h +++ /dev/null @@ -1,123 +0,0 @@ -#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 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 { - 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; - friend class SubscriptionManager; -}; -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SUBSCRIPTION_H*/ diff --git a/qpid/cpp/src/qpid/client/SubscriptionImpl.cpp b/qpid/cpp/src/qpid/client/SubscriptionImpl.cpp deleted file mode 100644 index a8a0b47d94..0000000000 --- a/qpid/cpp/src/qpid/client/SubscriptionImpl.cpp +++ /dev/null @@ -1,169 +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/client/AsyncSession.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionSettings.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/client/PrivateImplRef.h" - -namespace qpid { -namespace client { - -using sys::Mutex; -using framing::MessageAcquireResult; - -SubscriptionImpl::SubscriptionImpl(SubscriptionManager m, const std::string& q, const SubscriptionSettings& s, const std::string& n, MessageListener* l) - : manager(*PrivateImplRef::get(m)), name(n), queue(q), settings(s), listener(l) -{} - -void SubscriptionImpl::subscribe() -{ - async(manager.getSession()).messageSubscribe( - arg::queue=queue, - arg::destination=name, - arg::acceptMode=settings.acceptMode, - arg::acquireMode=settings.acquireMode, - arg::exclusive=settings.exclusive); - setFlowControl(settings.flowControl); -} - -std::string SubscriptionImpl::getName() const { return name; } - -std::string SubscriptionImpl::getQueue() const { return queue; } - -const SubscriptionSettings& SubscriptionImpl::getSettings() const { - Mutex::ScopedLock l(lock); - return settings; -} - -void SubscriptionImpl::setFlowControl(const FlowControl& f) { - Mutex::ScopedLock l(lock); - AsyncSession s=manager.getSession(); - if (&settings.flowControl != &f) settings.flowControl = f; - s.messageSetFlowMode(name, f.window); - s.messageFlow(name, CREDIT_UNIT_MESSAGE, f.messages); - s.messageFlow(name, CREDIT_UNIT_BYTE, f.bytes); - s.sync(); -} - -void SubscriptionImpl::grantCredit(framing::message::CreditUnit unit, uint32_t value) { - async(manager.getSession()).messageFlow(name, unit, value); -} - -void SubscriptionImpl::setAutoAck(size_t n) { - Mutex::ScopedLock l(lock); - settings.autoAck = n; -} - -SequenceSet SubscriptionImpl::getUnacquired() const { Mutex::ScopedLock l(lock); return unacquired; } -SequenceSet SubscriptionImpl::getUnaccepted() const { Mutex::ScopedLock l(lock); return unaccepted; } - -void SubscriptionImpl::acquire(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - MessageAcquireResult result = manager.getSession().messageAcquire(messageIds); - unacquired.remove(result.getTransfers()); - if (settings.acceptMode == ACCEPT_MODE_EXPLICIT) - unaccepted.add(result.getTransfers()); -} - -void SubscriptionImpl::accept(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - manager.getSession().messageAccept(messageIds); - unaccepted.remove(messageIds); - switch (settings.completionMode) { - case COMPLETE_ON_ACCEPT: - manager.getSession().markCompleted(messageIds, true); - break; - case COMPLETE_ON_DELIVERY: - manager.getSession().sendCompletion(); - break; - default://do nothing - break; - } -} - -void SubscriptionImpl::release(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - manager.getSession().messageRelease(messageIds); - if (settings.acceptMode == ACCEPT_MODE_EXPLICIT) - unaccepted.remove(messageIds); -} - -Session SubscriptionImpl::getSession() const { return manager.getSession(); } - -SubscriptionManager SubscriptionImpl::getSubscriptionManager() { return SubscriptionManager(&manager); } - -void SubscriptionImpl::cancel() { manager.cancel(name); } - -void SubscriptionImpl::received(Message& m) { - Mutex::ScopedLock l(lock); - MessageImpl& mi = *MessageImpl::get(m); - if (mi.getMethod().getAcquireMode() == ACQUIRE_MODE_NOT_ACQUIRED) - unacquired.add(m.getId()); - else if (mi.getMethod().getAcceptMode() == ACCEPT_MODE_EXPLICIT) - unaccepted.add(m.getId()); - - if (listener) { - Mutex::ScopedUnlock u(lock); - listener->received(m); - } - - if (settings.completionMode == COMPLETE_ON_DELIVERY) { - manager.getSession().markCompleted(m.getId(), false, false); - } - if (settings.autoAck) { - if (unaccepted.size() >= settings.autoAck) { - async(manager.getSession()).messageAccept(unaccepted); - switch (settings.completionMode) { - case COMPLETE_ON_ACCEPT: - manager.getSession().markCompleted(unaccepted, true); - break; - case COMPLETE_ON_DELIVERY: - manager.getSession().sendCompletion(); - break; - default://do nothing - break; - } - unaccepted.clear(); - } - } -} - -Demux::QueuePtr SubscriptionImpl::divert() -{ - Session session(manager.getSession()); - Demux& demux = SessionBase_0_10Access(session).get()->getDemux(); - demuxRule = std::auto_ptr(new ScopedDivert(name, demux)); - return demuxRule->getQueue(); -} - -void SubscriptionImpl::cancelDiversion() { - demuxRule.reset(); -} - -}} // namespace qpid::client - diff --git a/qpid/cpp/src/qpid/client/SubscriptionImpl.h b/qpid/cpp/src/qpid/client/SubscriptionImpl.h deleted file mode 100644 index da77213423..0000000000 --- a/qpid/cpp/src/qpid/client/SubscriptionImpl.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef QPID_CLIENT_SUBSCRIPTIONIMPL_H -#define QPID_CLIENT_SUBSCRIPTIONIMPL_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/SubscriptionSettings.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/Session.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/Demux.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/Mutex.h" -#include "qpid/RefCounted.h" -#include "qpid/client/ClientImportExport.h" -#include - -namespace qpid { -namespace client { - -class SubscriptionManager; -class SubscriptionManagerImpl; - -class SubscriptionImpl : public RefCounted, public MessageListener { - public: - QPID_CLIENT_EXTERN SubscriptionImpl(SubscriptionManager, const std::string& queue, - const SubscriptionSettings&, const std::string& name, MessageListener* =0); - - /** The name of the subsctription, 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(size_t n); - - /** Get the set of ID's for messages received by this subscription but not yet acquired. - * This will always be empty if acquireMode=ACQUIRE_MODE_PRE_ACQUIRED - */ - QPID_CLIENT_EXTERN SequenceSet getUnacquired() const; - - /** Get the set of ID's for messages acquired by this subscription but not yet accepted. */ - QPID_CLIENT_EXTERN SequenceSet getUnaccepted() const; - - /** Acquire messageIds and remove them from the un-acquired set for the session. */ - QPID_CLIENT_EXTERN void acquire(const SequenceSet& messageIds); - - /** Accept messageIds and remove them from the un-accepted set for the session. */ - QPID_CLIENT_EXTERN void accept(const SequenceSet& messageIds); - - /** Release messageIds and remove them from the un-accepted set for the session. */ - QPID_CLIENT_EXTERN void release(const SequenceSet& messageIds); - - /** 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(); - - /** Send subscription request and issue appropriate flow control commands. */ - QPID_CLIENT_EXTERN void subscribe(); - - /** Cancel the subscription. */ - QPID_CLIENT_EXTERN void cancel(); - - /** Grant specified credit for this subscription **/ - QPID_CLIENT_EXTERN void grantCredit(framing::message::CreditUnit unit, uint32_t value); - - QPID_CLIENT_EXTERN void received(Message&); - - /** - * Set up demux diversion for messages sent to this subscription - */ - Demux::QueuePtr divert(); - /** - * Cancel any demux diversion that may have been setup for this - * subscription - */ - QPID_CLIENT_EXTERN void cancelDiversion(); - - private: - - mutable sys::Mutex lock; - SubscriptionManagerImpl& manager; - std::string name, queue; - SubscriptionSettings settings; - framing::SequenceSet unacquired, unaccepted; - MessageListener* listener; - std::auto_ptr demuxRule; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SUBSCRIPTIONIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/SubscriptionManager.cpp b/qpid/cpp/src/qpid/client/SubscriptionManager.cpp deleted file mode 100644 index 485361d577..0000000000 --- a/qpid/cpp/src/qpid/client/SubscriptionManager.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/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/PrivateImplRef.h" - - -namespace qpid { -namespace client { - -typedef PrivateImplRef PI; - -SubscriptionManager::SubscriptionManager(const Session& s) { PI::ctor(*this, new SubscriptionManagerImpl(s)); } -SubscriptionManager::SubscriptionManager(SubscriptionManagerImpl* i) { PI::ctor(*this, i); } -SubscriptionManager::SubscriptionManager(const SubscriptionManager& x) : Runnable(), Handle() { PI::copy(*this, x); } -SubscriptionManager::~SubscriptionManager() { PI::dtor(*this); } -SubscriptionManager& SubscriptionManager::operator=(const SubscriptionManager& x) { return PI::assign(*this, x); } - -Subscription SubscriptionManager::subscribe( - MessageListener& listener, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ return impl->subscribe(listener, q, ss, n); } - -Subscription SubscriptionManager::subscribe( - LocalQueue& lq, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ return impl->subscribe(lq, q, ss, n); } - - -Subscription SubscriptionManager::subscribe( - MessageListener& listener, const std::string& q, const std::string& n) -{ return impl->subscribe(listener, q, n); } - - -Subscription SubscriptionManager::subscribe( - LocalQueue& lq, const std::string& q, const std::string& n) -{ return impl->subscribe(lq, q, n); } - -void SubscriptionManager::cancel(const std::string& dest) { return impl->cancel(dest); } - -void SubscriptionManager::setAutoStop(bool set) { impl->setAutoStop(set); } - -void SubscriptionManager::run() { impl->run(); } - -void SubscriptionManager::start() { impl->start(); } - -void SubscriptionManager::wait() { impl->wait(); } - -void SubscriptionManager::stop() { impl->stop(); } - -bool SubscriptionManager::get(Message& result, const std::string& queue, sys::Duration timeout) { - return impl->get(result, queue, timeout); -} - -Message SubscriptionManager::get(const std::string& queue, sys::Duration timeout) { - return impl->get(queue, timeout); -} - -Session SubscriptionManager::getSession() const { return impl->getSession(); } - -Subscription SubscriptionManager::getSubscription(const std::string& name) const { - return impl->getSubscription(name); -} -void SubscriptionManager::registerFailoverHandler (boost::function fh) { - impl->registerFailoverHandler(fh); -} - -void SubscriptionManager::setFlowControl(const std::string& name, const FlowControl& flow) { - impl->setFlowControl(name, flow); -} - -void SubscriptionManager::setDefaultSettings(const SubscriptionSettings& s){ - impl->setDefaultSettings(s); -} - -void SubscriptionManager::setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window) { - impl->setFlowControl(name, FlowControl(messages, bytes, window)); -} - -void SubscriptionManager::setFlowControl(uint32_t messages, uint32_t bytes, bool window) { - impl->setFlowControl(messages, bytes, window); -} - -void SubscriptionManager::setAcceptMode(AcceptMode mode) { impl->setAcceptMode(mode); } -void SubscriptionManager::setAcquireMode(AcquireMode mode) { impl->setAcquireMode(mode); } - -}} // namespace qpid::client - - diff --git a/qpid/cpp/src/qpid/client/SubscriptionManager.h b/qpid/cpp/src/qpid/client/SubscriptionManager.h deleted file mode 100644 index 404a9c6eb9..0000000000 --- a/qpid/cpp/src/qpid/client/SubscriptionManager.h +++ /dev/null @@ -1,292 +0,0 @@ -#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 - -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 - * - *

Subscribing and canceling subscriptions

- * - *
    - *
  • - *

    subscribe()

    - *
     SubscriptionManager subscriptions(session);
    - * Listener listener(subscriptions);
    - * subscriptions.subscribe(listener, myQueue);
    - *
     SubscriptionManager subscriptions(session);
    - * LocalQueue local_queue;
    - * subscriptions.subscribe(local_queue, string("message_queue"));
  • - *
  • - *

    cancel()

    - *
    subscriptions.cancel();
  • - *
- * - *

Waiting for messages (and returning)

- * - *
    - *
  • - *

    run()

    - *
     // Give up control to receive messages
    - * subscriptions.run();
  • - *
  • - *

    stop()

    - *
    .// Use this code in a listener to return from run()
    - * subscriptions.stop();
  • - *
  • - *

    setAutoStop()

    - *
    .// Return from subscriptions.run() when last subscription is cancelled
    - *.subscriptions.setAutoStop(true);
    - *.subscriptons.run();
    - * 
  • - *
  • - *

    Ending a subscription in a listener

    - *
    - * void Listener::received(Message& message) {
    - *
    - *  if (message.getData() == "That's all, folks!") {
    - *       subscriptions.cancel(message.getDestination());
    - *   }
    - * }
    - * 
    - *
  • - *
- * - */ -class QPID_CLIENT_CLASS_EXTERN SubscriptionManager : public sys::Runnable, public Handle -{ - 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 fh ); - - QPID_CLIENT_EXTERN Session getSession() const; - - SubscriptionManager(SubscriptionManagerImpl*); ///<@internal - - private: - typedef SubscriptionManagerImpl Impl; - friend class PrivateImplRef; -}; - -/** 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/SubscriptionManagerImpl.cpp b/qpid/cpp/src/qpid/client/SubscriptionManagerImpl.cpp deleted file mode 100644 index 44f81776c0..0000000000 --- a/qpid/cpp/src/qpid/client/SubscriptionManagerImpl.cpp +++ /dev/null @@ -1,182 +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/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/LocalQueueImpl.h" -#include "qpid/client/PrivateImplRef.h" -#include -#include -#include -#include -#include -#include -#include - - -namespace qpid { -namespace client { - -SubscriptionManagerImpl::SubscriptionManagerImpl(const Session& s) - : dispatcher(s), session(s), autoStop(true) -{} - -SubscriptionManagerImpl::~SubscriptionManagerImpl() -{ - sys::Mutex::ScopedLock l(lock); - for (std::map::iterator i = subscriptions.begin(); i != subscriptions.end(); ++i) { - boost::intrusive_ptr s = PrivateImplRef::get(i->second); - if (s) s->cancelDiversion(); - } - subscriptions.clear(); -} - -Subscription SubscriptionManagerImpl::subscribe( - MessageListener& listener, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ - sys::Mutex::ScopedLock l(lock); - std::string name=n.empty() ? q:n; - boost::intrusive_ptr si = new SubscriptionImpl(SubscriptionManager(this), q, ss, name, &listener); - dispatcher.listen(si); - //issue subscription request after listener is registered with dispatcher - si->subscribe(); - return subscriptions[name] = Subscription(si.get()); -} - -Subscription SubscriptionManagerImpl::subscribe( - LocalQueue& lq, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ - sys::Mutex::ScopedLock l(lock); - std::string name=n.empty() ? q:n; - boost::intrusive_ptr si = new SubscriptionImpl(SubscriptionManager(this), q, ss, name, 0); - boost::intrusive_ptr lqi = PrivateImplRef::get(lq); - lqi->queue=si->divert(); - si->subscribe(); - lqi->subscription = Subscription(si.get()); - return subscriptions[name] = lqi->subscription; -} - -Subscription SubscriptionManagerImpl::subscribe( - MessageListener& listener, const std::string& q, const std::string& n) -{ - return subscribe(listener, q, defaultSettings, n); -} - -Subscription SubscriptionManagerImpl::subscribe( - LocalQueue& lq, const std::string& q, const std::string& n) -{ - return subscribe(lq, q, defaultSettings, n); -} - -void SubscriptionManagerImpl::cancel(const std::string& dest) -{ - sys::Mutex::ScopedLock l(lock); - std::map::iterator i = subscriptions.find(dest); - if (i != subscriptions.end()) { - sync(session).messageCancel(dest); - dispatcher.cancel(dest); - Subscription s = i->second; - if (s.isValid()) - PrivateImplRef::get(s)->cancelDiversion(); - subscriptions.erase(i); - } -} - -void SubscriptionManagerImpl::setAutoStop(bool set) { autoStop=set; } - -void SubscriptionManagerImpl::run() -{ - dispatcher.setAutoStop(autoStop); - dispatcher.run(); -} - -void SubscriptionManagerImpl::start() -{ - dispatcher.setAutoStop(autoStop); - dispatcher.start(); -} - -void SubscriptionManagerImpl::wait() -{ - dispatcher.wait(); -} - -void SubscriptionManagerImpl::stop() -{ - dispatcher.stop(); -} - -bool SubscriptionManagerImpl::get(Message& result, const std::string& queue, sys::Duration timeout) { - LocalQueue lq; - std::string unique = framing::Uuid(true).str(); - subscribe(lq, queue, SubscriptionSettings(FlowControl::messageCredit(1)), unique); - SubscriptionManager sm(this); - AutoCancel ac(sm, unique); - //first wait for message to be delivered if a timeout has been specified - if (timeout && lq.get(result, timeout)) - return true; - //make sure message is not on queue before final check - sync(session).messageFlush(unique); - return lq.get(result, 0); -} - -Message SubscriptionManagerImpl::get(const std::string& queue, sys::Duration timeout) { - Message result; - if (!get(result, queue, timeout)) - throw Exception("Timed out waiting for a message"); - return result; -} - -Session SubscriptionManagerImpl::getSession() const { return session; } - -Subscription SubscriptionManagerImpl::getSubscription(const std::string& name) const { - sys::Mutex::ScopedLock l(lock); - std::map::const_iterator i = subscriptions.find(name); - if (i == subscriptions.end()) - throw Exception(QPID_MSG("Subscription not found: " << name)); - return i->second; -} - -void SubscriptionManagerImpl::registerFailoverHandler (boost::function fh) { - dispatcher.registerFailoverHandler(fh); -} - -void SubscriptionManagerImpl::setFlowControl(const std::string& name, const FlowControl& flow) { - getSubscription(name).setFlowControl(flow); -} - -void SubscriptionManagerImpl::setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window) { - setFlowControl(name, FlowControl(messages, bytes, window)); -} - -AutoCancel::AutoCancel(SubscriptionManager& sm_, const std::string& tag_) : sm(sm_), tag(tag_) {} -AutoCancel::~AutoCancel() { - try { - sm.cancel(tag); - } catch (const qpid::Exception& e) { - QPID_LOG(info, "Exception in AutoCancel destructor: " << e.what()); - } -} - -}} // namespace qpid::client - - diff --git a/qpid/cpp/src/qpid/client/SubscriptionManagerImpl.h b/qpid/cpp/src/qpid/client/SubscriptionManagerImpl.h deleted file mode 100644 index 64d922e387..0000000000 --- a/qpid/cpp/src/qpid/client/SubscriptionManagerImpl.h +++ /dev/null @@ -1,279 +0,0 @@ -#ifndef QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_H -#define QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace client { - -/** - * A class to help create and manage subscriptions. - * - * Set up your subscriptions, then call run() to have messages - * delivered. - * - * \ingroup clientapi - * - * \details - * - *

Subscribing and canceling subscriptions

- * - *
    - *
  • - *

    subscribe()

    - *
     SubscriptionManager subscriptions(session);
    - * Listener listener(subscriptions);
    - * subscriptions.subscribe(listener, myQueue);
    - *
     SubscriptionManager subscriptions(session);
    - * LocalQueue local_queue;
    - * subscriptions.subscribe(local_queue, string("message_queue"));
  • - *
  • - *

    cancel()

    - *
    subscriptions.cancel();
  • - *
- * - *

Waiting for messages (and returning)

- * - *
    - *
  • - *

    run()

    - *
     // Give up control to receive messages
    - * subscriptions.run();
  • - *
  • - *

    stop()

    - *
    .// Use this code in a listener to return from run()
    - * subscriptions.stop();
  • - *
  • - *

    setAutoStop()

    - *
    .// Return from subscriptions.run() when last subscription is cancelled
    - *.subscriptions.setAutoStop(true);
    - *.subscriptons.run();
    - * 
  • - *
  • - *

    Ending a subscription in a listener

    - *
    - * void Listener::received(Message& message) {
    - * 
    - *  if (message.getData() == "That's all, folks!") {
    - *       subscriptions.cancel(message.getDestination());
    - *   }
    - * }
    - * 
    - *
  • - *
- * - */ -class SubscriptionManagerImpl : public sys::Runnable, public RefCounted -{ - public: - /** Create a new SubscriptionManagerImpl associated with a session */ - SubscriptionManagerImpl(const Session& session); - ~SubscriptionManagerImpl(); - - /** - * 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. - */ - 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. - */ - 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. - */ - 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. - */ - Subscription subscribe(LocalQueue& localQueue, - const std::string& queue, - const std::string& name=std::string()); - - - /** Get a single message from a queue. - *@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. - */ - bool get(Message& result, const std::string& queue, sys::Duration timeout=0); - - /** Get a single message from a queue. - *@param timeout wait up this timeout for a message to appear. - *@return message from the queue. - *@throw Exception if the timeout is exceeded. - */ - Message get(const std::string& queue, sys::Duration timeout=sys::TIME_INFINITE); - - /** Get a subscription by name. - *@throw Exception if not found. - */ - Subscription getSubscription(const std::string& name) const; - - /** Cancel a subscription. See also: Subscription.cancel() */ - 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 - */ - void run(); - - /** Start a new thread to deliver messages. - * Only one thread may be running in a SubscriptionManager at a time. - * @see start - */ - void start(); - - /** - * Wait for the thread started by a call to start() to complete. - */ - 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. - */ - void setAutoStop(bool set=true); - - /** Stop delivery. Causes run() to return, or the thread started with start() to exit. */ - void stop(); - - static const uint32_t UNLIMITED=0xFFFFFFFF; - - /** Set the flow control for a subscription. */ - 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. - */ - 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. - */ - void setDefaultSettings(const SubscriptionSettings& s) { defaultSettings = s; } - - /** Get the default settings for subscribe() calls that don't - * include a SubscriptionSettings parameter. - */ - const SubscriptionSettings& getDefaultSettings() const { return defaultSettings; } - - /** Get the default settings for subscribe() calls that don't - * include a SubscriptionSettings parameter. - */ - SubscriptionSettings& getDefaultSettings() { return defaultSettings; } - - /** - * 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. - */ - void setFlowControl(uint32_t messages, uint32_t bytes, bool window=true) { - defaultSettings.flowControl = FlowControl(messages, bytes, window); - } - - /** - *Set the default accept-mode for subscribe() calls that don't - *include a SubscriptionSettings parameter. - */ - void setAcceptMode(AcceptMode mode) { defaultSettings.acceptMode = mode; } - - /** - * Set the default acquire-mode subscribe()s that don't specify SubscriptionSettings. - */ - void setAcquireMode(AcquireMode mode) { defaultSettings.acquireMode = mode; } - - void registerFailoverHandler ( boost::function fh ); - - Session getSession() const; - - private: - mutable sys::Mutex lock; - qpid::client::Dispatcher dispatcher; - qpid::client::AsyncSession session; - bool autoStop; - SubscriptionSettings defaultSettings; - std::map subscriptions; -}; - - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/SubscriptionSettings.h b/qpid/cpp/src/qpid/client/SubscriptionSettings.h deleted file mode 100644 index bee39f6816..0000000000 --- a/qpid/cpp/src/qpid/client/SubscriptionSettings.h +++ /dev/null @@ -1,135 +0,0 @@ -#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/TCPConnector.cpp b/qpid/cpp/src/qpid/client/TCPConnector.cpp deleted file mode 100644 index 0a570fb1d9..0000000000 --- a/qpid/cpp/src/qpid/client/TCPConnector.cpp +++ /dev/null @@ -1,323 +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/client/TCPConnector.h" - -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Codec.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/Msg.h" - -#include -#include -#include - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; -using boost::format; -using boost::str; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - return new TCPConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - Connector::registerFactory("tcp", &create); - }; - } init; -} - -TCPConnector::TCPConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - lastEof(0), - currentSize(0), - bounds(cimpl), - version(ver), - initiated(false), - closed(true), - shutdownHandler(0), - input(0), - socket(createSocket()), - connector(0), - aio(0), - poller(p) -{ - QPID_LOG(debug, "TCPConnector created for " << version); - settings.configureSocket(*socket); -} - -TCPConnector::~TCPConnector() { - close(); -} - -void TCPConnector::connect(const std::string& host, const std::string& port) { - Mutex::ScopedLock l(lock); - assert(closed); - connector = AsynchConnector::create( - *socket, - host, port, - boost::bind(&TCPConnector::connected, this, _1), - boost::bind(&TCPConnector::connectFailed, this, _3)); - closed = false; - - connector->start(poller); -} - -void TCPConnector::connected(const Socket&) { - connector = 0; - aio = AsynchIO::create(*socket, - boost::bind(&TCPConnector::readbuff, this, _1, _2), - boost::bind(&TCPConnector::eof, this, _1), - boost::bind(&TCPConnector::disconnected, this, _1), - boost::bind(&TCPConnector::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&TCPConnector::writebuff, this, _1)); - start(aio); - initAmqp(); - aio->start(poller); -} - -void TCPConnector::start(sys::AsynchIO* aio_) { - aio = aio_; - - aio->createBuffers(maxFrameSize); - - identifier = str(format("[%1%]") % socket->getFullAddress()); -} - -void TCPConnector::initAmqp() { - ProtocolInitiation init(version); - writeDataBlock(init); -} - -void TCPConnector::connectFailed(const std::string& msg) { - connector = 0; - QPID_LOG(warning, "Connect failed: " << msg); - socket->close(); - if (!closed) - closed = true; - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void TCPConnector::close() { - Mutex::ScopedLock l(lock); - if (!closed) { - closed = true; - if (aio) - aio->queueWriteClose(); - } -} - -void TCPConnector::socketClosed(AsynchIO&, const Socket&) { - if (aio) - aio->queueForDeletion(); - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void TCPConnector::connectAborted() { - connector->stop(); - connectFailed("Connection timedout"); -} - -void TCPConnector::abort() { - // Can't abort a closed connection - if (!closed) { - if (aio) { - // Established connection - aio->requestCallback(boost::bind(&TCPConnector::disconnected, this, _1)); - } else if (connector) { - // We're still connecting - connector->requestCallback(boost::bind(&TCPConnector::connectAborted, this)); - } - } -} - -void TCPConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void TCPConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -const std::string& TCPConnector::getIdentifier() const { - return identifier; -} - -void TCPConnector::handle(AMQFrame& frame) { - bool notifyWrite = false; - { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - //only ask to write if this is the end of a frameset or if we - //already have a buffers worth of data - currentSize += frame.encodedSize(); - if (frame.getEof()) { - lastEof = frames.size(); - notifyWrite = true; - } else { - notifyWrite = (currentSize >= maxFrameSize); - } - /* - NOTE: Moving the following line into this mutex block - is a workaround for BZ 570168, in which the test - testConcurrentSenders causes a hang about 1.5% - of the time. ( To see the hang much more frequently - leave this line out of the mutex block, and put a - small usleep just before it.) - - TODO mgoulish - fix the underlying cause and then - move this call back outside the mutex. - */ - if (notifyWrite && !closed) aio->notifyPendingWrite(); - } -} - -void TCPConnector::writebuff(AsynchIO& /*aio*/) -{ - // It's possible to be disconnected and be writable - if (closed) - return; - - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - - if (!codec->canEncode()) { - return; - } - - AsynchIO::BufferBase* buffer = aio->getQueuedBuffer(); - if (buffer) { - - size_t encoded = codec->encode(buffer->bytes, buffer->byteCount); - - buffer->dataStart = 0; - buffer->dataCount = encoded; - aio->queueWrite(buffer); - } -} - -// Called in IO thread. -bool TCPConnector::canEncode() -{ - Mutex::ScopedLock l(lock); - //have at least one full frameset or a whole buffers worth of data - return lastEof || currentSize >= maxFrameSize; -} - -// Called in IO thread. -size_t TCPConnector::encode(char* buffer, size_t size) -{ - framing::Buffer out(buffer, size); - size_t bytesWritten(0); - { - Mutex::ScopedLock l(lock); - while (!frames.empty() && out.available() >= frames.front().encodedSize() ) { - frames.front().encode(out); - QPID_LOG(trace, "SENT [" << identifier << "]: " << frames.front()); - frames.pop_front(); - if (lastEof) --lastEof; - } - bytesWritten = size - out.available(); - currentSize -= bytesWritten; - } - if (bounds) bounds->reduce(bytesWritten); - return bytesWritten; -} - -void TCPConnector::readbuff(AsynchIO& aio, AsynchIO::BufferBase* buff) -{ - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - int32_t decoded = codec->decode(buff->bytes+buff->dataStart, buff->dataCount); - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (decoded < buff->dataCount) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += decoded; - buff->dataCount -= decoded; - aio.unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio.queueReadBuffer(buff); - } -} - -size_t TCPConnector::decode(const char* buffer, size_t size) -{ - framing::Buffer in(const_cast(buffer), size); - try { - if (checkProtocolHeader(in, version)) { - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV [" << identifier << "]: " << frame); - input->received(frame); - } - } - } catch (const ProtocolVersionError& e) { - QPID_LOG(info, "Closing connection due to " << e.what()); - close(); - } - return size - in.available(); -} - -void TCPConnector::writeDataBlock(const AMQDataBlock& data) { - AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); - assert(buff); - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void TCPConnector::eof(AsynchIO&) { - close(); -} - -void TCPConnector::disconnected(AsynchIO&) { - close(); - socketClosed(*aio, *socket); -} - -void TCPConnector::activateSecurityLayer(std::auto_ptr sl) -{ - securityLayer = sl; - securityLayer->init(this); -} - -}} // namespace qpid::client diff --git a/qpid/cpp/src/qpid/client/TCPConnector.h b/qpid/cpp/src/qpid/client/TCPConnector.h deleted file mode 100644 index 20bd2fa5b8..0000000000 --- a/qpid/cpp/src/qpid/client/TCPConnector.h +++ /dev/null @@ -1,116 +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. - * - */ - -#ifndef _TCPConnector_ -#define _TCPConnector_ - -#include "Connector.h" -#include "qpid/client/Bounds.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Codec.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/Thread.h" - -#include -#include -#include -#include - -namespace qpid { - -namespace framing { - class InitiationHandler; -} - -namespace client { - -class TCPConnector : public Connector, public sys::Codec -{ - typedef std::deque Frames; - - const uint16_t maxFrameSize; - - sys::Mutex lock; - Frames frames; // Outgoing frame queue - size_t lastEof; // Position after last EOF in frames - uint64_t currentSize; - Bounds* bounds; - - framing::ProtocolVersion version; - bool initiated; - bool closed; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - - boost::scoped_ptr socket; - - sys::AsynchConnector* connector; - sys::AsynchIO* aio; - std::string identifier; - boost::shared_ptr poller; - std::auto_ptr securityLayer; - - virtual void connected(const sys::Socket&); - void writeDataBlock(const framing::AMQDataBlock& data); - - void close(); - void handle(framing::AMQFrame& frame); - void abort(); - void connectAborted(); - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - const std::string& getIdentifier() const; - void activateSecurityLayer(std::auto_ptr); - const qpid::sys::SecuritySettings* getSecuritySettings() { return 0; } - - size_t decode(const char* buffer, size_t size); - size_t encode(char* buffer, size_t size); - bool canEncode(); - -protected: - virtual ~TCPConnector(); - void connect(const std::string& host, const std::string& port); - void start(sys::AsynchIO* aio_); - void initAmqp(); - virtual void connectFailed(const std::string& msg); - void readbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); - void writebuff(qpid::sys::AsynchIO&); - void eof(qpid::sys::AsynchIO&); - void disconnected(qpid::sys::AsynchIO&); - void socketClosed(qpid::sys::AsynchIO&, const qpid::sys::Socket&); - -public: - TCPConnector(boost::shared_ptr, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -}} // namespace qpid::client - -#endif /* _TCPConnector_ */ diff --git a/qpid/cpp/src/qpid/client/TypedResult.h b/qpid/cpp/src/qpid/client/TypedResult.h deleted file mode 100644 index 8e1a16580c..0000000000 --- a/qpid/cpp/src/qpid/client/TypedResult.h +++ /dev/null @@ -1,65 +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. - * - */ - -#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 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/AcceptTracker.cpp b/qpid/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp deleted file mode 100644 index d2accddcd0..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp +++ /dev/null @@ -1,153 +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 "AcceptTracker.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -void AcceptTracker::State::accept() -{ - unconfirmed.add(unaccepted); - unaccepted.clear(); -} - -SequenceSet AcceptTracker::State::accept(qpid::framing::SequenceNumber id, bool cumulative) -{ - SequenceSet accepting; - if (cumulative) { - for (SequenceSet::iterator i = unaccepted.begin(); i != unaccepted.end() && *i <= id; ++i) { - accepting.add(*i); - } - unconfirmed.add(accepting); - unaccepted.remove(accepting); - } else { - if (unaccepted.contains(id)) { - unaccepted.remove(id); - unconfirmed.add(id); - accepting.add(id); - } - } - return accepting; -} - -void AcceptTracker::State::release() -{ - unaccepted.clear(); -} - -uint32_t AcceptTracker::State::acceptsPending() -{ - return unconfirmed.size(); -} - -void AcceptTracker::State::completed(qpid::framing::SequenceSet& set) -{ - unconfirmed.remove(set); -} - -void AcceptTracker::delivered(const std::string& destination, const qpid::framing::SequenceNumber& id) -{ - aggregateState.unaccepted.add(id); - destinationState[destination].unaccepted.add(id); -} - -namespace -{ -const size_t FLUSH_FREQUENCY = 1024; -} - -void AcceptTracker::addToPending(qpid::client::AsyncSession& session, const Record& record) -{ - pending.push_back(record); - if (pending.size() % FLUSH_FREQUENCY == 0) session.flush(); -} - - -void AcceptTracker::accept(qpid::client::AsyncSession& session) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.accept(); - } - Record record; - record.status = session.messageAccept(aggregateState.unaccepted); - record.accepted = aggregateState.unaccepted; - addToPending(session, record); - aggregateState.accept(); -} - -void AcceptTracker::accept(qpid::framing::SequenceNumber id, qpid::client::AsyncSession& session, bool cumulative) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.accept(id, cumulative); - } - Record record; - record.accepted = aggregateState.accept(id, cumulative); - record.status = session.messageAccept(record.accepted); - addToPending(session, record); -} - -void AcceptTracker::release(qpid::client::AsyncSession& session) -{ - session.messageRelease(aggregateState.unaccepted); - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.release(); - } - aggregateState.release(); -} - -uint32_t AcceptTracker::acceptsPending() -{ - checkPending(); - return aggregateState.acceptsPending(); -} - -uint32_t AcceptTracker::acceptsPending(const std::string& destination) -{ - checkPending(); - return destinationState[destination].acceptsPending(); -} - -void AcceptTracker::reset() -{ - destinationState.clear(); - aggregateState.unaccepted.clear(); - aggregateState.unconfirmed.clear(); - pending.clear(); -} - -void AcceptTracker::checkPending() -{ - while (!pending.empty() && pending.front().status.isComplete()) { - completed(pending.front().accepted); - pending.pop_front(); - } -} - -void AcceptTracker::completed(qpid::framing::SequenceSet& set) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.completed(set); - } - aggregateState.completed(set); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/qpid/cpp/src/qpid/client/amqp0_10/AcceptTracker.h b/qpid/cpp/src/qpid/client/amqp0_10/AcceptTracker.h deleted file mode 100644 index 85209c3b87..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/AcceptTracker.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_H -#define QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_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/Completion.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceSet.h" -#include -#include - -namespace qpid { -namespace client { -namespace amqp0_10 { - -/** - * Tracks the set of messages requiring acceptance, and those for - * which an accept has been issued but is yet to be confirmed - * complete. - */ -class AcceptTracker -{ - public: - void delivered(const std::string& destination, const qpid::framing::SequenceNumber& id); - void accept(qpid::client::AsyncSession&); - void accept(qpid::framing::SequenceNumber, qpid::client::AsyncSession&, bool cumulative); - void release(qpid::client::AsyncSession&); - uint32_t acceptsPending(); - uint32_t acceptsPending(const std::string& destination); - void reset(); - private: - struct State - { - /** - * ids of messages that have been delivered but not yet - * accepted - */ - qpid::framing::SequenceSet unaccepted; - /** - * ids of messages for which an accept has been issued but not - * yet confirmed as completed - */ - qpid::framing::SequenceSet unconfirmed; - - void accept(); - qpid::framing::SequenceSet accept(qpid::framing::SequenceNumber, bool cumulative); - void release(); - uint32_t acceptsPending(); - void completed(qpid::framing::SequenceSet&); - }; - typedef std::map StateMap; - struct Record - { - qpid::client::Completion status; - qpid::framing::SequenceSet accepted; - }; - typedef std::deque Records; - - State aggregateState; - StateMap destinationState; - Records pending; - - void addToPending(qpid::client::AsyncSession&, const Record&); - void checkPending(); - void completed(qpid::framing::SequenceSet&); -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp deleted file mode 100644 index ed931c90fb..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp +++ /dev/null @@ -1,1058 +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/client/amqp0_10/AddressResolution.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/client/amqp0_10/MessageSource.h" -#include "qpid/client/amqp0_10/MessageSink.h" -#include "qpid/client/amqp0_10/OutgoingMessage.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/AddressImpl.h" -#include "qpid/messaging/Message.h" -#include "qpid/types/Variant.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/ExchangeBoundResult.h" -#include "qpid/framing/ExchangeQueryResult.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/QueueQueryResult.h" -#include "qpid/framing/ReplyTo.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Uuid.h" -#include -#include - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::Exception; -using qpid::messaging::Address; -using qpid::messaging::AddressError; -using qpid::messaging::MalformedAddress; -using qpid::messaging::ResolutionError; -using qpid::messaging::NotFound; -using qpid::messaging::AssertionFailed; -using qpid::framing::ExchangeBoundResult; -using qpid::framing::ExchangeQueryResult; -using qpid::framing::FieldTable; -using qpid::framing::FieldValue; -using qpid::framing::QueueQueryResult; -using qpid::framing::ReplyTo; -using qpid::framing::Uuid; -using namespace qpid::types; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; -using namespace boost::assign; - -class Verifier -{ - public: - Verifier(); - void verify(const Address& address) const; - private: - Variant::Map defined; - void verify(const Variant::Map& allowed, const Variant::Map& actual) const; -}; - -namespace{ -const Variant EMPTY_VARIANT; -const FieldTable EMPTY_FIELD_TABLE; -const Variant::List EMPTY_LIST; -const std::string EMPTY_STRING; - -//policy types -const std::string CREATE("create"); -const std::string ASSERT("assert"); -const std::string DELETE("delete"); - -//option names -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"); -const std::string X_SUBSCRIBE("x-subscribe"); -const std::string X_BINDINGS("x-bindings"); -const std::string SELECTOR("selector"); -const std::string APACHE_SELECTOR("x-apache-selector"); -const std::string QPID_FILTER("qpid.filter"); -const std::string EXCHANGE("exchange"); -const std::string QUEUE("queue"); -const std::string KEY("key"); -const std::string ARGUMENTS("arguments"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string TYPE("type"); -const std::string EXCLUSIVE("exclusive"); -const std::string AUTO_DELETE("auto-delete"); - -//policy values -const std::string ALWAYS("always"); -const std::string NEVER("never"); -const std::string RECEIVER("receiver"); -const std::string SENDER("sender"); - -//address types -const std::string QUEUE_ADDRESS("queue"); -const std::string TOPIC_ADDRESS("topic"); - -//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"); - -//receiver modes: -const std::string BROWSE("browse"); -const std::string CONSUME("consume"); - -//0-10 exchange types: -const std::string TOPIC_EXCHANGE("topic"); -const std::string FANOUT_EXCHANGE("fanout"); -const std::string DIRECT_EXCHANGE("direct"); -const std::string HEADERS_EXCHANGE("headers"); -const std::string XML_EXCHANGE("xml"); -const std::string WILDCARD_ANY("#"); - -//exchange prefixes: -const std::string PREFIX_AMQ("amq."); -const std::string PREFIX_QPID("qpid."); - -const Verifier verifier; - -bool areEquivalent(const FieldValue& a, const FieldValue& b) -{ - return ((a == b) || (a.convertsTo() && b.convertsTo() && a.get() == b.get())); -} -} - -struct Binding -{ - Binding(const Variant::Map&); - Binding(const std::string& exchange, const std::string& queue, const std::string& key); - - std::string exchange; - std::string queue; - std::string key; - FieldTable arguments; -}; - -struct Bindings : std::vector -{ - void add(const Variant::List& bindings); - void setDefaultExchange(const std::string&); - void setDefaultQueue(const std::string&); - void bind(qpid::client::AsyncSession& session); - void unbind(qpid::client::AsyncSession& session); - void check(qpid::client::AsyncSession& session); -}; - -class Node -{ - protected: - enum CheckMode {FOR_RECEIVER, FOR_SENDER}; - - Node(const Address& address); - - const std::string name; - Variant createPolicy; - Variant assertPolicy; - Variant deletePolicy; - Bindings nodeBindings; - Bindings linkBindings; - - static bool enabled(const Variant& policy, CheckMode mode); - static bool createEnabled(const Address& address, CheckMode mode); - static void convert(const Variant& option, FieldTable& arguments); - static std::vector RECEIVER_MODES; - static std::vector SENDER_MODES; -}; - - -class Queue : protected Node -{ - public: - Queue(const Address& address); - protected: - void checkCreate(qpid::client::AsyncSession&, CheckMode); - void checkAssert(qpid::client::AsyncSession&, CheckMode); - void checkDelete(qpid::client::AsyncSession&, CheckMode); - private: - const bool durable; - bool autoDelete; - bool exclusive; - const std::string alternateExchange; - FieldTable arguments; -}; - -class Exchange : protected Node -{ - public: - Exchange(const Address& address); - protected: - void checkCreate(qpid::client::AsyncSession&, CheckMode); - void checkAssert(qpid::client::AsyncSession&, CheckMode); - void checkDelete(qpid::client::AsyncSession&, CheckMode); - bool isReservedName(); - - protected: - const std::string specifiedType; - private: - const bool durable; - bool autoDelete; - const std::string alternateExchange; - FieldTable arguments; -}; - -class QueueSource : public Queue, public MessageSource -{ - public: - QueueSource(const Address& address); - void subscribe(qpid::client::AsyncSession& session, const std::string& destination); - void cancel(qpid::client::AsyncSession& session, const std::string& destination); - private: - const AcquireMode acquireMode; - const AcceptMode acceptMode; - bool exclusive; - FieldTable options; -}; - -class Subscription : public Exchange, public MessageSource -{ - public: - Subscription(const Address&, const std::string& actualType); - void subscribe(qpid::client::AsyncSession& session, const std::string& destination); - void cancel(qpid::client::AsyncSession& session, const std::string& destination); - private: - const std::string queue; - const bool durable; - const bool reliable; - const std::string actualType; - const bool exclusiveQueue; - const bool autoDeleteQueue; - const bool exclusiveSubscription; - const std::string alternateExchange; - FieldTable queueOptions; - FieldTable subscriptionOptions; - Bindings bindings; - - void bindSubject(const std::string& subject); - void bindAll(); - void add(const std::string& exchange, const std::string& key); - static std::string getSubscriptionName(const std::string& base, const std::string& name); -}; - -class ExchangeSink : public Exchange, public MessageSink -{ - public: - ExchangeSink(const Address& name); - void declare(qpid::client::AsyncSession& session, const std::string& name); - void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message); - void cancel(qpid::client::AsyncSession& session, const std::string& name); - private: -}; - -class QueueSink : public Queue, public MessageSink -{ - public: - QueueSink(const Address& name); - void declare(qpid::client::AsyncSession& session, const std::string& name); - void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message); - void cancel(qpid::client::AsyncSession& session, const std::string& name); - private: -}; -bool isQueue(qpid::client::Session session, const qpid::messaging::Address& address); -bool isTopic(qpid::client::Session session, const qpid::messaging::Address& address); - -bool in(const Variant& value, const std::vector& choices) -{ - if (!value.isVoid()) { - for (std::vector::const_iterator i = choices.begin(); i != choices.end(); ++i) { - if (value.asString() == *i) return true; - } - } - return false; -} - -const Variant& getOption(const Variant::Map& options, const std::string& name) -{ - Variant::Map::const_iterator j = options.find(name); - if (j == options.end()) { - return EMPTY_VARIANT; - } else { - return j->second; - } -} - -const Variant& getOption(const Address& address, const std::string& name) -{ - return getOption(address.getOptions(), name); -} - -bool getReceiverPolicy(const Address& address, const std::string& key) -{ - return in(getOption(address, key), list_of(ALWAYS)(RECEIVER)); -} - -bool getSenderPolicy(const Address& address, const std::string& key) -{ - return in(getOption(address, key), list_of(ALWAYS)(SENDER)); -} - -struct Opt -{ - Opt(const Address& address); - Opt(const Variant::Map& base); - Opt& operator/(const std::string& name); - operator bool() const; - operator std::string() const; - std::string str() const; - bool asBool(bool defaultValue) const; - const Variant::List& asList() const; - void collect(qpid::framing::FieldTable& args) const; - bool hasKey(const std::string&) const; - - const Variant::Map* options; - const Variant* value; -}; - -Opt::Opt(const Address& address) : options(&(address.getOptions())), value(0) {} -Opt::Opt(const Variant::Map& base) : options(&base), value(0) {} -Opt& Opt::operator/(const std::string& name) -{ - if (options) { - Variant::Map::const_iterator j = options->find(name); - if (j == options->end()) { - value = 0; - options = 0; - } else { - value = &(j->second); - if (value->getType() == VAR_MAP) options = &(value->asMap()); - else options = 0; - } - } - return *this; -} - - -Opt::operator bool() const -{ - return value && !value->isVoid() && value->asBool(); -} - -Opt::operator std::string() const -{ - return str(); -} - -bool Opt::asBool(bool defaultValue) const -{ - if (value) return value->asBool(); - else return defaultValue; -} - -std::string Opt::str() const -{ - if (value) return value->asString(); - else return EMPTY_STRING; -} - -const Variant::List& Opt::asList() const -{ - if (value) return value->asList(); - else return EMPTY_LIST; -} - -void Opt::collect(qpid::framing::FieldTable& args) const -{ - if (value) { - translate(value->asMap(), args); - } -} -bool Opt::hasKey(const std::string& key) const -{ - if (value) { - Variant::Map::const_iterator i = value->asMap().find(key); - return i != value->asMap().end(); - } else { - return false; - } -} - -bool AddressResolution::is_unreliable(const Address& address) -{ - - return in((Opt(address)/LINK/RELIABILITY).str(), - list_of(UNRELIABLE)(AT_MOST_ONCE)); -} - -bool AddressResolution::is_reliable(const Address& address) -{ - return in((Opt(address)/LINK/RELIABILITY).str(), - list_of(AT_LEAST_ONCE)(EXACTLY_ONCE)); -} - -std::string checkAddressType(qpid::client::Session session, const Address& address) -{ - verifier.verify(address); - if (address.getName().empty()) { - throw MalformedAddress("Name cannot be null"); - } - std::string type = (Opt(address)/NODE/TYPE).str(); - if (type.empty()) { - ExchangeBoundResult result = session.exchangeBound(arg::exchange=address.getName(), arg::queue=address.getName()); - if (result.getQueueNotFound() && result.getExchangeNotFound()) { - //neither a queue nor an exchange exists with that name; treat it as a queue - type = QUEUE_ADDRESS; - } else if (result.getExchangeNotFound()) { - //name refers to a queue - type = QUEUE_ADDRESS; - } else if (result.getQueueNotFound()) { - //name refers to an exchange - type = TOPIC_ADDRESS; - } else { - //both a queue and exchange exist for that name - throw ResolutionError("Ambiguous address, please specify queue or topic as node type"); - } - } - return type; -} - -std::auto_ptr AddressResolution::resolveSource(qpid::client::Session session, - const Address& address) -{ - std::string type = checkAddressType(session, address); - if (type == TOPIC_ADDRESS) { - std::string exchangeType = sync(session).exchangeQuery(address.getName()).getType(); - std::auto_ptr source(new Subscription(address, exchangeType)); - QPID_LOG(debug, "treating source address as topic: " << address); - return source; - } else if (type == QUEUE_ADDRESS) { - std::auto_ptr source(new QueueSource(address)); - QPID_LOG(debug, "treating source address as queue: " << address); - return source; - } else { - throw ResolutionError("Unrecognised type: " + type); - } -} - - -std::auto_ptr AddressResolution::resolveSink(qpid::client::Session session, - const qpid::messaging::Address& address) -{ - std::string type = checkAddressType(session, address); - if (type == TOPIC_ADDRESS) { - std::auto_ptr sink(new ExchangeSink(address)); - QPID_LOG(debug, "treating target address as topic: " << address); - return sink; - } else if (type == QUEUE_ADDRESS) { - std::auto_ptr sink(new QueueSink(address)); - QPID_LOG(debug, "treating target address as queue: " << address); - return sink; - } else { - throw ResolutionError("Unrecognised type: " + type); - } -} - -bool isBrowse(const Address& address) -{ - const Variant& mode = getOption(address, MODE); - if (!mode.isVoid()) { - std::string value = mode.asString(); - if (value == BROWSE) return true; - else if (value != CONSUME) throw ResolutionError("Invalid mode"); - } - return false; -} - -QueueSource::QueueSource(const Address& address) : - Queue(address), - acquireMode(isBrowse(address) ? ACQUIRE_MODE_NOT_ACQUIRED : ACQUIRE_MODE_PRE_ACQUIRED), - //since this client does not provide any means by which an - //unacquired message can be acquired, there is no value in an - //explicit accept - acceptMode(acquireMode == ACQUIRE_MODE_NOT_ACQUIRED || AddressResolution::is_unreliable(address) ? ACCEPT_MODE_NONE : ACCEPT_MODE_EXPLICIT), - exclusive(false) -{ - exclusive = Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE; - (Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(options); - std::string selector = Opt(address)/LINK/SELECTOR; - if (!selector.empty()) options.setString(APACHE_SELECTOR, selector); -} - -void QueueSource::subscribe(qpid::client::AsyncSession& session, const std::string& destination) -{ - checkCreate(session, FOR_RECEIVER); - checkAssert(session, FOR_RECEIVER); - linkBindings.bind(session); - session.messageSubscribe(arg::queue=name, - arg::destination=destination, - arg::acceptMode=acceptMode, - arg::acquireMode=acquireMode, - arg::exclusive=exclusive, - arg::arguments=options); -} - -void QueueSource::cancel(qpid::client::AsyncSession& session, const std::string& destination) -{ - linkBindings.unbind(session); - session.messageCancel(destination); - checkDelete(session, FOR_RECEIVER); -} - -std::string Subscription::getSubscriptionName(const std::string& base, const std::string& name) -{ - if (name.empty()) { - return (boost::format("%1%_%2%") % base % Uuid(true).str()).str(); - } else { - return name; - } -} - -Subscription::Subscription(const Address& address, const std::string& type) - : Exchange(address), - queue(getSubscriptionName(name, (Opt(address)/LINK/NAME).str())), - 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)), - autoDeleteQueue((Opt(address)/LINK/X_DECLARE/AUTO_DELETE).asBool(!(durable || reliable))), - exclusiveSubscription((Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE).asBool(exclusiveQueue)), - alternateExchange((Opt(address)/LINK/X_DECLARE/ALTERNATE_EXCHANGE).str()) -{ - - if ((Opt(address)/LINK).hasKey(TIMEOUT)) { - const Variant* timeout = (Opt(address)/LINK/TIMEOUT).value; - if (timeout->asUint32()) queueOptions.setInt("qpid.auto_delete_timeout", timeout->asUint32()); - } else if (durable && !AddressResolution::is_reliable(address) && !(Opt(address)/LINK/X_DECLARE).hasKey(AUTO_DELETE)) { - //if durable, not explicitly reliable, and auto-delete not - //explicitly set, then set a non-zero default for the - //autodelete timeout - queueOptions.setInt("qpid.auto_delete_timeout", 2*60); - } - (Opt(address)/LINK/X_DECLARE/ARGUMENTS).collect(queueOptions); - (Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(subscriptionOptions); - std::string selector = Opt(address)/LINK/SELECTOR; - if (!selector.empty()) queueOptions.setString(QPID_FILTER, selector); - - if (!address.getSubject().empty()) bindSubject(address.getSubject()); - else if (linkBindings.empty()) bindAll(); -} - -void Subscription::bindSubject(const std::string& subject) -{ - if (actualType == HEADERS_EXCHANGE) { - Binding b(name, queue, subject); - b.arguments.setString("qpid.subject", subject); - b.arguments.setString("x-match", "all"); - bindings.push_back(b); - } else if (actualType == XML_EXCHANGE) { - Binding b(name, queue, subject); - std::string query = (boost::format("declare variable $qpid.subject external; $qpid.subject = '%1%'") - % subject).str(); - b.arguments.setString("xquery", query); - bindings.push_back(b); - } else { - //Note: the fanout exchange doesn't support any filtering, so - //the subject is ignored in that case - add(name, subject); - } -} - -void Subscription::bindAll() -{ - if (actualType == TOPIC_EXCHANGE) { - add(name, WILDCARD_ANY); - } else if (actualType == FANOUT_EXCHANGE) { - add(name, queue); - } else if (actualType == HEADERS_EXCHANGE) { - Binding b(name, queue, "match-all"); - b.arguments.setString("x-match", "all"); - bindings.push_back(b); - } else if (actualType == XML_EXCHANGE) { - Binding b(name, queue, EMPTY_STRING); - b.arguments.setString("xquery", "true()"); - bindings.push_back(b); - } else { - add(name, EMPTY_STRING); - } -} - -void Subscription::add(const std::string& exchange, const std::string& key) -{ - bindings.push_back(Binding(exchange, queue, key)); -} - -void Subscription::subscribe(qpid::client::AsyncSession& session, const std::string& destination) -{ - //create exchange if required and specified by policy: - checkCreate(session, FOR_RECEIVER); - checkAssert(session, FOR_RECEIVER); - - //create subscription queue: - session.queueDeclare(arg::queue=queue, arg::exclusive=exclusiveQueue, - arg::autoDelete=autoDeleteQueue, arg::durable=durable, - arg::alternateExchange=alternateExchange, - arg::arguments=queueOptions); - //'default' binding: - bindings.bind(session); - //any explicit bindings: - linkBindings.setDefaultQueue(queue); - linkBindings.bind(session); - //subscribe to subscription queue: - AcceptMode accept = reliable ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE; - session.messageSubscribe(arg::queue=queue, arg::destination=destination, - arg::exclusive=exclusiveSubscription, arg::acceptMode=accept, arg::arguments=subscriptionOptions); -} - -void Subscription::cancel(qpid::client::AsyncSession& session, const std::string& destination) -{ - linkBindings.unbind(session); - session.messageCancel(destination); - if (exclusiveQueue) session.queueDelete(arg::queue=queue, arg::ifUnused=true); - checkDelete(session, FOR_RECEIVER); -} - -ExchangeSink::ExchangeSink(const Address& address) : Exchange(address) {} - -void ExchangeSink::declare(qpid::client::AsyncSession& session, const std::string&) -{ - checkCreate(session, FOR_SENDER); - checkAssert(session, FOR_SENDER); - linkBindings.bind(session); -} - -void ExchangeSink::send(qpid::client::AsyncSession& session, const std::string&, OutgoingMessage& m) -{ - m.send(session, name, m.getSubject()); -} - -void ExchangeSink::cancel(qpid::client::AsyncSession& session, const std::string&) -{ - linkBindings.unbind(session); - checkDelete(session, FOR_SENDER); -} - -QueueSink::QueueSink(const Address& address) : Queue(address) {} - -void QueueSink::declare(qpid::client::AsyncSession& session, const std::string&) -{ - checkCreate(session, FOR_SENDER); - checkAssert(session, FOR_SENDER); - linkBindings.bind(session); -} -void QueueSink::send(qpid::client::AsyncSession& session, const std::string&, OutgoingMessage& m) -{ - m.send(session, name); -} - -void QueueSink::cancel(qpid::client::AsyncSession& session, const std::string&) -{ - linkBindings.unbind(session); - checkDelete(session, FOR_SENDER); -} - -Address AddressResolution::convert(const qpid::framing::ReplyTo& rt) -{ - Address address; - if (rt.getExchange().empty()) {//if default exchange, treat as queue - if (!rt.getRoutingKey().empty()) { - address.setName(rt.getRoutingKey()); - address.setType(QUEUE_ADDRESS); - } - } else { - address.setName(rt.getExchange()); - address.setSubject(rt.getRoutingKey()); - address.setType(TOPIC_ADDRESS); - } - return address; -} - -qpid::framing::ReplyTo AddressResolution::convert(const Address& address) -{ - if (address.getType() == QUEUE_ADDRESS || address.getType().empty()) { - return ReplyTo(EMPTY_STRING, address.getName()); - } else if (address.getType() == TOPIC_ADDRESS) { - return ReplyTo(address.getName(), address.getSubject()); - } else { - QPID_LOG(notice, "Unrecognised type for reply-to: " << address.getType()); - return ReplyTo(EMPTY_STRING, address.getName());//treat as queue - } -} - -bool isQueue(qpid::client::Session session, const qpid::messaging::Address& address) -{ - return address.getType() == QUEUE_ADDRESS || - (address.getType().empty() && session.queueQuery(address.getName()).getQueue() == address.getName()); -} - -bool isTopic(qpid::client::Session session, const qpid::messaging::Address& address) -{ - if (address.getType().empty()) { - return !session.exchangeQuery(address.getName()).getNotFound(); - } else if (address.getType() == TOPIC_ADDRESS) { - return true; - } else { - return false; - } -} - -Node::Node(const Address& address) : name(address.getName()), - createPolicy(getOption(address, CREATE)), - assertPolicy(getOption(address, ASSERT)), - deletePolicy(getOption(address, DELETE)) -{ - nodeBindings.add((Opt(address)/NODE/X_BINDINGS).asList()); - linkBindings.add((Opt(address)/LINK/X_BINDINGS).asList()); -} - -Queue::Queue(const Address& a) : Node(a), - durable(Opt(a)/NODE/DURABLE), - autoDelete(Opt(a)/NODE/X_DECLARE/AUTO_DELETE), - exclusive(Opt(a)/NODE/X_DECLARE/EXCLUSIVE), - alternateExchange((Opt(a)/NODE/X_DECLARE/ALTERNATE_EXCHANGE).str()) -{ - (Opt(a)/NODE/X_DECLARE/ARGUMENTS).collect(arguments); - nodeBindings.setDefaultQueue(name); - linkBindings.setDefaultQueue(name); - if (qpid::messaging::AddressImpl::isTemporary(a) && createPolicy.isVoid()) { - createPolicy = "always"; - Opt specified = Opt(a)/NODE/X_DECLARE; - if (!specified.hasKey(AUTO_DELETE)) autoDelete = true; - if (!specified.hasKey(EXCLUSIVE)) exclusive = true; - } -} - -void Queue::checkCreate(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(createPolicy, mode)) { - QPID_LOG(debug, "Auto-creating queue '" << name << "'"); - try { - session.queueDeclare(arg::queue=name, - arg::durable=durable, - arg::autoDelete=autoDelete, - arg::exclusive=exclusive, - arg::alternateExchange=alternateExchange, - arg::arguments=arguments); - nodeBindings.bind(session); - session.sync(); - } catch (const qpid::framing::ResourceLockedException& e) { - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotAllowedException& e) { - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotFoundException& e) {//may be thrown when creating bindings - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } - } else { - try { - sync(session).queueDeclare(arg::queue=name, arg::passive=true); - } catch (const qpid::framing::NotFoundException& /*e*/) { - throw NotFound((boost::format("Queue %1% does not exist") % name).str()); - } - } -} - -void Queue::checkDelete(qpid::client::AsyncSession& session, CheckMode mode) -{ - //Note: queue-delete will cause a session exception if the queue - //does not exist, the query here prevents obvious cases of this - //but there is a race whenever two deletions are made concurrently - //so careful use of the delete policy is recommended at present - if (enabled(deletePolicy, mode) && sync(session).queueQuery(name).getQueue() == name) { - QPID_LOG(debug, "Auto-deleting queue '" << name << "'"); - sync(session).queueDelete(arg::queue=name); - } -} - -void Queue::checkAssert(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(assertPolicy, mode)) { - QueueQueryResult result = sync(session).queueQuery(name); - if (result.getQueue() != name) { - throw NotFound((boost::format("Queue not found: %1%") % name).str()); - } else { - if (durable && !result.getDurable()) { - throw AssertionFailed((boost::format("Queue not durable: %1%") % name).str()); - } - if (autoDelete && !result.getAutoDelete()) { - throw AssertionFailed((boost::format("Queue not set to auto-delete: %1%") % name).str()); - } - if (exclusive && !result.getExclusive()) { - throw AssertionFailed((boost::format("Queue not exclusive: %1%") % name).str()); - } - if (!alternateExchange.empty() && result.getAlternateExchange() != alternateExchange) { - throw AssertionFailed((boost::format("Alternate exchange does not match for %1%, expected %2%, got %3%") - % name % alternateExchange % result.getAlternateExchange()).str()); - } - for (FieldTable::ValueMap::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { - FieldTable::ValuePtr v = result.getArguments().get(i->first); - if (!v) { - throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str()); - } else if (!areEquivalent(*i->second, *v)) { - throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%") - % i->first % name % *(i->second) % *v).str()); - } - } - nodeBindings.check(session); - } - } -} - -Exchange::Exchange(const Address& a) : Node(a), - specifiedType((Opt(a)/NODE/X_DECLARE/TYPE).str()), - durable(Opt(a)/NODE/DURABLE), - autoDelete(Opt(a)/NODE/X_DECLARE/AUTO_DELETE), - alternateExchange((Opt(a)/NODE/X_DECLARE/ALTERNATE_EXCHANGE).str()) -{ - (Opt(a)/NODE/X_DECLARE/ARGUMENTS).collect(arguments); - nodeBindings.setDefaultExchange(name); - linkBindings.setDefaultExchange(name); - if (qpid::messaging::AddressImpl::isTemporary(a) && createPolicy.isVoid()) { - createPolicy = "always"; - if (!(Opt(a)/NODE/X_DECLARE).hasKey(AUTO_DELETE)) autoDelete = true; - } -} - -bool Exchange::isReservedName() -{ - return name.find(PREFIX_AMQ) != std::string::npos || name.find(PREFIX_QPID) != std::string::npos; -} - -void Exchange::checkCreate(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(createPolicy, mode)) { - try { - if (isReservedName()) { - try { - sync(session).exchangeDeclare(arg::exchange=name, arg::passive=true); - } catch (const qpid::framing::NotFoundException& /*e*/) { - throw ResolutionError((boost::format("Cannot create exchange %1%; names beginning with \"amq.\" or \"qpid.\" are reserved.") % name).str()); - } - - } else { - std::string type = specifiedType; - if (type.empty()) type = TOPIC_EXCHANGE; - session.exchangeDeclare(arg::exchange=name, - arg::type=type, - arg::durable=durable, - arg::autoDelete=autoDelete, - arg::alternateExchange=alternateExchange, - arg::arguments=arguments); - } - nodeBindings.bind(session); - session.sync(); - } catch (const qpid::framing::NotAllowedException& e) { - throw ResolutionError((boost::format("Create failed for exchange %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotFoundException& e) {//can be caused when creating bindings - throw ResolutionError((boost::format("Create failed for exchange %1%; %2%") % name % e.what()).str()); - } - } else { - try { - sync(session).exchangeDeclare(arg::exchange=name, arg::passive=true); - } catch (const qpid::framing::NotFoundException& /*e*/) { - throw NotFound((boost::format("Exchange %1% does not exist") % name).str()); - } - } -} - -void Exchange::checkDelete(qpid::client::AsyncSession& session, CheckMode mode) -{ - //Note: exchange-delete will cause a session exception if the - //exchange does not exist, the query here prevents obvious cases - //of this but there is a race whenever two deletions are made - //concurrently so careful use of the delete policy is recommended - //at present - if (enabled(deletePolicy, mode) && !sync(session).exchangeQuery(name).getNotFound()) { - sync(session).exchangeDelete(arg::exchange=name); - } -} - -void Exchange::checkAssert(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(assertPolicy, mode)) { - ExchangeQueryResult result = sync(session).exchangeQuery(name); - if (result.getNotFound()) { - throw NotFound((boost::format("Exchange not found: %1%") % name).str()); - } else { - if (specifiedType.size() && result.getType() != specifiedType) { - throw AssertionFailed((boost::format("Exchange %1% is of incorrect type, expected %2% but got %3%") - % name % specifiedType % result.getType()).str()); - } - if (durable && !result.getDurable()) { - throw AssertionFailed((boost::format("Exchange not durable: %1%") % name).str()); - } - //Note: Can't check auto-delete or alternate-exchange via - //exchange-query-result as these are not returned - //TODO: could use a passive declare to check alternate-exchange - for (FieldTable::ValueMap::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { - FieldTable::ValuePtr v = result.getArguments().get(i->first); - if (!v) { - throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str()); - } else if (!areEquivalent(*i->second, *v)) { - throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%") - % i->first % name % *(i->second) % *v).str()); - } - } - nodeBindings.check(session); - } - } -} - -Binding::Binding(const Variant::Map& b) : - exchange((Opt(b)/EXCHANGE).str()), - queue((Opt(b)/QUEUE).str()), - key((Opt(b)/KEY).str()) -{ - (Opt(b)/ARGUMENTS).collect(arguments); -} - -Binding::Binding(const std::string& e, const std::string& q, const std::string& k) : exchange(e), queue(q), key(k) {} - - -void Bindings::add(const Variant::List& list) -{ - for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { - push_back(Binding(i->asMap())); - } -} - -void Bindings::setDefaultExchange(const std::string& exchange) -{ - for (Bindings::iterator i = begin(); i != end(); ++i) { - if (i->exchange.empty()) i->exchange = exchange; - } -} - -void Bindings::setDefaultQueue(const std::string& queue) -{ - for (Bindings::iterator i = begin(); i != end(); ++i) { - if (i->queue.empty()) i->queue = queue; - } -} - -void Bindings::bind(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - session.exchangeBind(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key, - arg::arguments=i->arguments); - } -} - -void Bindings::unbind(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - session.exchangeUnbind(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key); - } -} - -void Bindings::check(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - ExchangeBoundResult result = sync(session).exchangeBound(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key); - if (result.getQueueNotMatched() || result.getKeyNotMatched()) { - throw AssertionFailed((boost::format("No such binding [exchange=%1%, queue=%2%, key=%3%]") - % i->exchange % i->queue % i->key).str()); - } - } -} - -bool Node::enabled(const Variant& policy, CheckMode mode) -{ - bool result = false; - switch (mode) { - case FOR_RECEIVER: - result = in(policy, RECEIVER_MODES); - break; - case FOR_SENDER: - result = in(policy, SENDER_MODES); - break; - } - return result; -} - -bool Node::createEnabled(const Address& address, CheckMode mode) -{ - const Variant& policy = getOption(address, CREATE); - return enabled(policy, mode); -} - -void Node::convert(const Variant& options, FieldTable& arguments) -{ - if (!options.isVoid()) { - translate(options.asMap(), arguments); - } -} -std::vector Node::RECEIVER_MODES = list_of(ALWAYS) (RECEIVER); -std::vector Node::SENDER_MODES = list_of(ALWAYS) (SENDER); - -Verifier::Verifier() -{ - defined[CREATE] = true; - defined[ASSERT] = true; - defined[DELETE] = true; - defined[MODE] = true; - Variant::Map node; - node[TYPE] = true; - node[DURABLE] = true; - node[X_DECLARE] = true; - node[X_BINDINGS] = true; - defined[NODE] = node; - Variant::Map link; - link[NAME] = true; - link[DURABLE] = true; - link[RELIABILITY] = true; - link[TIMEOUT] = true; - link[X_SUBSCRIBE] = true; - link[X_DECLARE] = true; - link[X_BINDINGS] = true; - link[SELECTOR] = true; - defined[LINK] = link; -} -void Verifier::verify(const Address& address) const -{ - verify(defined, address.getOptions()); -} - -void Verifier::verify(const Variant::Map& allowed, const Variant::Map& actual) const -{ - for (Variant::Map::const_iterator i = actual.begin(); i != actual.end(); ++i) { - Variant::Map::const_iterator option = allowed.find(i->first); - if (option == allowed.end()) { - throw AddressError((boost::format("Unrecognised option: %1%") % i->first).str()); - } else if (option->second.getType() == qpid::types::VAR_MAP) { - verify(option->second.asMap(), i->second.asMap()); - } - } -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.h b/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.h deleted file mode 100644 index fc8f1a1d18..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_H -#define QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_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" - -namespace qpid { - -namespace framing{ -class ReplyTo; -} - -namespace messaging { -class Address; -} - -namespace client { -namespace amqp0_10 { - -class MessageSource; -class MessageSink; - -/** - * Maps from a generic Address and optional Filter to an AMQP 0-10 - * MessageSource which will then be used by a ReceiverImpl instance - * created for the address. - */ -class AddressResolution -{ - public: - std::auto_ptr resolveSource(qpid::client::Session session, - const qpid::messaging::Address& address); - - std::auto_ptr resolveSink(qpid::client::Session session, - const qpid::messaging::Address& address); - - static qpid::messaging::Address convert(const qpid::framing::ReplyTo&); - static qpid::framing::ReplyTo convert(const qpid::messaging::Address&); - static bool is_unreliable(const qpid::messaging::Address& address); - static bool is_reliable(const qpid::messaging::Address& address); - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp b/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp deleted file mode 100644 index 20fcc7e432..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp +++ /dev/null @@ -1,432 +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 "ConnectionImpl.h" -#include "SessionImpl.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/PrivateImplRef.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include "qpid/Options.h" -#include "qpid/Url.h" -#include "qpid/amqp_0_10/Codecs.h" -#include -#include "config.h" -#include -#include -#include - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::types::Variant; -using qpid::types::VAR_LIST; -using qpid::framing::Uuid; - -namespace { -struct DefaultConnectionOptions : qpid::Options -{ - bool disableAutoDecode; - - DefaultConnectionOptions() : qpid::Options("Connection Option Defaults") - { - addOptions() - ("disable-auto-decode", optValue(disableAutoDecode, "TRUE|FALSE"), "Whether to decode amqp 0-10 maps and lists automatically by default"); - - CommonOptions common("", "", QPIDC_CONF_FILE); - try { - common.parse(0, 0, common.clientConfig, true); - this->parse(0, 0, common.clientConfig, true); - } catch (const std::exception& e) { - throw qpid::types::Exception(QPID_MSG("Failed to parse default connection options: " << e.what())); - } - } -}; - -const DefaultConnectionOptions& getDefaultOptions() -{ - static DefaultConnectionOptions defaultOptions; - return defaultOptions; -} - - - -const std::string TCP("tcp"); -const std::string COLON(":"); -double FOREVER(std::numeric_limits::max()); - -// Time values in seconds can be specified as integer or floating point values. -double timeValue(const Variant& value) { - if (types::isIntegerType(value.getType())) - return double(value.asInt64()); - return value.asDouble(); -} - -void merge(const std::string& value, std::vector& list) { - if (std::find(list.begin(), list.end(), value) == list.end()) - list.push_back(value); -} - -void merge(const Variant::List& from, std::vector& to) -{ - for (Variant::List::const_iterator i = from.begin(); i != from.end(); ++i) - merge(i->asString(), to); -} - -std::string asString(const std::vector& v) { - std::stringstream os; - os << "["; - for(std::vector::const_iterator i = v.begin(); i != v.end(); ++i ) { - if (i != v.begin()) os << ", "; - os << *i; - } - os << "]"; - return os.str(); -} - -bool expired(const sys::AbsTime& start, double timeout) -{ - if (timeout == 0) return true; - if (timeout == FOREVER) return false; - sys::Duration used(start, sys::now()); - sys::Duration allowed((int64_t)(timeout*sys::TIME_SEC)); - return allowed < used; -} - -} // namespace - -ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& options) : - replaceUrls(false), autoReconnect(false), timeout(FOREVER), limit(-1), - minReconnectInterval(0.001), maxReconnectInterval(2), - retries(0), reconnectOnLimitExceeded(true), disableAutoDecode(getDefaultOptions().disableAutoDecode) -{ - setOptions(options); - urls.insert(urls.begin(), url); -} - -void ConnectionImpl::setOptions(const Variant::Map& options) -{ - for (Variant::Map::const_iterator i = options.begin(); i != options.end(); ++i) { - setOption(i->first, i->second); - } -} - -void ConnectionImpl::setOption(const std::string& name, const Variant& value) -{ - sys::Mutex::ScopedLock l(lock); - if (name == "reconnect") { - autoReconnect = value; - } else if (name == "reconnect-timeout" || name == "reconnect_timeout") { - timeout = timeValue(value); - } else if (name == "reconnect-limit" || name == "reconnect_limit") { - limit = value; - } else if (name == "reconnect-interval" || name == "reconnect_interval") { - maxReconnectInterval = minReconnectInterval = timeValue(value); - } else if (name == "reconnect-interval-min" || name == "reconnect_interval_min") { - minReconnectInterval = timeValue(value); - } else if (name == "reconnect-interval-max" || name == "reconnect_interval_max") { - maxReconnectInterval = timeValue(value); - } else if (name == "reconnect-urls-replace" || name == "reconnect_urls_replace") { - replaceUrls = value.asBool(); - } else if (name == "reconnect-urls" || name == "reconnect_urls") { - if (replaceUrls) urls.clear(); - if (value.getType() == VAR_LIST) { - merge(value.asList(), urls); - } else { - merge(value.asString(), urls); - } - } else if (name == "username") { - settings.username = value.asString(); - } else if (name == "password") { - settings.password = value.asString(); - } else if (name == "sasl-mechanism" || name == "sasl_mechanism" || - name == "sasl-mechanisms" || name == "sasl_mechanisms") { - settings.mechanism = value.asString(); - } else if (name == "sasl-service" || name == "sasl_service") { - settings.service = value.asString(); - } else if (name == "sasl-min-ssf" || name == "sasl_min_ssf") { - settings.minSsf = value; - } else if (name == "sasl-max-ssf" || name == "sasl_max_ssf") { - settings.maxSsf = value; - } else if (name == "heartbeat") { - settings.heartbeat = value; - } else if (name == "tcp-nodelay" || name == "tcp_nodelay") { - settings.tcpNoDelay = value; - } else if (name == "locale") { - settings.locale = value.asString(); - } else if (name == "max-channels" || name == "max_channels") { - settings.maxChannels = value; - } else if (name == "max-frame-size" || name == "max_frame_size") { - settings.maxFrameSize = value; - } else if (name == "bounds") { - settings.bounds = value; - } else if (name == "transport") { - settings.protocol = value.asString(); - } else if (name == "ssl-cert-name" || name == "ssl_cert_name") { - settings.sslCertName = value.asString(); - } else if (name == "ssl-ignore-hostname-verification-failure" || name == "ssl_ignore_hostname_verification_failure") { - settings.sslIgnoreHostnameVerificationFailure = value; - } else if (name == "x-reconnect-on-limit-exceeded" || name == "x_reconnect_on_limit_exceeded") { - reconnectOnLimitExceeded = value; - } 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")); - } -} - - -void ConnectionImpl::close() -{ - while(true) { - messaging::Session session; - { - qpid::sys::Mutex::ScopedLock l(lock); - if (sessions.empty()) break; - session = sessions.begin()->second; - } - session.close(); - } - detach(); -} - -void ConnectionImpl::detach() -{ - qpid::sys::Mutex::ScopedLock l(lock); - connection.close(); -} - -bool ConnectionImpl::isOpen() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return connection.isOpen(); -} - -boost::intrusive_ptr getImplPtr(qpid::messaging::Session& session) -{ - return boost::dynamic_pointer_cast( - qpid::messaging::PrivateImplRef::get(session) - ); -} - -void ConnectionImpl::closed(SessionImpl& s) -{ - qpid::sys::Mutex::ScopedLock l(lock); - for (Sessions::iterator i = sessions.begin(); i != sessions.end(); ++i) { - if (getImplPtr(i->second).get() == &s) { - sessions.erase(i); - break; - } - } -} - -qpid::messaging::Session ConnectionImpl::getSession(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Sessions::const_iterator i = sessions.find(name); - if (i == sessions.end()) { - throw qpid::messaging::KeyError("No such session: " + name); - } else { - return i->second; - } -} - -qpid::messaging::Session ConnectionImpl::newSession(bool transactional, const std::string& n) -{ - std::string name = n.empty() ? Uuid(true).str() : n; - qpid::messaging::Session impl(new SessionImpl(*this, transactional)); - while (true) { - try { - getImplPtr(impl)->setSession(connection.newSession(name)); - qpid::sys::Mutex::ScopedLock l(lock); - sessions[name] = impl; - break; - } catch (const qpid::TransportFailure&) { - reopen(); - } catch (const qpid::SessionException& e) { - SessionImpl::rethrow(e); - } catch (const std::exception& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } - return impl; -} - -void ConnectionImpl::open() -{ - qpid::sys::AbsTime start = qpid::sys::now(); - qpid::sys::ScopedLock l(semaphore); - try { - if (!connection.isOpen()) connect(start); - } - catch (const types::Exception&) { throw; } - catch (const qpid::Exception& e) { throw messaging::ConnectionError(e.what()); } -} - -void ConnectionImpl::reopen() -{ - if (!autoReconnect) { - throw qpid::messaging::TransportFailure("Failed to connect (reconnect disabled)"); - } - open(); -} - - -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 (!autoReconnect) { - 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. - } - QPID_LOG(debug, "Connection successful, urls=" << asString(urls)); - retries = 0; -} - -void ConnectionImpl::mergeUrls(const std::vector& more, const sys::Mutex::ScopedLock&) { - for (std::vector::const_iterator i = more.begin(); i != more.end(); ++i) - merge(i->str(), urls); - QPID_LOG(debug, "Added known-hosts, reconnect-urls=" << asString(urls)); -} - -bool ConnectionImpl::tryConnect() -{ - sys::Mutex::ScopedLock l(lock); - for (std::vector::const_iterator i = urls.begin(); i != urls.end(); ++i) { - try { - QPID_LOG(info, "Trying to connect to " << *i << "..."); - Url url(*i, 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 " << *i); - mergeUrls(connection.getInitialBrokers(), l); - return resetSessions(l); - } catch (const qpid::ProtocolVersionError& e) { - throw qpid::messaging::ProtocolVersionError("AMQP 0-10 not supported"); - } catch (const qpid::TransportFailure& e) { - QPID_LOG(info, "Failed to connect to " << *i << ": " << e.what()); - } - } - return false; -} - -bool ConnectionImpl::resetSessions(const sys::Mutex::ScopedLock& ) -{ - try { - qpid::sys::Mutex::ScopedLock l(lock); - for (Sessions::iterator i = sessions.begin(); i != sessions.end(); ++i) { - if (!getImplPtr(i->second)->isTransactional()) { - getImplPtr(i->second)->setSession(connection.newSession(i->first)); - } - } - return true; - } catch (const qpid::TransportFailure& e) { - QPID_LOG(debug, "Connection Failed to re-initialize sessions: " << e.what()); - return false; - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (reconnectOnLimitExceeded) { - QPID_LOG(debug, "Detaching and reconnecting due to: " << e.what()); - detach(); - return false; - } else { - throw qpid::messaging::TargetCapacityExceeded(e.what()); - } - } -} - -bool ConnectionImpl::backoff() -{ - if (reconnectOnLimitExceeded) { - detach(); - open(); - return true; - } else { - return false; - } -} - -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; -} -bool ConnectionImpl::getAutoReconnect() const -{ - return autoReconnect; -} - -}}} // 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 deleted file mode 100644 index bf8a759107..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_H -#define QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_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/messaging/ConnectionImpl.h" -#include "qpid/types/Variant.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Semaphore.h" -#include -#include - -namespace qpid { -struct Url; - -namespace client { -namespace amqp0_10 { - -class SessionImpl; - -class ConnectionImpl : public qpid::messaging::ConnectionImpl -{ - public: - ConnectionImpl(const std::string& url, const qpid::types::Variant::Map& options); - void open(); - void reopen(); - bool isOpen() const; - void close(); - qpid::messaging::Session newSession(bool transactional, const std::string& name); - qpid::messaging::Session getSession(const std::string& name) const; - void closed(SessionImpl&); - void detach(); - 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; - bool getAutoReconnect() const; - private: - typedef std::map Sessions; - - mutable qpid::sys::Mutex lock;//used to protect data structures - qpid::sys::Semaphore semaphore;//used to coordinate reconnection - Sessions sessions; - qpid::client::Connection connection; - bool replaceUrls; // Replace rather than merging with reconnect-urls - std::vector urls; - qpid::client::ConnectionSettings settings; - 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); - bool tryConnect(); - bool resetSessions(const sys::Mutex::ScopedLock&); // dummy parameter indicates call with lock held. - void mergeUrls(const std::vector& more, const sys::Mutex::ScopedLock&); -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp b/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp deleted file mode 100644 index a105a67b3f..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp +++ /dev/null @@ -1,468 +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/client/amqp0_10/IncomingMessages.h" -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/types/Variant.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/enum.h" -#include - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using namespace qpid::framing; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::messaging::MessageImplAccess; -using qpid::types::Variant; - -namespace { -const std::string EMPTY_STRING; - - -struct GetNone : IncomingMessages::Handler -{ - bool accept(IncomingMessages::MessageTransfer&) { return false; } - bool expire(IncomingMessages::MessageTransfer&) { return false; } -}; - -struct GetAny : IncomingMessages::Handler -{ - bool accept(IncomingMessages::MessageTransfer& transfer) - { - transfer.retrieve(0); - return true; - } - bool expire(IncomingMessages::MessageTransfer&) { return false; } -}; - -struct MatchAndTrack -{ - const std::string destination; - SequenceSet ids; - - MatchAndTrack(const std::string& d) : destination(d) {} - - bool operator()(boost::shared_ptr command) - { - if (command->as()->getDestination() == destination) { - ids.add(command->getId()); - return true; - } else { - return false; - } - } -}; - -struct Match -{ - const std::string destination; - uint32_t matched; - - Match(const std::string& d) : destination(d), matched(0) {} - - bool operator()(boost::shared_ptr command) - { - if (command->as()->getDestination() == destination) { - ++matched; - return true; - } else { - return false; - } - } -}; - -struct ScopedRelease -{ - bool& flag; - qpid::sys::Monitor& lock; - - ScopedRelease(bool& f, qpid::sys::Monitor& l) : flag(f), lock(l) {} - ~ScopedRelease() - { - sys::Monitor::ScopedLock l(lock); - flag = false; - lock.notifyAll(); - } -}; -} - -IncomingMessages::IncomingMessages() : inUse(false) {} - -void IncomingMessages::setSession(qpid::client::AsyncSession s) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - incoming = SessionBase_0_10Access(session).get()->getDemux().getDefault(); - acceptTracker.reset(); -} - -namespace { -qpid::sys::Duration get_duration(qpid::sys::Duration timeout, qpid::sys::AbsTime deadline) -{ - if (timeout == qpid::sys::TIME_INFINITE) { - return qpid::sys::TIME_INFINITE; - } else { - return std::max(qpid::sys::Duration(0), qpid::sys::Duration(AbsTime::now(), deadline)); - } -} -} - -bool IncomingMessages::get(Handler& handler, qpid::sys::Duration timeout) -{ - sys::Mutex::ScopedLock l(lock); - AbsTime deadline(AbsTime::now(), timeout); - do { - //search through received list for any transfer of interest: - for (FrameSetQueue::iterator i = received.begin(); i != received.end();) - { - MessageTransfer transfer(*i, *this); - if (transfer.checkExpired() && handler.expire(transfer)) { - i = received.erase(i); - } else if (handler.accept(transfer)) { - received.erase(i); - return true; - } else { - ++i; - } - } - if (inUse) { - //someone is already waiting on the incoming session queue, wait for them to finish - lock.wait(deadline); - } else { - inUse = true; - ScopedRelease release(inUse, lock); - sys::Mutex::ScopedUnlock l(lock); - //wait for suitable new message to arrive - switch (process(&handler, get_duration(timeout, deadline))) { - case OK: - return true; - case CLOSED: - return false; - case EMPTY: - break; - } - } - if (handler.isClosed()) throw qpid::messaging::ReceiverError("Receiver has been closed"); - } while (AbsTime::now() < deadline); - return false; -} -namespace { -struct Wakeup : public qpid::types::Exception {}; -} - -void IncomingMessages::wakeup() -{ - sys::Mutex::ScopedLock l(lock); - incoming->close(qpid::sys::ExceptionHolder(new Wakeup())); - lock.notifyAll(); -} - -bool IncomingMessages::getNextDestination(std::string& destination, qpid::sys::Duration timeout) -{ - sys::Mutex::ScopedLock l(lock); - AbsTime deadline(AbsTime::now(), timeout); - while (received.empty()) { - if (inUse) { - //someone is already waiting on the sessions incoming queue - lock.wait(deadline); - } else { - inUse = true; - ScopedRelease release(inUse, lock); - sys::Mutex::ScopedUnlock l(lock); - //wait for an incoming message - wait(get_duration(timeout, deadline)); - } - if (!(AbsTime::now() < deadline)) break; - } - if (!received.empty()) { - destination = received.front()->as()->getDestination(); - return true; - } else { - return false; - } -} - -void IncomingMessages::accept() -{ - sys::Mutex::ScopedLock l(lock); - acceptTracker.accept(session); -} - -void IncomingMessages::accept(qpid::framing::SequenceNumber id, bool cumulative) -{ - sys::Mutex::ScopedLock l(lock); - acceptTracker.accept(id, session, cumulative); -} - - -void IncomingMessages::releaseAll() -{ - { - //first process any received messages... - sys::Mutex::ScopedLock l(lock); - while (!received.empty()) { - retrieve(received.front(), 0); - received.pop_front(); - } - } - //then pump out any available messages from incoming queue... - GetAny handler; - while (process(&handler, 0) == OK) ; - //now release all messages - sys::Mutex::ScopedLock l(lock); - acceptTracker.release(session); -} - -void IncomingMessages::releasePending(const std::string& destination) -{ - //first pump all available messages from incoming to received... - while (process(0, 0) == OK) ; - - //now remove all messages for this destination from received list, recording their ids... - sys::Mutex::ScopedLock l(lock); - MatchAndTrack match(destination); - for (FrameSetQueue::iterator i = received.begin(); i != received.end(); i = match(*i) ? received.erase(i) : ++i) ; - //now release those messages - session.messageRelease(match.ids); -} - -bool IncomingMessages::pop(FrameSet::shared_ptr& content, qpid::sys::Duration timeout) -{ - try { - return incoming->pop(content, timeout); - } catch (const Wakeup&) { - incoming->open(); - return false; - } -} - -/** - * Get a frameset that is accepted by the specified handler from - * session queue, waiting for up to the specified duration and - * returning true if this could be achieved, false otherwise. Messages - * that are not accepted by the handler are pushed onto received queue - * for later retrieval. - */ -IncomingMessages::ProcessState IncomingMessages::process(Handler* handler, qpid::sys::Duration duration) -{ - AbsTime deadline(AbsTime::now(), duration); - FrameSet::shared_ptr content; - try { - for (Duration timeout = duration; pop(content, timeout); timeout = Duration(AbsTime::now(), deadline)) { - if (content->isA()) { - MessageTransfer transfer(content, *this); - if (handler && transfer.checkExpired() && handler->expire(transfer)) { - QPID_LOG(debug, "Expired received transfer: " << *content->getMethod()); - } else if (handler && handler->accept(transfer)) { - QPID_LOG(debug, "Delivered " << *content->getMethod() << " " - << *content->getHeaders()); - return OK; - } else { - //received message for another destination, keep for later - QPID_LOG(debug, "Pushed " << *content->getMethod() << " to received queue"); - sys::Mutex::ScopedLock l(lock); - received.push_back(content); - lock.notifyAll(); - } - } else { - //TODO: handle other types of commands (e.g. message-accept, message-flow etc) - } - } - } - catch (const qpid::ClosedException&) { return CLOSED; } - return EMPTY; -} - -bool IncomingMessages::wait(qpid::sys::Duration duration) -{ - AbsTime deadline(AbsTime::now(), duration); - FrameSet::shared_ptr content; - for (Duration timeout = duration; pop(content, timeout); timeout = Duration(AbsTime::now(), deadline)) { - if (content->isA()) { - QPID_LOG(debug, "Pushed " << *content->getMethod() << " to received queue"); - sys::Mutex::ScopedLock l(lock); - received.push_back(content); - lock.notifyAll(); - return true; - } else { - //TODO: handle other types of commands (e.g. message-accept, message-flow etc) - } - } - return false; -} - -uint32_t IncomingMessages::pendingAccept() -{ - sys::Mutex::ScopedLock l(lock); - return acceptTracker.acceptsPending(); -} -uint32_t IncomingMessages::pendingAccept(const std::string& destination) -{ - sys::Mutex::ScopedLock l(lock); - return acceptTracker.acceptsPending(destination); -} - -uint32_t IncomingMessages::available() -{ - //first pump all available messages from incoming to received... - while (process(0, 0) == OK) {} - //return the count of received messages - sys::Mutex::ScopedLock l(lock); - return received.size(); -} - -uint32_t IncomingMessages::available(const std::string& destination) -{ - //first pump all available messages from incoming to received... - while (process(0, 0) == OK) {} - - //count all messages for this destination from received list - sys::Mutex::ScopedLock l(lock); - return std::for_each(received.begin(), received.end(), Match(destination)).matched; -} - -void populate(qpid::messaging::Message& message, FrameSet& command); - -/** - * Called when message is retrieved; records retrieval for subsequent - * acceptance, marks the command as completed and converts command to - * message if message is required - */ -void IncomingMessages::retrieve(FrameSetPtr command, qpid::messaging::Message* message) -{ - if (message) { - populate(*message, *command); - } - const MessageTransferBody* transfer = command->as(); - if (transfer->getAcceptMode() == ACCEPT_MODE_EXPLICIT) { - sys::Mutex::ScopedLock l(lock); - acceptTracker.delivered(transfer->getDestination(), command->getId()); - } - session.markCompleted(command->getId(), false, false); -} - -IncomingMessages::MessageTransfer::MessageTransfer(FrameSetPtr c, IncomingMessages& p) : content(c), parent(p) {} - -const std::string& IncomingMessages::MessageTransfer::getDestination() -{ - return content->as()->getDestination(); -} -void IncomingMessages::MessageTransfer::retrieve(qpid::messaging::Message* message) -{ - parent.retrieve(content, message); -} - -bool IncomingMessages::MessageTransfer::checkExpired() -{ - if (content->hasExpired()) { - retrieve(0); - parent.accept(content->getId(), false); - return true; - } else { - return false; - } -} - -namespace { -//TODO: unify conversion to and from 0-10 message that is currently -//split between IncomingMessages and OutgoingMessage -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 X_TIMESTAMP("x-amqp-0-10.timestamp"); -} - -void populateHeaders(qpid::messaging::Message& message, - const DeliveryProperties* deliveryProperties, - const MessageProperties* messageProperties) -{ - if (deliveryProperties) { - message.setTtl(qpid::messaging::Duration(deliveryProperties->getTtl())); - message.setDurable(deliveryProperties->getDeliveryMode() == DELIVERY_MODE_PERSISTENT); - message.setPriority(deliveryProperties->getPriority()); - message.setRedelivered(deliveryProperties->getRedelivered()); - } - if (messageProperties) { - message.setContentType(messageProperties->getContentType()); - if (messageProperties->hasReplyTo()) { - message.setReplyTo(AddressResolution::convert(messageProperties->getReplyTo())); - } - message.setSubject(messageProperties->getApplicationHeaders().getAsString(SUBJECT)); - message.getProperties().clear(); - translate(messageProperties->getApplicationHeaders(), message.getProperties()); - message.setCorrelationId(messageProperties->getCorrelationId()); - message.setUserId(messageProperties->getUserId()); - if (messageProperties->hasMessageId()) { - message.setMessageId(messageProperties->getMessageId().str()); - } - //expose 0-10 specific items through special properties: - // app-id, content-encoding - if (messageProperties->hasAppId()) { - message.getProperties()[X_APP_ID] = messageProperties->getAppId(); - } - if (messageProperties->hasContentEncoding()) { - message.getProperties()[X_CONTENT_ENCODING] = messageProperties->getContentEncoding(); - } - // routing-key, timestamp, others? - if (deliveryProperties && deliveryProperties->hasRoutingKey()) { - message.getProperties()[X_ROUTING_KEY] = deliveryProperties->getRoutingKey(); - } - if (deliveryProperties && deliveryProperties->hasTimestamp()) { - message.getProperties()[X_TIMESTAMP] = deliveryProperties->getTimestamp(); - } - } -} - -void populateHeaders(qpid::messaging::Message& message, const AMQHeaderBody* headers) -{ - populateHeaders(message, headers->get(), headers->get()); -} - -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()); -} - - -}}} // namespace qpid::client::amqp0_10 diff --git a/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.h b/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.h deleted file mode 100644 index 38c293eefc..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_H -#define QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_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 -#include -#include "qpid/client/AsyncSession.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/sys/Time.h" -#include "qpid/client/amqp0_10/AcceptTracker.h" - -namespace qpid { - -namespace framing{ -class FrameSet; -} - -namespace messaging { -class Message; -} - -namespace client { -namespace amqp0_10 { - -/** - * Queue of incoming messages. - */ -class IncomingMessages -{ - public: - typedef boost::shared_ptr FrameSetPtr; - class MessageTransfer - { - public: - const std::string& getDestination(); - void retrieve(qpid::messaging::Message* message); - private: - FrameSetPtr content; - IncomingMessages& parent; - bool checkExpired(); - - MessageTransfer(FrameSetPtr, IncomingMessages&); - friend class IncomingMessages; - }; - - struct Handler - { - virtual ~Handler() {} - virtual bool accept(MessageTransfer& transfer) = 0; - virtual bool expire(MessageTransfer& transfer) = 0; - virtual bool isClosed() { return false; } - }; - - IncomingMessages(); - void setSession(qpid::client::AsyncSession session); - bool get(Handler& handler, qpid::sys::Duration timeout); - void wakeup(); - bool getNextDestination(std::string& destination, qpid::sys::Duration timeout); - void accept(); - void accept(qpid::framing::SequenceNumber id, bool cumulative); - void releaseAll(); - void releasePending(const std::string& destination); - - uint32_t pendingAccept(); - uint32_t pendingAccept(const std::string& destination); - - uint32_t available(); - uint32_t available(const std::string& destination); - private: - typedef std::deque FrameSetQueue; - enum ProcessState {EMPTY=0,OK=1,CLOSED=2}; - - sys::Monitor lock; - qpid::client::AsyncSession session; - boost::shared_ptr< sys::BlockingQueue > incoming; - bool inUse; - FrameSetQueue received; - AcceptTracker acceptTracker; - - ProcessState process(Handler*, qpid::sys::Duration); - bool wait(qpid::sys::Duration); - bool pop(FrameSetPtr&, qpid::sys::Duration); - - void retrieve(FrameSetPtr, qpid::messaging::Message*); - -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/MessageSink.h b/qpid/cpp/src/qpid/client/amqp0_10/MessageSink.h deleted file mode 100644 index d66d2ecb3c..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/MessageSink.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_MESSAGESINK_H -#define QPID_CLIENT_AMQP0_10_MESSAGESINK_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 -#include "qpid/client/AsyncSession.h" - -namespace qpid { - -namespace messaging { -class Message; -} - -namespace client { -namespace amqp0_10 { - -class OutgoingMessage; - -/** - * - */ -class MessageSink -{ - public: - virtual ~MessageSink() {} - virtual void declare(qpid::client::AsyncSession& session, const std::string& name) = 0; - virtual void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message) = 0; - virtual void cancel(qpid::client::AsyncSession& session, const std::string& name) = 0; - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_MESSAGESINK_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/MessageSource.h b/qpid/cpp/src/qpid/client/amqp0_10/MessageSource.h deleted file mode 100644 index 74f2732f59..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/MessageSource.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_MESSAGESOURCE_H -#define QPID_CLIENT_AMQP0_10_MESSAGESOURCE_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 -#include "qpid/client/AsyncSession.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -/** - * Abstraction behind which the AMQP 0-10 commands required to - * establish (and tear down) an incoming stream of messages from a - * given address are hidden. - */ -class MessageSource -{ - public: - virtual ~MessageSource() {} - virtual void subscribe(qpid::client::AsyncSession& session, const std::string& destination) = 0; - virtual void cancel(qpid::client::AsyncSession& session, const std::string& destination) = 0; - - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_MESSAGESOURCE_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp b/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp deleted file mode 100644 index f2b205a78a..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp +++ /dev/null @@ -1,170 +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/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/Duration.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::messaging::Address; -using qpid::messaging::MessageImplAccess; -using qpid::types::Variant; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; - -namespace { -//TODO: unify conversion to and from 0-10 message that is currently -//split between IncomingMessages and OutgoingMessage -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 - 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()); - const Address& address = from.getReplyTo(); - if (address) { - message.getMessageProperties().setReplyTo(AddressResolution::convert(address)); - } - if (!subject.empty()) { - Variant v(subject); v.setEncoding("utf8"); - translate(from.getProperties(), SUBJECT, v, message.getMessageProperties().getApplicationHeaders()); - } else { - translate(from.getProperties(), message.getMessageProperties().getApplicationHeaders()); - } - if (from.getTtl().getMilliseconds()) { - message.getDeliveryProperties().setTtl(from.getTtl().getMilliseconds()); - } - if (from.getDurable()) { - message.getDeliveryProperties().setDeliveryMode(DELIVERY_MODE_PERSISTENT); - } - if (from.getRedelivered()) { - message.getDeliveryProperties().setRedelivered(true); - } - if (from.getPriority()) message.getDeliveryProperties().setPriority(from.getPriority()); - - //allow certain 0-10 specific items to be set through special properties: - // message-id, app-id, content-encoding - if (from.getMessageId().size()) { - qpid::framing::Uuid uuid; - std::istringstream data(from.getMessageId()); - data >> uuid; - message.getMessageProperties().setMessageId(uuid); - } - Variant::Map::const_iterator i; - i = from.getProperties().find(X_APP_ID); - if (i != from.getProperties().end()) { - message.getMessageProperties().setAppId(i->second.asString()); - } - i = from.getProperties().find(X_CONTENT_ENCODING); - if (i != from.getProperties().end()) { - message.getMessageProperties().setContentEncoding(i->second.asString()); - } - base = qpid::sys::now(); -} - -void OutgoingMessage::setSubject(const std::string& s) -{ - subject = s; -} - -std::string OutgoingMessage::getSubject() const -{ - return subject; -} - -void OutgoingMessage::send(qpid::client::AsyncSession& session, const std::string& destination, const std::string& routingKey) -{ - if (!expired) { - message.getDeliveryProperties().setRoutingKey(routingKey); - status = session.messageTransfer(arg::destination=destination, arg::content=message); - if (destination.empty()) { - QPID_LOG(debug, "Sending to queue " << routingKey << " " << message.getMessageProperties() << " " << message.getDeliveryProperties()); - } else { - QPID_LOG(debug, "Sending to exchange " << destination << " " << message.getMessageProperties() << " " << message.getDeliveryProperties()); - } - } -} -void OutgoingMessage::send(qpid::client::AsyncSession& session, const std::string& routingKey) -{ - send(session, std::string(), routingKey); -} - -bool OutgoingMessage::isComplete() -{ - return expired || (status.isValid() && status.isComplete()); -} -void OutgoingMessage::markRedelivered() -{ - message.setRedelivered(true); - if (message.getDeliveryProperties().hasTtl()) { - uint64_t delta = qpid::sys::Duration(base, qpid::sys::now())/qpid::sys::TIME_MSEC; - uint64_t ttl = message.getDeliveryProperties().getTtl(); - if (ttl <= delta) { - QPID_LOG(debug, "Expiring outgoing message (" << ttl << " < " << delta << ")"); - expired = true; - message.getDeliveryProperties().setTtl(1); - } else { - QPID_LOG(debug, "Adjusting ttl on outgoing message from " << ttl << " by " << delta); - ttl = ttl - delta; - message.getDeliveryProperties().setTtl(ttl); - } - } -} -OutgoingMessage::OutgoingMessage() : expired (false) {} - - -}}} // namespace qpid::client::amqp0_10 diff --git a/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h b/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h deleted file mode 100644 index a17ef03e10..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_H -#define QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_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/Completion.h" -#include "qpid/client/Message.h" -#include "qpid/sys/Time.h" - -namespace qpid { -namespace messaging { -class Message; -} -namespace client { -namespace amqp0_10 { - -class OutgoingMessage -{ - private: - qpid::client::Message message; - qpid::client::Completion status; - std::string subject; - qpid::sys::AbsTime base; - bool expired; - - public: - OutgoingMessage(); - void convert(const qpid::messaging::Message&); - void setSubject(const std::string& subject); - std::string getSubject() const; - void send(qpid::client::AsyncSession& session, const std::string& destination, const std::string& routingKey); - void send(qpid::client::AsyncSession& session,const std::string& routingKey); - bool isComplete(); - void markRedelivered(); -}; - - - -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp b/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp deleted file mode 100644 index 507b2ddfbf..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp +++ /dev/null @@ -1,263 +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 "ReceiverImpl.h" -#include "AddressResolution.h" -#include "MessageSource.h" -#include "SessionImpl.h" -#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 { -namespace amqp0_10 { - -using qpid::messaging::NoMessageAvailable; -using qpid::messaging::Receiver; -using qpid::messaging::Duration; - -void ReceiverImpl::received() -{ - //TODO: should this be configurable - sys::Mutex::ScopedLock l(lock); - if (capacity && --window <= capacity/2) { - session.sendCompletion(); - window = capacity; - } -} - -qpid::messaging::Message ReceiverImpl::get(qpid::messaging::Duration timeout) -{ - qpid::messaging::Message result; - if (!get(result, timeout)) throw NoMessageAvailable(); - return result; -} - -qpid::messaging::Message ReceiverImpl::fetch(qpid::messaging::Duration timeout) -{ - qpid::messaging::Message result; - if (!fetch(result, timeout)) throw NoMessageAvailable(); - return result; -} - -bool ReceiverImpl::get(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - Get f(*this, message, timeout); - while (!parent->execute(f)) {} - return f.result; -} - -bool ReceiverImpl::fetch(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - Fetch f(*this, message, timeout); - while (!parent->execute(f)) {} - return f.result; -} - -void ReceiverImpl::close() -{ - execute(); -} - -void ReceiverImpl::start() -{ - sys::Mutex::ScopedLock l(lock); - if (state == STOPPED) { - state = STARTED; - startFlow(l); - session.sendCompletion(); - } -} - -void ReceiverImpl::stop() -{ - sys::Mutex::ScopedLock l(lock); - state = STOPPED; - session.messageStop(destination); -} - -void ReceiverImpl::setCapacity(uint32_t c) -{ - execute1(c); -} - -void ReceiverImpl::startFlow(const sys::Mutex::ScopedLock&) -{ - if (capacity > 0) { - session.messageSetFlowMode(destination, FLOW_MODE_WINDOW); - session.messageFlow(destination, CREDIT_UNIT_MESSAGE, capacity); - session.messageFlow(destination, CREDIT_UNIT_BYTE, byteCredit); - window = capacity; - } -} - -void ReceiverImpl::init(qpid::client::AsyncSession s, AddressResolution& resolver) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - if (state == CANCELLED) return; - if (state == UNRESOLVED) { - source = resolver.resolveSource(session, address); - assert(source.get()); - state = STARTED; - } - source->subscribe(session, destination); - startFlow(l); -} - -const std::string& ReceiverImpl::getName() const { - return destination; -} - -uint32_t ReceiverImpl::getCapacity() -{ - sys::Mutex::ScopedLock l(lock); - return capacity; -} - -uint32_t ReceiverImpl::getAvailable() -{ - return parent->getReceivable(destination); -} - -uint32_t ReceiverImpl::getUnsettled() -{ - return parent->getUnsettledAcks(destination); -} - -qpid::messaging::Address ReceiverImpl::getAddress() const -{ - return address; -} - -ReceiverImpl::ReceiverImpl(SessionImpl& p, const std::string& name, - const qpid::messaging::Address& a, bool autoDecode_) : - - 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; - } - 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) -{ - { - sys::Mutex::ScopedLock l(lock); - if (state == CANCELLED) return false; - - if (capacity == 0 || state != STARTED) { - session.messageSetFlowMode(destination, FLOW_MODE_CREDIT); - session.messageFlow(destination, CREDIT_UNIT_MESSAGE, 1); - session.messageFlow(destination, CREDIT_UNIT_BYTE, 0xFFFFFFFF); - } - } - if (getImpl(message, timeout)) { - return true; - } else { - qpid::client::Session s; - { - sys::Mutex::ScopedLock l(lock); - if (state == CANCELLED) return false; // Might have been closed during get. - s = sync(session); - } - s.messageFlush(destination); - { - sys::Mutex::ScopedLock l(lock); - startFlow(l); //reallocate credit - session.sendCompletion();//ensure previously received messages are signalled as completed - } - return getImpl(message, Duration::IMMEDIATE); - } -} - -void ReceiverImpl::closeImpl() -{ - sys::Mutex::ScopedLock l(lock); - if (state != CANCELLED) { - state = CANCELLED; - sync(session).messageStop(destination); - { - sys::Mutex::ScopedUnlock l(lock); - parent->releasePending(destination); - } - source->cancel(session, destination); - { - sys::Mutex::ScopedUnlock l(lock); - parent->receiverCancelled(destination); - } - } -} - -bool ReceiverImpl::isClosed() const { - sys::Mutex::ScopedLock l(lock); - return state == CANCELLED; -} - -void ReceiverImpl::setCapacityImpl(uint32_t c) -{ - sys::Mutex::ScopedLock l(lock); - if (c != capacity) { - capacity = c; - if (state == STARTED) { - session.messageStop(destination); - startFlow(l); - } - } -} - -qpid::messaging::Session ReceiverImpl::getSession() const -{ - return qpid::messaging::Session(parent.get()); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h b/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h deleted file mode 100644 index 0d36c862e7..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_RECEIVERIMPL_H -#define QPID_CLIENT_AMQP0_10_RECEIVERIMPL_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/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/ReceiverImpl.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/amqp0_10/SessionImpl.h" -#include "qpid/messaging/Duration.h" -#include "qpid/sys/Mutex.h" -#include -#include - -namespace qpid { -namespace client { -namespace amqp0_10 { - -class AddressResolution; -class MessageSource; - -/** - * A receiver implementation based on an AMQP 0-10 subscription. - */ -class ReceiverImpl : public qpid::messaging::ReceiverImpl -{ - public: - - enum State {UNRESOLVED, STOPPED, STARTED, CANCELLED}; - - ReceiverImpl(SessionImpl& parent, const std::string& name, - 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); - qpid::messaging::Message get(qpid::messaging::Duration timeout); - bool fetch(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - qpid::messaging::Message fetch(qpid::messaging::Duration timeout); - void close(); - void start(); - void stop(); - const std::string& getName() const; - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getAvailable(); - uint32_t getUnsettled(); - void received(); - qpid::messaging::Session getSession() const; - bool isClosed() const; - qpid::messaging::Address getAddress() const; - - private: - mutable sys::Mutex lock; - boost::intrusive_ptr parent; - const std::string destination; - const qpid::messaging::Address address; - const uint32_t byteCredit; - const bool autoDecode; - State state; - - std::auto_ptr source; - uint32_t capacity; - qpid::client::AsyncSession session; - uint32_t window; - - void startFlow(const sys::Mutex::ScopedLock&); // Dummy param, call with lock held - //implementation of public facing methods - bool fetchImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - bool getImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - void closeImpl(); - void setCapacityImpl(uint32_t); - - //functors for public facing methods. - struct Command - { - ReceiverImpl& impl; - - Command(ReceiverImpl& i) : impl(i) {} - }; - - struct Get : Command - { - qpid::messaging::Message& message; - qpid::messaging::Duration timeout; - bool result; - - Get(ReceiverImpl& i, qpid::messaging::Message& m, qpid::messaging::Duration t) : - Command(i), message(m), timeout(t), result(false) {} - void operator()() { result = impl.getImpl(message, timeout); } - }; - - struct Fetch : Command - { - qpid::messaging::Message& message; - qpid::messaging::Duration timeout; - bool result; - - Fetch(ReceiverImpl& i, qpid::messaging::Message& m, qpid::messaging::Duration t) : - Command(i), message(m), timeout(t), result(false) {} - void operator()() { result = impl.fetchImpl(message, timeout); } - }; - - struct Close : Command - { - Close(ReceiverImpl& i) : Command(i) {} - void operator()() { impl.closeImpl(); } - }; - - struct SetCapacity : Command - { - uint32_t capacity; - - SetCapacity(ReceiverImpl& i, uint32_t c) : Command(i), capacity(c) {} - void operator()() { impl.setCapacityImpl(capacity); } - }; - - //helper templates for some common patterns - template void execute() - { - F f(*this); - parent->execute(f); - } - - template void execute1(P p) - { - F f(*this, p); - parent->execute(f); - } -}; - -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_RECEIVERIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp b/qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp deleted file mode 100644 index 7575aaa306..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp +++ /dev/null @@ -1,206 +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 "SenderImpl.h" -#include "MessageSink.h" -#include "SessionImpl.h" -#include "AddressResolution.h" -#include "OutgoingMessage.h" -#include "qpid/messaging/Session.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -SenderImpl::SenderImpl(SessionImpl& _parent, const std::string& _name, - const qpid::messaging::Address& _address, bool _autoReconnect) : - parent(&_parent), autoReconnect(_autoReconnect), name(_name), address(_address), state(UNRESOLVED), - capacity(50), window(0), flushed(false), unreliable(AddressResolution::is_unreliable(address)) {} - -qpid::messaging::Address SenderImpl::getAddress() const -{ - return address; -} - -void SenderImpl::send(const qpid::messaging::Message& message, bool sync) -{ - if (unreliable) { // immutable, don't need lock - UnreliableSend f(*this, message); - parent->execute(f); - } else { - Send f(*this, message); - while (f.repeat) parent->execute(f); - } - if (sync) parent->sync(true); -} - -void SenderImpl::close() -{ - execute(); -} - -void SenderImpl::setCapacity(uint32_t c) -{ - bool flush; - { - sys::Mutex::ScopedLock l(lock); - flush = c < capacity; - capacity = c; - } - execute1(flush); -} - -uint32_t SenderImpl::getCapacity() { - sys::Mutex::ScopedLock l(lock); - return capacity; -} - -uint32_t SenderImpl::getUnsettled() -{ - CheckPendingSends f(*this, false); - parent->execute(f); - return f.pending; -} - -void SenderImpl::init(qpid::client::AsyncSession s, AddressResolution& resolver) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - if (state == UNRESOLVED) { - sink = resolver.resolveSink(session, address); - state = ACTIVE; - } - if (state == CANCELLED) { - sink->cancel(session, name); - sys::Mutex::ScopedUnlock u(lock); - parent->senderCancelled(name); - } else { - sink->declare(session, name); - replay(l); - } -} - -void SenderImpl::waitForCapacity() -{ - sys::Mutex::ScopedLock l(lock); - try { - //TODO: add option to throw exception rather than blocking? - if (!unreliable && capacity <= - (flushed ? checkPendingSends(false, l) : outgoing.size())) - { - //Initial implementation is very basic. As outgoing is - //currently only reduced on receiving completions and we are - //blocking anyway we may as well sync(). If successful that - //should clear all outstanding sends. - session.sync(); - checkPendingSends(false, l); - } - //flush periodically and check for conmpleted sends - if (++window > (capacity / 4)) {//TODO: make this configurable? - checkPendingSends(true, l); - window = 0; - } - } catch (const qpid::TransportFailure&) { - //Disconnection prevents flushing or syncing. If we have any - //capacity we will return anyway (the subsequent attempt to - //send will fail, but message will be on replay buffer). - if (capacity > outgoing.size()) return; - //If we are out of capacity, but autoreconnect is on, then - //rethrow the transport failure to trigger reconnect which - //will have the effect of blocking until connected and - //capacity is freed up - if (autoReconnect) throw; - //Otherwise, in order to clearly signal to the application - //that the message was not pushed to replay buffer, throw an - //out of capacity error - throw qpid::messaging::OutOfCapacity(name); - } -} - -void SenderImpl::sendImpl(const qpid::messaging::Message& m) -{ - sys::Mutex::ScopedLock l(lock); - std::auto_ptr msg(new OutgoingMessage()); - msg->setSubject(m.getSubject().empty() ? address.getSubject() : m.getSubject()); - msg->convert(m); - outgoing.push_back(msg.release()); - sink->send(session, name, outgoing.back()); -} - -void SenderImpl::sendUnreliable(const qpid::messaging::Message& m) -{ - sys::Mutex::ScopedLock l(lock); - OutgoingMessage msg; - msg.setSubject(m.getSubject().empty() ? address.getSubject() : m.getSubject()); - msg.convert(m); - sink->send(session, name, msg); -} - -void SenderImpl::replay(const sys::Mutex::ScopedLock& l) -{ - checkPendingSends(false, l); - for (OutgoingMessages::iterator i = outgoing.begin(); i != outgoing.end(); ++i) { - i->markRedelivered(); - sink->send(session, name, *i); - } -} - -uint32_t SenderImpl::checkPendingSends(bool flush) { - sys::Mutex::ScopedLock l(lock); - return checkPendingSends(flush, l); -} - -uint32_t SenderImpl::checkPendingSends(bool flush, const sys::Mutex::ScopedLock&) -{ - if (flush) { - session.flush(); - flushed = true; - } else { - flushed = false; - } - while (!outgoing.empty() && outgoing.front().isComplete()) { - outgoing.pop_front(); - } - return outgoing.size(); -} - -void SenderImpl::closeImpl() -{ - { - sys::Mutex::ScopedLock l(lock); - state = CANCELLED; - sink->cancel(session, name); - } - parent->senderCancelled(name); -} - -const std::string& SenderImpl::getName() const -{ - sys::Mutex::ScopedLock l(lock); - return name; -} - -qpid::messaging::Session SenderImpl::getSession() const -{ - sys::Mutex::ScopedLock l(lock); - return qpid::messaging::Session(parent.get()); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.h b/qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.h deleted file mode 100644 index 35ce82cf5d..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/SenderImpl.h +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_SENDERIMPL_H -#define QPID_CLIENT_AMQP0_10_SENDERIMPL_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/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/SenderImpl.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/amqp0_10/SessionImpl.h" -#include -#include -#include - -namespace qpid { -namespace client { -namespace amqp0_10 { - -class AddressResolution; -class MessageSink; -class OutgoingMessage; - -/** - * - */ -class SenderImpl : public qpid::messaging::SenderImpl -{ - public: - enum State {UNRESOLVED, ACTIVE, CANCELLED}; - - SenderImpl(SessionImpl& parent, const std::string& name, - const qpid::messaging::Address& address, bool autoReconnect); - void send(const qpid::messaging::Message&, bool sync); - void close(); - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getUnsettled(); - void init(qpid::client::AsyncSession, AddressResolution&); - const std::string& getName() const; - qpid::messaging::Session getSession() const; - qpid::messaging::Address getAddress() const; - - private: - mutable sys::Mutex lock; - boost::intrusive_ptr parent; - const bool autoReconnect; - const std::string name; - const qpid::messaging::Address address; - State state; - std::auto_ptr sink; - - qpid::client::AsyncSession session; - std::string destination; - std::string routingKey; - - typedef boost::ptr_deque OutgoingMessages; - OutgoingMessages outgoing; - uint32_t capacity; - uint32_t window; - bool flushed; - const bool unreliable; - - uint32_t checkPendingSends(bool flush); - // Dummy ScopedLock parameter means call with lock held - uint32_t checkPendingSends(bool flush, const sys::Mutex::ScopedLock&); - void replay(const sys::Mutex::ScopedLock&); - void waitForCapacity(); - - //logic for application visible methods: - void sendImpl(const qpid::messaging::Message&); - void sendUnreliable(const qpid::messaging::Message&); - void closeImpl(); - - - //functors for application visible methods (allowing locking and - //retry to be centralised): - struct Command - { - SenderImpl& impl; - - Command(SenderImpl& i) : impl(i) {} - }; - - struct Send : Command - { - const qpid::messaging::Message& message; - bool repeat; - - Send(SenderImpl& i, const qpid::messaging::Message& m) : Command(i), message(m), repeat(true) {} - void operator()() - { - impl.waitForCapacity(); - //from this point message will be recorded if there is any - //failure (and replayed) so need not repeat the call - repeat = false; - impl.sendImpl(message); - } - }; - - struct UnreliableSend : Command - { - const qpid::messaging::Message& message; - - UnreliableSend(SenderImpl& i, const qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() - { - //TODO: ideally want to put messages on the outbound - //queue and pull them off in io thread, but the old - //0-10 client doesn't support that option so for now - //we simply don't queue unreliable messages - impl.sendUnreliable(message); - } - }; - - struct Close : Command - { - Close(SenderImpl& i) : Command(i) {} - void operator()() { impl.closeImpl(); } - }; - - struct CheckPendingSends : Command - { - bool flush; - uint32_t pending; - CheckPendingSends(SenderImpl& i, bool f) : Command(i), flush(f), pending(0) {} - void operator()() { pending = impl.checkPendingSends(flush); } - }; - - //helper templates for some common patterns - template void execute() - { - F f(*this); - parent->execute(f); - } - - template bool execute1(P p) - { - F f(*this, p); - return parent->execute(f); - } -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_SENDERIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp b/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp deleted file mode 100644 index df3d6504d9..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp +++ /dev/null @@ -1,616 +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/client/amqp0_10/SessionImpl.h" -#include "qpid/client/amqp0_10/ConnectionImpl.h" -#include "qpid/client/amqp0_10/ReceiverImpl.h" -#include "qpid/client/amqp0_10/SenderImpl.h" -#include "qpid/client/amqp0_10/MessageSource.h" -#include "qpid/client/amqp0_10/MessageSink.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/messaging/PrivateImplRef.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Session.h" -#include "qpid/framing/enum.h" -#include -#include -#include - -using qpid::messaging::KeyError; -using qpid::messaging::NoMessageAvailable; -using qpid::messaging::MessagingException; -using qpid::messaging::TransactionError; -using qpid::messaging::TransactionAborted; -using qpid::messaging::TransactionUnknown; -using qpid::messaging::SessionError; -using qpid::messaging::MessageImplAccess; -using qpid::messaging::Sender; -using qpid::messaging::Receiver; - -namespace qpid { -namespace client { -namespace amqp0_10 { - -typedef qpid::sys::Mutex::ScopedLock ScopedLock; -typedef qpid::sys::Mutex::ScopedUnlock ScopedUnlock; - -SessionImpl::SessionImpl(ConnectionImpl& c, bool t) : - connection(&c), transactional(t), committing(false) {} - -bool SessionImpl::isTransactional() const -{ - return transactional; -} - -void SessionImpl::checkError() -{ - ScopedLock l(lock); - txError.raise(); - qpid::client::SessionBase_0_10Access s(session); - try { - s.get()->assertOpen(); - } catch (const qpid::TransportFailure&) { - throw qpid::messaging::TransportFailure(std::string()); - } catch (const qpid::framing::ResourceLimitExceededException& e) { - throw qpid::messaging::TargetCapacityExceeded(e.what()); - } catch (const qpid::framing::UnauthorizedAccessException& e) { - throw qpid::messaging::UnauthorizedAccess(e.what()); - } catch (const qpid::framing::NotFoundException& e) { - throw qpid::messaging::NotFound(e.what()); - } catch (const qpid::framing::ResourceDeletedException& e) { - throw qpid::messaging::NotFound(e.what()); - } catch (const qpid::SessionException& e) { - throw qpid::messaging::SessionError(e.what()); - } catch (const qpid::ConnectionException& e) { - throw qpid::messaging::ConnectionError(e.what()); - } catch (const qpid::Exception& e) { - throw qpid::messaging::MessagingException(e.what()); - } -} - -bool SessionImpl::hasError() -{ - ScopedLock l(lock); - qpid::client::SessionBase_0_10Access s(session); - return s.get()->hasError(); -} - -void SessionImpl::sync(bool block) -{ - if (block) retry(); - else execute(); -} - -namespace { -struct ScopedSet { - bool& flag; - ScopedSet(bool& f) : flag(f) { flag = true; } - ~ScopedSet() { flag = false; } -}; -} - -void SessionImpl::commit() -{ - try { - checkError(); - ScopedSet s(committing); - execute(); - } - catch (const TransactionError&) { - assert(txError); // Must be set by thrower of TransactionError - } - catch (const std::exception& e) { - txError = new TransactionAborted(Msg() << "Transaction aborted: " << e.what()); - } - checkError(); -} - -void SessionImpl::rollback() -{ - //If the session fails during this operation, the transaction will - //be rolled back anyway. - execute(); -} - -void SessionImpl::acknowledge(bool sync_) -{ - //Should probably throw an exception on failure here, or indicate - //it through a return type at least. Failure means that the - //message may be redelivered; i.e. the application cannot delete - //any state necessary for preventing reprocessing of the message - execute(); - sync(sync_); -} - -void SessionImpl::reject(qpid::messaging::Message& m) -{ - //Possibly want to somehow indicate failure here as well. Less - //clear need as compared to acknowledge however. - execute1(m); -} - -void SessionImpl::release(qpid::messaging::Message& m) -{ - execute1(m); -} - -void SessionImpl::acknowledge(qpid::messaging::Message& m, bool cumulative) -{ - //Should probably throw an exception on failure here, or indicate - //it through a return type at least. Failure means that the - //message may be redelivered; i.e. the application cannot delete - //any state necessary for preventing reprocessing of the message - Acknowledge2 ack(*this, m, cumulative); - execute(ack); -} - -void SessionImpl::close() -{ - if (hasError()) { - ScopedLock l(lock); - senders.clear(); - receivers.clear(); - } else { - Senders sCopy; - Receivers rCopy; - { - ScopedLock l(lock); - senders.swap(sCopy); - receivers.swap(rCopy); - } - for (Senders::iterator i = sCopy.begin(); i != sCopy.end(); ++i) - { - // outside the lock, will call senderCancelled - i->second.close(); - } - for (Receivers::iterator i = rCopy.begin(); i != rCopy.end(); ++i) - { - // outside the lock, will call receiverCancelled - i->second.close(); - } - } - connection->closed(*this); - if (!hasError()) { - ScopedLock l(lock); - session.close(); - } -} - -template boost::intrusive_ptr getImplPtr(T& t) -{ - return boost::dynamic_pointer_cast(qpid::messaging::PrivateImplRef::get(t)); -} - -template void getFreeKey(std::string& key, T& map) -{ - std::string name = key; - int count = 1; - for (typename T::const_iterator i = map.find(name); i != map.end(); i = map.find(name)) { - name = (boost::format("%1%_%2%") % key % ++count).str(); - } - key = name; -} - -void SessionImpl::setSession(qpid::client::Session s) -{ - session = s; - incoming.setSession(session); - if (transactional) { - session.txSelect(); - } - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr(i->second)->init(session, resolver); - } - for (Senders::iterator i = senders.begin(); i != senders.end(); ++i) { - getImplPtr(i->second)->init(session, resolver); - } - session.sync(); -} - -struct SessionImpl::CreateReceiver : Command -{ - qpid::messaging::Receiver result; - const qpid::messaging::Address& address; - - CreateReceiver(SessionImpl& i, const qpid::messaging::Address& a) : - Command(i), address(a) {} - void operator()() { result = impl.createReceiverImpl(address); } -}; - -Receiver SessionImpl::createReceiver(const qpid::messaging::Address& address) -{ - return get1(address); -} - -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, connection->getAutoDecode())); - getImplPtr(receiver)->init(session, resolver); - receivers[name] = receiver; - return receiver; -} - -struct SessionImpl::CreateSender : Command -{ - qpid::messaging::Sender result; - const qpid::messaging::Address& address; - - CreateSender(SessionImpl& i, const qpid::messaging::Address& a) : - Command(i), address(a) {} - void operator()() { result = impl.createSenderImpl(address); } -}; - -Sender SessionImpl::createSender(const qpid::messaging::Address& address) -{ - return get1(address); -} - -Sender SessionImpl::createSenderImpl(const qpid::messaging::Address& address) -{ - ScopedLock l(lock); - std::string name = address.getName(); - getFreeKey(name, senders); - Sender sender(new SenderImpl(*this, name, address, connection->getAutoReconnect())); - getImplPtr(sender)->init(session, resolver); - senders[name] = sender; - return sender; -} - -Sender SessionImpl::getSender(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Senders::const_iterator i = senders.find(name); - if (i == senders.end()) { - throw KeyError(name); - } else { - return i->second; - } -} - -Receiver SessionImpl::getReceiver(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(name); - if (i == receivers.end()) { - throw KeyError(name); - } else { - return i->second; - } -} - -SessionImpl& SessionImpl::convert(qpid::messaging::Session& s) -{ - boost::intrusive_ptr impl = getImplPtr(s); - if (!impl) { - throw SessionError(QPID_MSG("Configuration error; require qpid::client::amqp0_10::SessionImpl")); - } - return *impl; -} - -namespace { - -struct IncomingMessageHandler : IncomingMessages::Handler -{ - typedef boost::function1 Callback; - Callback callback; - ReceiverImpl* receiver; - - IncomingMessageHandler(Callback c) : callback(c), receiver(0) {} - - bool accept(IncomingMessages::MessageTransfer& transfer) - { - return callback(transfer); - } - - bool expire(IncomingMessages::MessageTransfer& transfer) - { - if (receiver && receiver->getName() == transfer.getDestination()) { - receiver->received(); - return true; - } else { - return false; - } - } - - bool isClosed() - { - return receiver && receiver->isClosed(); - } -}; - -} - - -bool SessionImpl::getNextReceiver(Receiver* receiver, IncomingMessages::MessageTransfer& transfer) -{ - ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(transfer.getDestination()); - if (i == receivers.end()) { - QPID_LOG(error, "Received message for unknown destination " << transfer.getDestination()); - return false; - } else { - *receiver = i->second; - return true; - } -} - -bool SessionImpl::accept(ReceiverImpl* receiver, - qpid::messaging::Message* message, - IncomingMessages::MessageTransfer& transfer) -{ - if (receiver->getName() == transfer.getDestination()) { - transfer.retrieve(message); - receiver->received(); - return true; - } else { - return false; - } -} - -qpid::sys::Duration adjust(qpid::messaging::Duration timeout) -{ - uint64_t ms = timeout.getMilliseconds(); - if (ms < (uint64_t) (qpid::sys::TIME_INFINITE/qpid::sys::TIME_MSEC)) { - return ms * qpid::sys::TIME_MSEC; - } else { - return qpid::sys::TIME_INFINITE; - } -} - -bool SessionImpl::getIncoming(IncomingMessages::Handler& handler, qpid::messaging::Duration timeout) -{ - return incoming.get(handler, adjust(timeout)); -} - -bool SessionImpl::get(ReceiverImpl& receiver, qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - IncomingMessageHandler handler(boost::bind(&SessionImpl::accept, this, &receiver, &message, _1)); - handler.receiver = &receiver; - return getIncoming(handler, timeout); -} - -bool SessionImpl::nextReceiver(qpid::messaging::Receiver& receiver, qpid::messaging::Duration timeout) -{ - while (true) { - txError.raise(); - try { - std::string destination; - if (incoming.getNextDestination(destination, adjust(timeout))) { - qpid::sys::Mutex::ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(destination); - if (i == receivers.end()) { - throw qpid::messaging::ReceiverError(QPID_MSG("Received message for unknown destination " << destination)); - } else { - receiver = i->second; - } - return true; - } else { - return false; - } - } catch (TransportFailure&) { - reconnect(); - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (backoff()) return false; - else throw qpid::messaging::TargetCapacityExceeded(e.what()); - } catch (const qpid::SessionException& e) { - rethrow(e); - } catch (const qpid::ClosedException&) { - throw qpid::messaging::SessionClosed(); - } catch (const qpid::ConnectionException& e) { - throw qpid::messaging::ConnectionError(e.what()); - } catch (const qpid::ChannelException& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } -} - -qpid::messaging::Receiver SessionImpl::nextReceiver(qpid::messaging::Duration timeout) -{ - qpid::messaging::Receiver receiver; - if (!nextReceiver(receiver, timeout)) throw NoMessageAvailable(); - if (!receiver) throw SessionError("Bad receiver returned!"); - return receiver; -} - -uint32_t SessionImpl::getReceivable() -{ - return get1((const std::string*) 0); -} -uint32_t SessionImpl::getReceivable(const std::string& destination) -{ - return get1(&destination); -} - -struct SessionImpl::Receivable : Command -{ - const std::string* destination; - uint32_t result; - - Receivable(SessionImpl& i, const std::string* d) : Command(i), destination(d), result(0) {} - void operator()() { result = impl.getReceivableImpl(destination); } -}; - -uint32_t SessionImpl::getReceivableImpl(const std::string* destination) -{ - ScopedLock l(lock); - if (destination) { - return incoming.available(*destination); - } else { - return incoming.available(); - } -} - -uint32_t SessionImpl::getUnsettledAcks() -{ - return get1((const std::string*) 0); -} - -uint32_t SessionImpl::getUnsettledAcks(const std::string& destination) -{ - return get1(&destination); -} - -struct SessionImpl::UnsettledAcks : Command -{ - const std::string* destination; - uint32_t result; - - UnsettledAcks(SessionImpl& i, const std::string* d) : Command(i), destination(d), result(0) {} - void operator()() { result = impl.getUnsettledAcksImpl(destination); } -}; - -uint32_t SessionImpl::getUnsettledAcksImpl(const std::string* destination) -{ - ScopedLock l(lock); - if (destination) { - return incoming.pendingAccept(*destination); - } else { - return incoming.pendingAccept(); - } -} - -void SessionImpl::syncImpl(bool block) -{ - { - ScopedLock l(lock); - if (block) session.sync(); - else session.flush(); - } - //cleanup unconfirmed accept records: - incoming.pendingAccept(); -} - -void SessionImpl::commitImpl() -{ - ScopedLock l(lock); - incoming.accept(); - session.txCommit(); -} - -void SessionImpl::rollbackImpl() -{ - ScopedLock l(lock); - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr(i->second)->stop(); - } - //ensure that stop has been processed and all previously sent - //messages are available for release: - session.sync(); - incoming.releaseAll(); - session.txRollback(); - - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr(i->second)->start(); - } -} - -void SessionImpl::acknowledgeImpl() -{ - if (!transactional) incoming.accept(); -} - -void SessionImpl::acknowledgeImpl(qpid::messaging::Message& m, bool cumulative) -{ - if (!transactional) incoming.accept(MessageImplAccess::get(m).getInternalId(), cumulative); -} - -void SessionImpl::rejectImpl(qpid::messaging::Message& m) -{ - SequenceSet set; - set.add(MessageImplAccess::get(m).getInternalId()); - session.messageReject(set); -} - -void SessionImpl::releaseImpl(qpid::messaging::Message& m) -{ - SequenceSet set; - set.add(MessageImplAccess::get(m).getInternalId()); - session.messageRelease(set, true); -} - -void SessionImpl::receiverCancelled(const std::string& name) -{ - { - ScopedLock l(lock); - receivers.erase(name); - session.sync(); - incoming.releasePending(name); - } - incoming.wakeup(); -} - -void SessionImpl::releasePending(const std::string& name) -{ - ScopedLock l(lock); - incoming.releasePending(name); -} - -void SessionImpl::senderCancelled(const std::string& name) -{ - ScopedLock l(lock); - senders.erase(name); -} - -void SessionImpl::reconnect() -{ - if (transactional) { - if (committing) - txError = new TransactionUnknown("Transaction outcome unknown: transport failure"); - else - txError = new TransactionAborted("Transaction aborted: transport failure"); - txError.raise(); - } - connection->reopen(); -} - -bool SessionImpl::backoff() -{ - return connection->backoff(); -} - -qpid::messaging::Connection SessionImpl::getConnection() const -{ - return qpid::messaging::Connection(connection.get()); -} - -void SessionImpl::rethrow(const qpid::SessionException& e) { - switch (e.code) { - case framing::execution::ERROR_CODE_NOT_ALLOWED: - case framing::execution::ERROR_CODE_UNAUTHORIZED_ACCESS: throw messaging::UnauthorizedAccess(e.what()); - - case framing::execution::ERROR_CODE_NOT_FOUND: - case framing::execution::ERROR_CODE_RESOURCE_DELETED: throw messaging::NotFound(e.what()); - - default: throw SessionError(e.what()); - } -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.h b/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.h deleted file mode 100644 index 2bb72aa877..0000000000 --- a/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.h +++ /dev/null @@ -1,259 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_SESSIONIMPL_H -#define QPID_CLIENT_AMQP0_10_SESSIONIMPL_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/messaging/SessionImpl.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/client/amqp0_10/IncomingMessages.h" -#include "qpid/sys/Mutex.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/ExceptionHolder.h" -#include - -namespace qpid { - -namespace messaging { -class Address; -class Connection; -class Message; -class Receiver; -class Sender; -class Session; -} - -namespace client { -namespace amqp0_10 { - -class ConnectionImpl; -class ReceiverImpl; -class SenderImpl; - -/** - * Implementation of the protocol independent Session interface using - * AMQP 0-10. - */ -class SessionImpl : public qpid::messaging::SessionImpl -{ - public: - SessionImpl(ConnectionImpl&, bool transactional); - void commit(); - void rollback(); - void acknowledge(bool sync); - void reject(qpid::messaging::Message&); - void release(qpid::messaging::Message&); - void acknowledge(qpid::messaging::Message& msg, bool cumulative); - void close(); - void sync(bool block); - qpid::messaging::Sender createSender(const qpid::messaging::Address& address); - qpid::messaging::Receiver createReceiver(const qpid::messaging::Address& address); - - qpid::messaging::Sender getSender(const std::string& name) const; - qpid::messaging::Receiver getReceiver(const std::string& name) const; - - bool nextReceiver(qpid::messaging::Receiver& receiver, qpid::messaging::Duration timeout); - qpid::messaging::Receiver nextReceiver(qpid::messaging::Duration timeout); - - qpid::messaging::Connection getConnection() const; - void checkError(); - bool hasError(); - bool isTransactional() const; - - bool get(ReceiverImpl& receiver, qpid::messaging::Message& message, qpid::messaging::Duration timeout); - - void releasePending(const std::string& destination); - void receiverCancelled(const std::string& name); - void senderCancelled(const std::string& name); - - uint32_t getReceivable(); - uint32_t getReceivable(const std::string& destination); - - uint32_t getUnsettledAcks(); - uint32_t getUnsettledAcks(const std::string& destination); - - void setSession(qpid::client::Session); - - template bool execute(T& f) - { - try { - txError.raise(); - f(); - return true; - } catch (const qpid::TransportFailure&) { - reconnect(); - return false; - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (backoff()) return false; - else throw qpid::messaging::TargetCapacityExceeded(e.what()); - } catch (const qpid::framing::UnauthorizedAccessException& e) { - throw qpid::messaging::UnauthorizedAccess(e.what()); - } catch (const qpid::framing::NotFoundException& e) { - throw qpid::messaging::NotFound(e.what()); - } catch (const qpid::framing::ResourceDeletedException& e) { - throw qpid::messaging::NotFound(e.what()); - } catch (const qpid::SessionException& e) { - rethrow(e); - return false; // Keep the compiler happy - } catch (const qpid::ConnectionException& e) { - throw qpid::messaging::ConnectionError(e.what()); - } catch (const qpid::ChannelException& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } - - static SessionImpl& convert(qpid::messaging::Session&); - static void rethrow(const qpid::SessionException&); - - private: - typedef std::map Receivers; - typedef std::map Senders; - - mutable qpid::sys::Mutex lock; - boost::intrusive_ptr connection; - qpid::client::Session session; - AddressResolution resolver; - IncomingMessages incoming; - Receivers receivers; - Senders senders; - const bool transactional; - bool committing; - sys::ExceptionHolder txError; - - bool accept(ReceiverImpl*, qpid::messaging::Message*, IncomingMessages::MessageTransfer&); - bool getIncoming(IncomingMessages::Handler& handler, qpid::messaging::Duration timeout); - bool getNextReceiver(qpid::messaging::Receiver* receiver, IncomingMessages::MessageTransfer& transfer); - void reconnect(); - bool backoff(); - - void commitImpl(); - void rollbackImpl(); - void acknowledgeImpl(); - void acknowledgeImpl(qpid::messaging::Message&, bool cumulative); - void rejectImpl(qpid::messaging::Message&); - void releaseImpl(qpid::messaging::Message&); - void closeImpl(); - void syncImpl(bool block); - qpid::messaging::Sender createSenderImpl(const qpid::messaging::Address& address); - qpid::messaging::Receiver createReceiverImpl(const qpid::messaging::Address& address); - uint32_t getReceivableImpl(const std::string* destination); - uint32_t getUnsettledAcksImpl(const std::string* destination); - - //functors for public facing methods (allows locking and retry - //logic to be centralised) - struct Command - { - SessionImpl& impl; - - Command(SessionImpl& i) : impl(i) {} - }; - - struct Commit : Command - { - Commit(SessionImpl& i) : Command(i) {} - void operator()() { impl.commitImpl(); } - }; - - struct Rollback : Command - { - Rollback(SessionImpl& i) : Command(i) {} - void operator()() { impl.rollbackImpl(); } - }; - - struct Acknowledge : Command - { - Acknowledge(SessionImpl& i) : Command(i) {} - void operator()() { impl.acknowledgeImpl(); } - }; - - struct Sync : Command - { - Sync(SessionImpl& i) : Command(i) {} - void operator()() { impl.syncImpl(true); } - }; - - struct NonBlockingSync : Command - { - NonBlockingSync(SessionImpl& i) : Command(i) {} - void operator()() { impl.syncImpl(false); } - }; - - struct Reject : Command - { - qpid::messaging::Message& message; - - Reject(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() { impl.rejectImpl(message); } - }; - - struct Release : Command - { - qpid::messaging::Message& message; - - Release(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() { impl.releaseImpl(message); } - }; - - struct Acknowledge2 : Command - { - qpid::messaging::Message& message; - bool cumulative; - - Acknowledge2(SessionImpl& i, qpid::messaging::Message& m, bool c) : Command(i), message(m), cumulative(c) {} - void operator()() { impl.acknowledgeImpl(message, cumulative); } - }; - - struct CreateSender; - struct CreateReceiver; - struct UnsettledAcks; - struct Receivable; - - //helper templates for some common patterns - template bool execute() - { - F f(*this); - return execute(f); - } - - template void retry() - { - while (!execute()) {} - } - - template bool execute1(P p) - { - F f(*this, p); - return execute(f); - } - - template R get1(P p) - { - F f(*this, p); - while (!execute(f)) {} - return f.result; - } -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_SESSIONIMPL_H*/ diff --git a/qpid/cpp/src/qpid/client/ssl.h b/qpid/cpp/src/qpid/client/ssl.h deleted file mode 100644 index 0adef21f7e..0000000000 --- a/qpid/cpp/src/qpid/client/ssl.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef QPID_CLIENT_SSL_H -#define QPID_CLIENT_SSL_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 client { -void initialiseSSL(); -void shutdownSSL(); -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SSL_H*/ diff --git a/qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp b/qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp deleted file mode 100644 index d636489908..0000000000 --- a/qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp +++ /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. - * - */ - -#include "qpid/sys/windows/QpidDllMain.h" diff --git a/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp b/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp deleted file mode 100644 index 0f02c572ce..0000000000 --- a/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp +++ /dev/null @@ -1,202 +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/SaslFactory.h" - -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/log/Statement.h" -#include "qpid/NullSaslServer.h" -#include "qpid/sys/SystemInfo.h" - -#include "boost/tokenizer.hpp" - -namespace qpid { - -using qpid::sys::SecurityLayer; -using qpid::sys::SecuritySettings; -using qpid::framing::InternalErrorException; - -struct WindowsSaslSettings -{ - WindowsSaslSettings ( ) : - username ( std::string(0) ), - password ( std::string(0) ), - service ( std::string(0) ), - host ( std::string(0) ), - minSsf ( 0 ), - maxSsf ( 0 ) - { - } - - WindowsSaslSettings ( const std::string & user, const std::string & password, const std::string & service, const std::string & host, int minSsf, int maxSsf ) : - username(user), - password(password), - service(service), - host(host), - minSsf(minSsf), - maxSsf(maxSsf) - { - } - - std::string username, - password, - service, - host; - - int minSsf, - maxSsf; -}; - -class WindowsSasl : public Sasl -{ - public: - WindowsSasl( const std::string &, const std::string &, const std::string &, const std::string &, int, int ); - ~WindowsSasl(); - bool start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings); - std::string step(const std::string& challenge); - std::string getMechanism(); - std::string getUserId(); - std::auto_ptr getSecurityLayer(uint16_t maxFrameSize); - private: - WindowsSaslSettings settings; - std::string mechanism; -}; - -qpid::sys::Mutex SaslFactory::lock; -std::auto_ptr SaslFactory::instance; - -SaslFactory::SaslFactory() -{ -} - -SaslFactory::~SaslFactory() -{ -} - -SaslFactory& SaslFactory::getInstance() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!instance.get()) { - instance = std::auto_ptr(new SaslFactory()); - } - return *instance; -} - -std::auto_ptr SaslFactory::create( const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool ) -{ - std::auto_ptr sasl(new WindowsSasl( username, password, serviceName, hostName, minSsf, maxSsf )); - return sasl; -} - -std::auto_ptr SaslFactory::createServer( const std::string& realm, const std::string& /*service*/, bool /*encryptionRequired*/, const qpid::sys::SecuritySettings& ) -{ - std::auto_ptr server(new NullSaslServer(realm)); - return server; -} - -namespace { - const std::string ANONYMOUS = "ANONYMOUS"; - const std::string PLAIN = "PLAIN"; - const std::string EXTERNAL = "EXTERNAL"; -} - -WindowsSasl::WindowsSasl( const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf ) - : settings(username, password, serviceName, hostName, minSsf, maxSsf) -{ -} - -WindowsSasl::~WindowsSasl() -{ -} - -bool WindowsSasl::start(const std::string& mechanisms, std::string& response, - const SecuritySettings* /*externalSettings*/) -{ - QPID_LOG(debug, "WindowsSasl::start(" << mechanisms << ")"); - - typedef boost::tokenizer > tokenizer; - boost::char_separator sep(" "); - bool haveExt = false; - bool havePlain = false; - bool haveAnon = false; - tokenizer mechs(mechanisms, sep); - for (tokenizer::iterator mech = mechs.begin(); - mech != mechs.end(); - ++mech) { - if (*mech == EXTERNAL) - haveExt = true; - else if (*mech == ANONYMOUS) - haveAnon = true; - else if (*mech == PLAIN) - havePlain = true; - } - if (!haveAnon && !havePlain && !haveExt) - throw InternalErrorException(QPID_MSG("Sasl error: no common mechanism")); - - if (haveExt && settings.username.size() > 0) { - mechanism = EXTERNAL; - response = ((char)0) + settings.username.c_str(); - } - else if (havePlain && settings.username.size() > 0) { - mechanism = PLAIN; - response = ((char)0) + settings.username + ((char)0) + settings.password; - } - else if (haveAnon) { - std::string osName; - std::string nodeName; - std::string release; - std::string version; - std::string machine; - qpid::sys::SystemInfo::getSystemId(osName, nodeName, release, version, machine); - - mechanism = ANONYMOUS; - response = "anonymous@" + nodeName; - } else { - throw InternalErrorException(QPID_MSG("Sasl error: no user name specified")); - } - return true; -} - -std::string WindowsSasl::step(const std::string& /*challenge*/) -{ - // Shouldn't get this for PLAIN... - throw InternalErrorException(QPID_MSG("Sasl step error")); -} - -std::string WindowsSasl::getMechanism() -{ - return mechanism; -} - -std::string WindowsSasl::getUserId() -{ - return std::string(); // TODO - when GSSAPI is supported, return userId for connection. -} - -std::auto_ptr WindowsSasl::getSecurityLayer(uint16_t /*maxFrameSize*/) -{ - return std::auto_ptr(0); -} - -} // namespace qpid diff --git a/qpid/cpp/src/qpid/client/windows/SslConnector.cpp b/qpid/cpp/src/qpid/client/windows/SslConnector.cpp deleted file mode 100644 index dc82ece9d1..0000000000 --- a/qpid/cpp/src/qpid/client/windows/SslConnector.cpp +++ /dev/null @@ -1,147 +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/client/TCPConnector.h" - -#include "config.h" -#include "qpid/Msg.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/util.h" -#include "qpid/sys/windows/SslAsynchIO.h" -#include "qpid/sys/windows/SslCredential.h" - -#include - -#include -#include - - - -namespace qpid { -namespace client { -namespace windows { - -using qpid::sys::Socket; - -class SslConnector : public qpid::client::TCPConnector -{ - qpid::sys::windows::ClientSslAsynchIO *shim; - boost::shared_ptr poller; - std::string brokerHost; - qpid::sys::windows::SslCredential sslCredential; - bool certLoaded; - - void negotiationDone(SECURITY_STATUS status); - - void connect(const std::string& host, const std::string& port); - void connected(const Socket&); - -public: - SslConnector(boost::shared_ptr, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -// Static constructor which registers connector here -namespace { - Connector* create(boost::shared_ptr p, - framing::ProtocolVersion v, - const ConnectionSettings& s, - ConnectionImpl* c) { - return new SslConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - try { - CommonOptions common("", "", QPIDC_CONF_FILE); - qpid::sys::ssl::SslOptions options; - common.parse(0, 0, common.clientConfig, true); - options.parse (0, 0, common.clientConfig, true); - Connector::registerFactory("ssl", &create); - initWinSsl(options); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL connector: " << e.what()); - } - }; - ~StaticInit() { } - } init; - -} - -void SslConnector::negotiationDone(SECURITY_STATUS status) -{ - if (status == SEC_E_OK) { - initAmqp(); - } - else { - if (status == SEC_E_INCOMPLETE_CREDENTIALS && !certLoaded) { - // Server requested a client cert but we supplied none for the following reason: - connectFailed(QPID_MSG(sslCredential.error())); - } - else - connectFailed(QPID_MSG(qpid::sys::strError(status))); - } -} - -SslConnector::SslConnector(boost::shared_ptr p, - framing::ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : TCPConnector(p, ver, settings, cimpl), shim(0), poller(p) -{ - if (settings.sslIgnoreHostnameVerificationFailure) { - sslCredential.ignoreHostnameVerificationFailure(); - } - const std::string& name = (settings.sslCertName != "") ? - settings.sslCertName : qpid::sys::ssl::SslOptions::global.certName; - certLoaded = sslCredential.load(name); - QPID_LOG(debug, "SslConnector created for " << ver.toString()); -} - -void SslConnector::connect(const std::string& host, const std::string& port) { - brokerHost = host; - TCPConnector::connect(host, port); -} - -void SslConnector::connected(const Socket& s) { - shim = new qpid::sys::windows::ClientSslAsynchIO(brokerHost, - s, - sslCredential.handle(), - boost::bind(&SslConnector::readbuff, this, _1, _2), - boost::bind(&SslConnector::eof, this, _1), - boost::bind(&SslConnector::disconnected, this, _1), - boost::bind(&SslConnector::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&SslConnector::writebuff, this, _1), - boost::bind(&SslConnector::negotiationDone, this, _1)); - start(shim); - shim->start(poller); -} - -}}} // namespace qpid::client::windows diff --git a/qpid/cpp/src/qpid/framing/AMQBody.cpp b/qpid/cpp/src/qpid/framing/AMQBody.cpp deleted file mode 100644 index b3eeae0615..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQBody.cpp +++ /dev/null @@ -1,64 +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/framing/AMQBody.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" -#include - -namespace qpid { -namespace framing { - -std::ostream& operator<<(std::ostream& out, const AMQBody& body) -{ - body.print(out); - return out; -} - -AMQBody::~AMQBody() {} - -namespace { -struct MatchBodies : public AMQBodyConstVisitor { - const AMQBody& body; - bool match; - - MatchBodies(const AMQBody& b) : body(b), match(false) {} - virtual ~MatchBodies() {} - - virtual void visit(const AMQHeaderBody&) { match=dynamic_cast(&body); } - virtual void visit(const AMQContentBody&) { match=dynamic_cast(&body); } - virtual void visit(const AMQHeartbeatBody&) { match=dynamic_cast(&body); } - virtual void visit(const AMQMethodBody& x) { - const AMQMethodBody* y=dynamic_cast(&body); - match = (y && y->amqpMethodId() == x.amqpMethodId() && y->amqpClassId() == x.amqpClassId()); - } -}; - -} -bool AMQBody::match(const AMQBody& a, const AMQBody& b) { - MatchBodies matcher(a); - b.accept(matcher); - return matcher.match; -} - -}} // namespace diff --git a/qpid/cpp/src/qpid/framing/AMQBody.h b/qpid/cpp/src/qpid/framing/AMQBody.h deleted file mode 100644 index 56d1d250c1..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQBody.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef QPID_FRAMING_AMQBODY_H -#define QPID_FRAMING_AMQBODY_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/RefCounted.h" -#include "qpid/framing/BodyFactory.h" -#include -#include -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class Buffer; - -class AMQMethodBody; -class AMQHeaderBody; -class AMQContentBody; -class AMQHeartbeatBody; - -struct AMQBodyConstVisitor { - virtual ~AMQBodyConstVisitor() {} - virtual void visit(const AMQHeaderBody&) = 0; - virtual void visit(const AMQContentBody&) = 0; - virtual void visit(const AMQHeartbeatBody&) = 0; - virtual void visit(const AMQMethodBody&) = 0; -}; - -class QPID_COMMON_CLASS_EXTERN AMQBody : public RefCounted { - public: - AMQBody() {} - QPID_COMMON_EXTERN virtual ~AMQBody(); - - // Make AMQBody copyable even though RefCounted. - AMQBody(const AMQBody&) : RefCounted() {} - AMQBody& operator=(const AMQBody&) { return *this; } - - virtual uint8_t type() const = 0; - - virtual void encode(Buffer& buffer) const = 0; - virtual void decode(Buffer& buffer, uint32_t=0) = 0; - virtual uint32_t encodedSize() const = 0; - - virtual void print(std::ostream& out) const = 0; - virtual void accept(AMQBodyConstVisitor&) const = 0; - - virtual AMQMethodBody* getMethod() { return 0; } - virtual const AMQMethodBody* getMethod() const { return 0; } - - /** Match if same type and same class/method ID for methods */ - static bool match(const AMQBody& , const AMQBody& ); - virtual boost::intrusive_ptr clone() const = 0; -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& out, const AMQBody& body) ; - -enum BodyTypes { - METHOD_BODY = 1, - HEADER_BODY = 2, - CONTENT_BODY = 3, - HEARTBEAT_BODY = 8 -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_AMQBODY_H*/ diff --git a/qpid/cpp/src/qpid/framing/AMQContentBody.cpp b/qpid/cpp/src/qpid/framing/AMQContentBody.cpp deleted file mode 100644 index 18f6994f8f..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQContentBody.cpp +++ /dev/null @@ -1,46 +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/framing/AMQContentBody.h" -#include - -qpid::framing::AMQContentBody::AMQContentBody(){ -} - -qpid::framing::AMQContentBody::AMQContentBody(const std::string& _data) : data(_data){ -} - -uint32_t qpid::framing::AMQContentBody::encodedSize() const{ - return data.size(); -} -void qpid::framing::AMQContentBody::encode(Buffer& buffer) const{ - buffer.putRawData(data); -} -void qpid::framing::AMQContentBody::decode(Buffer& buffer, uint32_t _size){ - buffer.getRawData(data, _size); -} - -void qpid::framing::AMQContentBody::print(std::ostream& out) const -{ - out << "content (" << encodedSize() << " bytes)"; - const size_t max = 32; - out << " " << data.substr(0, max); - if (data.size() > max) out << "..."; -} diff --git a/qpid/cpp/src/qpid/framing/AMQContentBody.h b/qpid/cpp/src/qpid/framing/AMQContentBody.h deleted file mode 100644 index 148b293a2f..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQContentBody.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/Buffer.h" -#include "qpid/CommonImportExport.h" - -#ifndef _AMQContentBody_ -#define _AMQContentBody_ - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN AMQContentBody : public AMQBody -{ - std::string data; - -public: - QPID_COMMON_EXTERN AMQContentBody(); - QPID_COMMON_EXTERN AMQContentBody(const std::string& data); - inline virtual ~AMQContentBody(){} - inline uint8_t type() const { return CONTENT_BODY; }; - inline const std::string& getData() const { return data; } - inline std::string& getData() { return data; } - QPID_COMMON_EXTERN uint32_t encodedSize() const; - QPID_COMMON_EXTERN void encode(Buffer& buffer) const; - QPID_COMMON_EXTERN void decode(Buffer& buffer, uint32_t size); - QPID_COMMON_EXTERN void print(std::ostream& out) const; - void accept(AMQBodyConstVisitor& v) const { v.visit(*this); } - boost::intrusive_ptr clone() const { return BodyFactory::copy(*this); } -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/AMQDataBlock.h b/qpid/cpp/src/qpid/framing/AMQDataBlock.h deleted file mode 100644 index 7f0d0dc2b5..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQDataBlock.h +++ /dev/null @@ -1,42 +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/framing/Buffer.h" - -#ifndef _AMQDataBlock_ -#define _AMQDataBlock_ - -namespace qpid { -namespace framing { - -class AMQDataBlock -{ -public: - virtual ~AMQDataBlock() {} - virtual void encode(Buffer& buffer) const = 0; - virtual bool decode(Buffer& buffer) = 0; - virtual uint32_t encodedSize() const = 0; -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/AMQFrame.cpp b/qpid/cpp/src/qpid/framing/AMQFrame.cpp deleted file mode 100644 index 5e065d598c..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQFrame.cpp +++ /dev/null @@ -1,158 +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/framing/AMQFrame.h" - -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/BodyFactory.h" -#include "qpid/framing/MethodBodyFactory.h" -#include "qpid/Msg.h" - -#include -#include - -namespace qpid { -namespace framing { - -void AMQFrame::init() { bof = eof = bos = eos = true; subchannel=0; channel=0; } - -AMQFrame::AMQFrame(const boost::intrusive_ptr& b) : body(b) { init(); } - -AMQFrame::AMQFrame(const AMQBody& b) : body(b.clone()) { init(); } - -AMQFrame::~AMQFrame() {} - -void AMQFrame::setMethod(ClassId c, MethodId m) { body = MethodBodyFactory::create(c,m); } - -uint32_t AMQFrame::encodedSize() const { - uint32_t size = frameOverhead() + body->encodedSize(); - if (body->getMethod()) - size += sizeof(ClassId)+sizeof(MethodId); - return size; -} - -uint32_t AMQFrame::frameOverhead() { - return 12 /*frame header*/; -} - -uint16_t AMQFrame::DECODE_SIZE_MIN=4; - -uint16_t AMQFrame::decodeSize(char* data) { - Buffer buf(data+2, DECODE_SIZE_MIN); - return buf.getShort(); -} - -void AMQFrame::encode(Buffer& buffer) const -{ - //set track first (controls on track 0, everything else on 1): - uint8_t track = getBody()->type() ? 1 : 0; - - uint8_t flags = (bof ? 0x08 : 0) | (eof ? 0x04 : 0) | (bos ? 0x02 : 0) | (eos ? 0x01 : 0); - buffer.putOctet(flags); - buffer.putOctet(getBody()->type()); - buffer.putShort(encodedSize()); - buffer.putOctet(0); - buffer.putOctet(0x0f & track); - buffer.putShort(channel); - buffer.putLong(0); - const AMQMethodBody* method=getMethod(); - if (method) { - buffer.putOctet(method->amqpClassId()); - buffer.putOctet(method->amqpMethodId()); - } - body->encode(buffer); -} - -bool AMQFrame::decode(Buffer& buffer) -{ - if(buffer.available() < frameOverhead()) - return false; - uint32_t pos = buffer.getPosition(); - - uint8_t flags = buffer.getOctet(); - uint8_t framing_version = (flags & 0xc0) >> 6; - if (framing_version != 0) - throw FramingErrorException(QPID_MSG("Framing version unsupported")); - bof = flags & 0x08; - eof = flags & 0x04; - bos = flags & 0x02; - eos = flags & 0x01; - uint8_t type = buffer.getOctet(); - uint16_t frame_size = buffer.getShort(); - if (frame_size < frameOverhead()) - throw FramingErrorException(QPID_MSG("Frame size too small " << frame_size)); - uint8_t reserved1 = buffer.getOctet(); - uint8_t field1 = buffer.getOctet(); - subchannel = field1 & 0x0f; - channel = buffer.getShort(); - (void) buffer.getLong(); // reserved2 - - // Verify that the protocol header meets current spec - // TODO: should we check reserved2 against zero as well? - the - // spec isn't clear - if ((flags & 0x30) != 0 || reserved1 != 0 || (field1 & 0xf0) != 0) - throw FramingErrorException(QPID_MSG("Reserved bits not zero")); - - // TODO: should no longer care about body size and only pass up - // B,E,b,e flags - uint16_t body_size = frame_size - frameOverhead(); - if (buffer.available() < body_size){ - buffer.setPosition(pos); - return false; - } - - switch(type) - { - case 0://CONTROL - case METHOD_BODY: { - ClassId c = buffer.getOctet(); - MethodId m = buffer.getOctet(); - body = MethodBodyFactory::create(c, m); - break; - } - case HEADER_BODY: body = BodyFactory::create(); break; - case CONTENT_BODY: body = BodyFactory::create(); break; - case HEARTBEAT_BODY: body = BodyFactory::create(); break; - default: - throw IllegalArgumentException(QPID_MSG("Invalid frame type " << type)); - } - body->decode(buffer, body_size); - - return true; -} - -void AMQFrame::cloneBody() -{ - body = body->clone(); -} - -std::ostream& operator<<(std::ostream& out, const AMQFrame& f) -{ - return - out << "Frame[" - << (f.getBof() ? "B" : "") << (f.getEof() ? "E" : "") - << (f.getBos() ? "b" : "") << (f.getEos() ? "e" : "") << "; " - << "channel=" << f.getChannel() << "; " << *f.getBody() - << "]"; -} - - -}} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/AMQFrame.h b/qpid/cpp/src/qpid/framing/AMQFrame.h deleted file mode 100644 index 19675ce6ff..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQFrame.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef _AMQFrame_ -#define _AMQFrame_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/AMQDataBlock.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" -#include "qpid/framing/ProtocolVersion.h" -#include -#include -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN AMQFrame : public AMQDataBlock -{ - public: - QPID_COMMON_EXTERN AMQFrame(const boost::intrusive_ptr& b=0); - QPID_COMMON_EXTERN AMQFrame(const AMQBody& b); - QPID_COMMON_EXTERN ~AMQFrame(); - - ChannelId getChannel() const { return channel; } - void setChannel(ChannelId c) { channel = c; } - - AMQBody* getBody() const { return body.get(); } - - AMQMethodBody* getMethod() { return getBody() ? getBody()->getMethod() : 0; } - const AMQMethodBody* getMethod() const { return getBody() ? getBody()->getMethod() : 0; } - - void setMethod(ClassId c, MethodId m); - - template T* castBody() { - return boost::polymorphic_downcast(getBody()); - } - - template const T* castBody() const { - return boost::polymorphic_downcast(getBody()); - } - - /** - * Take a deep copy of the body currently referenced - */ - QPID_COMMON_EXTERN void cloneBody(); - - QPID_COMMON_EXTERN void encode(Buffer& buffer) const; - QPID_COMMON_EXTERN bool decode(Buffer& buffer); - QPID_COMMON_EXTERN uint32_t encodedSize() const; - - // 0-10 terminology: first/last frame (in segment) first/last segment (in assembly) - - bool isFirstSegment() const { return bof; } - bool isLastSegment() const { return eof; } - bool isFirstFrame() const { return bos; } - bool isLastFrame() const { return eos; } - - void setFirstSegment(bool set=true) { bof = set; } - void setLastSegment(bool set=true) { eof = set; } - void setFirstFrame(bool set=true) { bos = set; } - void setLastFrame(bool set=true) { eos = set; } - - // 0-9 terminology: beginning/end of frameset, beginning/end of segment. - - bool getBof() const { return bof; } - void setBof(bool isBof) { bof = isBof; } - bool getEof() const { return eof; } - void setEof(bool isEof) { eof = isEof; } - - bool getBos() const { return bos; } - void setBos(bool isBos) { bos = isBos; } - bool getEos() const { return eos; } - void setEos(bool isEos) { eos = isEos; } - - static uint16_t DECODE_SIZE_MIN; - QPID_COMMON_EXTERN static uint32_t frameOverhead(); - /** Must point to at least DECODE_SIZE_MIN bytes of data */ - static uint16_t decodeSize(char* data); - - private: - void init(); - - boost::intrusive_ptr body; - uint16_t channel : 16; - uint8_t subchannel : 8; - bool bof : 1; - bool eof : 1; - bool bos : 1; - bool eos : 1; -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const AMQFrame&); - -}} // namespace qpid::framing - - -#endif diff --git a/qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp b/qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp deleted file mode 100644 index 14218f1b45..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp +++ /dev/null @@ -1,63 +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/framing/AMQHeaderBody.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" - -uint32_t qpid::framing::AMQHeaderBody::encodedSize() const { - return properties.encodedSize(); -} - -void qpid::framing::AMQHeaderBody::encode(Buffer& buffer) const { - properties.encode(buffer); -} - -void qpid::framing::AMQHeaderBody::decode(Buffer& buffer, uint32_t size) { - uint32_t limit = buffer.available() - size; - while (buffer.available() > limit + 2) { - uint32_t len = buffer.getLong(); - uint16_t type = buffer.getShort(); - if (!properties.decode(buffer, len, type)) { - // TODO: should just skip & keep for later dispatch. - throw Exception(QPID_MSG("Unexpected property type: " << type)); - } - } -} - -uint64_t qpid::framing::AMQHeaderBody::getContentLength() const -{ - const MessageProperties* mProps = get(); - if (mProps) - return mProps->getContentLength(); - return 0; -} - -void qpid::framing::AMQHeaderBody::print(std::ostream& out) const -{ - out << "header (" << encodedSize() << " bytes)"; - out << "; properties={"; - properties.print(out); - out << "}"; -} - -void qpid::framing::AMQHeaderBody::accept(AMQBodyConstVisitor& v) const { - v.visit(*this); -} diff --git a/qpid/cpp/src/qpid/framing/AMQHeaderBody.h b/qpid/cpp/src/qpid/framing/AMQHeaderBody.h deleted file mode 100644 index 452154eb5c..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQHeaderBody.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef QPID_FRAMING_AMQHEADERBODY_H -#define QPID_FRAMING_AMQHEADERBODY_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/AMQBody.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/CommonImportExport.h" -#include - -#include - - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN AMQHeaderBody : public AMQBody -{ - template struct OptProps { boost::optional props; }; - template - struct PropSet : public Base, public OptProps { - uint32_t encodedSize() const { - const boost::optional& p=this->OptProps::props; - return (p ? p->encodedSize() : 0) + Base::encodedSize(); - } - void encode(Buffer& buffer) const { - const boost::optional& p=this->OptProps::props; - if (p) p->encode(buffer); - Base::encode(buffer); - } - bool decode(Buffer& buffer, uint32_t size, uint16_t type) { - boost::optional& p=this->OptProps::props; - if (type == T::TYPE) { - p=T(); - p->decodeStructBody(buffer, size); - return true; - } - else - return Base::decode(buffer, size, type); - } - void print(std::ostream& out) const { - const boost::optional& p=this->OptProps::props; - if (p) out << *p; - Base::print(out); - } - }; - - struct Empty { - uint32_t encodedSize() const { return 0; } - void encode(Buffer&) const {}; - bool decode(Buffer&, uint32_t, uint16_t) const { return false; }; - void print(std::ostream&) const {} - }; - - // Could use boost::mpl::fold to construct a larger set. - typedef PropSet, MessageProperties> Properties; - - Properties properties; - -public: - - inline uint8_t type() const { return HEADER_BODY; } - - QPID_COMMON_EXTERN uint32_t encodedSize() const; - QPID_COMMON_EXTERN void encode(Buffer& buffer) const; - QPID_COMMON_EXTERN void decode(Buffer& buffer, uint32_t size); - QPID_COMMON_EXTERN uint64_t getContentLength() const; - QPID_COMMON_EXTERN void print(std::ostream& out) const; - QPID_COMMON_EXTERN void accept(AMQBodyConstVisitor&) const; - - template T* get(bool create) { - boost::optional& p=properties.OptProps::props; - if (create && !p) p=T(); - return p.get_ptr(); - } - - template const T* get() const { - return properties.OptProps::props.get_ptr(); - } - - template void erase() { - properties.OptProps::props.reset(); - } - - boost::intrusive_ptr clone() const { return BodyFactory::copy(*this); } -}; - -}} - - - -#endif /*!QPID_FRAMING_AMQHEADERBODY_H*/ diff --git a/qpid/cpp/src/qpid/framing/AMQHeartbeatBody.cpp b/qpid/cpp/src/qpid/framing/AMQHeartbeatBody.cpp deleted file mode 100644 index 477616221c..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQHeartbeatBody.cpp +++ /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. - * - */ - -#include "qpid/framing/AMQHeartbeatBody.h" -#include - -qpid::framing::AMQHeartbeatBody::~AMQHeartbeatBody() {} - -void qpid::framing::AMQHeartbeatBody::print(std::ostream& out) const { - out << "heartbeat"; -} diff --git a/qpid/cpp/src/qpid/framing/AMQHeartbeatBody.h b/qpid/cpp/src/qpid/framing/AMQHeartbeatBody.h deleted file mode 100644 index 19ac2be013..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQHeartbeatBody.h +++ /dev/null @@ -1,48 +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/framing/amqp_types.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/Buffer.h" -#include "qpid/CommonImportExport.h" - -#ifndef _AMQHeartbeatBody_ -#define _AMQHeartbeatBody_ - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN AMQHeartbeatBody : public AMQBody -{ -public: - QPID_COMMON_EXTERN virtual ~AMQHeartbeatBody(); - inline uint32_t encodedSize() const { return 0; } - inline uint8_t type() const { return HEARTBEAT_BODY; } - inline void encode(Buffer& ) const {} - inline void decode(Buffer& , uint32_t /*size*/) {} - QPID_COMMON_EXTERN virtual void print(std::ostream& out) const; - void accept(AMQBodyConstVisitor& v) const { v.visit(*this); } - boost::intrusive_ptr clone() const { return BodyFactory::copy(*this); } -}; - -} -} - -#endif diff --git a/qpid/cpp/src/qpid/framing/AMQMethodBody.cpp b/qpid/cpp/src/qpid/framing/AMQMethodBody.cpp deleted file mode 100644 index 594af4c6dc..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQMethodBody.cpp +++ /dev/null @@ -1,28 +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/framing/AMQMethodBody.h" - -namespace qpid { -namespace framing { - -AMQMethodBody::~AMQMethodBody() {} - -}} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/AMQMethodBody.h b/qpid/cpp/src/qpid/framing/AMQMethodBody.h deleted file mode 100644 index c634180712..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQMethodBody.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _AMQMethodBody_ -#define _AMQMethodBody_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/AMQBody.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/CommonImportExport.h" - -#include -#include -#include - -namespace qpid { -namespace framing { - -class Buffer; -class AMQP_ServerOperations; -class MethodBodyConstVisitor; - -class AMQMethodBody : public AMQBody { - public: - AMQMethodBody() {} - QPID_COMMON_EXTERN virtual ~AMQMethodBody(); - - virtual void accept(MethodBodyConstVisitor&) const = 0; - - virtual MethodId amqpMethodId() const = 0; - virtual ClassId amqpClassId() const = 0; - virtual bool isContentBearing() const = 0; - virtual bool resultExpected() const = 0; - virtual bool responseExpected() const = 0; - - template bool isA() const { - return amqpClassId()==T::CLASS_ID && amqpMethodId()==T::METHOD_ID; - } - - virtual uint32_t encodedSize() const = 0; - virtual uint8_t type() const { return METHOD_BODY; } - - virtual bool isSync() const { return false; /*only ModelMethods can have the sync flag set*/ } - virtual void setSync(bool) const { /*only ModelMethods can have the sync flag set*/ } - - AMQMethodBody* getMethod() { return this; } - const AMQMethodBody* getMethod() const { return this; } - void accept(AMQBodyConstVisitor& v) const { v.visit(*this); } -}; - - -}} // namespace qpid::framing - - -#endif diff --git a/qpid/cpp/src/qpid/framing/AMQP_HighestVersion.h b/qpid/cpp/src/qpid/framing/AMQP_HighestVersion.h deleted file mode 100644 index 42139c7937..0000000000 --- a/qpid/cpp/src/qpid/framing/AMQP_HighestVersion.h +++ /dev/null @@ -1,40 +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. - * - */ - -/* - * This file used to be auto-generated by Qpid Gentools v.0.1 - * its here temporarily until we get a full solution to multi-version support - */ -#ifndef qpid_framing_highestProtocolVersion__ -#define qpid_framing_highestProtocolVersion__ - -#include "qpid/framing/ProtocolVersion.h" - - -namespace qpid { -namespace framing { - -static ProtocolVersion highestProtocolVersion(0, 10); - -} /* namespace framing */ -} /* namespace qpid */ - -#endif diff --git a/qpid/cpp/src/qpid/framing/AccumulatedAck.cpp b/qpid/cpp/src/qpid/framing/AccumulatedAck.cpp deleted file mode 100644 index 2e6433a82f..0000000000 --- a/qpid/cpp/src/qpid/framing/AccumulatedAck.cpp +++ /dev/null @@ -1,164 +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/framing/AccumulatedAck.h" - -#include -#include -#include - -using std::list; -using std::max; -using std::min; -using namespace qpid::framing; - -AccumulatedAck::AccumulatedAck(SequenceNumber r) : mark(r) {} - -void AccumulatedAck::update(SequenceNumber first, SequenceNumber last){ - assert(first <= last); - if (last < mark) return; - - - Range r(first, last); - bool handled = false; - bool markMerged = false; - list::iterator merged = ranges.end(); - if (r.mergeable(mark)) { - mark = r.end; - markMerged = true; - handled = true; - } else { - for (list::iterator i = ranges.begin(); i != ranges.end() && !handled; i++) { - if (i->merge(r)) { - merged = i; - handled = true; - } else if (r.start < i->start) { - ranges.insert(i, r); - handled = true; - } - } - } - if (!handled) { - ranges.push_back(r); - } else { - while (!ranges.empty() && ranges.front().end <= mark) { - ranges.pop_front(); - } - if (markMerged) { - //new range is incorporated, but may be possible to consolidate - merged = ranges.begin(); - while (merged != ranges.end() && merged->mergeable(mark)) { - mark = merged->end; - merged = ranges.erase(merged); - } - } - if (merged != ranges.end()) { - //consolidate ranges - list::iterator i = merged; - list::iterator j = i++; - while (i != ranges.end() && j->merge(*i)) { - j = i++; - } - } - } -} - -void AccumulatedAck::consolidate(){} - -void AccumulatedAck::clear(){ - mark = SequenceNumber(0);//not sure that this is valid when wraparound is a possibility - ranges.clear(); -} - -bool AccumulatedAck::covers(SequenceNumber tag) const{ - if (tag <= mark) return true; - for (list::const_iterator i = ranges.begin(); i != ranges.end(); i++) { - if (i->contains(tag)) return true; - } - return false; -} - -void AccumulatedAck::collectRanges(SequenceNumberSet& set) const -{ - for (list::const_iterator i = ranges.begin(); i != ranges.end(); i++) { - set.push_back(i->start); - set.push_back(i->end); - } -} - -void AccumulatedAck::update(const SequenceNumber cumulative, const SequenceNumberSet& range) -{ - update(mark, cumulative); - range.processRanges(*this); -} - - -bool Range::contains(SequenceNumber i) const -{ - return i >= start && i <= end; -} - -bool Range::intersect(const Range& r) const -{ - return r.contains(start) || r.contains(end) || contains(r.start) || contains(r.end); -} - -bool Range::merge(const Range& r) -{ - if (intersect(r) || mergeable(r.end) || r.mergeable(end)) { - start = min(start, r.start); - end = max(end, r.end); - return true; - } else { - return false; - } -} - -bool Range::mergeable(const SequenceNumber& s) const -{ - if (contains(s) || start - s == 1) { - return true; - } else { - return false; - } -} - -Range::Range(SequenceNumber s, SequenceNumber e) : start(s), end(e) {} - - -namespace qpid{ -namespace framing{ - std::ostream& operator<<(std::ostream& out, const Range& r) - { - out << "[" << r.start.getValue() << "-" << r.end.getValue() << "]"; - return out; - } - - std::ostream& operator<<(std::ostream& out, const AccumulatedAck& a) - { - out << "{mark: " << a.mark.getValue() << ", ranges: ("; - for (list::const_iterator i = a.ranges.begin(); i != a.ranges.end(); i++) { - if (i != a.ranges.begin()) out << ", "; - out << *i; - } - out << ")]"; - return out; - } -}} diff --git a/qpid/cpp/src/qpid/framing/AccumulatedAck.h b/qpid/cpp/src/qpid/framing/AccumulatedAck.h deleted file mode 100644 index 8e241b4ba1..0000000000 --- a/qpid/cpp/src/qpid/framing/AccumulatedAck.h +++ /dev/null @@ -1,77 +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. - * - */ -#ifndef _AccumulatedAck_ -#define _AccumulatedAck_ - -#include -#include -#include -#include -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceNumberSet.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { - namespace framing { - - struct Range - { - SequenceNumber start; - SequenceNumber end; - - Range(SequenceNumber s, SequenceNumber e); - bool contains(SequenceNumber i) const; - bool intersect(const Range& r) const; - bool merge(const Range& r); - bool mergeable(const SequenceNumber& r) const; - }; - /** - * Keeps an accumulated record of acknowledged messages (by delivery - * tag). - */ - class AccumulatedAck { - public: - /** - * Everything up to this value has been acknowledged. - */ - SequenceNumber mark; - /** - * List of individually acknowledged messages greater than the - * 'mark'. - */ - std::list ranges; - - QPID_COMMON_EXTERN explicit AccumulatedAck(SequenceNumber r = SequenceNumber()); - QPID_COMMON_EXTERN void update(SequenceNumber firstTag, SequenceNumber lastTag); - QPID_COMMON_EXTERN void consolidate(); - QPID_COMMON_EXTERN void clear(); - QPID_COMMON_EXTERN bool covers(SequenceNumber tag) const; - void collectRanges(SequenceNumberSet& set) const; - QPID_COMMON_EXTERN void update(const SequenceNumber cumulative, const SequenceNumberSet& range); - void operator()(SequenceNumber first, SequenceNumber last) { update(first, last); } - }; - QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const Range&); - QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const AccumulatedAck&); - } -} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/Array.cpp b/qpid/cpp/src/qpid/framing/Array.cpp deleted file mode 100644 index 4b4338f931..0000000000 --- a/qpid/cpp/src/qpid/framing/Array.cpp +++ /dev/null @@ -1,137 +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/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" -#include - -namespace qpid { -namespace framing { - -Array::Array() : type(TYPE_CODE_VOID) {} - -Array::Array(TypeCode t) : type(t) {} - -Array::Array(uint8_t t) : type(typeCode(t)) {} - -Array::Array(const std::vector& in) -{ - type = TYPE_CODE_STR16; - for (std::vector::const_iterator i = in.begin(); i != in.end(); ++i) { - ValuePtr value(new Str16Value(*i)); - values.push_back(value); - } -} - -uint32_t Array::encodedSize() const { - //note: size is only included when used as a 'top level' type - uint32_t len(4/*size*/ + 1/*type*/ + 4/*count*/); - for(ValueVector::const_iterator i = values.begin(); i != values.end(); ++i) { - len += (*i)->getData().encodedSize(); - } - return len; -} - -int Array::count() const { - return values.size(); -} - -std::ostream& operator<<(std::ostream& out, const Array& a) { - out << typeName(a.getType()) << "{"; - for(Array::ValueVector::const_iterator i = a.values.begin(); i != a.values.end(); ++i) { - if (i != a.values.begin()) out << ", "; - (*i)->print(out); - } - return out << "}"; -} - -void Array::encode(Buffer& buffer) const{ - buffer.putLong(encodedSize() - 4);//size added only when array is a top-level type - buffer.putOctet(type); - buffer.putLong(count()); - for (ValueVector::const_iterator i = values.begin(); i!=values.end(); ++i) { - (*i)->getData().encode(buffer); - } -} - -void Array::decode(Buffer& buffer){ - values.clear(); - uint32_t size = buffer.getLong();//size added only when array is a top-level type - uint32_t available = buffer.available(); - if (available < size) { - throw IllegalArgumentException(QPID_MSG("Not enough data for array, expected " - << size << " bytes but only " << available << " available")); - } - if (size) { - type = TypeCode(buffer.getOctet()); - uint32_t count = buffer.getLong(); - - FieldValue dummy; - dummy.setType(type); - available = buffer.available(); - uint32_t elementSize = dummy.getData().encodedSize(); - if (available < count * elementSize) { - throw IllegalArgumentException(QPID_MSG("Not enough data for array, expected " - << count << " items of " << elementSize - << " bytes each but only " << available << " bytes available")); - } - // Special check to avoid ridiculously long arrays of zero length elements (they must all be the same - // value, but consume broker resources without consuming any on the wire) - if (elementSize == 0 && count > 256) { - throw IllegalArgumentException(QPID_MSG("Too many zero length elements in array: " << count)); - } - - for (uint32_t i = 0; i < count; i++) { - ValuePtr value(new FieldValue); - value->setType(type); - value->getData().decode(buffer); - values.push_back(ValuePtr(value)); - } - } -} - - -bool Array::operator==(const Array& x) const { - if (type != x.type) return false; - if (values.size() != x.values.size()) return false; - - for (ValueVector::const_iterator i = values.begin(), j = x.values.begin(); i != values.end(); ++i, ++j) { - if (*(i->get()) != *(j->get())) return false; - } - - return true; -} - -void Array::insert(iterator i, ValuePtr value) { - if (type != value->getType()) { - // FIXME aconway 2008-10-31: put meaningful strings in this message. - throw Exception(QPID_MSG("Wrong type of value in Array, expected " << type - << " but found " << TypeCode(value->getType()))); - } - values.insert(i, value); -} - - -} -} diff --git a/qpid/cpp/src/qpid/framing/Array.h b/qpid/cpp/src/qpid/framing/Array.h deleted file mode 100644 index 6254f6271a..0000000000 --- a/qpid/cpp/src/qpid/framing/Array.h +++ /dev/null @@ -1,99 +0,0 @@ -#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 - -#include -#include - -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class Buffer; -class FieldValue; - -class QPID_COMMON_CLASS_EXTERN Array -{ - public: - typedef boost::shared_ptr ValuePtr; - typedef std::vector 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& 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 - static R get(const V& v) { - return v->template get(); - } - - 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/Blob.cpp b/qpid/cpp/src/qpid/framing/Blob.cpp deleted file mode 100644 index 0c8316f3d2..0000000000 --- a/qpid/cpp/src/qpid/framing/Blob.cpp +++ /dev/null @@ -1,31 +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/framing/Blob.h" - - -namespace qpid { -namespace framing { - -void BlobHelper::destroy(void*) {} - -void BlobHelper::copy(void*, const void*) {} - -}} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/Blob.h b/qpid/cpp/src/qpid/framing/Blob.h deleted file mode 100644 index 9878d92fe4..0000000000 --- a/qpid/cpp/src/qpid/framing/Blob.h +++ /dev/null @@ -1,21 +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. - * - */ - diff --git a/qpid/cpp/src/qpid/framing/BodyFactory.h b/qpid/cpp/src/qpid/framing/BodyFactory.h deleted file mode 100644 index 6a8d9b1988..0000000000 --- a/qpid/cpp/src/qpid/framing/BodyFactory.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_FRAMING_BODYFACTORY_H -#define QPID_FRAMING_BODYFACTORY_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 - -namespace qpid { -namespace framing { - -/** - * Indirect creation of body types to allow centralized changes to - * memory management strategy. - */ -class BodyFactory { - public: - template static boost::intrusive_ptr create() { - return new BodyType; - } - - template static boost::intrusive_ptr copy(const BodyType& body) { - return new BodyType(body); - } -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_BODYFACTORY_H*/ diff --git a/qpid/cpp/src/qpid/framing/Buffer.cpp b/qpid/cpp/src/qpid/framing/Buffer.cpp deleted file mode 100644 index 1c4caef046..0000000000 --- a/qpid/cpp/src/qpid/framing/Buffer.cpp +++ /dev/null @@ -1,342 +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/framing/Buffer.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/Msg.h" -#include -#include - -namespace qpid { - -namespace framing { - -using std::string; - -Buffer::Buffer(char* _data, uint32_t _size) - : size(_size), data(_data), position(0) { -} - -void Buffer::reset(){ - position = 0; -} - -/////////////////////////////////////////////////// - -void Buffer::putOctet(uint8_t i){ - checkAvailable(1); - data[position++] = i; -} - -void Buffer::putShort(uint16_t i){ - checkAvailable(2); - uint16_t b = i; - data[position++] = (uint8_t) (0xFF & (b >> 8)); - data[position++] = (uint8_t) (0xFF & b); -} - -void Buffer::putLong(uint32_t i){ - checkAvailable(4); - uint32_t b = i; - data[position++] = (uint8_t) (0xFF & (b >> 24)); - data[position++] = (uint8_t) (0xFF & (b >> 16)); - data[position++] = (uint8_t) (0xFF & (b >> 8)); - data[position++] = (uint8_t) (0xFF & b); -} - -void Buffer::putLongLong(uint64_t i){ - uint32_t hi = i >> 32; - uint32_t lo = i; - putLong(hi); - putLong(lo); -} - -void Buffer::putInt8(int8_t i){ - checkAvailable(1); - data[position++] = (uint8_t) i; -} - -void Buffer::putInt16(int16_t i){ - putShort((uint16_t) i); -} - -void Buffer::putInt32(int32_t i){ - putLong((uint32_t) i); -} - -void Buffer::putInt64(int64_t i){ - putLongLong((uint64_t) i); -} - -void Buffer::putFloat(float f){ - union { - uint32_t i; - float f; - } val; - - val.f = f; - putLong (val.i); -} - -void Buffer::putDouble(double f){ - union { - uint64_t i; - double f; - } val; - - val.f = f; - putLongLong (val.i); -} - -void Buffer::putBin128(const uint8_t* b){ - checkAvailable(16); - memcpy (data + position, b, 16); - position += 16; -} - -uint8_t Buffer::getOctet(){ - checkAvailable(1); - uint8_t octet = static_cast(data[position++]); - return octet; -} - -uint16_t Buffer::getShort(){ - checkAvailable(2); - uint16_t hi = (unsigned char) data[position++]; - hi = hi << 8; - hi |= (unsigned char) data[position++]; - return hi; -} - -uint32_t Buffer::getLong(){ - checkAvailable(4); - uint32_t a = (unsigned char) data[position++]; - uint32_t b = (unsigned char) data[position++]; - uint32_t c = (unsigned char) data[position++]; - uint32_t d = (unsigned char) data[position++]; - a = a << 24; - a |= b << 16; - a |= c << 8; - a |= d; - return a; -} - -uint64_t Buffer::getLongLong(){ - uint64_t hi = getLong(); - uint64_t lo = getLong(); - hi = hi << 32; - return hi | lo; -} - -int8_t Buffer::getInt8(){ - checkAvailable(1); - int8_t i = static_cast(data[position++]); - return i; -} - -int16_t Buffer::getInt16(){ - return (int16_t) getShort(); -} - -int32_t Buffer::getInt32(){ - return (int32_t) getLong(); -} - -int64_t Buffer::getInt64(){ - return (int64_t) getLongLong(); -} - -float Buffer::getFloat(){ - union { - uint32_t i; - float f; - } val; - val.i = getLong(); - return val.f; -} - -double Buffer::getDouble(){ - union { - uint64_t i; - double f; - } val; - val.i = getLongLong(); - return val.f; -} - -template <> -QPID_COMMON_EXTERN uint64_t Buffer::getUInt<1>() { - return getOctet(); -} - -template <> -QPID_COMMON_EXTERN uint64_t Buffer::getUInt<2>() { - return getShort(); -} - -template <> -QPID_COMMON_EXTERN uint64_t Buffer::getUInt<4>() { - return getLong(); -} - -template <> -QPID_COMMON_EXTERN uint64_t Buffer::getUInt<8>() { - return getLongLong(); -} - -template <> -QPID_COMMON_EXTERN void Buffer::putUInt<1>(uint64_t i) { - if (std::numeric_limits::min() <= i && i <= std::numeric_limits::max()) { - putOctet(i); - return; - } - throw Exception(QPID_MSG("Could not encode (" << i << ") as uint8_t.")); -} - -template <> -QPID_COMMON_EXTERN void Buffer::putUInt<2>(uint64_t i) { - if (std::numeric_limits::min() <= i && i <= std::numeric_limits::max()) { - putShort(i); - return; - } - throw Exception(QPID_MSG("Could not encode (" << i << ") as uint16_t.")); -} - -template <> -QPID_COMMON_EXTERN void Buffer::putUInt<4>(uint64_t i) { - if (std::numeric_limits::min() <= i && i <= std::numeric_limits::max()) { - putLong(i); - return; - } - throw Exception(QPID_MSG("Could not encode (" << i << ") as uint32_t.")); -} - -template <> -QPID_COMMON_EXTERN void Buffer::putUInt<8>(uint64_t i) { - putLongLong(i); -} - -void Buffer::putShortString(const string& s){ - size_t slen = s.length(); - if (slen <= std::numeric_limits::max()) { - uint8_t len = (uint8_t) slen; - putOctet(len); - checkAvailable(slen); - s.copy(data + position, len); - position += len; - return; - } - throw Exception(QPID_MSG("Could not encode string of " << slen << " bytes as uint8_t string.")); -} - -void Buffer::putMediumString(const string& s){ - size_t slen = s.length(); - if (slen <= std::numeric_limits::max()) { - uint16_t len = (uint16_t) slen; - putShort(len); - checkAvailable(slen); - s.copy(data + position, len); - position += len; - return; - } - throw Exception(QPID_MSG("Could not encode string of " << slen << " bytes as uint16_t string.")); -} - -void Buffer::putLongString(const string& s){ - size_t slen = s.length(); - if (slen <= std::numeric_limits::max()) { - uint32_t len = (uint32_t) slen; - putLong(len); - checkAvailable(slen); - s.copy(data + position, len); - position += len; - return; - } - throw Exception(QPID_MSG("Could not encode string of " << slen << " bytes as uint32_t string.")); -} - -void Buffer::getShortString(string& s){ - uint8_t len = getOctet(); - checkAvailable(len); - s.assign(data + position, len); - position += len; -} - -void Buffer::getMediumString(string& s){ - uint16_t len = getShort(); - checkAvailable(len); - s.assign(data + position, len); - position += len; -} - -void Buffer::getLongString(string& s){ - uint32_t len = getLong(); - checkAvailable(len); - s.assign(data + position, len); - position += len; -} - -void Buffer::getBin128(uint8_t* b){ - checkAvailable(16); - memcpy (b, data + position, 16); - position += 16; -} - -void Buffer::putRawData(const string& s){ - size_t len = s.length(); - checkAvailable(len); - s.copy(data + position, len); - position += len; -} - -void Buffer::getRawData(string& s, uint32_t len){ - checkAvailable(len); - s.assign(data + position, len); - position += len; -} - -void Buffer::putRawData(const uint8_t* s, size_t len){ - checkAvailable(len); - memcpy(data + position, s, len); - position += len; -} - -void Buffer::getRawData(uint8_t* s, size_t len){ - checkAvailable(len); - memcpy(s, data + position, len); - position += len; -} - -void Buffer::dump(std::ostream& out) const { - for (uint32_t i = position; i < size; i++) - { - if (i != position) - out << " "; - out << boost::format("%02x") % ((unsigned) (uint8_t) data[i]); - } -} - -std::ostream& operator<<(std::ostream& out, const Buffer& b){ - out << "Buffer["; - b.dump(out); - return out << "]"; -} - -}} diff --git a/qpid/cpp/src/qpid/framing/Buffer.h b/qpid/cpp/src/qpid/framing/Buffer.h deleted file mode 100644 index 166b524e3c..0000000000 --- a/qpid/cpp/src/qpid/framing/Buffer.h +++ /dev/null @@ -1,115 +0,0 @@ -#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 - -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 - QPID_COMMON_EXTERN uint64_t getUInt(); - - template - 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 void put(const T& data) { data.encode(*this); } - template 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/BufferTypes.h b/qpid/cpp/src/qpid/framing/BufferTypes.h deleted file mode 100644 index 4199755852..0000000000 --- a/qpid/cpp/src/qpid/framing/BufferTypes.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef QPID_FRAMING_BUFFERTYPES_H -#define QPID_FRAMING_BUFFERTYPES_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 - * Using templates with framing::Buffer is difficultg becase of the many - * different put/get function names. Here we define a set of types - * corresponding the basic types of Buffer but presenting a uniform - * encode/decode/encodedSize interface. - * - * It also provides some convenience templates for the common case of - * encoding a single encodable value as a string, e.g. - * - * LongString ls("hello"); - * std::string encoded = encodeStr(ls); - * LongString ls2 = decodeStr(encoded); - * LongString ls3; - * decodeStr(encoded, ls3); - */ - -namespace qpid { -namespace framing { - -// Templates to help define types -template struct BufferTypeTraits { - typedef void (Buffer::*Put)(const ValueType&); - typedef void (Buffer::*Get)(ValueType&); -}; - -template ::Put PutFn, - typename BufferTypeTraits::Get GetFn> -struct EncodeDecodeTemplate { - EncodeDecodeTemplate(const ValueType& s) : value(s) {} - operator ValueType() const { return value; } - - ValueType value; - void encode(framing::Buffer& buf) const { (buf.*PutFn)(value); } - void decode(framing::Buffer& buf) { (buf.*GetFn)(value); } -}; - -template ::Put PutFn, - typename BufferTypeTraits::Get GetFn - > -struct StringTypeTemplate : public EncodeDecodeTemplate { - typedef EncodeDecodeTemplate Base; - StringTypeTemplate(const std::string& s) : Base(s) {} - size_t encodedSize() const { return Size + Base::value.size(); } -}; - - -// Convenience tempates for encoding/decoding values to/from a std::string. - -/** Encode value as a string. */ -template 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 void decodeStr(const std::string& encoded, T& value) { - framing::Buffer b(const_cast(&encoded[0]), encoded.size()); - value.decode(b); -} - -/** Decode value from a string. */ -template T decodeStr(const std::string& encoded) { - T value; - decodeStr(encoded, value); - return value; -} - -// The types - -typedef StringTypeTemplate<4, &Buffer::putLongString, &Buffer::getLongString> LongString; -typedef StringTypeTemplate<2, &Buffer::putMediumString, &Buffer::getMediumString> MediumString; -typedef StringTypeTemplate<1, &Buffer::putShortString, &Buffer::getShortString> ShortString; - -// TODO aconway 2013-07-26: Add integer types. - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_BUFFERTYPES_H*/ diff --git a/qpid/cpp/src/qpid/framing/ChannelHandler.h b/qpid/cpp/src/qpid/framing/ChannelHandler.h deleted file mode 100644 index ddab204578..0000000000 --- a/qpid/cpp/src/qpid/framing/ChannelHandler.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef QPID_FRAMING_CHANNELHANDLER_H -#define QPID_FRAMING_CHANNELHANDLER_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/FrameHandler.h" -#include "qpid/framing/AMQFrame.h" - -namespace qpid { -namespace framing { - -/** - * Sets the channel number on outgoing frames. - */ -class ChannelHandler : public FrameHandler -{ - public: - ChannelHandler(uint16_t channelId=0, FrameHandler* next=0) - : FrameHandler(next), channel(channelId) {} - void handle(AMQFrame& frame) { - frame.setChannel(channel); - next->handle(frame); - } - uint16_t get() const { return channel; } - ChannelHandler& set(uint16_t ch) { channel=ch; return *this; } - operator uint16_t() const { return get(); } - ChannelHandler& operator=(uint16_t ch) { return set(ch); } - - private: - uint16_t channel; -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_CHANNELHANDLER_H*/ diff --git a/qpid/cpp/src/qpid/framing/Endian.h b/qpid/cpp/src/qpid/framing/Endian.h deleted file mode 100644 index faf553fed5..0000000000 --- a/qpid/cpp/src/qpid/framing/Endian.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_FRAMING_ENDIAN_H -#define QPID_FRAMING_ENDIAN_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 framing { -namespace endian { - -/** Decode integer from network byte order buffer to type T, buffer must be at least sizeof(T). */ -template T decodeInt(const uint8_t* buffer) { - T v = buffer[0]; - for (size_t i = 1; i < sizeof(T); ++i) { - v <<= 8; - v |= buffer[i]; - } - return v; -} - -/** Encode integer value to network byte order in buffer, buffer must be at least sizeof(T). */ -template void encodeInt(uint8_t* buffer, T value) { - for (size_t i = sizeof(T); i > 0; --i) { - buffer[i-1] = value & 0XFF; - value >>= 8; - } -} - -// Compute the int type that can hold a float type. -template struct IntBox { typedef T Type; }; -template <> struct IntBox { typedef uint32_t Type; }; -template <> struct IntBox { typedef uint64_t Type; }; - -/** Decode floating from network byte order buffer to type T, buffer must be at least sizeof(T). */ -template T decodeFloat(const uint8_t* buffer) { - typedef typename IntBox::Type Box; - union { T f; Box i; } u; - u.i = decodeInt(buffer); - return u.f; -} - -/** Encode floating value to network byte order in buffer, buffer must be at least sizeof(T). */ -template void encodeFloat(uint8_t* buffer, T value) { - typedef typename IntBox::Type Box; - union { T f; Box i; } u; - u.f = value; - encodeInt(buffer, u.i); -} - -}}} // namespace qpid::framing::endian - -#endif /*!QPID_FRAMING_ENDIAN_H*/ - - - - - - diff --git a/qpid/cpp/src/qpid/framing/FieldTable.cpp b/qpid/cpp/src/qpid/framing/FieldTable.cpp deleted file mode 100644 index 0b677a6ccb..0000000000 --- a/qpid/cpp/src/qpid/framing/FieldTable.cpp +++ /dev/null @@ -1,433 +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/framing/FieldTable.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" -#include - -// The locking rationale in the FieldTable seems a little odd, but it -// maintains the concurrent guarantees and requirements that were in -// place before the cachedBytes/cachedSize were added: -// -// The FieldTable client code needs to make sure that they call no write -// operation in parallel with any other operation on the FieldTable. -// However multiple parallel read operations are safe. -// -// To this end the only code that is locked is code that can transparently -// change the state of the FieldTable during a read only operation. -// (In other words the code that required the mutable members in the class -// definition!) -// -namespace qpid { - -using sys::Mutex; -using sys::ScopedLock; - -namespace framing { - -FieldTable::FieldTable() : - cachedSize(0), - newBytes(false) -{ -} - -FieldTable::FieldTable(const FieldTable& ft) -{ - ScopedLock l(ft.lock); // lock _source_ FieldTable - - cachedBytes = ft.cachedBytes; - cachedSize = ft.cachedSize; - newBytes = ft.newBytes; - - // Only copy the values if we have no raw data - // - copying the map is expensive and we can - // reconstruct it if necessary from the raw data - if (cachedBytes) { - newBytes = true; - return; - } - // In practice Encoding the source field table and only copying - // the encoded bytes is faster than copying the whole value map. - // (Because we nearly always copy a field table internally before - // encoding it to send, but don't change it after the copy) - if (!ft.values.empty()) { - // Side effect of getting encoded size will cache it in ft.cachedSize - ft.cachedBytes = boost::shared_array(new uint8_t[ft.encodedSize()]); - - Buffer buffer((char*)&ft.cachedBytes[0], ft.cachedSize); - - // Cut and paste ahead... - buffer.putLong(ft.encodedSize() - 4); - buffer.putLong(ft.values.size()); - for (ValueMap::const_iterator i = ft.values.begin(); i!=ft.values.end(); ++i) { - buffer.putShortString(i->first); - i->second->encode(buffer); - } - - cachedBytes = ft.cachedBytes; - cachedSize = ft.cachedSize; - newBytes = true; - } -} - -FieldTable& FieldTable::operator=(const FieldTable& ft) -{ - FieldTable nft(ft); - values.swap(nft.values); - cachedBytes.swap(nft.cachedBytes); - cachedSize = nft.cachedSize; - newBytes = nft.newBytes; - return (*this); -} - -uint32_t FieldTable::encodedSize() const { - ScopedLock l(lock); - - if (cachedSize != 0) { - return cachedSize; - } - uint32_t len(4/*size field*/ + 4/*count field*/); - for(ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { - // shortstr_len_byte + key size + value size - len += 1 + (i->first).size() + (i->second)->encodedSize(); - } - cachedSize = len; - return len; -} - -int FieldTable::count() const { - return values.size(); -} - -namespace -{ -std::ostream& operator<<(std::ostream& out, const FieldTable::ValueMap::value_type& i) { - return out << i.first << ":" << *i.second; -} -} - -std::ostream& operator<<(std::ostream& out, const FieldTable& t) { - t.realDecode(); - out << "{"; - FieldTable::ValueMap::const_iterator i = t.begin(); - if (i != t.end()) out << *i++; - while (i != t.end()) - { - out << "," << *i++; - } - return out << "}"; -} - -void FieldTable::set(const std::string& name, const ValuePtr& value){ - realDecode(); - values[name] = value; - flushRawCache(); -} - -void FieldTable::setString(const std::string& name, const std::string& value){ - realDecode(); - values[name] = ValuePtr(new Str16Value(value)); - flushRawCache(); -} - -void FieldTable::setInt(const std::string& name, const int value){ - realDecode(); - values[name] = ValuePtr(new IntegerValue(value)); - flushRawCache(); -} - -void FieldTable::setInt64(const std::string& name, const int64_t value){ - realDecode(); - values[name] = ValuePtr(new Integer64Value(value)); - flushRawCache(); -} - -void FieldTable::setTimestamp(const std::string& name, const uint64_t value){ - realDecode(); - values[name] = ValuePtr(new TimeValue(value)); - flushRawCache(); -} - -void FieldTable::setUInt64(const std::string& name, const uint64_t value){ - realDecode(); - values[name] = ValuePtr(new Unsigned64Value(value)); - flushRawCache(); -} - -void FieldTable::setTable(const std::string& name, const FieldTable& value) -{ - realDecode(); - values[name] = ValuePtr(new FieldTableValue(value)); - flushRawCache(); -} -void FieldTable::setArray(const std::string& name, const Array& value) -{ - realDecode(); - values[name] = ValuePtr(new ArrayValue(value)); - flushRawCache(); -} - -void FieldTable::setFloat(const std::string& name, const float value){ - realDecode(); - values[name] = ValuePtr(new FloatValue(value)); - flushRawCache(); -} - -void FieldTable::setDouble(const std::string& name, const double value){ - realDecode(); - values[name] = ValuePtr(new DoubleValue(value)); - flushRawCache(); -} - -FieldTable::ValuePtr FieldTable::get(const std::string& name) const -{ - // Ensure we have any values we're trying to read - realDecode(); - ValuePtr value; - ValueMap::const_iterator i = values.find(name); - if ( i!=values.end() ) - value = i->second; - return value; -} - -namespace { - template T default_value() { return T(); } - template <> int default_value() { return 0; } - //template <> uint64_t default_value() { return 0; } -} - -template -T getValue(const FieldTable::ValuePtr value) -{ - if (!value || !value->convertsTo()) - return default_value(); - - return value->get(); -} - -std::string FieldTable::getAsString(const std::string& name) const { - return getValue(get(name)); -} - -int FieldTable::getAsInt(const std::string& name) const { - return getValue(get(name)); -} - -uint64_t FieldTable::getAsUInt64(const std::string& name) const { - return static_cast( getValue(get(name))); -} - -int64_t FieldTable::getAsInt64(const std::string& name) const { - return getValue(get(name)); -} - -bool FieldTable::getTable(const std::string& name, FieldTable& value) const { - return getEncodedValue(get(name), value); -} - -bool FieldTable::getArray(const std::string& name, Array& value) const { - return getEncodedValue(get(name), value); -} - -template -bool getRawFixedWidthValue(FieldTable::ValuePtr vptr, T& value) -{ - if (vptr && vptr->getType() == typecode) { - value = vptr->get(); - return true; - } - return false; -} - -bool FieldTable::getFloat(const std::string& name, float& value) const { - return getRawFixedWidthValue(get(name), value); -} - -bool FieldTable::getDouble(const std::string& name, double& value) const { - return getRawFixedWidthValue(get(name), value); -} - -//uint64_t FieldTable::getTimestamp(const std::string& name) const { -// return getValue(name); -//} - -void FieldTable::encode(Buffer& buffer) const { - // If we've still got the input field table - // we can just copy it directly to the output - if (cachedBytes) { - ScopedLock l(lock); - buffer.putRawData(&cachedBytes[0], cachedSize); - } else { - buffer.putLong(encodedSize() - 4); - buffer.putLong(values.size()); - for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) { - buffer.putShortString(i->first); - i->second->encode(buffer); - } - } -} - -// Decode lazily - just record the raw bytes until we need them -void FieldTable::decode(Buffer& buffer){ - if (buffer.available() < 4) - throw IllegalArgumentException(QPID_MSG("Not enough data for field table.")); - uint32_t p = buffer.getPosition(); - uint32_t len = buffer.getLong(); - if (len) { - uint32_t available = buffer.available(); - if ((available < len) || (available < 4)) - throw IllegalArgumentException(QPID_MSG("Not enough data for field table.")); - } - ScopedLock l(lock); - // Throw away previous stored values - values.clear(); - // Copy data into our buffer - cachedBytes = boost::shared_array(new uint8_t[len + 4]); - cachedSize = len + 4; - newBytes = true; - buffer.setPosition(p); - buffer.getRawData(&cachedBytes[0], cachedSize); -} - -void FieldTable::realDecode() const -{ - ScopedLock l(lock); - - // If we've got no raw data stored up then nothing to do - if (!newBytes) - return; - - Buffer buffer((char*)&cachedBytes[0], cachedSize); - uint32_t len = buffer.getLong(); - if (len) { - uint32_t available = buffer.available(); - uint32_t count = buffer.getLong(); - uint32_t leftover = available - len; - while(buffer.available() > leftover && count--){ - std::string name; - ValuePtr value(new FieldValue); - - buffer.getShortString(name); - value->decode(buffer); - values[name] = ValuePtr(value); - } - } - newBytes = false; -} - -void FieldTable::flushRawCache() -{ - ScopedLock l(lock); - // We can only flush the cache if there are no cached bytes to decode - assert(newBytes==false); - // Avoid recreating shared array unless we actually have one. - if (cachedBytes) cachedBytes.reset(); - cachedSize = 0; -} - -bool FieldTable::operator==(const FieldTable& x) const { - realDecode(); - x.realDecode(); - if (values.size() != x.values.size()) return false; - for (ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { - ValueMap::const_iterator j = x.values.find(i->first); - if (j == x.values.end()) return false; - if (*(i->second) != *(j->second)) return false; - } - return true; -} - -void FieldTable::erase(const std::string& name) -{ - realDecode(); - if (values.find(name) != values.end()) { - values.erase(name); - flushRawCache(); - } -} - -void FieldTable::clear() -{ - values.clear(); - newBytes = false; - flushRawCache(); -} - -// Map-like interface. -FieldTable::ValueMap::const_iterator FieldTable::begin() const -{ - realDecode(); - return values.begin(); -} - -FieldTable::ValueMap::const_iterator FieldTable::end() const -{ - realDecode(); - return values.end(); -} - -FieldTable::ValueMap::const_iterator FieldTable::find(const std::string& s) const -{ - realDecode(); - return values.find(s); -} - -FieldTable::ValueMap::iterator FieldTable::begin() -{ - realDecode(); - flushRawCache(); - return values.begin(); -} - -FieldTable::ValueMap::iterator FieldTable::end() -{ - realDecode(); - flushRawCache(); - return values.end(); -} - -FieldTable::ValueMap::iterator FieldTable::find(const std::string& s) -{ - realDecode(); - flushRawCache(); - return values.find(s); -} - -std::pair FieldTable::insert(const ValueMap::value_type& value) -{ - realDecode(); - flushRawCache(); - return values.insert(value); -} - -FieldTable::ValueMap::iterator FieldTable::insert(ValueMap::iterator position, const ValueMap::value_type& value) -{ - realDecode(); - flushRawCache(); - return values.insert(position, value); -} - -} -} diff --git a/qpid/cpp/src/qpid/framing/FieldTable.h b/qpid/cpp/src/qpid/framing/FieldTable.h deleted file mode 100644 index 1986a72d10..0000000000 --- a/qpid/cpp/src/qpid/framing/FieldTable.h +++ /dev/null @@ -1,139 +0,0 @@ -#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 -#include - -#include -#include - -#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 ValuePtr; - typedef std::map 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 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 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.cpp b/qpid/cpp/src/qpid/framing/FieldValue.cpp deleted file mode 100644 index 227c12e44e..0000000000 --- a/qpid/cpp/src/qpid/framing/FieldValue.cpp +++ /dev/null @@ -1,267 +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/framing/FieldValue.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/List.h" -#include "qpid/framing/Uuid.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Endian.h" -#include "qpid/Msg.h" - -namespace qpid { -namespace framing { - -// Some template magic for computing types from sizes. -template struct IntType{}; -template<> struct IntType<1> { typedef int8_t Type; }; -template<> struct IntType<2> { typedef int16_t Type; }; -template<> struct IntType<4> { typedef int32_t Type; }; -template<> struct IntType<8> { typedef int64_t Type; }; - -template struct UintType{}; -template<> struct UintType<1> { typedef uint8_t Type; }; -template<> struct UintType<2> { typedef uint16_t Type; }; -template<> struct UintType<4> { typedef uint32_t Type; }; -template<> struct UintType<8> { typedef uint64_t Type; }; - -template struct FloatType{}; -template<> struct FloatType<1> { typedef int8_t Type; }; // Dummy, never used. -template<> struct FloatType<2> { typedef int16_t Type; }; // Dummy, never used. -template<> struct FloatType<4> { typedef float Type; }; -template<> struct FloatType<8> { typedef double Type; }; - -// Construct the right subclass of FixedWidthValue for numeric types using width and kind. -// Kind 1=int, 2=unsigned int, 3=float -template FixedWidthValue* numericFixedWidthValue(uint8_t kind) { - switch (kind) { - case 1: return new FixedWidthIntValue::Type>(); - case 2: return new FixedWidthIntValue::Type>(); - case 3: return new FixedWidthFloatValue::Type>(); - default: return new FixedWidthValue(); - } -} - -uint8_t FieldValue::getType() const -{ - return typeOctet; -} - -void FieldValue::setType(uint8_t type) -{ - typeOctet = type; - if (typeOctet == 0xA8) { - data.reset(new EncodedValue()); - } else if (typeOctet == 0xA9) { - data.reset(new EncodedValue()); - } else if (typeOctet == 0xAA) { - data.reset(new EncodedValue()); - } else if (typeOctet == 0x48) { - data.reset(new UuidData()); - } else { - uint8_t kind = typeOctet & 0xF; - uint8_t lenType = typeOctet >> 4; - switch(lenType){ - case 0: - data.reset(numericFixedWidthValue<1>(kind)); - break; - case 1: - data.reset(numericFixedWidthValue<2>(kind)); - break; - case 2: - data.reset(numericFixedWidthValue<4>(kind)); - break; - case 3: - data.reset(numericFixedWidthValue<8>(kind)); - break; - // None of the remaining widths can be numeric types so just use new FixedWidthValue - case 4: - data.reset(new FixedWidthValue<16>()); - break; - case 5: - data.reset(new FixedWidthValue<32>()); - break; - case 6: - data.reset(new FixedWidthValue<64>()); - break; - case 7: - data.reset(new FixedWidthValue<128>()); - break; - case 8: - data.reset(new VariableWidthValue<1>()); - break; - case 9: - data.reset(new VariableWidthValue<2>()); - break; - case 0xA: - data.reset(new VariableWidthValue<4>()); - break; - case 0xC: - data.reset(new FixedWidthValue<5>()); - break; - case 0xD: - data.reset(new FixedWidthValue<9>()); - break; - case 0xF: - data.reset(new FixedWidthValue<0>()); - break; - default: - throw IllegalArgumentException(QPID_MSG("Unknown field table value type: " << (int)typeOctet)); - } - } -} - -void FieldValue::decode(Buffer& buffer) -{ - setType(buffer.getOctet()); - data->decode(buffer); -} - -void FieldValue::encode(Buffer& buffer) -{ - buffer.putOctet(typeOctet); - data->encode(buffer); -} - -bool FieldValue::operator==(const FieldValue& v) const -{ - return - typeOctet == v.typeOctet && - *data == *v.data; -} - -Str8Value::Str8Value(const std::string& v) : - FieldValue( - TYPE_CODE_STR8, - new VariableWidthValue<1>( - reinterpret_cast(v.data()), - reinterpret_cast(v.data()+v.size()))) -{ -} - -Str16Value::Str16Value(const std::string& v) : - FieldValue( - 0x95, - new VariableWidthValue<2>( - reinterpret_cast(v.data()), - reinterpret_cast(v.data()+v.size()))) -{} - -Var16Value::Var16Value(const std::string& v, uint8_t code) : - FieldValue( - code, - new VariableWidthValue<2>( - reinterpret_cast(v.data()), - reinterpret_cast(v.data()+v.size()))) -{} -Var32Value::Var32Value(const std::string& v, uint8_t code) : - FieldValue( - code, - new VariableWidthValue<4>( - reinterpret_cast(v.data()), - reinterpret_cast(v.data()+v.size()))) -{} - -Struct32Value::Struct32Value(const std::string& v) : - FieldValue( - 0xAB, - new VariableWidthValue<4>( - reinterpret_cast(v.data()), - reinterpret_cast(v.data()+v.size()))) -{} - -IntegerValue::IntegerValue(int v) : - FieldValue(0x21, new FixedWidthIntValue(v)) -{} - -FloatValue::FloatValue(float v) : - FieldValue(0x23, new FixedWidthFloatValue(v)) -{} - -DoubleValue::DoubleValue(double v) : - FieldValue(0x33, new FixedWidthFloatValue(v)) -{} - -Integer64Value::Integer64Value(int64_t v) : - FieldValue(0x31, new FixedWidthIntValue(v)) -{} - -Unsigned64Value::Unsigned64Value(uint64_t v) : - FieldValue(0x32, new FixedWidthIntValue(v)) -{} - - -TimeValue::TimeValue(uint64_t v) : - FieldValue(0x38, new FixedWidthIntValue(v)) -{ -} - -FieldTableValue::FieldTableValue(const FieldTable& f) : FieldValue(0xa8, new EncodedValue(f)) -{ -} - -ListValue::ListValue(const List& l) : FieldValue(0xa9, new EncodedValue(l)) -{ -} - -ArrayValue::ArrayValue(const Array& a) : FieldValue(0xaa, new EncodedValue(a)) -{ -} - -VoidValue::VoidValue() : FieldValue(0xf0, new FixedWidthValue<0>()) {} - -BoolValue::BoolValue(bool b) : - FieldValue(0x08, new FixedWidthIntValue(b)) -{} - -Unsigned8Value::Unsigned8Value(uint8_t v) : - FieldValue(0x02, new FixedWidthIntValue(v)) -{} -Unsigned16Value::Unsigned16Value(uint16_t v) : - FieldValue(0x12, new FixedWidthIntValue(v)) -{} -Unsigned32Value::Unsigned32Value(uint32_t v) : - FieldValue(0x22, new FixedWidthIntValue(v)) -{} - -Integer8Value::Integer8Value(int8_t v) : - FieldValue(0x01, new FixedWidthIntValue(v)) -{} -Integer16Value::Integer16Value(int16_t v) : - FieldValue(0x11, new FixedWidthIntValue(v)) -{} - -UuidData::UuidData() {} -UuidData::UuidData(const unsigned char* bytes) : FixedWidthValue<16>(bytes) {} -bool UuidData::convertsToString() const { return true; } -std::string UuidData::getString() const { return Uuid(rawOctets()).str(); } -UuidValue::UuidValue(const unsigned char* v) : FieldValue(0x48, new UuidData(v)) {} - -void FieldValue::print(std::ostream& out) const { - data->print(out); - out << TypeCode(typeOctet) << '('; - if (data->convertsToString()) out << data->getString(); - else if (data->convertsToInt()) out << data->getInt(); - else data->print(out); - out << ')'; -} - -}} diff --git a/qpid/cpp/src/qpid/framing/FieldValue.h b/qpid/cpp/src/qpid/framing/FieldValue.h deleted file mode 100644 index e20244e7c9..0000000000 --- a/qpid/cpp/src/qpid/framing/FieldValue.h +++ /dev/null @@ -1,482 +0,0 @@ -#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/framing/Endian.h" -#include "qpid/CommonImportExport.h" - -#include -#include -#include - -#include - -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 convertsToFloat() const { return false; } - virtual bool convertsToString() const { return false; } - virtual int64_t getInt() const { throw InvalidConversionException();} - virtual double getFloat() 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 bool convertsTo() const { return false; } - template T get() const { throw InvalidConversionException(); } - - template T getIntegerValue() const; - template T getIntegerValue() const; - template T getFloatingPointValue() const; - template void getFixedWidthValue(unsigned char*) const; - template bool get(T&) const; - - protected: - FieldValue(uint8_t t, Data* d): typeOctet(t), data(d) {} - - private: - uint8_t typeOctet; - std::auto_ptr data; -}; - -template <> -inline bool FieldValue::convertsTo() const { return data->convertsToInt(); } - -template <> -inline bool FieldValue::convertsTo() const { return data->convertsToInt(); } - -template <> -inline bool FieldValue::convertsTo() const { return data->convertsToString(); } - -template <> -inline bool FieldValue::convertsTo() const { return data->convertsToFloat(); } - -template <> -inline bool FieldValue::convertsTo() const { return data->convertsToFloat(); } - -template <> -inline int FieldValue::get() const { return static_cast(data->getInt()); } - -template <> -inline int64_t FieldValue::get() const { return data->getInt(); } - -template <> -inline float FieldValue::get() const { return data->getFloat(); } - -template <> -inline double FieldValue::get() const { return data->getFloat(); } - -template <> -inline std::string FieldValue::get() const { return data->getString(); } - -inline std::ostream& operator<<(std::ostream& out, const FieldValue& v) { - v.print(out); - return out; -} - -template -class FixedWidthValue : public FieldValue::Data { - protected: - uint8_t octets[width]; - - public: - FixedWidthValue() {} - FixedWidthValue(const uint8_t (&data)[width]) : octets(data) {} - FixedWidthValue(const uint8_t* const data) { std::copy(data, data + width, octets); } - - 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* rhs = dynamic_cast< const FixedWidthValue* >(&d); - if (rhs == 0) return false; - else return std::equal(&octets[0], &octets[width], &rhs->octets[0]); - } - uint8_t* rawOctets() { return octets; } - const uint8_t* rawOctets() const { return octets; } - - void print(std::ostream& o) const { o << "F" << width << ":"; }; -}; - -template class FixedWidthIntValue : public FixedWidthValue { - public: - FixedWidthIntValue(T v = 0) { endian::encodeInt(this->octets, v); } - bool convertsToInt() const { return true; } - int64_t getInt() const { return endian::decodeInt(this->octets); } - bool convertsToFloat() const { return true; } - double getFloat() const { return getInt(); } -}; - -template class FixedWidthFloatValue : public FixedWidthValue { - public: - FixedWidthFloatValue(T v = 0) { endian::encodeFloat(this->octets, v); } - bool convertsToFloat() const { return true; } - double getFloat() const { return endian::decodeFloat(this->octets); } -}; - -// Dummy implementations that are never used but needed to avoid compile errors. -template <> class FixedWidthFloatValue : public FixedWidthValue<1> { - FixedWidthFloatValue() { assert(0); } -}; -template <> class FixedWidthFloatValue : public FixedWidthValue<2> { - FixedWidthFloatValue() { assert(0); } -}; - - -class UuidData : public FixedWidthValue<16> { - public: - UuidData(); - UuidData(const unsigned char* bytes); - bool convertsToString() const; - std::string getString() const; -}; - -template -inline T FieldValue::getIntegerValue() const -{ - FixedWidthValue* const fwv = dynamic_cast< FixedWidthValue* const>(data.get()); - if (fwv) { - return endian::decodeInt(fwv->rawOctets()); - } else { - throw InvalidConversionException(); - } -} - -template -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 -inline T FieldValue::getFloatingPointValue() const { - const FixedWidthFloatValue* fv = dynamic_cast*>(data.get()); - if (fv) { - return endian::decodeFloat(fv->rawOctets()); - } else { - throw InvalidConversionException(); - } -} - -template void FieldValue::getFixedWidthValue(unsigned char* value) const -{ - FixedWidthValue* const fwv = dynamic_cast< FixedWidthValue* const>(data.get()); - if (fwv) { - std::copy(fwv->rawOctets(), fwv->rawOctets() + W, value); - } else { - throw InvalidConversionException(); - } -} - -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 -class VariableWidthValue : public FieldValue::Data { - std::vector octets; - - public: - VariableWidthValue() {} - VariableWidthValue(const std::vector& 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(octets.size()); - if (octets.size() > 0) - buffer.putRawData(&octets[0], octets.size()); - }; - void decode(Buffer& buffer) { - uint32_t len = buffer.getUInt(); - buffer.checkAvailable(len); - octets.resize(len); - if (len > 0) - buffer.getRawData(&octets[0], len); - } - bool operator==(const Data& d) const { - const VariableWidthValue* rhs = dynamic_cast< const VariableWidthValue* >(&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 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* rhs = dynamic_cast< const EncodedValue* >(&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 -inline bool FieldValue::get(T& t) const -{ - const EncodedValue* v = dynamic_cast< EncodedValue* >(data.get()); - if (v != 0) { - t = v->getValue(); - return true; - } else { - try { - t = get(); - 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 -bool getEncodedValue(FieldTable::ValuePtr vptr, T& value) -{ - if (vptr) { - const EncodedValue* ev = dynamic_cast< EncodedValue* >(&(vptr->getData())); - if (ev != 0) { - value = ev->getValue(); - return true; - } - } - return false; -} - -}} // qpid::framing - -#endif diff --git a/qpid/cpp/src/qpid/framing/FrameDecoder.cpp b/qpid/cpp/src/qpid/framing/FrameDecoder.cpp deleted file mode 100644 index 90cbbd84a1..0000000000 --- a/qpid/cpp/src/qpid/framing/FrameDecoder.cpp +++ /dev/null @@ -1,81 +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/framing/FrameDecoder.h" -#include "qpid/framing/Buffer.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" -#include -#include - -namespace qpid { -namespace framing { - -namespace { -/** Append up to n bytes from start of buf to end of bytes. */ -void append(std::vector& bytes, Buffer& buffer, size_t n) { - size_t oldSize = bytes.size(); - if ((n = std::min(n, size_t(buffer.available()))) == 0) - return; - bytes.resize(oldSize+n); - char* p = &bytes[oldSize]; - buffer.getRawData(reinterpret_cast(p), n); -} -} - -bool FrameDecoder::decode(Buffer& buffer) { - if (buffer.available() == 0) return false; - if (fragment.empty()) { - if (frame.decode(buffer)) // Decode from buffer - return true; - else // Store fragment - append(fragment, buffer, buffer.available()); - } - else { // Already have a fragment - // Get enough data to decode the frame size. - if (fragment.size() < AMQFrame::DECODE_SIZE_MIN) { - append(fragment, buffer, AMQFrame::DECODE_SIZE_MIN - fragment.size()); - } - if (fragment.size() >= AMQFrame::DECODE_SIZE_MIN) { - uint16_t size = AMQFrame::decodeSize(&fragment[0]); - if (size <= fragment.size()) - throw FramingErrorException(QPID_MSG("Frame size " << size << " is too small.")); - append(fragment, buffer, size-fragment.size()); - Buffer b(&fragment[0], fragment.size()); - if (frame.decode(b)) { - assert(b.available() == 0); - fragment.clear(); - return true; - } - } - } - return false; -} - -void FrameDecoder::setFragment(const char* data, size_t size) { - fragment.resize(size); - ::memcpy(&fragment[0], data, size); -} - -std::pair FrameDecoder::getFragment() const { - return std::pair(&fragment[0], fragment.size()); -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/FrameDecoder.h b/qpid/cpp/src/qpid/framing/FrameDecoder.h deleted file mode 100644 index 26bed6c447..0000000000 --- a/qpid/cpp/src/qpid/framing/FrameDecoder.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_FRAMING_FRAMEDECODER_H -#define QPID_FRAMING_FRAMEDECODER_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/AMQFrame.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -/** - * Decode a frame from buffer. If buffer does not contain a complete - * frame, caches the fragment for the next call to decode. - */ -class FrameDecoder -{ - public: - QPID_COMMON_EXTERN bool decode(Buffer& buffer); - const AMQFrame& getFrame() const { return frame; } - AMQFrame& getFrame() { return frame; } - - void setFragment(const char*, size_t); - std::pair getFragment() const; - - private: - std::vector fragment; - AMQFrame frame; - -}; -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_FRAMEDECODER_H*/ diff --git a/qpid/cpp/src/qpid/framing/FrameDefaultVisitor.h b/qpid/cpp/src/qpid/framing/FrameDefaultVisitor.h deleted file mode 100644 index bd676960bf..0000000000 --- a/qpid/cpp/src/qpid/framing/FrameDefaultVisitor.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_FRAMING_FRAMEVISITOR_H -#define QPID_FRAMING_FRAMEVISITOR_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/MethodBodyDefaultVisitor.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" - -namespace qpid { -namespace framing { -/** - * Visitor for all concrete frame body types, which combines - * AMQBodyConstVisitor and MethodBodyDefaultVisitor. - * - * Derived classes can override visit methods to specify actions. - * Derived classes must override defaultVisit(), which is called - * for any non-overridden visit functions. - * - */ -struct FrameDefaultVisitor : public AMQBodyConstVisitor, - protected MethodBodyDefaultVisitor -{ - virtual void defaultVisit(const AMQBody&) = 0; - void defaultVisit(const AMQMethodBody& method) { defaultVisit(static_cast(method)); } - - void visit(const AMQHeaderBody& b) { defaultVisit(b); } - void visit(const AMQContentBody& b) { defaultVisit(b); } - void visit(const AMQHeartbeatBody& b) { defaultVisit(b); } - void visit(const AMQMethodBody& b) { b.accept(static_cast(*this)); } - - using AMQBodyConstVisitor::visit; - using MethodBodyDefaultVisitor::visit; -}; - -}} // namespace qpid::framing - - -#endif /*!QPID_FRAMING_FRAMEVISITOR_H*/ diff --git a/qpid/cpp/src/qpid/framing/FrameHandler.h b/qpid/cpp/src/qpid/framing/FrameHandler.h deleted file mode 100644 index fa1fb535ef..0000000000 --- a/qpid/cpp/src/qpid/framing/FrameHandler.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef QPID_FRAMING_FRAMEHANDLER_H -#define QPID_FRAMING_FRAMEHANDLER_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/Handler.h" - -namespace qpid { -namespace framing { - -class AMQFrame; -typedef Handler FrameHandler; - - -}} -#endif /*!QPID_FRAMING_FRAMEHANDLER_H*/ diff --git a/qpid/cpp/src/qpid/framing/FrameSet.cpp b/qpid/cpp/src/qpid/framing/FrameSet.cpp deleted file mode 100644 index 4089475c7a..0000000000 --- a/qpid/cpp/src/qpid/framing/FrameSet.cpp +++ /dev/null @@ -1,128 +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/framing/FrameSet.h" -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/frame_functors.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/TypeFilter.h" - -using namespace qpid::framing; -using qpid::sys::AbsTime; -using qpid::sys::TIME_MSEC; - -FrameSet::FrameSet(const SequenceNumber& _id) : id(_id),contentSize(0),recalculateSize(true),received(AbsTime::FarFuture()) { } -FrameSet::FrameSet(const FrameSet& original) : id(original.id), contentSize(0), recalculateSize(true), received(AbsTime::FarFuture()) -{ - for (Frames::const_iterator i = original.begin(); i != original.end(); ++i) { - parts.push_back(AMQFrame(*(i->getBody()))); - parts.back().setFirstSegment(i->isFirstSegment()); - parts.back().setLastSegment(i->isLastSegment()); - parts.back().setFirstFrame(i->isFirstFrame()); - parts.back().setLastFrame(i->isLastFrame()); - } -} - -void FrameSet::append(const AMQFrame& part) -{ - parts.push_back(part); - recalculateSize = true; -} - -bool FrameSet::isComplete() const -{ - return !parts.empty() && parts.back().getEof() && parts.back().getEos(); -} - -bool FrameSet::isContentBearing() const -{ - const AMQMethodBody* method = getMethod(); - return method && method->isContentBearing(); -} - -const AMQMethodBody* FrameSet::getMethod() const -{ - return parts.empty() ? 0 : parts[0].getMethod(); -} - -AMQMethodBody* FrameSet::getMethod() -{ - return parts.empty() ? 0 : parts[0].getMethod(); -} - -const AMQHeaderBody* FrameSet::getHeaders() const -{ - return parts.size() < 2 ? 0 : parts[1].castBody(); -} - -AMQHeaderBody* FrameSet::getHeaders() -{ - return parts.size() < 2 ? 0 : parts[1].castBody(); -} - -uint64_t FrameSet::getContentSize() const -{ - if (recalculateSize) - { - SumBodySize sum; - map_if(sum, TypeFilter()); - contentSize = sum.getSize(); - recalculateSize = false; - } - return contentSize; -} - -void FrameSet::getContent(std::string& out) const { - out.clear(); - out.reserve(getContentSize()); - for(Frames::const_iterator i = parts.begin(); i != parts.end(); i++) { - if (i->getBody()->type() == CONTENT_BODY) - out += i->castBody()->getData(); - } -} - -std::string FrameSet::getContent() const { - std::string out; - getContent(out); - return out; -} - -bool FrameSet::hasContent() const { - return parts.size() >= 3; -} - -void FrameSet::setReceived() -{ - received = AbsTime::now(); -} -namespace { -uint64_t MAX_TTL = std::numeric_limits::max()/TIME_MSEC; -} - -bool FrameSet::hasExpired() const -{ - const DeliveryProperties* props = getHeaderProperties(); - if (props && props->hasTtl() && props->getTtl() < MAX_TTL) { - AbsTime expiration(received, props->getTtl()*TIME_MSEC); - return expiration < AbsTime::now(); - } - return false; -} diff --git a/qpid/cpp/src/qpid/framing/FrameSet.h b/qpid/cpp/src/qpid/framing/FrameSet.h deleted file mode 100644 index e234864dfd..0000000000 --- a/qpid/cpp/src/qpid/framing/FrameSet.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef QPID_FRAMING_FRAMESET_H -#define QPID_FRAMING_FRAMESET_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 -#include "qpid/InlineVector.h" -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/sys/Time.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -/** - * Collects the frames representing a message. - */ -class FrameSet -{ -public: - typedef InlineVector Frames; - -private: - const SequenceNumber id; - Frames parts; - mutable uint64_t contentSize; - mutable bool recalculateSize; - qpid::sys::AbsTime received; - -public: - typedef boost::shared_ptr 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&); - QPID_COMMON_EXTERN void append(const AMQFrame& part); - QPID_COMMON_EXTERN bool isComplete() const; - - QPID_COMMON_EXTERN uint64_t getContentSize() const; - - QPID_COMMON_EXTERN void getContent(std::string&) const; - QPID_COMMON_EXTERN std::string getContent() const; - QPID_COMMON_EXTERN bool hasContent() const; - - QPID_COMMON_EXTERN void setReceived(); - QPID_COMMON_EXTERN bool hasExpired() const; - - bool isContentBearing() const; - - QPID_COMMON_EXTERN const AMQMethodBody* getMethod() const; - QPID_COMMON_EXTERN AMQMethodBody* getMethod(); - QPID_COMMON_EXTERN const AMQHeaderBody* getHeaders() const; - QPID_COMMON_EXTERN AMQHeaderBody* getHeaders(); - - template bool isA() const { - const AMQMethodBody* method = getMethod(); - return method && method->isA(); - } - - template const T* as() const { - const AMQMethodBody* method = getMethod(); - return (method && method->isA()) ? dynamic_cast(method) : 0; - } - - template T* as() { - AMQMethodBody* method = getMethod(); - return (method && method->isA()) ? dynamic_cast(method) : 0; - } - - template const T* getHeaderProperties() const { - const AMQHeaderBody* header = getHeaders(); - return header ? header->get() : 0; - } - - Frames::const_iterator begin() const { return parts.begin(); } - Frames::const_iterator end() const { return parts.end(); } - - const SequenceNumber& getId() const { return id; } - - template void remove(P predicate) { - parts.erase(std::remove_if(parts.begin(), parts.end(), predicate), parts.end()); - } - - template void map(F& functor) { - std::for_each(parts.begin(), parts.end(), functor); - } - - template void map(F& functor) const { - std::for_each(parts.begin(), parts.end(), functor); - } - - template void map_if(F& functor, P predicate) { - for(Frames::iterator i = parts.begin(); i != parts.end(); i++) { - if (predicate(*i)) functor(*i); - } - } - - template void map_if(F& functor, P predicate) const { - for(Frames::const_iterator i = parts.begin(); i != parts.end(); i++) { - if (predicate(*i)) functor(*i); - } - } -}; - -} -} - - -#endif /*!QPID_FRAMING_FRAMESET_H*/ diff --git a/qpid/cpp/src/qpid/framing/Handler.h b/qpid/cpp/src/qpid/framing/Handler.h deleted file mode 100644 index f2a9fccde0..0000000000 --- a/qpid/cpp/src/qpid/framing/Handler.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef QPID_FRAMING_HANDLER_H -#define QPID_FRAMING_HANDLER_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 framing { - -template -struct Handler { - typedef T HandledType; - typedef void handleFptr(T); - typedef void result_type; // Compatible with std/boost functors. - - Handler(Handler* next_=0) : next(next_) {} - virtual ~Handler() {} - virtual void handle(T) = 0; - - /** Allow functor syntax for calling handle */ - void operator()(T t) { handle(t); } - - - /** Pointer to next handler in a linked list. */ - Handler* next; - - /** Adapt any void(T) functor as a Handler. - * Functor(f) will copy f. - * Functor(f) will only take a reference to x. - */ - template class Functor; - - /** Adapt a member function of X as a Handler. - * Only holds a reference to its target, not a copy. - */ - template class MemFunRef; - - /** Interface for a handler that implements a - * pair of in/out handle operations. - * @see InOutHandler - */ - class InOutHandlerInterface { - public: - virtual ~InOutHandlerInterface() {} - virtual void handleIn(T) = 0; - virtual void handleOut(T) = 0; - }; - - /** Support for implementing an in-out handler pair as a single class. - * Overrides handleIn, handleOut functions in a single class. - */ - struct InOutHandler : protected InOutHandlerInterface { - InOutHandler(Handler* nextIn=0, Handler* nextOut=0) : in(*this, nextIn), out(*this, nextOut) {} - MemFunRef in; - MemFunRef out; - }; -}; - -template -template -class Handler::Functor : public Handler { - public: - Functor(F f, Handler* next=0) : Handler(next), functor(f) {} - void handle(T t) { functor(t); } - private: - F functor; -}; - -template -template -class Handler::MemFunRef : public Handler { - public: - MemFunRef(X& x, Handler* next=0) : Handler(next), target(&x) {} - void handle(T t) { (target->*F)(t); } - - /** Allow calling with -> syntax */ - MemFunRef* operator->() { return this; } - - private: - X* target; -}; - -}} -#endif /*!QPID_FRAMING_HANDLER_H*/ -// diff --git a/qpid/cpp/src/qpid/framing/HeaderProperties.h b/qpid/cpp/src/qpid/framing/HeaderProperties.h deleted file mode 100644 index 8b1828daec..0000000000 --- a/qpid/cpp/src/qpid/framing/HeaderProperties.h +++ /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. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" - -#ifndef _HeaderProperties_ -#define _HeaderProperties_ - -namespace qpid { -namespace framing { - - class HeaderProperties - { - - public: - inline virtual ~HeaderProperties(){} - virtual uint8_t classId() const = 0; - virtual uint32_t encodedSize() const = 0; - virtual void encode(Buffer& buffer) const = 0; - virtual void decode(Buffer& buffer, uint32_t size) = 0; - }; -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/InitiationHandler.cpp b/qpid/cpp/src/qpid/framing/InitiationHandler.cpp deleted file mode 100644 index 7ded505a47..0000000000 --- a/qpid/cpp/src/qpid/framing/InitiationHandler.cpp +++ /dev/null @@ -1,24 +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/framing/InitiationHandler.h" - -qpid::framing::InitiationHandler::~InitiationHandler() {} diff --git a/qpid/cpp/src/qpid/framing/InitiationHandler.h b/qpid/cpp/src/qpid/framing/InitiationHandler.h deleted file mode 100644 index 5dfcc6b468..0000000000 --- a/qpid/cpp/src/qpid/framing/InitiationHandler.h +++ /dev/null @@ -1,41 +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 - -#ifndef _InitiationHandler_ -#define _InitiationHandler_ - -#include "qpid/framing/ProtocolInitiation.h" - -namespace qpid { -namespace framing { - - class InitiationHandler{ - public: - virtual ~InitiationHandler(); - virtual void initiated(const ProtocolInitiation&) = 0; - }; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/InputHandler.h b/qpid/cpp/src/qpid/framing/InputHandler.h deleted file mode 100644 index 3efb23632a..0000000000 --- a/qpid/cpp/src/qpid/framing/InputHandler.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _InputHandler_ -#define _InputHandler_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/FrameHandler.h" -#include - -namespace qpid { -namespace framing { - -// TODO aconway 2007-08-29: Eliminate, replace with FrameHandler. -class InputHandler : public FrameHandler { - public: - virtual ~InputHandler() {} - virtual void received(AMQFrame&) = 0; - void handle(AMQFrame& f) { received(f); } -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/Invoker.h b/qpid/cpp/src/qpid/framing/Invoker.h deleted file mode 100644 index 4f1cf7c331..0000000000 --- a/qpid/cpp/src/qpid/framing/Invoker.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef QPID_FRAMING_INVOKER_H -#define QPID_FRAMING_INVOKER_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/AMQMethodBody.h" -#include "qpid/framing/MethodBodyDefaultVisitor.h" -#include "qpid/framing/StructHelper.h" - -#include - -namespace qpid { -namespace framing { - -class AMQMethodBody; - -/** - * Base class for invoker visitors. - */ -class Invoker: public MethodBodyDefaultVisitor, protected StructHelper -{ - public: - struct Result { - public: - Result() : handled(false) {} - const std::string& getResult() const { return result; } - bool hasResult() const { return !result.empty(); } - bool wasHandled() const { return handled; } - operator bool() const { return handled; } - - std::string result; - bool handled; - }; - - void defaultVisit(const AMQMethodBody&) {} - Result getResult() const { return result; } - - protected: - Result result; -}; - -/** - * Invoke an invocable object. - * Invocable classes must provide a nested type Invoker. - */ -template -Invoker::Result invoke(Invocable& target, const AMQMethodBody& body) { - typename Invocable::Invoker invoker(target); - body.accept(invoker); - return invoker.getResult(); -} - -/** - * Invoke an invocable object. - * Invocable classes must provide a nested type Invoker. - */ -template -Invoker::Result invoke(Invocable& target, const AMQBody& body) { - typename Invocable::Invoker invoker(target); - const AMQMethodBody* method = body.getMethod(); - if (method) - method->accept(invoker); - return invoker.getResult(); -} - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_INVOKER_H*/ diff --git a/qpid/cpp/src/qpid/framing/IsInSequenceSet.h b/qpid/cpp/src/qpid/framing/IsInSequenceSet.h deleted file mode 100644 index fe10c1b9fa..0000000000 --- a/qpid/cpp/src/qpid/framing/IsInSequenceSet.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef QPID_FRAMING_ISINSEQUENCESET_H -#define QPID_FRAMING_ISINSEQUENCESET_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/SequenceSet.h" - -namespace qpid { -namespace framing { -/** - * Functor to test whether values are in a sequence set. This is a - * stateful functor that requires the values to be supplied in order - * and takes advantage of that ordering to avoid multiple scans. - */ -class IsInSequenceSet -{ - public: - IsInSequenceSet(const SequenceSet& s) : set(s), i(set.rangesBegin()) {} - - bool operator()(const SequenceNumber& n) { - while (i != set.rangesEnd() && i->end() <= n) ++i; - return i != set.rangesEnd() && i->begin() <= n; - } - - private: - const SequenceSet& set; - SequenceSet::RangeIterator i; -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_ISINSEQUENCESET_H*/ diff --git a/qpid/cpp/src/qpid/framing/List.cpp b/qpid/cpp/src/qpid/framing/List.cpp deleted file mode 100644 index d7ea172bac..0000000000 --- a/qpid/cpp/src/qpid/framing/List.cpp +++ /dev/null @@ -1,90 +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/framing/List.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" - -namespace qpid { -namespace framing { - -uint32_t List::encodedSize() const -{ - uint32_t len(4/*size*/ + 4/*count*/); - for(Values::const_iterator i = values.begin(); i != values.end(); ++i) { - len += (*i)->encodedSize(); - } - return len; -} - -void List::encode(Buffer& buffer) const -{ - buffer.putLong(encodedSize() - 4); - buffer.putLong(size()); - for (Values::const_iterator i = values.begin(); i!=values.end(); ++i) { - (*i)->encode(buffer); - } -} - -void List::decode(Buffer& buffer) -{ - values.clear(); - if (buffer.available() < 4) - throw IllegalArgumentException(QPID_MSG("Not enough data for list, expected at least " - " 4 bytes but only " << buffer.available() << " available")); - uint32_t size = buffer.getLong(); - uint32_t available = buffer.available(); - if (available < size) { - throw IllegalArgumentException(QPID_MSG("Not enough data for list, expected " - << size << " bytes but only " << available << " available")); - } - if (size) { - if (buffer.available() < 4) - throw IllegalArgumentException(QPID_MSG("Not enough data for list, expected at least " - " 4 bytes but only " << buffer.available() << " available")); - uint32_t count = buffer.getLong(); - for (uint32_t i = 0; i < count; i++) { - ValuePtr value(new FieldValue); - value->decode(buffer); - values.push_back(value); - } - } -} - - -bool List::operator==(const List& other) const { - return values.size() == other.values.size() && - std::equal(values.begin(), values.end(), other.values.begin()); -} - -std::ostream& operator<<(std::ostream& out, const List& l) -{ - out << "{"; - for(List::Values::const_iterator i = l.values.begin(); i != l.values.end(); ++i) { - if (i != l.values.begin()) out << ", "; - (*i)->print(out); - } - return out << "}"; -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/List.h b/qpid/cpp/src/qpid/framing/List.h deleted file mode 100644 index 681445947c..0000000000 --- a/qpid/cpp/src/qpid/framing/List.h +++ /dev/null @@ -1,78 +0,0 @@ -#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 -#include -#include - -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 ValuePtr; - typedef ValuePtr value_type; - typedef std::list 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/MethodBodyFactory.h b/qpid/cpp/src/qpid/framing/MethodBodyFactory.h deleted file mode 100644 index 88bc444795..0000000000 --- a/qpid/cpp/src/qpid/framing/MethodBodyFactory.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_FRAMING_METHODBODYFACTORY_H -#define QPID_FRAMING_METHODBODYFACTORY_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/AMQBody.h" -#include - -namespace qpid { -namespace framing { - -class AMQMethodBody; - -/** - * Functions to create instances of AMQMethodBody sub-classes. - * Note: MethodBodyFactory.cpp file is generated by rubygen. - */ -class MethodBodyFactory -{ - public: - static boost::intrusive_ptr create(ClassId c, MethodId m); -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_METHODBODYFACTORY_H*/ diff --git a/qpid/cpp/src/qpid/framing/MethodContent.h b/qpid/cpp/src/qpid/framing/MethodContent.h deleted file mode 100644 index 58c9143cfa..0000000000 --- a/qpid/cpp/src/qpid/framing/MethodContent.h +++ /dev/null @@ -1,40 +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. - * - */ -#ifndef _MethodContent_ -#define _MethodContent_ - -#include -#include "qpid/framing/AMQHeaderBody.h" - -namespace qpid { -namespace framing { - -class MethodContent -{ -public: - virtual ~MethodContent() {} - //TODO: rethink this interface - virtual const AMQHeaderBody& getHeader() const = 0; - virtual const std::string& getData() const = 0; -}; - -}} -#endif diff --git a/qpid/cpp/src/qpid/framing/ModelMethod.h b/qpid/cpp/src/qpid/framing/ModelMethod.h deleted file mode 100644 index d99bd06cfa..0000000000 --- a/qpid/cpp/src/qpid/framing/ModelMethod.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _ModelMethod_ -#define _ModelMethod_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/AMQMethodBody.h" -#include "qpid/framing/Header.h" - -namespace qpid { -namespace framing { - - -class ModelMethod : public AMQMethodBody -{ - mutable Header header; -public: - virtual ~ModelMethod() {} - virtual void encodeHeader(Buffer& buffer) const { header.encode(buffer); } - virtual void decodeHeader(Buffer& buffer, uint32_t size=0) { header.decode(buffer, size); } - virtual uint32_t headerSize() const { return header.encodedSize(); } - virtual bool isSync() const { return header.getSync(); } - virtual void setSync(bool on) const { header.setSync(on); } - Header& getHeader() { return header; } - const Header& getHeader() const { return header; } -}; - - -}} // namespace qpid::framing - - -#endif diff --git a/qpid/cpp/src/qpid/framing/ProtocolInitiation.cpp b/qpid/cpp/src/qpid/framing/ProtocolInitiation.cpp deleted file mode 100644 index 19cb3f0e3d..0000000000 --- a/qpid/cpp/src/qpid/framing/ProtocolInitiation.cpp +++ /dev/null @@ -1,83 +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/framing/ProtocolInitiation.h" - -#include - -namespace qpid { -namespace framing { - -ProtocolInitiation::ProtocolInitiation(){} - -ProtocolInitiation::ProtocolInitiation(uint8_t _major, uint8_t _minor) : version(_major, _minor) {} - -ProtocolInitiation::ProtocolInitiation(ProtocolVersion p) : version(p) {} - -ProtocolInitiation::~ProtocolInitiation(){} - -void ProtocolInitiation::encode(Buffer& buffer) const { - buffer.putOctet('A'); - buffer.putOctet('M'); - buffer.putOctet('Q'); - buffer.putOctet('P'); - if (version.getMajor() == 1) { - buffer.putOctet(version.getProtocol()); - buffer.putOctet(version.getMajor()); - buffer.putOctet(version.getMinor()); - buffer.putOctet(0);//revision - } else { - buffer.putOctet(1);//class - buffer.putOctet(1);//instance - buffer.putOctet(version.getMajor()); - buffer.putOctet(version.getMinor()); - } -} - -bool ProtocolInitiation::decode(Buffer& buffer){ - if(buffer.available() >= 8){ - buffer.getOctet();//A - buffer.getOctet();//M - buffer.getOctet();//Q - buffer.getOctet();//P - uint8_t protocolClass = buffer.getOctet();//class - version.setProtocol(protocolClass); - if (protocolClass == 1) { - //old (pre-1.0) style - buffer.getOctet();//instance - version.setMajor(buffer.getOctet()); - version.setMinor(buffer.getOctet()); - } else { - version.setMajor(buffer.getOctet()); - version.setMinor(buffer.getOctet()); - buffer.getOctet();//revision - } - return true; - }else{ - return false; - } -} - - -std::ostream& operator<<(std::ostream& o, const framing::ProtocolInitiation& pi) { - return o << int(pi.getMajor()) << "-" << int(pi.getMinor()); -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/ProtocolInitiation.h b/qpid/cpp/src/qpid/framing/ProtocolInitiation.h deleted file mode 100644 index fe6410af55..0000000000 --- a/qpid/cpp/src/qpid/framing/ProtocolInitiation.h +++ /dev/null @@ -1,60 +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/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/AMQDataBlock.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/CommonImportExport.h" - -#ifndef _ProtocolInitiation_ -#define _ProtocolInitiation_ - -namespace qpid { -namespace framing { - -class ProtocolInitiation : public AMQDataBlock -{ -private: - ProtocolVersion version; - -public: - QPID_COMMON_EXTERN ProtocolInitiation(); - QPID_COMMON_EXTERN ProtocolInitiation(uint8_t major, uint8_t minor); - QPID_COMMON_EXTERN ProtocolInitiation(ProtocolVersion p); - QPID_COMMON_EXTERN virtual ~ProtocolInitiation(); - QPID_COMMON_EXTERN virtual void encode(Buffer& buffer) const; - QPID_COMMON_EXTERN virtual bool decode(Buffer& buffer); - inline virtual uint32_t encodedSize() const { return 8; } - inline uint8_t getMajor() const { return version.getMajor(); } - inline uint8_t getMinor() const { return version.getMinor(); } - inline ProtocolVersion getVersion() const { return version; } - bool operator==(ProtocolVersion v) const { return v == getVersion(); } - bool matches(ProtocolVersion v) const { return v == getVersion(); } -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& o, const framing::ProtocolInitiation& pi); - - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/ProtocolVersion.cpp b/qpid/cpp/src/qpid/framing/ProtocolVersion.cpp deleted file mode 100644 index 269b861191..0000000000 --- a/qpid/cpp/src/qpid/framing/ProtocolVersion.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 "qpid/framing/ProtocolVersion.h" -#include - -using namespace qpid::framing; - -const std::string ProtocolVersion::toString() const -{ - std::stringstream ss; - ss << unsigned(major_) << "-" << unsigned(minor_); - if (major_ == 1) { - if (protocol_ == SASL) ss << " (SASL)"; - else if (protocol_ == TLS) ss << " (TLS)"; - } - return ss.str(); -} - -ProtocolVersion& ProtocolVersion::operator=(ProtocolVersion p) -{ - major_ = p.major_; - minor_ = p.minor_; - return *this; -} - -bool ProtocolVersion::operator==(ProtocolVersion p) const -{ - return major_ == p.major_ && minor_ == p.minor_; -} - -const uint8_t ProtocolVersion::AMQP(0); -const uint8_t ProtocolVersion::LEGACY_AMQP(1); -const uint8_t ProtocolVersion::TLS(2); -const uint8_t ProtocolVersion::SASL(3); diff --git a/qpid/cpp/src/qpid/framing/ProtocolVersion.h b/qpid/cpp/src/qpid/framing/ProtocolVersion.h deleted file mode 100644 index 92580baf1a..0000000000 --- a/qpid/cpp/src/qpid/framing/ProtocolVersion.h +++ /dev/null @@ -1,67 +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. - * - */ -#ifndef _ProtocolVersion_ -#define _ProtocolVersion_ - -#include "qpid/framing/amqp_types.h" -#include "qpid/CommonImportExport.h" - -#include - -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 const uint8_t AMQP; - QPID_COMMON_EXTERN static const uint8_t LEGACY_AMQP; - QPID_COMMON_EXTERN static const uint8_t TLS; - QPID_COMMON_EXTERN static const uint8_t SASL; -}; - -} // namespace framing -} // namespace qpid - - -#endif // ifndef _ProtocolVersion_ diff --git a/qpid/cpp/src/qpid/framing/Proxy.cpp b/qpid/cpp/src/qpid/framing/Proxy.cpp deleted file mode 100644 index 452fb13b01..0000000000 --- a/qpid/cpp/src/qpid/framing/Proxy.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * 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/framing/Proxy.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace framing { - -Proxy::Proxy(FrameHandler& h) : out(&h), sync(false) {} - -Proxy::~Proxy() {} - -void Proxy::send(const AMQBody& b) { - if (sync) { - const AMQMethodBody* m = dynamic_cast(&b); - if (m) m->setSync(sync); - } - AMQFrame f(b); - out->handle(f); -} - -ProtocolVersion Proxy::getVersion() const { - return ProtocolVersion(); -} - -FrameHandler& Proxy::getHandler() { return *out; } - -void Proxy::setHandler(FrameHandler& f) { out=&f; } - -Proxy::ScopedSync::ScopedSync(Proxy& p) : proxy(p) { proxy.sync = true; } -Proxy::ScopedSync::~ScopedSync() { proxy.sync = false; } - -}} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/Proxy.h b/qpid/cpp/src/qpid/framing/Proxy.h deleted file mode 100644 index 0884e9cbd2..0000000000 --- a/qpid/cpp/src/qpid/framing/Proxy.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _framing_Proxy_h -#define _framing_Proxy_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/framing/FrameHandler.h" -#include "qpid/framing/ProtocolVersion.h" - -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class AMQBody; - -/** - * Base class for proxies. - */ -class Proxy -{ - public: - class ScopedSync - { - Proxy& proxy; - public: - QPID_COMMON_EXTERN ScopedSync(Proxy& p); - QPID_COMMON_EXTERN ~ScopedSync(); - }; - - QPID_COMMON_EXTERN Proxy(FrameHandler& h); - QPID_COMMON_EXTERN virtual ~Proxy(); - - QPID_COMMON_EXTERN void send(const AMQBody&); - - QPID_COMMON_EXTERN ProtocolVersion getVersion() const; - - QPID_COMMON_EXTERN FrameHandler& getHandler(); - QPID_COMMON_EXTERN void setHandler(FrameHandler&); - private: - FrameHandler* out; - bool sync; -}; - -}} // namespace qpid::framing - - - -#endif /*!_framing_Proxy_h*/ diff --git a/qpid/cpp/src/qpid/framing/ResizableBuffer.h b/qpid/cpp/src/qpid/framing/ResizableBuffer.h deleted file mode 100644 index 0abc5ba7f4..0000000000 --- a/qpid/cpp/src/qpid/framing/ResizableBuffer.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_FRAMING_RESIZABLEBUFFER_H -#define QPID_FRAMING_RESIZABLEBUFFER_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/Buffer.h" -#include - -namespace qpid { -namespace framing { - -/** - * A buffer that maintains its own storage and can be resized, - * keeping any data already written to the buffer. - */ -class ResizableBuffer : public Buffer -{ - public: - ResizableBuffer(size_t initialSize) : store(initialSize) { - static_cast(*this) = Buffer(&store[0], store.size()); - } - - void resize(size_t newSize) { - size_t oldPos = getPosition(); - store.resize(newSize); - static_cast(*this) = Buffer(&store[0], store.size()); - setPosition(oldPos); - } - - /** Make sure at least n bytes are available */ - void makeAvailable(size_t n) { - if (n > available()) - resize(getSize() + n - available()); - } - - private: - std::vector store; -}; -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_RESIZABLEBUFFER_H*/ diff --git a/qpid/cpp/src/qpid/framing/SendContent.cpp b/qpid/cpp/src/qpid/framing/SendContent.cpp deleted file mode 100644 index 04b60396da..0000000000 --- a/qpid/cpp/src/qpid/framing/SendContent.cpp +++ /dev/null @@ -1,66 +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/framing/SendContent.h" - -qpid::framing::SendContent::SendContent(FrameHandler& h, uint16_t mfs, uint efc) : handler(h), - maxFrameSize(mfs), - expectedFrameCount(efc), frameCount(0) {} - -void qpid::framing::SendContent::operator()(const AMQFrame& f) -{ - bool first = frameCount == 0; - bool last = ++frameCount == expectedFrameCount; - - uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead(); - const AMQContentBody* body(f.castBody()); - if (body->encodedSize() > maxContentSize) { - uint32_t offset = 0; - for (int chunk = body->encodedSize() / maxContentSize; chunk > 0; chunk--) { - sendFragment(*body, offset, maxContentSize, first && offset == 0, last && offset + maxContentSize == body->encodedSize()); - offset += maxContentSize; - } - uint32_t remainder = body->encodedSize() % maxContentSize; - if (remainder) { - sendFragment(*body, offset, remainder, first && offset == 0, last); - } - } else { - AMQFrame copy(f); - setFlags(copy, first, last); - handler.handle(copy); - } -} - -void qpid::framing::SendContent::sendFragment(const AMQContentBody& body, uint32_t offset, uint16_t size, bool first, bool last) const -{ - AMQFrame fragment((AMQContentBody(body.getData().substr(offset, size)))); - setFlags(fragment, first, last); - handler.handle(fragment); -} - -void qpid::framing::SendContent::setFlags(AMQFrame& f, bool first, bool last) const -{ - f.setBof(false); - f.setBos(first); - f.setEof(true);//content is always the last segment - f.setEos(last); -} - diff --git a/qpid/cpp/src/qpid/framing/SendContent.h b/qpid/cpp/src/qpid/framing/SendContent.h deleted file mode 100644 index 1c464b9c8b..0000000000 --- a/qpid/cpp/src/qpid/framing/SendContent.h +++ /dev/null @@ -1,56 +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 -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/CommonImportExport.h" - -#ifndef _SendContent_ -#define _SendContent_ - -namespace qpid { -namespace framing { - -/** - * Functor that sends frame to handler, refragmenting if - * necessary. Currently only works on content frames but this could be - * changed once we support multi-frame segments in general. - */ -class SendContent -{ - FrameHandler& handler; - const uint16_t maxFrameSize; - uint expectedFrameCount; - uint frameCount; - - void sendFragment(const AMQContentBody& body, uint32_t offset, uint16_t size, bool first, bool last) const; - void setFlags(AMQFrame& f, bool first, bool last) const; -public: - QPID_COMMON_EXTERN SendContent(FrameHandler& _handler, uint16_t _maxFrameSize, uint frameCount); - QPID_COMMON_EXTERN void operator()(const AMQFrame& f); -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/SequenceNumber.cpp b/qpid/cpp/src/qpid/framing/SequenceNumber.cpp deleted file mode 100644 index 41cb236629..0000000000 --- a/qpid/cpp/src/qpid/framing/SequenceNumber.cpp +++ /dev/null @@ -1,50 +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/framing/SequenceNumber.h" -#include "qpid/framing/Buffer.h" -#include - -using qpid::framing::SequenceNumber; -using qpid::framing::Buffer; - -void SequenceNumber::encode(Buffer& buffer) const -{ - buffer.putLong(value); -} - -void SequenceNumber::decode(Buffer& buffer) -{ - value = buffer.getLong(); -} - -uint32_t SequenceNumber::encodedSize() const { - return 4; -} - -namespace qpid { -namespace framing { - -std::ostream& operator<<(std::ostream& o, const SequenceNumber& n) { - return o << n.getValue(); -} - -}} diff --git a/qpid/cpp/src/qpid/framing/SequenceNumber.h b/qpid/cpp/src/qpid/framing/SequenceNumber.h deleted file mode 100644 index 00fa2469c8..0000000000 --- a/qpid/cpp/src/qpid/framing/SequenceNumber.h +++ /dev/null @@ -1,85 +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. - * - */ -#ifndef _framing_SequenceNumber_h -#define _framing_SequenceNumber_h - -#include "qpid/framing/amqp_types.h" -#include -#include -#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 > > > -{ - 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 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/SequenceNumberSet.cpp b/qpid/cpp/src/qpid/framing/SequenceNumberSet.cpp deleted file mode 100644 index e9d78f3c17..0000000000 --- a/qpid/cpp/src/qpid/framing/SequenceNumberSet.cpp +++ /dev/null @@ -1,90 +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/framing/SequenceNumberSet.h" - -using namespace qpid::framing; - -void SequenceNumberSet::encode(Buffer& buffer) const -{ - buffer.putShort(size() * 4); - for (const_iterator i = begin(); i != end(); i++) { - buffer.putLong(i->getValue()); - } -} - -void SequenceNumberSet::decode(Buffer& buffer) -{ - clear(); - uint16_t count = (buffer.getShort() / 4); - for (uint16_t i = 0; i < count; i++) { - push_back(SequenceNumber(buffer.getLong())); - } -} - -uint32_t SequenceNumberSet::encodedSize() const -{ - return 2 /*count*/ + (size() * 4); -} - -SequenceNumberSet SequenceNumberSet::condense() const -{ - SequenceNumberSet result; - const_iterator last = end(); - const_iterator start = end(); - for (const_iterator i = begin(); i != end(); i++) { - if (start == end()) { - start = i; - } else if (*i - *last > 1) { - result.push_back(*start); - result.push_back(*last); - start = i; - } - last = i; - } - if (start != end()) { - result.push_back(*start); - result.push_back(*last); - } - return result; -} - -void SequenceNumberSet::addRange(const SequenceNumber& start, const SequenceNumber& end) -{ - push_back(start); - push_back(end); -} - -namespace qpid{ -namespace framing{ - -std::ostream& operator<<(std::ostream& out, const SequenceNumberSet& set) { - out << "{"; - for (SequenceNumberSet::const_iterator i = set.begin(); i != set.end(); i++) { - if (i != set.begin()) out << ", "; - out << (i->getValue()); - } - out << "}"; - return out; -} - -} -} diff --git a/qpid/cpp/src/qpid/framing/SequenceNumberSet.h b/qpid/cpp/src/qpid/framing/SequenceNumberSet.h deleted file mode 100644 index c8356c8163..0000000000 --- a/qpid/cpp/src/qpid/framing/SequenceNumberSet.h +++ /dev/null @@ -1,69 +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. - * - */ -#ifndef _framing_SequenceNumberSet_h -#define _framing_SequenceNumberSet_h - -#include -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/InlineVector.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class SequenceNumberSet : public InlineVector -{ - typedef InlineVector Base; -public: - typedef Base::const_iterator const_iterator; - typedef Base::iterator iterator; - - void encode(Buffer& buffer) const; - void decode(Buffer& buffer); - uint32_t encodedSize() const; - QPID_COMMON_EXTERN SequenceNumberSet condense() const; - QPID_COMMON_EXTERN void addRange(const SequenceNumber& start, const SequenceNumber& end); - - template - void processRanges(T& t) const - { - if (size() % 2) { //must be even number - throw InvalidArgumentException("SequenceNumberSet contains odd number of elements"); - } - - for (SequenceNumberSet::const_iterator i = begin(); i != end(); i++) { - SequenceNumber first = *(i); - SequenceNumber last = *(++i); - t(first, last); - } - } - - friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const SequenceNumberSet&); -}; - - -}} // namespace qpid::framing - - -#endif diff --git a/qpid/cpp/src/qpid/framing/SequenceSet.cpp b/qpid/cpp/src/qpid/framing/SequenceSet.cpp deleted file mode 100644 index 6510842c58..0000000000 --- a/qpid/cpp/src/qpid/framing/SequenceSet.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" - -using namespace qpid::framing; -using std::max; -using std::min; - -namespace qpid { -namespace framing { - -namespace { -//each range contains 2 numbers, 4 bytes each -uint16_t RANGE_SIZE = 2 * 4; -int32_t MAX_RANGE = 2147483647;//2^31-1 - -int32_t gap(const SequenceNumber& a, const SequenceNumber& b) -{ - return a < b ? b - a : a - b; -} - -bool is_max_range(const SequenceNumber& a, const SequenceNumber& b) -{ - return gap(a, b) == MAX_RANGE; -} -} - -void SequenceSet::encode(Buffer& buffer) const -{ - buffer.putShort(rangesSize() * RANGE_SIZE); - for (RangeIterator i = rangesBegin(); i != rangesEnd(); i++) { - buffer.putLong(i->first().getValue()); - buffer.putLong(i->last().getValue()); - } -} - -void SequenceSet::decode(Buffer& buffer) -{ - clear(); - uint16_t size = buffer.getShort(); - uint16_t count = size / RANGE_SIZE;//number of ranges - if (size % RANGE_SIZE) - throw IllegalArgumentException(QPID_MSG("Invalid size for sequence set: " << size)); - - for (uint16_t i = 0; i < count; i++) { - SequenceNumber a(buffer.getLong()); - SequenceNumber b(buffer.getLong()); - if (b < a) - throw IllegalArgumentException(QPID_MSG("Invalid range in sequence set: " << a << " -> " << b)); - if (is_max_range(a, b)) { - //RangeSet holds 'half-closed' ranges, where the end is - //one past the 'highest' value in the range. So if the - //range is already the maximum expressable with a 32bit - //sequence number, we can't represent it as a - //'half-closed' range, so we represent it as two ranges. - add(a, b-1); - add(b); - } else { - add(a, b); - } - } -} - -uint32_t SequenceSet::encodedSize() const { - return 2 /*size field*/ + (rangesSize() * RANGE_SIZE); -} - -bool SequenceSet::contains(const SequenceNumber& s) const { - return RangeSet::contains(s); -} - -void SequenceSet::add(const SequenceNumber& s) { *this += s; } - -void SequenceSet::add(const SequenceNumber& start, const SequenceNumber& finish) { - *this += Range::makeClosed(std::min(start,finish), std::max(start, finish)); -} - -void SequenceSet::add(const SequenceSet& set) { *this += set; } - -void SequenceSet::remove(const SequenceSet& set) { *this -= set; } - -void SequenceSet::remove(const SequenceNumber& start, const SequenceNumber& finish) { - *this -= Range::makeClosed(std::min(start,finish), std::max(start, finish)); -} - -void SequenceSet::remove(const SequenceNumber& s) { *this -= s; } - - -struct RangePrinter { - std::ostream& out; - RangePrinter(std::ostream& o) : out(o) {} - void operator()(SequenceNumber i, SequenceNumber j) const { - out << "[" << i.getValue() << "," << j.getValue() << "] "; - } -}; - -std::ostream& operator<<(std::ostream& o, const SequenceSet& s) { - RangePrinter print(o); - o << "{ "; - s.for_each(print); - return o << "}"; -} - -}} // namespace qpid::framing - diff --git a/qpid/cpp/src/qpid/framing/SequenceSet.h b/qpid/cpp/src/qpid/framing/SequenceSet.h deleted file mode 100644 index 827c8999b3..0000000000 --- a/qpid/cpp/src/qpid/framing/SequenceSet.h +++ /dev/null @@ -1,69 +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. - * - */ -#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 { - public: - SequenceSet() {} - SequenceSet(const RangeSet& r) - : RangeSet(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 void for_each(T& t) const { - for (RangeIterator i = rangesBegin(); i != rangesEnd(); i++) - t(i->first(), i->last()); - } - - template 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 deleted file mode 100644 index fe2fa64ce7..0000000000 --- a/qpid/cpp/src/qpid/framing/StructHelper.h +++ /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. - * - */ -#ifndef _StructHelper_ -#define _StructHelper_ - -#include "qpid/Exception.h" -#include "qpid/CommonImportExport.h" -#include "qpid/framing/Buffer.h" - -#include // For alloca - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN StructHelper -{ -public: - - template void encode(const T& t, std::string& data) { - uint32_t size = t.bodySize() + 2/*type*/; - data.resize(size); - Buffer wbuffer(const_cast(data.data()), size); - wbuffer.putShort(T::TYPE); - t.encodeStructBody(wbuffer); - } - - template void decode(T& t, const std::string& data) { - Buffer rbuffer(const_cast(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/TransferContent.cpp b/qpid/cpp/src/qpid/framing/TransferContent.cpp deleted file mode 100644 index d997b24304..0000000000 --- a/qpid/cpp/src/qpid/framing/TransferContent.cpp +++ /dev/null @@ -1,102 +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/framing/TransferContent.h" - -namespace qpid { -namespace framing { - -TransferContent::TransferContent(const std::string& data, const std::string& key) { - setData(data); - if (!key.empty()) getDeliveryProperties().setRoutingKey(key); -} - - -const AMQHeaderBody& TransferContent::getHeader() const -{ - return header; -} - -const std::string& TransferContent::getData() const { - return data; -} - -std::string& TransferContent::getData() { - return data; -} - -void TransferContent::setData(const std::string& _data) -{ - data = _data; - header.get(true)->setContentLength(data.size()); -} - -void TransferContent::appendData(const std::string& _data) -{ - data += _data; - header.get(true)->setContentLength(data.size()); -} - -MessageProperties& TransferContent::getMessageProperties() -{ - return *header.get(true); -} - -DeliveryProperties& TransferContent::getDeliveryProperties() -{ - return *header.get(true); -} - -void TransferContent::populate(const FrameSet& frameset) -{ - const AMQHeaderBody* h = frameset.getHeaders(); - if (h) { - header = *h; - } - frameset.getContent(data); -} - -const MessageProperties& TransferContent::getMessageProperties() const -{ - const MessageProperties* props = header.get(); - if (!props) throw Exception("No message properties."); - return *props; -} - -const DeliveryProperties& TransferContent::getDeliveryProperties() const -{ - const DeliveryProperties* props = header.get(); - if (!props) throw Exception("No message properties."); - return *props; -} - -bool TransferContent::hasMessageProperties() const -{ - return header.get(); -} - -bool TransferContent::hasDeliveryProperties() const -{ - return header.get(); -} - - -}} diff --git a/qpid/cpp/src/qpid/framing/TransferContent.h b/qpid/cpp/src/qpid/framing/TransferContent.h deleted file mode 100644 index 32663d7020..0000000000 --- a/qpid/cpp/src/qpid/framing/TransferContent.h +++ /dev/null @@ -1,64 +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. - * - */ -#ifndef _TransferContent_ -#define _TransferContent_ - -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MethodContent.h" -#include "qpid/Exception.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -/** Message content */ -class QPID_COMMON_CLASS_EXTERN TransferContent : public MethodContent -{ - AMQHeaderBody header; - std::string data; -public: - QPID_COMMON_EXTERN TransferContent(const std::string& data = std::string(), const std::string& key=std::string()); - - ///@internal - QPID_COMMON_EXTERN const AMQHeaderBody& getHeader() const; - - QPID_COMMON_EXTERN void setData(const std::string&); - QPID_COMMON_EXTERN const std::string& getData() const; - QPID_COMMON_EXTERN std::string& getData(); - - QPID_COMMON_EXTERN void appendData(const std::string&); - - QPID_COMMON_EXTERN bool hasMessageProperties() const; - QPID_COMMON_EXTERN MessageProperties& getMessageProperties(); - QPID_COMMON_EXTERN const MessageProperties& getMessageProperties() const; - - QPID_COMMON_EXTERN bool hasDeliveryProperties() const; - QPID_COMMON_EXTERN DeliveryProperties& getDeliveryProperties(); - QPID_COMMON_EXTERN const DeliveryProperties& getDeliveryProperties() const; - - ///@internal - QPID_COMMON_EXTERN void populate(const FrameSet& frameset); -}; - -}} -#endif diff --git a/qpid/cpp/src/qpid/framing/TypeFilter.h b/qpid/cpp/src/qpid/framing/TypeFilter.h deleted file mode 100644 index d1c42de583..0000000000 --- a/qpid/cpp/src/qpid/framing/TypeFilter.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef QPID_FRAMING_TYPEFILTER_H -#define QPID_FRAMING_TYPEFILTER_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 -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FrameHandler.h" - -namespace qpid { -namespace framing { - -/** - * Predicate that selects frames by type - */ -template -struct TypeFilter { - bool operator()(const AMQFrame& f) const { - return f.getBody()->type() == Type; - } -}; - -template -struct TypeFilter2 { - bool operator()(const AMQFrame& f) const { - return f.getBody()->type() == T1 || f.getBody()->type() == T2; - } -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_TYPEFILTER_H*/ diff --git a/qpid/cpp/src/qpid/framing/Uuid.cpp b/qpid/cpp/src/qpid/framing/Uuid.cpp deleted file mode 100644 index eb4c33be75..0000000000 --- a/qpid/cpp/src/qpid/framing/Uuid.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * 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/framing/Uuid.h" - -#include "qpid/sys/uuid.h" -#include "qpid/Exception.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" - -namespace qpid { -namespace framing { - -using namespace std; - -Uuid::Uuid(bool unique): - qpid::types::Uuid(unique) -{} - -Uuid::Uuid(const uint8_t* data): - qpid::types::Uuid(data) -{} - -void Uuid::encode(Buffer& buf) const { - buf.putRawData(data(), size()); -} - -void Uuid::decode(Buffer& buf) { - if (buf.available() < size()) - throw IllegalArgumentException(QPID_MSG("Not enough data for UUID.")); - - // Break qpid::types::Uuid encapsulation - Nasty, but efficient - buf.getRawData(const_cast(data()), size()); -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/src/qpid/framing/Uuid.h b/qpid/cpp/src/qpid/framing/Uuid.h deleted file mode 100644 index 906e20951f..0000000000 --- a/qpid/cpp/src/qpid/framing/Uuid.h +++ /dev/null @@ -1,57 +0,0 @@ -#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 "qpid/types/Uuid.h" - -#include -#include - -namespace qpid { -namespace framing { - -class Buffer; - -/** - * Framing UUID is now a thine wrapper around qpid::types::Uuid - */ -struct Uuid : public qpid::types::Uuid { - /** 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); - - // We get most of our operations directly from qpid::types::Uuid - QPID_COMMON_INLINE_EXTERN static size_t size() - { return SIZE; } - - 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 size(); } -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_UUID_H*/ diff --git a/qpid/cpp/src/qpid/framing/amqp_framing.h b/qpid/cpp/src/qpid/framing/amqp_framing.h deleted file mode 100644 index bad1c08a46..0000000000 --- a/qpid/cpp/src/qpid/framing/amqp_framing.h +++ /dev/null @@ -1,30 +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/framing/amqp_types.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" -#include "qpid/framing/InputHandler.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/ProtocolVersion.h" diff --git a/qpid/cpp/src/qpid/framing/amqp_types.h b/qpid/cpp/src/qpid/framing/amqp_types.h deleted file mode 100644 index 3fe8b68dcd..0000000000 --- a/qpid/cpp/src/qpid/framing/amqp_types.h +++ /dev/null @@ -1,63 +0,0 @@ -#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. */ -const ChannelId CHANNEL_MAX=(ChannelId(~1)); - -// 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 deleted file mode 100644 index c5d84dedea..0000000000 --- a/qpid/cpp/src/qpid/framing/amqp_types_full.h +++ /dev/null @@ -1,38 +0,0 @@ -#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/framing/frame_functors.h b/qpid/cpp/src/qpid/framing/frame_functors.h deleted file mode 100644 index d2064d6a57..0000000000 --- a/qpid/cpp/src/qpid/framing/frame_functors.h +++ /dev/null @@ -1,116 +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 -#include -#include -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/Buffer.h" - -#ifndef _frame_functors_ -#define _frame_functors_ - -namespace qpid { -namespace framing { - -class SumFrameSize -{ - uint64_t size; -public: - SumFrameSize() : size(0) {} - void operator()(const AMQFrame& f) { size += f.encodedSize(); } - uint64_t getSize() { return size; } -}; - -class SumBodySize -{ - uint64_t size; -public: - SumBodySize() : size(0) {} - void operator()(const AMQFrame& f) { size += f.getBody()->encodedSize(); } - uint64_t getSize() { return size; } -}; - -class Count -{ - uint count; -public: - Count() : count(0) {} - void operator()(const AMQFrame&) { count++; } - uint getCount() { return count; } -}; - -class EncodeFrame -{ - Buffer& buffer; -public: - EncodeFrame(Buffer& b) : buffer(b) {} - void operator()(const AMQFrame& f) { f.encode(buffer); } -}; - -class EncodeBody -{ - Buffer& buffer; -public: - EncodeBody(Buffer& b) : buffer(b) {} - void operator()(const AMQFrame& f) { f.getBody()->encode(buffer); } -}; - -/** - * Sends to the specified handler a copy of the frame it is applied to. - */ -class Relay -{ - FrameHandler& handler; - -public: - Relay(FrameHandler& h) : handler(h) {} - - void operator()(const AMQFrame& f) - { - AMQFrame copy(f); - handler.handle(copy); - } -}; - -class Print -{ - std::ostream& out; -public: - Print(std::ostream& o) : out(o) {} - - void operator()(const AMQFrame& f) - { - out << f << std::endl; - } -}; - -class MarkLastSegment -{ -public: - void operator()(AMQFrame& f) const { f.setEof(true); } -}; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/framing/variant.h b/qpid/cpp/src/qpid/framing/variant.h deleted file mode 100644 index 8e13063385..0000000000 --- a/qpid/cpp/src/qpid/framing/variant.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef QPID_FRAMING_VARIANT_H -#define QPID_FRAMING_VARIANT_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 Tools for using boost::variant. */ - - -#include - -namespace qpid { -namespace framing { -class Buffer; - -/** boost::static_visitor that throws an exception if variant contains a blank. - * Subclasses need to have a using() declaration, which can be generated - * with QPID_USING_NOBLANK(R) - */ -template -struct NoBlankVisitor : public boost::static_visitor { - R foundBlank() const { - assert(0); - throw Exception(QPID_MSG("Invalid variant value.")); - } - R operator()(const boost::blank&) const { return foundBlank(); } - R operator()(boost::blank&) const { return foundBlank(); } -}; - - -}} // qpid::framing - - -/** Generate a using statement, needed in visitors inheriting NoBlankVisitor - * @param R return type. - */ -#define QPID_USING_NOBLANK(R) using ::qpid::framing::NoBlankVisitor::operator() - -namespace qpid { -namespace framing { - -/** Convert the variant value to type R. */ -template struct ConvertVisitor : public NoBlankVisitor { - QPID_USING_NOBLANK(R); - template R operator()(T& t) const { return t; } -}; - -/** Convert the address of variant value to type R. */ -template struct AddressVisitor : public NoBlankVisitor { - QPID_USING_NOBLANK(R); - template R operator()(T& t) const { return &t; } -}; - -/** Apply a visitor to the nested variant.*/ -template -struct ApplyVisitor : public NoBlankVisitor { - QPID_USING_NOBLANK(typename V::result_type); - const V& visitor; - ApplyVisitor(const V& v) : visitor(v) {} - template typename V::result_type operator()(T& t) const { - return boost::apply_visitor(visitor, t); - } -}; - -/** Convenience function to construct and apply an ApplyVisitor */ -template -typename Visitor::result_type applyApplyVisitor(const Visitor& visitor, Visitable& visitable) { - return boost::apply_visitor(ApplyVisitor(visitor), visitable); -} - -}} // namespace qpid::framing - - -#endif /*!QPID_FRAMING_VARIANT_H*/ diff --git a/qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h b/qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h deleted file mode 100644 index fbf4755e7d..0000000000 --- a/qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef QPID_HA_ALTERNATEEXCHANGESETTER_H -#define QPID_HA_ALTERNATEEXCHANGESETTER_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/log/Statement.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/ExchangeRegistry.h" -#include - -namespace qpid { -namespace ha { - -/** - * Sets the alternate exchange on queues and exchanges. - * Holds onto queues/exchanges if necessary till the alternate exchange is available. - * THREAD UNSAFE - */ -class AlternateExchangeSetter -{ - public: - typedef boost::function)> SetFunction; - - AlternateExchangeSetter(broker::ExchangeRegistry& er) : exchanges(er) {} - - /** If altEx is already known, call setter(altEx) now else save for later */ - void setAlternate(const std::string& altEx, const SetFunction& setter) { - boost::shared_ptr ex = exchanges.find(altEx); - if (ex) setter(ex); // Set immediately. - else setters.insert(Setters::value_type(altEx, setter)); // Save for later. - } - - /** Add an exchange and call any setters that are waiting for it. */ - void addExchange(boost::shared_ptr exchange) { - // Update the setters for this exchange - std::pair range = setters.equal_range(exchange->getName()); - for (Setters::iterator i = range.first; i != range.second; ++i) - i->second(exchange); - setters.erase(range.first, range.second); - } - - void clear() { - if (!setters.empty()) - QPID_LOG(warning, "Some alternate exchanges were not resolved."); - setters.clear(); - } - - private: - typedef std::multimap Setters; - broker::ExchangeRegistry& exchanges; - Setters setters; -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_ALTERNATEEXCHANGESETTER_H*/ diff --git a/qpid/cpp/src/qpid/ha/Backup.cpp b/qpid/cpp/src/qpid/ha/Backup.cpp deleted file mode 100644 index f1b6eadd75..0000000000 --- a/qpid/cpp/src/qpid/ha/Backup.cpp +++ /dev/null @@ -1,128 +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 "Backup.h" -#include "BrokerReplicator.h" -#include "ConnectionObserver.h" -#include "HaBroker.h" -#include "Primary.h" -#include "ReplicatingSubscription.h" -#include "Settings.h" -#include "StatusCheck.h" -#include "qpid/Url.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Link.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/types/Variant.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace ha { - -using namespace framing; -using namespace broker; -using types::Variant; -using std::string; -using sys::Mutex; - -Backup::Backup(HaBroker& hb, const Settings& s) : - logPrefix(hb.logPrefix), membership(hb.getMembership()), stopped(false), - haBroker(hb), broker(hb.getBroker()), settings(s), - statusCheck(new StatusCheck(hb)) -{} - -void Backup::setBrokerUrl(const Url& brokers) { - if (brokers.empty()) return; - Mutex::ScopedLock l(lock); - if (stopped) return; - if (haBroker.getStatus() == JOINING) statusCheck->setUrl(brokers); - if (!link) { // Not yet initialized - QPID_LOG(info, logPrefix << "Connecting to cluster: " << brokers); - string protocol = brokers[0].protocol.empty() ? "tcp" : brokers[0].protocol; - types::Uuid uuid(true); - link = broker.getLinks().declare( - broker::QPID_NAME_PREFIX + string("ha.link.") + uuid.str(), - brokers[0].host, brokers[0].port, protocol, - false, // durable - settings.mechanism, settings.username, settings.password, - false).first; // no amq.failover - don't want to use client URL. - replicator = BrokerReplicator::create(haBroker, link); - broker.getExchanges().registerExchange(replicator); - } - link->setUrl(brokers); -} - -void Backup::stop(Mutex::ScopedLock&) { - if (stopped) return; - stopped = true; - if (link) link->close(); - if (replicator.get()) { - replicator->shutdown(); - replicator.reset(); - } -} - -Role* Backup::recover(Mutex::ScopedLock&) { - BrokerInfo::Set backups; - { - Mutex::ScopedLock l(lock); - if (stopped) return 0; - stop(l); // Stop backup activity before starting primary. - // Reset membership before allowing backups to connect. - backups = membership.otherBackups(); - membership.clear(); - } - return new Primary(haBroker, backups); -} - -Role* Backup::promote() { - Mutex::ScopedLock l(lock); - if (stopped) return 0; - switch (haBroker.getStatus()) { - case JOINING: - if (statusCheck->canPromote()) return recover(l); - else { - QPID_LOG(error, logPrefix << "Joining active cluster, cannot be promoted."); - throw Exception("Joining active cluster, cannot be promoted."); - } - break; - case CATCHUP: - QPID_LOG(error, logPrefix << "Still catching up, cannot be promoted."); - throw Exception("Still catching up, cannot be promoted."); - break; - case READY: return recover(l); break; - default: - assert(0); // Not a valid state for the Backup role.. - } - return 0; // Keep compiler happy -} - -Backup::~Backup() { - Mutex::ScopedLock l(lock); - stop(l); -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/Backup.h b/qpid/cpp/src/qpid/ha/Backup.h deleted file mode 100644 index 47c44aa59c..0000000000 --- a/qpid/cpp/src/qpid/ha/Backup.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef QPID_HA_BACKUP_H -#define QPID_HA_BACKUP_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 "LogPrefix.h" -#include "Role.h" -#include "Settings.h" -#include "qpid/Url.h" -#include "qpid/sys/Mutex.h" -#include - -namespace qpid { - -namespace broker { -class Broker; -class Link; -} - -namespace ha { -class Settings; -class BrokerReplicator; -class HaBroker; -class StatusCheck; -class Membership; - -/** - * Backup role: Manages connections to primary, replicates management events and queue contents. - * - * THREAD SAFE - */ -class Backup : public Role -{ - public: - Backup(HaBroker&, const Settings&); - ~Backup(); - - void setBrokerUrl(const Url&); - - Role* promote(); - - boost::shared_ptr getBrokerReplicator() { return replicator; } - - private: - void stop(sys::Mutex::ScopedLock&); - Role* recover(sys::Mutex::ScopedLock&); - - const LogPrefix& logPrefix; - Membership& membership; - - sys::Mutex lock; - bool stopped; - HaBroker& haBroker; - broker::Broker& broker; - Settings settings; - boost::shared_ptr link; - boost::shared_ptr replicator; - std::auto_ptr statusCheck; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_BACKUP_H*/ diff --git a/qpid/cpp/src/qpid/ha/BackupConnectionExcluder.h b/qpid/cpp/src/qpid/ha/BackupConnectionExcluder.h deleted file mode 100644 index a58e666fa7..0000000000 --- a/qpid/cpp/src/qpid/ha/BackupConnectionExcluder.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_HA_BACKUPCONNECTIONEXCLUDER_H -#define QPID_HA_BACKUPCONNECTIONEXCLUDER_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 "LogPrefix.h" -#include "qpid/broker/ConnectionObserver.h" -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace ha { - -/** - * Exclude connections to a backup broker. - */ -class BackupConnectionExcluder : public broker::ConnectionObserver -{ - public: - BackupConnectionExcluder(const LogPrefix& lp) : logPrefix(lp) {} - - void opened(broker::Connection& connection) { - QPID_LOG(trace, logPrefix << "Rejected connection "+connection.getMgmtId()); - connection.abort(); - } - - void closed(broker::Connection&) {} - - private: - const LogPrefix& logPrefix; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_BACKUPCONNECTIONEXCLUDER_H*/ diff --git a/qpid/cpp/src/qpid/ha/BrokerInfo.cpp b/qpid/cpp/src/qpid/ha/BrokerInfo.cpp deleted file mode 100644 index c8a652a7ab..0000000000 --- a/qpid/cpp/src/qpid/ha/BrokerInfo.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 "BrokerInfo.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include -#include -#include - -namespace qpid { -namespace ha { - -namespace { -const std::string SYSTEM_ID="system-id"; -const std::string PROTOCOL="protocol"; -const std::string HOST_NAME="host-name"; -const std::string PORT="port"; -const std::string STATUS="status"; -} - -using types::Uuid; -using types::Variant; -using framing::FieldTable; - -BrokerInfo::BrokerInfo() : status(JOINING) {} - -BrokerInfo::BrokerInfo(const types::Uuid& id, BrokerStatus s, const Address& a) - : address(a), systemId(id), status(s) -{} - -FieldTable BrokerInfo::asFieldTable() const { - Variant::Map m = asMap(); - FieldTable ft; - amqp_0_10::translate(m, ft); - return ft; -} - -Variant::Map BrokerInfo::asMap() const { - Variant::Map m; - m[SYSTEM_ID] = systemId; - m[PROTOCOL] = address.protocol; - m[HOST_NAME] = address.host; - m[PORT] = address.port; - m[STATUS] = status; - return m; -} - -void BrokerInfo::assign(const FieldTable& ft) { - Variant::Map m; - amqp_0_10::translate(ft, m); - assign(m); -} - -namespace { -const Variant& get(const Variant::Map& m, const std::string& k) { - Variant::Map::const_iterator i = m.find(k); - if (i == m.end()) throw Exception( - QPID_MSG("Missing field '" << k << "' in broker information")); - return i->second; -} -const Address empty; -} - -void BrokerInfo::assign(const Variant::Map& m) { - systemId = get(m, SYSTEM_ID).asUuid(); - address = Address(get(m, PROTOCOL).asString(), - get(m, HOST_NAME).asString(), - get(m, PORT).asUint16()); - status = BrokerStatus(get(m, STATUS).asUint8()); -} - -std::ostream& BrokerInfo::printId(std::ostream& o) const { - o << shortStr(getSystemId()); - if (getAddress() != empty) o << "@" << getAddress(); - return o; -} - -std::ostream& operator<<(std::ostream& o, const BrokerInfo& b) { - return b.printId(o) << "(" << printable(b.getStatus()) << ")"; -} - -std::ostream& operator<<(std::ostream& o, const BrokerInfo::Set& infos) { - std::ostream_iterator out(o, " "); - copy(infos.begin(), infos.end(), out); - return o; -} - -std::ostream& operator<<(std::ostream& o, const BrokerInfo::Map::value_type& v) { - return o << v.second; -} - -std::ostream& operator<<(std::ostream& o, const BrokerInfo::Map& infos) { - std::ostream_iterator out(o, " "); - copy(infos.begin(), infos.end(), out); - return o; -} - -}} diff --git a/qpid/cpp/src/qpid/ha/BrokerInfo.h b/qpid/cpp/src/qpid/ha/BrokerInfo.h deleted file mode 100644 index 92556a5c4b..0000000000 --- a/qpid/cpp/src/qpid/ha/BrokerInfo.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef QPID_HA_BROKERINFO_H -#define QPID_HA_BROKERINFO_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 "hash.h" -#include "qpid/Url.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/types/Uuid.h" -#include "qpid/types/Variant.h" -#include "qpid/sys/unordered_map.h" -#include -#include -#include - -namespace qpid { -namespace ha { - -/** - * Information about a cluster broker, maintained by the cluster primary. - */ -class BrokerInfo -{ - public: - typedef std::set Set; - typedef qpid::sys::unordered_map > Map; - - BrokerInfo(); - BrokerInfo(const types::Uuid& id, BrokerStatus, const Address& = Address()); - BrokerInfo(const framing::FieldTable& ft) { assign(ft); } - BrokerInfo(const types::Variant::Map& m) { assign(m); } - - types::Uuid getSystemId() const { return systemId; } - BrokerStatus getStatus() const { return status; } - void setStatus(BrokerStatus s) { status = s; } - Address getAddress() const { return address; } - void setAddress(const Address& a) { address = a; } - - framing::FieldTable asFieldTable() const; - types::Variant::Map asMap() const; - - void assign(const framing::FieldTable&); - void assign(const types::Variant::Map&); - - // So it can be put in a set. - bool operator<(const BrokerInfo& x) const { return systemId < x.systemId; } - - bool operator==(const BrokerInfo& x) const - { return address == x.address && systemId == x.systemId && status == x.status; } - - bool operator!=(const BrokerInfo& x) const { return !(*this == x); } - - // Print just the identifying information (shortId@address), not the status. - std::ostream& printId(std::ostream& o) const; - - private: - Address address; - types::Uuid systemId; - BrokerStatus status; -}; - -std::ostream& operator<<(std::ostream&, const BrokerInfo&); -std::ostream& operator<<(std::ostream&, const BrokerInfo::Set&); -std::ostream& operator<<(std::ostream&, const BrokerInfo::Map::value_type&); -std::ostream& operator<<(std::ostream&, const BrokerInfo::Map&); - -}} // namespace qpid::ha - -#endif /*!QPID_HA_BROKERINFO_H*/ diff --git a/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp b/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp deleted file mode 100644 index d664f13893..0000000000 --- a/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp +++ /dev/null @@ -1,900 +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 "BrokerReplicator.h" -#include "HaBroker.h" -#include "QueueReplicator.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/log/Statement.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/broker/SessionHandler.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qmf/org/apache/qpid/broker/EventBind.h" -#include "qmf/org/apache/qpid/broker/EventUnbind.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h" -#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h" -#include "qmf/org/apache/qpid/broker/EventQueueDelete.h" -#include "qmf/org/apache/qpid/broker/EventSubscribe.h" -#include "qmf/org/apache/qpid/ha/EventMembersUpdate.h" -#include -#include -#include -#include -#include - -namespace qpid { -namespace ha { - -using qmf::org::apache::qpid::broker::EventBind; -using qmf::org::apache::qpid::broker::EventUnbind; -using qmf::org::apache::qpid::broker::EventExchangeDeclare; -using qmf::org::apache::qpid::broker::EventExchangeDelete; -using qmf::org::apache::qpid::broker::EventQueueDeclare; -using qmf::org::apache::qpid::broker::EventQueueDelete; -using qmf::org::apache::qpid::broker::EventSubscribe; -using qmf::org::apache::qpid::ha::EventMembersUpdate; -using qpid::broker::amqp_0_10::MessageTransfer; -using namespace framing; -using namespace std; -using std::ostream; -using types::Variant; -using namespace broker; - -namespace { - -const string QPID_CONFIGURATION_REPLICATOR("qpid.broker-replicator"); -const string CLASS_NAME("_class_name"); -const string EVENT("_event"); -const string OBJECT_NAME("_object_name"); -const string PACKAGE_NAME("_package_name"); -const string QUERY_RESPONSE("_query_response"); -const string VALUES("_values"); -const string SCHEMA_ID("_schema_id"); -const string WHAT("_what"); - -const string ALTEX("altEx"); -const string ALTEXCHANGE("altExchange"); -const string ARGS("args"); -const string ARGUMENTS("arguments"); -const string AUTODEL("autoDel"); -const string AUTODELETE("autoDelete"); -const string BIND("bind"); -const string BINDING("binding"); -const string BINDING_KEY("bindingKey"); -const string CREATED("created"); -const string DISP("disp"); -const string DEST("dest"); -const string DURABLE("durable"); -const string EXCHANGE("exchange"); -const string EXCL("excl"); -const string EXCLUSIVE("exclusive"); -const string EXNAME("exName"); -const string EXTYPE("exType"); -const string HA_BROKER("habroker"); -const string KEY("key"); -const string NAME("name"); -const string PARTIAL("partial"); -const string QNAME("qName"); -const string QUEUE("queue"); -const string TYPE("type"); -const string UNBIND("unbind"); -const string CONSUMER_COUNT("consumerCount"); - -const string AGENT_EVENT_BROKER("agent.ind.event.org_apache_qpid_broker.#"); -const string AGENT_EVENT_HA("agent.ind.event.org_apache_qpid_ha.#"); -const string QMF2("qmf2"); -const string QMF_CONTENT("qmf.content"); -const string QMF_DEFAULT_TOPIC("qmf.default.topic"); -const string QMF_OPCODE("qmf.opcode"); - -const string OBJECT("OBJECT"); -const string ORG_APACHE_QPID_BROKER("org.apache.qpid.broker"); -const string ORG_APACHE_QPID_HA("org.apache.qpid.ha"); -const string QMF_DEFAULT_DIRECT("qmf.default.direct"); -const string _QUERY_REQUEST("_query_request"); -const string BROKER("broker"); -const string MEMBERS("members"); -const string AUTO_DELETE_TIMEOUT("qpid.auto_delete_timeout"); - -const string COLON(":"); - -void sendQuery(const string& packageName, const string& className, const string& queueName, - SessionHandler& sessionHandler) -{ - Variant::Map request; - request[WHAT] = OBJECT; - Variant::Map schema; - schema[CLASS_NAME] = className; - schema[PACKAGE_NAME] = packageName; - request[SCHEMA_ID] = schema; - - AMQFrame method((MessageTransferBody(ProtocolVersion(), QMF_DEFAULT_DIRECT, 0, 0))); - method.setBof(true); - method.setEof(false); - method.setBos(true); - method.setEos(true); - AMQHeaderBody headerBody; - MessageProperties* props = headerBody.get(true); - props->setReplyTo(qpid::framing::ReplyTo("", queueName)); - props->setAppId(QMF2); - props->getApplicationHeaders().setString(QMF_OPCODE, _QUERY_REQUEST); - headerBody.get(true)->setRoutingKey(BROKER); - headerBody.get(true)->setCorrelationId(className); - AMQFrame header(headerBody); - header.setBof(false); - header.setEof(false); - header.setBos(true); - header.setEos(true); - AMQContentBody data; - qpid::amqp_0_10::MapCodec::encode(request, data.getData()); - AMQFrame content(data); - content.setBof(false); - content.setEof(true); - content.setBos(true); - content.setEos(true); - sessionHandler.out->handle(method); - sessionHandler.out->handle(header); - sessionHandler.out->handle(content); -} - -// Like Variant::asMap but treat void value as an empty map. -Variant::Map asMapVoid(const Variant& value) { - if (!value.isVoid()) return value.asMap(); - else return Variant::Map(); -} -} // namespace - -// Report errors on the broker replication session. -class BrokerReplicator::ErrorListener : public broker::SessionHandler::ErrorListener { - public: - ErrorListener(const LogPrefix& lp) : logPrefix(lp) {} - - void connectionException(framing::connection::CloseCode code, const std::string& msg) { - QPID_LOG(error, logPrefix << framing::createConnectionException(code, msg).what()); - } - void channelException(framing::session::DetachCode code, const std::string& msg) { - QPID_LOG(error, logPrefix << framing::createChannelException(code, msg).what()); - } - void executionException(framing::execution::ErrorCode code, const std::string& msg) { - QPID_LOG(error, logPrefix << framing::createSessionException(code, msg).what()); - } - void incomingExecutionException(framing::execution::ErrorCode code, const std::string& msg) { - QPID_LOG(error, logPrefix << "Incoming " << framing::createSessionException(code, msg).what()); - } - void detach() {} - - private: - const LogPrefix& logPrefix; -}; - -/** Keep track of queues or exchanges during the update process to solve 2 - * problems. - * - * 1. Once all responses are processed, remove any queues/exchanges - * that were not mentioned as they no longer exist on the primary. - * - * 2. During the update if we see an event for an object we should - * ignore any subsequent responses for that object as they are out - * of date. - */ -class BrokerReplicator::UpdateTracker { - public: - typedef std::set Names; - typedef boost::function CleanFn; - - UpdateTracker(const std::string& type_, // "queue" or "exchange" - CleanFn f, - const LogPrefix& lp) - : type(type_), cleanFn(f), logPrefix(lp) {} - - /** Destructor cleans up remaining initial queues. */ - ~UpdateTracker() { - // Don't throw in a destructor. - try { - for_each(initial.begin(), initial.end(), - boost::bind(&UpdateTracker::clean, this, _1)); - } - catch (const std::exception& e) { - QPID_LOG(error, logPrefix << "Error in cleanup of lost objects: " << e.what()); - } - } - - /** Add an exchange name */ - void addExchange(Exchange::shared_ptr ex) { initial.insert(ex->getName()); } - - /** Add a queue name. */ - void addQueue(Queue::shared_ptr q) { initial.insert(q->getName()); } - - /** Received an event for name */ - void event(const std::string& name) { - initial.erase(name); // no longer a candidate for deleting - events.insert(name); // we have seen an event for this name - } - - /** Received a response for name. - *@return true if this response should be processed, false if we have - *already seen an event for this object. - */ - bool response(const std::string& name) { - initial.erase(name); // no longer a candidate for deleting - return events.find(name) == events.end(); // true if no event seen yet. - } - - private: - void clean(const std::string& name) { - QPID_LOG(debug, logPrefix << "Deleted " << type << " " << name << - ": no longer exists on primary"); - try { cleanFn(name); } - catch (const framing::NotFoundException&) {} - } - - std::string type; - Names initial, events; - CleanFn cleanFn; - const LogPrefix& logPrefix; -}; - -namespace { -template std::string key() { - pair name = EventType::getFullName(); - return name.first + COLON + name.second; -} -} - -boost::shared_ptr BrokerReplicator::create( - HaBroker& hb, const boost::shared_ptr& l) -{ - boost::shared_ptr br(new BrokerReplicator(hb, l)); - br->initialize(); - return br; -} - -BrokerReplicator::BrokerReplicator(HaBroker& hb, const boost::shared_ptr& l) - : Exchange(QPID_CONFIGURATION_REPLICATOR), - logPrefix(hb.logPrefix), replicationTest(NONE), - haBroker(hb), broker(hb.getBroker()), - exchanges(broker.getExchanges()), queues(broker.getQueues()), - link(l), - initialized(false), - alternates(hb.getBroker().getExchanges()), - connect(0) -{ - framing::FieldTable args = getArgs(); - args.setString(QPID_REPLICATE, printable(NONE).str()); - setArgs(args); - - dispatch[key()] = &BrokerReplicator::doEventQueueDeclare; - dispatch[key()] = &BrokerReplicator::doEventQueueDelete; - dispatch[key()] = &BrokerReplicator::doEventExchangeDeclare; - dispatch[key()] = &BrokerReplicator::doEventExchangeDelete; - dispatch[key()] = &BrokerReplicator::doEventBind; - dispatch[key()] = &BrokerReplicator::doEventUnbind; - dispatch[key()] = &BrokerReplicator::doEventMembersUpdate; - dispatch[key()] = &BrokerReplicator::doEventSubscribe; -} - -void BrokerReplicator::initialize() { - // Can't do this in the constructor because we need a shared_ptr to this. - types::Uuid uuid(true); - const std::string name(QPID_CONFIGURATION_REPLICATOR + ".bridge." + uuid.str()); - std::pair result = broker.getLinks().declare( - name, // name for bridge - *link, // parent - false, // durable - QPID_CONFIGURATION_REPLICATOR, // src - QPID_CONFIGURATION_REPLICATOR, // dest - "", // key - false, // isQueue - false, // isLocal - "", // id/tag - "", // excludes - false, // dynamic - 0, // sync? - LinkRegistry::INFINITE_CREDIT, - // shared_ptr keeps this in memory until outstanding connected - // calls are run. - boost::bind(&BrokerReplicator::connected, shared_from_this(), _1, _2) - ); - assert(result.second); - result.first->setErrorListener(boost::shared_ptr(new ErrorListener(logPrefix))); - broker.getConnectionObservers().add(shared_from_this()); -} - -BrokerReplicator::~BrokerReplicator() {} - -namespace { -struct QueueReplicators : public std::deque > { - QueueReplicators(const ExchangeRegistry& er) { addAll(er); } - - /** Add the exchange if it is a QueueReplicator. */ - void add(const boost::shared_ptr& ex) { - boost::shared_ptr qr = - boost::dynamic_pointer_cast(ex); - if (qr) push_back(qr); - } - /** Add all QueueReplicator in the ExchangeRegistry. */ - void addAll(const ExchangeRegistry& er) { - // Make copy of exchanges so we can work outside the registry lock. - er.eachExchange(boost::bind(&QueueReplicators::add, this, _1)); - } -}; -} // namespace - -void BrokerReplicator::shutdown() { - // NOTE: this is called in a QMF dispatch thread, not the Link's connection - // thread. It's OK to be unlocked because it doesn't use any mutable state, - // it only calls thread safe functions objects belonging to the Broker. - - // Unregister with broker objects: - broker.getConnectionObservers().remove(shared_from_this()); - broker.getExchanges().destroy(getName()); -} - -// This is called in the connection IO thread when the bridge is started. -void BrokerReplicator::connected(Bridge& bridge, SessionHandler& sessionHandler) { - // Use the credentials of the outgoing Link connection for creating queues, - // exchanges etc. We know link->getConnection() is non-zero because we are - // being called in the connections thread context. - // - connect = link->getConnection(); - assert(connect); - userId = link->getConnection()->getUserId(); - remoteHost = link->getConnection()->getMgmtId(); - - link->getRemoteAddress(primary); - string queueName = bridge.getQueueName(); - - QPID_LOG(info, logPrefix << (initialized ? "Failing over" : "Connecting") - << " to primary " << primary); - initialized = true; - - exchangeTracker.reset( - new UpdateTracker("exchange", - boost::bind(&BrokerReplicator::deleteExchange, this, _1), - logPrefix)); - exchanges.eachExchange(boost::bind(&BrokerReplicator::existingExchange, this, _1)); - - queueTracker.reset( - new UpdateTracker("queue", - boost::bind(&BrokerReplicator::deleteQueue, this, _1, true), - logPrefix)); - queues.eachQueue(boost::bind(&BrokerReplicator::existingQueue, this, _1)); - - framing::AMQP_ServerProxy peer(sessionHandler.out); - const qmf::org::apache::qpid::broker::ArgsLinkBridge& args(bridge.getArgs()); - - //declare and bind an event queue - FieldTable declareArgs; - declareArgs.setString(QPID_REPLICATE, printable(NONE).str()); - peer.getQueue().declare(queueName, "", false, false, true, true, declareArgs); - peer.getExchange().bind(queueName, QMF_DEFAULT_TOPIC, AGENT_EVENT_BROKER, FieldTable()); - peer.getExchange().bind(queueName, QMF_DEFAULT_TOPIC, AGENT_EVENT_HA, FieldTable()); - //subscribe to the queue - FieldTable arguments; - arguments.setInt(QueueReplicator::QPID_SYNC_FREQUENCY, 1); // TODO aconway 2012-05-22: optimize? - peer.getMessage().subscribe( - queueName, args.i_dest, 1/*accept-none*/, 0/*pre-acquired*/, - false/*exclusive*/, "", 0, arguments); - peer.getMessage().setFlowMode(args.i_dest, 1); // Window - peer.getMessage().flow(args.i_dest, 0, haBroker.getSettings().getFlowMessages()); - peer.getMessage().flow(args.i_dest, 1, haBroker.getSettings().getFlowBytes()); - - // Issue a query request for queues, exchanges, bindings and the habroker - // using event queue as the reply-to address - sendQuery(ORG_APACHE_QPID_HA, HA_BROKER, queueName, sessionHandler); - sendQuery(ORG_APACHE_QPID_BROKER, QUEUE, queueName, sessionHandler); - sendQuery(ORG_APACHE_QPID_BROKER, EXCHANGE, queueName, 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& q) { - if (replicationTest.getLevel(*q)) { - QPID_LOG(debug, logPrefix << "Existing queue: " << q->getName()); - queueTracker->addQueue(q); - } -} - -void BrokerReplicator::existingExchange(const boost::shared_ptr& ex) { - if (replicationTest.getLevel(*ex)) { - QPID_LOG(debug, logPrefix << "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. - if (haBroker.getStatus() == JOINING) { - haBroker.getMembership().setStatus(CATCHUP); - QPID_LOG(notice, logPrefix << "Connected to primary " << primary); - } - Variant::List list; - try { - if (!MessageTransfer::isQMFv2(msg.getMessage())) - throw Exception("Unexpected message, not QMF2 event or query response."); - // decode as list - string content = msg.getMessage().getContent(); - qpid::amqp_0_10::ListCodec::decode(content, list); - - if (msg.getMessage().getPropertyAsString(QMF_CONTENT) == EVENT) { - for (Variant::List::iterator i = list.begin(); i != list.end(); ++i) { - Variant::Map& map = i->asMap(); - QPID_LOG(trace, logPrefix << "Broker replicator event: " << map); - Variant::Map& schema = map[SCHEMA_ID].asMap(); - Variant::Map& values = map[VALUES].asMap(); - std::string key = (schema[PACKAGE_NAME].asString() + - COLON + - schema[CLASS_NAME].asString()); - EventDispatchMap::iterator j = dispatch.find(key); - if (j != dispatch.end()) (this->*(j->second))(values); - } - } else if (msg.getMessage().getPropertyAsString(QMF_OPCODE) == QUERY_RESPONSE) { - for (Variant::List::iterator i = list.begin(); i != list.end(); ++i) { - Variant::Map& map = i->asMap(); - QPID_LOG(trace, logPrefix << "Broker replicator response: " << map); - string type = map[SCHEMA_ID].asMap()[CLASS_NAME].asString(); - Variant::Map& values = map[VALUES].asMap(); - framing::FieldTable args; - qpid::amqp_0_10::translate(asMapVoid(values[ARGUMENTS]), args); - if (type == QUEUE) doResponseQueue(values); - else if (type == EXCHANGE) doResponseExchange(values); - else if (type == BINDING) doResponseBind(values); - else if (type == HA_BROKER) doResponseHaBroker(values); - } - if (MessageTransfer::isLastQMFResponse(msg.getMessage(), EXCHANGE)) { - QPID_LOG(debug, logPrefix << "All exchange responses received.") - exchangeTracker.reset(); // Clean up exchanges that no longer exist in the primary - alternates.clear(); - } - if (MessageTransfer::isLastQMFResponse(msg.getMessage(), QUEUE)) { - QPID_LOG(debug, logPrefix << "All queue responses received."); - queueTracker.reset(); // Clean up queues that no longer exist in the primary - } - } - } catch (const std::exception& e) { -; - haBroker.shutdown( - QPID_MSG(logPrefix << "Configuration replication failed: " - << e.what() << ": while handling: " << list)); - throw; - } -} - - -void BrokerReplicator::doEventQueueDeclare(Variant::Map& values) { - Variant::Map argsMap = asMapVoid(values[ARGS]); - if (values[DISP] == CREATED && replicationTest.getLevel(argsMap)) { - string name = values[QNAME].asString(); - QueueSettings settings(values[DURABLE].asBool(), values[AUTODEL].asBool()); - QPID_LOG(debug, logPrefix << "Queue declare event: " << name); - if (queueTracker.get()) queueTracker->event(name); - framing::FieldTable args; - qpid::amqp_0_10::translate(argsMap, args); - // If we already have a queue with this name, replace it. - // The queue was definitely created on the primary. - if (queues.find(name)) { - QPID_LOG(warning, logPrefix << "Declare event, replacing exsiting queue: " - << name); - deleteQueue(name); - } - replicateQueue(name, values[DURABLE].asBool(), values[AUTODEL].asBool(), args, - values[ALTEX].asString()); - } -} - -boost::shared_ptr BrokerReplicator::findQueueReplicator( - const std::string& qname) -{ - string rname = QueueReplicator::replicatorName(qname); - boost::shared_ptr ex = exchanges.find(rname); - return boost::dynamic_pointer_cast(ex); -} - -void BrokerReplicator::doEventQueueDelete(Variant::Map& values) { - // The remote queue has already been deleted so replicator - // sessions may be closed by a "queue deleted" exception. - string name = values[QNAME].asString(); - boost::shared_ptr queue = queues.find(name); - if (queue && replicationTest.getLevel(*queue)) { - QPID_LOG(debug, logPrefix << "Queue delete event: " << name); - if (queueTracker.get()) queueTracker->event(name); - deleteQueue(name); - } -} - -void BrokerReplicator::doEventExchangeDeclare(Variant::Map& values) { - Variant::Map argsMap(asMapVoid(values[ARGS])); - if (values[DISP] == CREATED && replicationTest.getLevel(argsMap)) { - string name = values[EXNAME].asString(); - QPID_LOG(debug, logPrefix << "Exchange declare event: " << name); - if (exchangeTracker.get()) exchangeTracker->event(name); - framing::FieldTable args; - qpid::amqp_0_10::translate(argsMap, args); - // If we already have a exchange with this name, replace it. - // The exchange was definitely created on the primary. - if (exchanges.find(name)) { - deleteExchange(name); - QPID_LOG(warning, logPrefix << "Declare event, replacing existing exchange: " - << name); - } - //Note: unlike qieth queues, autodeleted exchanges have no - //messages, so need no special handling for autodelete in ha - CreateExchangeResult result = createExchange( - name, values[EXTYPE].asString(), values[DURABLE].asBool(), values[AUTODEL].asBool(), args, - values[ALTEX].asString()); - assert(result.second); - } -} - -void BrokerReplicator::doEventExchangeDelete(Variant::Map& values) { - string name = values[EXNAME].asString(); - boost::shared_ptr exchange = exchanges.find(name); - if (exchange && replicationTest.getLevel(*exchange)) { - QPID_LOG(debug, logPrefix << "Exchange delete event:" << name); - if (exchangeTracker.get()) exchangeTracker->event(name); - deleteExchange(name); - } -} - -void BrokerReplicator::doEventBind(Variant::Map& values) { - boost::shared_ptr exchange = - exchanges.find(values[EXNAME].asString()); - boost::shared_ptr queue = - queues.find(values[QNAME].asString()); - framing::FieldTable args; - qpid::amqp_0_10::translate(asMapVoid(values[ARGS]), args); - // We only replicate binds for a replicated queue to replicated exchange - // that both exist locally. Respect the replication level set in the - // bind arguments, but replicate by default. - if (exchange && replicationTest.getLevel(*exchange) && - queue && replicationTest.getLevel(*queue) && - ReplicationTest(ALL).getLevel(args)) - { - string key = values[KEY].asString(); - QPID_LOG(debug, logPrefix << "Bind event: exchange=" << exchange->getName() - << " queue=" << queue->getName() - << " key=" << key - << " args=" << args); - queue->bind(exchange, key, args); - } -} - -void BrokerReplicator::doEventUnbind(Variant::Map& values) { - boost::shared_ptr exchange = - exchanges.find(values[EXNAME].asString()); - boost::shared_ptr queue = - queues.find(values[QNAME].asString()); - // We only replicate unbinds for a replicated queue to replicated - // exchange that both exist locally. - if (exchange && replicationTest.getLevel(*exchange) && - queue && replicationTest.getLevel(*queue)) - { - string key = values[KEY].asString(); - QPID_LOG(debug, logPrefix << "Unbind event: exchange=" << exchange->getName() - << " queue=" << queue->getName() - << " key=" << key); - exchange->unbind(queue, key, 0); - } -} - -void BrokerReplicator::doEventMembersUpdate(Variant::Map& values) { - Variant::List members = values[MEMBERS].asList(); - setMembership(members); -} - -void BrokerReplicator::doEventSubscribe(Variant::Map& values) { - // Ignore queue replicator subscriptions. - if (QueueReplicator::isReplicatorName(values[DEST].asString())) return; - boost::shared_ptr qr = findQueueReplicator(values[QNAME]); - if (qr) { - qr->setSubscribed(); - QPID_LOG(debug, logPrefix << "Subscribe event: " << values[QNAME]); - } -} - -namespace { - -// Get the alternate exchange from the exchange field of a queue or exchange response. -static const string EXCHANGE_KEY_PREFIX("org.apache.qpid.broker:exchange:"); - -string getAltExchange(const types::Variant& var) { - if (!var.isVoid()) { - management::ObjectId oid(var); - string key = oid.getV2Key(); - if (key.find(EXCHANGE_KEY_PREFIX) != 0) throw Exception("Invalid exchange reference: "+key); - return key.substr(EXCHANGE_KEY_PREFIX.size()); - } - else return string(); -} - -Variant getHaUuid(const Variant::Map& map) { - Variant::Map::const_iterator i = map.find(QPID_HA_UUID); - return i == map.end() ? Variant() : i->second; -} - -} // namespace - - -void BrokerReplicator::doResponseQueue(Variant::Map& values) { - Variant::Map argsMap(asMapVoid(values[ARGUMENTS])); - if (!replicationTest.getLevel(argsMap)) return; - string name(values[NAME].asString()); - 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 = 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); - if (uuidOk && findQueueReplicator(name)) return; // already replicated, UUID OK. - QPID_LOG(debug, logPrefix << "Queue response replacing queue: " << name); - deleteQueue(name); - } - - framing::FieldTable args; - qpid::amqp_0_10::translate(argsMap, args); - boost::shared_ptr qr = replicateQueue( - name, values[DURABLE].asBool(), values[AUTODELETE].asBool(), args, - getAltExchange(values[ALTEXCHANGE])); - if (qr) { - Variant::Map::const_iterator i = values.find(CONSUMER_COUNT); - if (i != values.end() && isIntegerType(i->second.getType())) { - if (i->second.asInt64()) qr->setSubscribed(); - } - } -} - -void BrokerReplicator::doResponseExchange(Variant::Map& values) { - Variant::Map argsMap(asMapVoid(values[ARGUMENTS])); - if (!replicationTest.getLevel(argsMap)) return; - string name = values[NAME].asString(); - if (!exchangeTracker.get()) - throw Exception(QPID_MSG("Unexpected exchange response: " << values)); - if (!exchangeTracker->response(name)) return; // Response is out of date. - QPID_LOG(debug, logPrefix << "Exchange response: " << name); - framing::FieldTable args; - qpid::amqp_0_10::translate(argsMap, args); - // If we see an exchange with the same name as one we have, but a different UUID, - // then replace the one we have. - boost::shared_ptr exchange = exchanges.find(name); - if (exchange && - exchange->getArgs().getAsString(QPID_HA_UUID) != args.getAsString(QPID_HA_UUID)) - { - QPID_LOG(warning, logPrefix << "Exchange response replacing (UUID mismatch): " << name); - deleteExchange(name); - } - CreateExchangeResult result = createExchange( - name, values[TYPE].asString(), values[DURABLE].asBool(), values[AUTODELETE].asBool(), args, - getAltExchange(values[ALTEXCHANGE])); -} - -namespace { -const std::string QUEUE_REF_PREFIX("org.apache.qpid.broker:queue:"); -const std::string EXCHANGE_REF_PREFIX("org.apache.qpid.broker:exchange:"); - -std::string getRefName(const std::string& prefix, const Variant& ref) { - Variant::Map map(ref.asMap()); - Variant::Map::const_iterator i = map.find(OBJECT_NAME); - if (i == map.end()) - throw Exception(QPID_MSG("Replicator: invalid object reference: " << ref)); - const std::string name = i->second.asString(); - if (name.compare(0, prefix.size(), prefix) != 0) - throw Exception(QPID_MSG("Replicator: unexpected reference prefix: " << name)); - std::string ret = name.substr(prefix.size()); - return ret; -} - -const std::string EXCHANGE_REF("exchangeRef"); -const std::string QUEUE_REF("queueRef"); - -} // namespace - -void BrokerReplicator::doResponseBind(Variant::Map& values) { - std::string exName = getRefName(EXCHANGE_REF_PREFIX, values[EXCHANGE_REF]); - std::string qName = getRefName(QUEUE_REF_PREFIX, values[QUEUE_REF]); - boost::shared_ptr exchange = exchanges.find(exName); - boost::shared_ptr queue = queues.find(qName); - - framing::FieldTable args; - qpid::amqp_0_10::translate(asMapVoid(values[ARGUMENTS]), args); - - // Automatically replicate binding if queue and exchange exist and are replicated. - // Respect replicate setting in binding args but default to replicated. - if (exchange && replicationTest.getLevel(*exchange) && - queue && replicationTest.getLevel(*queue) && - ReplicationTest(ALL).getLevel(args)) - { - string key = values[BINDING_KEY].asString(); - QPID_LOG(debug, logPrefix << "Bind response: exchange:" << exName - << " queue:" << qName - << " key:" << key - << " args:" << args); - queue->bind(exchange, key, args); - } -} - -namespace { -const string REPLICATE_DEFAULT="replicateDefault"; -} - -// Received the ha-broker configuration object for the primary broker. -void BrokerReplicator::doResponseHaBroker(Variant::Map& values) { - try { - QPID_LOG(debug, logPrefix << "HA Broker response: " << values); - ReplicateLevel mine = haBroker.getSettings().replicateDefault.get(); - ReplicateLevel primary = replicationTest.getLevel(values[REPLICATE_DEFAULT].asString()); - if (mine != primary) - throw Exception(QPID_MSG("Replicate default on backup (" << mine - << ") does not match primary (" << primary << ")")); - setMembership(values[MEMBERS].asList()); - } catch (const std::exception& e) { - haBroker.shutdown( - QPID_MSG(logPrefix << "Invalid HA Broker response: " << e.what() - << ": " << values)); - - throw; - } -} - -boost::shared_ptr BrokerReplicator::startQueueReplicator( - const boost::shared_ptr& queue) -{ - if (replicationTest.getLevel(*queue) == ALL) { - return QueueReplicator::create(haBroker, queue, link); - } - return boost::shared_ptr(); -} - -void BrokerReplicator::deleteQueue(const std::string& name, bool purge) { - Queue::shared_ptr queue = queues.find(name); - if (queue) { - // Purge before deleting to ensure that we don't reroute any - // messages. Any reroutes will be done at the primary and - // replicated as normal. - if (purge) queue->purge(0, boost::shared_ptr()); - haBroker.getBroker().deleteQueue(name, userId, remoteHost); - QPID_LOG(debug, logPrefix << "Queue deleted: " << name); - } -} - -void BrokerReplicator::deleteExchange(const std::string& name) { - boost::shared_ptr exchange = exchanges.find(name); - if (!exchange) { - QPID_LOG(warning, logPrefix << "Cannot delete exchange, not found: " << name); - return; - } - if (exchange->inUseAsAlternate()) { - QPID_LOG(warning, logPrefix << "Cannot delete exchange, in use as alternate: " << name); - return; - } - broker.deleteExchange(name, userId, remoteHost); - QPID_LOG(debug, logPrefix << "Exchange deleted: " << name); -} - -boost::shared_ptr BrokerReplicator::replicateQueue( - const std::string& name, - bool durable, - bool autodelete, - const qpid::framing::FieldTable& arguments, - const std::string& alternateExchange) -{ - QueueSettings settings(durable, autodelete); - settings.populate(arguments, settings.storeSettings); - CreateQueueResult result = - broker.createQueue( - name, - settings, - 0,// no owner regardless of exclusivity on primary - string(), // Set alternate exchange below - userId, - remoteHost); - boost::shared_ptr qr; - if (!findQueueReplicator(name)) qr = startQueueReplicator(result.first); - if (result.second && !alternateExchange.empty()) { - alternates.setAlternate( - alternateExchange, boost::bind(&Queue::setAlternateExchange, result.first, _1)); - } - return qr; -} - -BrokerReplicator::CreateExchangeResult BrokerReplicator::createExchange( - const std::string& name, - const std::string& type, - bool durable, - bool autodelete, - const qpid::framing::FieldTable& args, - const std::string& alternateExchange) -{ - CreateExchangeResult result = - broker.createExchange( - name, - type, - durable, - autodelete, - string(), // Set alternate exchange below - args, - userId, - remoteHost); - alternates.addExchange(result.first); - if (!alternateExchange.empty()) { - alternates.setAlternate( - alternateExchange, boost::bind(&Exchange::setAlternate, result.first, _1)); - } - return result; -} - -bool BrokerReplicator::bind(boost::shared_ptr, const string&, const framing::FieldTable*) { return false; } -bool BrokerReplicator::unbind(boost::shared_ptr, const string&, const framing::FieldTable*) { return false; } -bool BrokerReplicator::isBound(boost::shared_ptr, const string* const, const framing::FieldTable* const) { return false; } -bool BrokerReplicator::hasBindings() { return false; } - -// ConnectionObserver methods -void BrokerReplicator::connection(broker::Connection&) {} -void BrokerReplicator::opened(broker::Connection&) {} - -void BrokerReplicator::closed(broker::Connection& c) { - if (link && &c == connect) disconnected(); -} - -void BrokerReplicator::forced(broker::Connection& c, const std::string& message) { - if (link && &c == link->getConnection()) { - haBroker.shutdown( - QPID_MSG(logPrefix << "Connection forced, cluster may be misconfigured: " - << message)); - } - closed(c); -} - -string BrokerReplicator::getType() const { return QPID_CONFIGURATION_REPLICATOR; } - -void BrokerReplicator::disconnectedQueueReplicator( - const boost::shared_ptr& qr) -{ - qr->disconnect(); -} - -// Called by ConnectionObserver::disconnected, disconnected from the network side. -void BrokerReplicator::disconnected() { - QPID_LOG(info, logPrefix << "Disconnected from primary " << primary); - connect = 0; - QueueReplicators qrs(broker.getExchanges()); - for_each(qrs.begin(), qrs.end(), - boost::bind(&BrokerReplicator::disconnectedQueueReplicator, this, _1)); -} - -void BrokerReplicator::setMembership(const Variant::List& brokers) { - haBroker.getMembership().assign(brokers); -} - -}} // namespace broker diff --git a/qpid/cpp/src/qpid/ha/BrokerReplicator.h b/qpid/cpp/src/qpid/ha/BrokerReplicator.h deleted file mode 100644 index 44e80263de..0000000000 --- a/qpid/cpp/src/qpid/ha/BrokerReplicator.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef QPID_HA_REPLICATOR_H -#define QPID_HA_REPLICATOR_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 "AlternateExchangeSetter.h" -#include "qpid/Address.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/ConnectionObserver.h" -#include "qpid/types/Variant.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/sys/unordered_map.h" -#include -#include -#include - -namespace qpid { - -namespace broker { -class Broker; -class Link; -class Bridge; -class SessionHandler; -class Connection; -class QueueRegistry; -class ExchangeRegistry; -} - -namespace framing { -class FieldTable; -} - -namespace ha { -class LogPrefix; -class HaBroker; -class QueueReplicator; - -/** - * Replicate configuration on a backup broker. - * - * Implemented as an exchange that subscribes to receive QMF - * configuration events from the primary. It configures local queues - * exchanges and bindings to replicate the primary. - * It also creates QueueReplicators for newly replicated queues. - * - * THREAD UNSAFE: - * All members except shutdown are only called in the Link's connection thread context. - * shutdown() does not use any mutable state. - * - */ -class BrokerReplicator : public broker::Exchange, - public boost::enable_shared_from_this, - public broker::ConnectionObserver -{ - public: - typedef boost::shared_ptr QueueReplicatorPtr; - - static boost::shared_ptr create( - HaBroker&, const boost::shared_ptr&); - - ~BrokerReplicator(); - - void shutdown(); - - // Exchange methods - std::string getType() const; - bool bind(boost::shared_ptr, const std::string&, const framing::FieldTable*); - bool unbind(boost::shared_ptr, const std::string&, const framing::FieldTable*); - void route(broker::Deliverable&); - bool isBound(boost::shared_ptr, const std::string* const, const framing::FieldTable* const); - bool hasBindings(); - - // ConnectionObserver methods - void connection(broker::Connection&); - void opened(broker::Connection&); - void closed(broker::Connection&); - void forced(broker::Connection&, const std::string& /*message*/); - - QueueReplicatorPtr findQueueReplicator(const std::string& qname); - - private: - BrokerReplicator(HaBroker&, const boost::shared_ptr&); - void initialize(); // Called in create() - - typedef std::pair, bool> CreateQueueResult; - typedef std::pair, bool> CreateExchangeResult; - - typedef void (BrokerReplicator::*DispatchFunction)(types::Variant::Map&); - typedef qpid::sys::unordered_map EventDispatchMap; - - class UpdateTracker; - class ErrorListener; - - void connected(broker::Bridge&, broker::SessionHandler&); - void existingQueue(const boost::shared_ptr&); - void existingExchange(const boost::shared_ptr&); - - void doEventQueueDeclare(types::Variant::Map& values); - void doEventQueueDelete(types::Variant::Map& values); - void doEventExchangeDeclare(types::Variant::Map& values); - void doEventExchangeDelete(types::Variant::Map& values); - void doEventBind(types::Variant::Map&); - void doEventUnbind(types::Variant::Map&); - void doEventMembersUpdate(types::Variant::Map&); - void doEventSubscribe(types::Variant::Map&); - - void doResponseQueue(types::Variant::Map& values); - void doResponseExchange(types::Variant::Map& values); - void doResponseBind(types::Variant::Map& values); - void doResponseHaBroker(types::Variant::Map& values); - - QueueReplicatorPtr startQueueReplicator(const boost::shared_ptr&); - - QueueReplicatorPtr replicateQueue( - const std::string& name, - bool durable, - bool autodelete, - const qpid::framing::FieldTable& arguments, - const std::string& alternateExchange); - - CreateExchangeResult createExchange( - const std::string& name, - const std::string& type, - bool durable, - bool autodelete, - const qpid::framing::FieldTable& args, - const std::string& alternateExchange); - - bool deactivate(boost::shared_ptr ex, bool destroy); - void deleteQueue(const std::string& name, bool purge=true); - void deleteExchange(const std::string& name); - - void disconnectedQueueReplicator(const boost::shared_ptr&); - void disconnected(); - - void setMembership(const types::Variant::List&); // Set membership from list. - - const LogPrefix& logPrefix; - ReplicationTest replicationTest; - std::string userId, remoteHost; - HaBroker& haBroker; - broker::Broker& broker; - broker::ExchangeRegistry& exchanges; - broker::QueueRegistry& queues; - boost::shared_ptr link; - bool initialized; - AlternateExchangeSetter alternates; - qpid::Address primary; - broker::Connection* connect; - EventDispatchMap dispatch; - std::auto_ptr queueTracker; - std::auto_ptr exchangeTracker; -}; -}} // namespace qpid::broker - -#endif /*!QPID_HA_REPLICATOR_H*/ diff --git a/qpid/cpp/src/qpid/ha/ConnectionObserver.cpp b/qpid/cpp/src/qpid/ha/ConnectionObserver.cpp deleted file mode 100644 index a824adb871..0000000000 --- a/qpid/cpp/src/qpid/ha/ConnectionObserver.cpp +++ /dev/null @@ -1,121 +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 "ConnectionObserver.h" -#include "BrokerInfo.h" -#include "HaBroker.h" -#include "qpid/Url.h" -#include "qpid/types/Variant.h" -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace ha { - -ConnectionObserver::ConnectionObserver(HaBroker& hb, const types::Uuid& uuid) - : haBroker(hb), logPrefix(hb.logPrefix), self(uuid) {} - -bool ConnectionObserver::getBrokerInfo(const broker::Connection& connection, BrokerInfo& info) { - qpid::types::Variant::Map::const_iterator i = connection.getClientProperties().find(ConnectionObserver::BACKUP_TAG); - if (i != connection.getClientProperties().end() && i->second.getType() == qpid::types::VAR_MAP) { - info = BrokerInfo(i->second.asMap()); - return true; - } - return false; -} - -bool ConnectionObserver::getAddress(const broker::Connection& connection, Address& addr) { - qpid::types::Variant::Map::const_iterator i = connection.getClientProperties().find(ConnectionObserver::ADDRESS_TAG); - if (i != connection.getClientProperties().end()) { - Url url; - url.parseNoThrow(i->second.asString().c_str()); - if (!url.empty()) { - addr = url[0]; - return true; - } - } - return false; -} - -void ConnectionObserver::setObserver(const ObserverPtr& o) -{ - sys::Mutex::ScopedLock l(lock); - observer = o; -} - -ConnectionObserver::ObserverPtr ConnectionObserver::getObserver() { - sys::Mutex::ScopedLock l(lock); - return observer; -} - -void ConnectionObserver::reset() { - sys::Mutex::ScopedLock l(lock); - observer.reset(); -} - -bool ConnectionObserver::isSelf(const broker::Connection& connection) { - BrokerInfo info; - return getBrokerInfo(connection, info) && info.getSystemId() == self; -} - -void ConnectionObserver::opened(broker::Connection& connection) { - try { - if (isSelf(connection)) { // Reject self connections - // Set my own address if there is an address header. - Address addr; - if (getAddress(connection, addr)) haBroker.setAddress(addr); - QPID_LOG(trace, logPrefix << "Rejected self connection "+connection.getMgmtId()); - connection.abort(); - return; - } - if (connection.isLink()) return; // Allow outgoing links. - if (connection.getClientProperties().find(ADMIN_TAG) != connection.getClientProperties().end()) { - QPID_LOG(trace, logPrefix << "Accepted admin connection: " << connection.getMgmtId()); - return; // No need to call observer, always allow admins. - } - ObserverPtr o(getObserver()); - if (o) o->opened(connection); - } - catch (const std::exception& e) { - QPID_LOG(error, logPrefix << "Error on incoming connection " << connection.getMgmtId() - << ": " << e.what()); - throw; - } -} - -void ConnectionObserver::closed(broker::Connection& connection) { - if (isSelf(connection)) return; // Ignore closing of self connections. - try { - ObserverPtr o(getObserver()); - if (o) o->closed(connection); - } - catch (const std::exception& e) { - QPID_LOG(error, logPrefix << "Error closing incoming connection " << connection.getMgmtId() - << ": " << e.what()); - throw; - } -} - -const std::string ConnectionObserver::ADMIN_TAG="qpid.ha-admin"; -const std::string ConnectionObserver::BACKUP_TAG="qpid.ha-backup"; -const std::string ConnectionObserver::ADDRESS_TAG="qpid.ha-address"; - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/ConnectionObserver.h b/qpid/cpp/src/qpid/ha/ConnectionObserver.h deleted file mode 100644 index f447d479f0..0000000000 --- a/qpid/cpp/src/qpid/ha/ConnectionObserver.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QPID_HA_CONNECTIONOBSERVER_H -#define QPID_HA_CONNECTIONOBSERVER_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/ConnectionObserver.h" -#include "qpid/types/Uuid.h" -#include "qpid/sys/Mutex.h" -#include "boost/shared_ptr.hpp" - -namespace qpid { -struct Address; - -namespace ha { -class BrokerInfo; -class HaBroker; -class LogPrefix; - -/** - * Observes connections, delegates to another ConnectionObserver for - * actions specific to primary or backup. - * - * THREAD SAFE: called in arbitrary connection threads. - * - * Main role of this class is to provide a continuous observer object - * on the connection so we can't lose observations between removing - * one observer and adding another. - */ -class ConnectionObserver : public broker::ConnectionObserver -{ - public: - typedef boost::shared_ptr ObserverPtr; - - static const std::string ADMIN_TAG; - static const std::string BACKUP_TAG; - static const std::string ADDRESS_TAG; - - static bool getBrokerInfo(const broker::Connection& connection, BrokerInfo&); - static bool getAddress(const broker::Connection& connection, Address&); - - ConnectionObserver(HaBroker& haBroker, const types::Uuid& self); - - void setObserver(const ObserverPtr&); - ObserverPtr getObserver(); - - void reset(); - - void opened(broker::Connection& connection); - void closed(broker::Connection& connection); - - private: - bool isSelf(const broker::Connection&); - - sys::Mutex lock; - HaBroker& haBroker; - const LogPrefix& logPrefix; - ObserverPtr observer; - types::Uuid self; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_CONNECTIONOBSERVER_H*/ diff --git a/qpid/cpp/src/qpid/ha/Event.cpp b/qpid/cpp/src/qpid/ha/Event.cpp deleted file mode 100644 index 8c1b52ea7a..0000000000 --- a/qpid/cpp/src/qpid/ha/Event.cpp +++ /dev/null @@ -1,78 +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 "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 { - -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"); - -broker::Message makeMessage( - const string& data, const string& destination, const string& routingKey) -{ - boost::intrusive_ptr 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())); - 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(&data[0]), data.size()); - content.castBody()->decode( - const_cast(buffer), buffer.getSize()); - transfer->getFrames().append(method); - transfer->getFrames().append(header); - transfer->getFrames().append(content); - transfer->getFrames().getHeaders()-> - get(true)->setRoutingKey(routingKey); - return broker::Message(transfer, 0); -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/Event.h b/qpid/cpp/src/qpid/ha/Event.h deleted file mode 100644 index 308673657c..0000000000 --- a/qpid/cpp/src/qpid/ha/Event.h +++ /dev/null @@ -1,99 +0,0 @@ -#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 EventBase : public Event { - public: - std::string key() const { return Derived::KEY; } -}; - -//////////////// Specific event type - -//// QueueReplicator events - -struct DequeueEvent : public EventBase { - 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 { - 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; } -}; - -}} // 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 deleted file mode 100644 index 9bda5ea5bf..0000000000 --- a/qpid/cpp/src/qpid/ha/FailoverExchange.cpp +++ /dev/null @@ -1,133 +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 "FailoverExchange.h" -#include "Event.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/Queue.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/Array.h" -#include "qpid/RefCounted.h" -#include "qpid/UrlArray.h" -#include -#include - - -namespace qpid { -namespace ha { - -using namespace std; - -using namespace broker; -using namespace framing; -using broker::amqp_0_10::MessageTransfer; - -const string FailoverExchange::typeName("amq.failover"); - -namespace { -struct OstreamUrls { - OstreamUrls(const FailoverExchange::Urls& u) : urls(u) {} - FailoverExchange::Urls urls; -}; - -ostream& operator<<(ostream& o, const OstreamUrls& urls) { - ostream_iterator out(o, " "); - copy(urls.urls.begin(), urls.urls.end(), out); - return o; -} -} - -FailoverExchange::FailoverExchange(management::Manageable& parent, Broker& b) - : Exchange(typeName, &parent, &b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -void FailoverExchange::setUrls(const vector& u) { - QPID_LOG(debug, typeName << " URLs set to " << OstreamUrls(u)); - Lock l(lock); - urls = u; -} - -void FailoverExchange::updateUrls(const vector& u) { - QPID_LOG(debug, typeName << " Updating URLs " << OstreamUrls(u) << " to " - << queues.size() << " subscribers."); - Lock l(lock); - urls=u; - if (!urls.empty() && !queues.empty()) { - for (Queues::const_iterator i = queues.begin(); i != queues.end(); ++i) - sendUpdate(*i, l); - } -} - -string FailoverExchange::getType() const { return typeName; } - -bool FailoverExchange::bind(Queue::shared_ptr queue, const string&, - const framing::FieldTable*) { - QPID_LOG(debug, typeName << " binding " << queue->getName()); - Lock l(lock); - sendUpdate(queue, l); - return queues.insert(queue).second; -} - -bool FailoverExchange::unbind(Queue::shared_ptr queue, const string&, - const framing::FieldTable*) { - QPID_LOG(debug, typeName << " un-binding " << queue->getName()); - Lock l(lock); - return queues.erase(queue); -} - -bool FailoverExchange::isBound(Queue::shared_ptr queue, const string* const, - const framing::FieldTable*) { - Lock l(lock); - return queues.find(queue) != queues.end(); -} - -bool FailoverExchange::hasBindings() { - Lock l(lock); - return !queues.empty(); -} - -void FailoverExchange::route(Deliverable&) { - QPID_LOG(warning, typeName << " unexpected message, ignored."); -} - -void FailoverExchange::sendUpdate(const Queue::shared_ptr& queue, sys::Mutex::ScopedLock&) { - QPID_LOG(debug, typeName << " sending " << OstreamUrls(urls) << " to " << queue->getName()); - if (urls.empty()) return; - framing::Array array = vectorToUrlArray(urls); - const ProtocolVersion v; - broker::Message message(makeMessage(std::string(), typeName, typeName)); - MessageTransfer& transfer = MessageTransfer::get(message); - MessageProperties* props = - transfer.getFrames().getHeaders()->get(true); - props->setContentLength(0); - props->getApplicationHeaders().setArray(typeName, array); - DeliverableMessage(message, 0).deliverTo(queue); -} - -}} // namespace ha diff --git a/qpid/cpp/src/qpid/ha/FailoverExchange.h b/qpid/cpp/src/qpid/ha/FailoverExchange.h deleted file mode 100644 index 5263bdfb03..0000000000 --- a/qpid/cpp/src/qpid/ha/FailoverExchange.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef QPID_HA_FAILOVEREXCHANGE_H -#define QPID_HA_FAILOVEREXCHANGE_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. - *ls - */ - -#include "qpid/broker/Exchange.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/Url.h" - -#include -#include - -namespace qpid { -namespace ha { - -/** - * Failover exchange provides failover host list, as specified in AMQP 0-10. - */ -class FailoverExchange : public broker::Exchange -{ - public: - typedef std::vector Urls; - - static const std::string typeName; - - FailoverExchange(management::Manageable& parent, broker::Broker& b); - - /** Set the URLs but don't send an update.*/ - void setUrls(const Urls&); - /** Set the URLs and send an update.*/ - void updateUrls(const Urls&); - - // Exchange overrides - std::string getType() const; - bool bind(boost::shared_ptr queue, const std::string& routingKey, const framing::FieldTable* args); - bool unbind(boost::shared_ptr queue, const std::string& routingKey, const framing::FieldTable* args); - bool isBound(boost::shared_ptr queue, const std::string* const routingKey, const framing::FieldTable* const args); - bool hasBindings(); - void route(broker::Deliverable& msg); - - private: - void sendUpdate(const boost::shared_ptr&, sys::Mutex::ScopedLock&); - - typedef sys::Mutex::ScopedLock Lock; - typedef std::set > Queues; - - sys::Mutex lock; - Urls urls; - Queues queues; -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_FAILOVEREXCHANGE_H*/ diff --git a/qpid/cpp/src/qpid/ha/HaBroker.cpp b/qpid/cpp/src/qpid/ha/HaBroker.cpp deleted file mode 100644 index 7699b0e1d2..0000000000 --- a/qpid/cpp/src/qpid/ha/HaBroker.cpp +++ /dev/null @@ -1,240 +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 "Backup.h" -#include "BackupConnectionExcluder.h" -#include "ConnectionObserver.h" -#include "HaBroker.h" -#include "IdSetter.h" -#include "Primary.h" -#include "QueueReplicator.h" -#include "ReplicatingSubscription.h" -#include "Settings.h" -#include "StandAlone.h" -#include "QueueSnapshot.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/assert.h" -#include "qpid/Exception.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/BrokerObserver.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/SignalHandler.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/types/Uuid.h" -#include "qpid/framing/Uuid.h" -#include "qmf/org/apache/qpid/ha/Package.h" -#include "qmf/org/apache/qpid/ha/ArgsHaBrokerReplicate.h" -#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetBrokersUrl.h" -#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetPublicUrl.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { -namespace ha { - -namespace _qmf = ::qmf::org::apache::qpid::ha; -using namespace management; -using namespace std; -using types::Variant; -using types::Uuid; -using sys::Mutex; -using boost::shared_ptr; -using boost::dynamic_pointer_cast; - -// In a HaBroker we always need to add QueueSnapshot and IdSetter to each queue -// because we don't know in advance which queues might be used for stand-alone -// replication. -// -// TODO aconway 2013-12-13: Can we restrict this to queues identified as replicated? -// -class HaBroker::BrokerObserver : public broker::BrokerObserver { - public: - BrokerObserver(const LogPrefix& lp) : logPrefix(lp) {} - - void queueCreate(const boost::shared_ptr& q) { - q->getObservers().add(boost::shared_ptr(new QueueSnapshot)); - q->getMessageInterceptors().add( - boost::shared_ptr(new IdSetter(logPrefix, q->getName()))); - } - - private: - const LogPrefix& logPrefix; -}; - -// Called in Plugin::earlyInitialize -HaBroker::HaBroker(broker::Broker& b, const Settings& s) - : systemId(b.getSystem()->getSystemId().data()), - settings(s), - userId(s.username+"@"+b.getRealm()), - broker(b), - observer(new ConnectionObserver(*this, systemId)), - role(new StandAlone), - membership(BrokerInfo(systemId, STANDALONE), *this), // Sets logPrefix - failoverExchange(new FailoverExchange(*b.GetVhostObject(), b)) -{ - // If we are joining a cluster we must start excluding clients now, - // otherwise there's a window for a client to connect before we get to - // initialize() - if (settings.cluster) { - shared_ptr excluder(new BackupConnectionExcluder(logPrefix)); - observer->setObserver(excluder); - broker.getConnectionObservers().add(observer); - broker.getExchanges().registerExchange(failoverExchange); - } - broker.getBrokerObservers().add(boost::shared_ptr(new BrokerObserver(logPrefix))); -} - -namespace { -const std::string NONE("none"); -bool isNone(const std::string& x) { return x.empty() || x == NONE; } -} - -// Called in Plugin::initialize -void HaBroker::initialize() { - if (settings.cluster) { - QPID_LOG(info, logPrefix << "Starting HA broker"); - membership.setStatus(JOINING); - } - - // Set up the management object. - ManagementAgent* ma = broker.getManagementAgent(); - if (settings.cluster && !ma) - throw Exception("Cannot start HA: management is disabled"); - _qmf::Package packageInit(ma); - mgmtObject = _qmf::HaBroker::shared_ptr(new _qmf::HaBroker(ma, this, "ha-broker")); - mgmtObject->set_replicateDefault(settings.replicateDefault.str()); - mgmtObject->set_systemId(systemId); - ma->addObject(mgmtObject); - membership.setMgmtObject(mgmtObject); - - // Register a factory for replicating subscriptions. - broker.getConsumerFactories().add( - shared_ptr( - new ReplicatingSubscription::Factory(*this))); - - // If we are in a cluster, start as backup in joining state. - if (settings.cluster) { - assert(membership.getStatus() == JOINING); - role.reset(new Backup(*this, settings)); - broker.getKnownBrokers = boost::bind(&HaBroker::getKnownBrokers, this); - if (!isNone(settings.publicUrl)) setPublicUrl(Url(settings.publicUrl)); - if (!isNone(settings.brokerUrl)) setBrokerUrl(Url(settings.brokerUrl)); - } -} - -HaBroker::~HaBroker() { - broker.getConnectionObservers().remove(observer); -} - -Manageable::status_t HaBroker::ManagementMethod (uint32_t methodId, Args& args, string&) { - switch (methodId) { - case _qmf::HaBroker::METHOD_PROMOTE: { - Role* r = role->promote(); - if (r) role.reset(r); - break; - } - case _qmf::HaBroker::METHOD_SETBROKERSURL: { - setBrokerUrl(Url(dynamic_cast<_qmf::ArgsHaBrokerSetBrokersUrl&>(args).i_url)); - break; - } - case _qmf::HaBroker::METHOD_SETPUBLICURL: { - setPublicUrl(Url(dynamic_cast<_qmf::ArgsHaBrokerSetPublicUrl&>(args).i_url)); - break; - } - case _qmf::HaBroker::METHOD_REPLICATE: { - _qmf::ArgsHaBrokerReplicate& bq_args = - dynamic_cast<_qmf::ArgsHaBrokerReplicate&>(args); - QPID_LOG(debug, logPrefix << "Replicate individual queue " - << bq_args.i_queue << " from " << bq_args.i_broker); - - shared_ptr queue = broker.getQueues().get(bq_args.i_queue); - Url url(bq_args.i_broker); - string protocol = url[0].protocol.empty() ? "tcp" : url[0].protocol; - Uuid uuid(true); - std::pair result = broker.getLinks().declare( - broker::QPID_NAME_PREFIX + string("ha.link.") + uuid.str(), - url[0].host, url[0].port, protocol, - false, // durable - settings.mechanism, settings.username, settings.password, - false); // no amq.failover - don't want to use client URL. - shared_ptr link = result.first; - link->setUrl(url); - // Create a queue replicator - shared_ptr qr(QueueReplicator::create(*this, queue, link)); - broker.getExchanges().registerExchange(qr); - break; - } - - default: - return Manageable::STATUS_UNKNOWN_METHOD; - } - return Manageable::STATUS_OK; -} - -void HaBroker::setPublicUrl(const Url& url) { - Mutex::ScopedLock l(lock); - publicUrl = url; - mgmtObject->set_publicUrl(url.str()); - knownBrokers.clear(); - knownBrokers.push_back(url); - vector urls(1, url); - failoverExchange->updateUrls(urls); - QPID_LOG(debug, logPrefix << "Public URL set to: " << url); -} - -void HaBroker::setBrokerUrl(const Url& url) { - { - Mutex::ScopedLock l(lock); - brokerUrl = url; - mgmtObject->set_brokersUrl(brokerUrl.str()); - QPID_LOG(info, logPrefix << "Brokers URL set to: " << url); - } - role->setBrokerUrl(url); // Oustside lock -} - -std::vector HaBroker::getKnownBrokers() const { - Mutex::ScopedLock l(lock); - return knownBrokers; -} - -void HaBroker::shutdown(const std::string& message) { - QPID_LOG(critical, logPrefix << "Shutting down: " << message); - broker.shutdown(); - throw Exception(message); -} - -BrokerStatus HaBroker::getStatus() const { - return membership.getStatus(); -} - -void HaBroker::setAddress(const Address& a) { - QPID_LOG(info, logPrefix << "Set self address to: " << a); - membership.setSelfAddress(a); -} - -boost::shared_ptr HaBroker::findQueueReplicator(const std::string& queueName) { - return boost::dynamic_pointer_cast( - broker.getExchanges().find(QueueReplicator::replicatorName(queueName))); -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/HaBroker.h b/qpid/cpp/src/qpid/ha/HaBroker.h deleted file mode 100644 index 023706e7e3..0000000000 --- a/qpid/cpp/src/qpid/ha/HaBroker.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef QPID_HA_BROKER_H -#define QPID_HA_BROKER_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 "BrokerInfo.h" -#include "Membership.h" -#include "types.h" -#include "LogPrefix.h" -#include "Settings.h" -#include "qpid/Url.h" -#include "FailoverExchange.h" -#include "qpid/sys/Mutex.h" -#include "qmf/org/apache/qpid/ha/HaBroker.h" -#include "qpid/management/Manageable.h" -#include "qpid/types/Variant.h" -#include -#include - -namespace qpid { - -namespace types { -class Variant; -} - -namespace broker { -class Broker; -class Queue; -} -namespace framing { -class FieldTable; -} - -namespace ha { -class Backup; -class ConnectionObserver; -class Primary; -class Role; -class QueueReplicator; - -/** - * HA state and actions associated with a HA broker. Holds all the management info. - * - * THREAD SAFE: may be called in arbitrary broker IO or timer threads. - - * NOTE: HaBroker and Role subclasses follow this lock hierarchy: - * - HaBroker MUST NOT hold its own lock across calls Role subclasses. - * - Role subclasses MAY hold their locks accross calls to HaBroker. - */ -class HaBroker : public management::Manageable -{ - public: - /** HaBroker is constructed during earlyInitialize */ - HaBroker(broker::Broker&, const Settings&); - ~HaBroker(); - - /** Called during plugin initialization */ - void initialize(); - - // Implement Manageable. - qpid::management::ManagementObject::shared_ptr GetManagementObject() const { return mgmtObject; } - management::Manageable::status_t ManagementMethod ( - uint32_t methodId, management::Args& args, std::string& text); - - broker::Broker& getBroker() { return broker; } - const Settings& getSettings() const { return settings; } - boost::shared_ptr getRole() const {return role; } - - /** Shut down the broker because of a critical error. */ - void shutdown(const std::string& message); - - BrokerStatus getStatus() const; - boost::shared_ptr getObserver() { return observer; } - - BrokerInfo getBrokerInfo() const { return membership.getSelf(); } - Membership& getMembership() { return membership; } - types::Uuid getSystemId() const { return systemId; } - - void setAddress(const Address&); // set self address from a self-connection - - boost::shared_ptr findQueueReplicator(const std::string& queueName); - - /** Authenticated user ID for queue create/delete */ - std::string getUserId() const { return userId; } - - /** logPrefix is thread safe and used by other classes (Membership) */ - LogPrefix logPrefix; - - private: - class BrokerObserver; - - void setPublicUrl(const Url&); - void setBrokerUrl(const Url&); - void updateClientUrl(sys::Mutex::ScopedLock&); - - std::vector getKnownBrokers() const; - - // Immutable members - const types::Uuid systemId; - const Settings settings; - const std::string userId; - - // Member variables protected by lock - mutable sys::Mutex lock; - Url publicUrl, brokerUrl; - std::vector knownBrokers; - - // Independently thread-safe member variables - broker::Broker& broker; - qmf::org::apache::qpid::ha::HaBroker::shared_ptr mgmtObject; - boost::shared_ptr observer; // Used by Backup and Primary - boost::shared_ptr role; - Membership membership; - boost::shared_ptr failoverExchange; -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_BROKER_H*/ diff --git a/qpid/cpp/src/qpid/ha/HaPlugin.cpp b/qpid/cpp/src/qpid/ha/HaPlugin.cpp deleted file mode 100644 index 913a9b5084..0000000000 --- a/qpid/cpp/src/qpid/ha/HaPlugin.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * 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 "HaBroker.h" -#include "Settings.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/OptionsTemplates.h" -#include "qpid/broker/Broker.h" -#include - -namespace qpid { - -template po::value_semantic* create_value(ha::Enum& val, const std::string& arg); - -namespace ha { - -using namespace std; - -struct Options : public qpid::Options { - Settings& settings; - Options(Settings& s) : qpid::Options("HA Options"), settings(s) { - addOptions() - ("ha-cluster", optValue(settings.cluster, "yes|no"), - "Join a HA active/passive cluster.") - ("ha-queue-replication", optValue(settings.queueReplication, "yes|no"), - "Enable replication of specific queues without joining a cluster") - ("ha-brokers-url", optValue(settings.brokerUrl,"URL"), - "URL with address of each broker in the cluster.") - ("ha-public-url", optValue(settings.publicUrl,"URL"), - "URL advertized to clients to connect to the cluster.") - ("ha-replicate", - optValue(settings.replicateDefault, "LEVEL"), - "Replication level for creating queues and exchanges if there is no qpid.replicate argument supplied. LEVEL is 'none', 'configuration' or 'all'") - ("ha-username", optValue(settings.username, "USER"), - "Username for connections between HA brokers") - ("ha-password", optValue(settings.password, "PASS"), - "Password for connections between HA brokers") - ("ha-mechanism", optValue(settings.mechanism, "MECH"), - "Authentication mechanism for connections between HA brokers") - ("ha-backup-timeout", optValue(settings.backupTimeout, "SECONDS"), - "Maximum time to wait for an expected backup to connect and become ready.") - ("ha-flow-messages", optValue(settings.flowMessages, "N"), - "Flow control message count limit for replication, 0 means no limit") - ("ha-flow-bytes", optValue(settings.flowBytes, "N"), - "Flow control byte limit for replication, 0 means no limit") - ; - } -}; - -struct HaPlugin : public Plugin { - - Settings settings; - Options options; - auto_ptr haBroker; - - HaPlugin() : options(settings) {} - - Options* getOptions() { return &options; } - - void earlyInitialize(Plugin::Target& target) { - broker::Broker* broker = dynamic_cast(&target); - if (broker && (settings.cluster || settings.queueReplication)) { - if (!broker->getManagementAgent()) { - QPID_LOG(warning, "Cannot start HA: management is disabled"); - if (settings.cluster) - throw Exception("Cannot start HA: management is disabled"); - } else { - // Must create the HaBroker in earlyInitialize so it can set up its - // connection observer before clients start connecting. - haBroker.reset(new ha::HaBroker(*broker, settings)); - broker->addFinalizer(boost::bind(&HaPlugin::finalize, this)); - } - } - } - - void initialize(Plugin::Target& target) { - broker::Broker* broker = dynamic_cast(&target); - if (broker && haBroker.get()) haBroker->initialize(); - } - - void finalize() { - haBroker.reset(); - } -}; - -HaPlugin instance; // Static initialization. - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/IdSetter.h b/qpid/cpp/src/qpid/ha/IdSetter.h deleted file mode 100644 index 94bc74668e..0000000000 --- a/qpid/cpp/src/qpid/ha/IdSetter.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef QPID_HA_IDSETTER_H -#define QPID_HA_IDSETTER_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/broker/MessageInterceptor.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/AtomicValue.h" - - -namespace qpid { -namespace ha { -class LogPrefix; - -/** - * A MessageInterceptor that sets the ReplicationId on each message as it is - * enqueued on a primary queue. - * - * THREAD UNSAFE: Called sequentially under the queue lock. - */ -class IdSetter : public broker::MessageInterceptor -{ - public: - IdSetter(const LogPrefix& lp, const std::string& q, ReplicationId firstId=1) : - logPrefix(lp), queue(q), nextId(firstId) - {} - - void record(broker::Message& m) { - // Record is called when a message is first delivered to a queue, before it has - // been enqueued or saved in a transaction buffer. This is when we normally want - // to assign a replication-id. - m.setReplicationId(nextId++); - } - - void publish(broker::Message& m) { - // Publish is called when a message is assigned a position on the queue, - // after any transaction has comitted. Normally this is too late to - // assign a replication-id but during broker start-up and recovery from - // store record() is not called, so set the ID now if not already set. - if (!m.hasReplicationId()) { - m.setReplicationId(nextId++); - } - } - - private: - const LogPrefix& logPrefix; - std::string queue; - sys::AtomicValue nextId; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_IDSETTER_H*/ diff --git a/qpid/cpp/src/qpid/ha/LogPrefix.cpp b/qpid/cpp/src/qpid/ha/LogPrefix.cpp deleted file mode 100644 index c1ccf050c1..0000000000 --- a/qpid/cpp/src/qpid/ha/LogPrefix.cpp +++ /dev/null @@ -1,35 +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 "LogPrefix.h" -#include - -namespace qpid { -namespace ha { - -std::ostream& operator<<(std::ostream& o, const LogPrefix& lp) { - return o << lp.get(); -} - -std::ostream& operator<<(std::ostream& o, const LogPrefix2& lp) { - return o << lp.prePrefix.get() << lp.get(); -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/LogPrefix.h b/qpid/cpp/src/qpid/ha/LogPrefix.h deleted file mode 100644 index 3b6bb17d99..0000000000 --- a/qpid/cpp/src/qpid/ha/LogPrefix.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef QPID_HA_LOGPREFIX_H -#define QPID_HA_LOGPREFIX_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 -#include -#include - -namespace qpid { -namespace ha { - -/** - * Thread safe string holder to hold a string that may be read and modified concurrently. - */ -class LogPrefix -{ - public: - explicit LogPrefix(const std::string& s=std::string()) : prefix(s) {} - void set(const std::string& s) { sys::RWlock::ScopedWlock l(lock); prefix = s; } - std::string get() const { sys::RWlock::ScopedRlock l(lock); return prefix; } - - LogPrefix& operator=(const std::string& s) { set(s); return *this; } - operator std::string() const { return get(); } - - private: - // Undefined, not copyable. - LogPrefix(const LogPrefix& lp); - LogPrefix& operator=(const LogPrefix&); - - mutable sys::RWlock lock; - std::string prefix; -}; -std::ostream& operator<<(std::ostream& o, const LogPrefix& lp); - -/** - * A two-part log prefix with a reference to a pre-prefix and a post-prefix. - * Operator << will print both parts, get/set just manage the post-prefix. - */ -class LogPrefix2 : public LogPrefix { - public: - const LogPrefix& prePrefix; - explicit LogPrefix2(const LogPrefix& lp, const std::string& s=std::string()) : LogPrefix(s), prePrefix(lp) {} - LogPrefix2& operator=(const std::string& s) { set(s); return *this; } - - private: - // Undefined, not copyable. - LogPrefix2(const LogPrefix2& lp); - LogPrefix2& operator=(const LogPrefix2&); -}; -std::ostream& operator<<(std::ostream& o, const LogPrefix2& lp); - - -}} // namespace qpid::ha - -#endif /*!QPID_HA_LOGPREFIX_H*/ diff --git a/qpid/cpp/src/qpid/ha/Membership.cpp b/qpid/cpp/src/qpid/ha/Membership.cpp deleted file mode 100644 index 92a0b7db70..0000000000 --- a/qpid/cpp/src/qpid/ha/Membership.cpp +++ /dev/null @@ -1,228 +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 "ConnectionObserver.h" -#include "HaBroker.h" -#include "Membership.h" -#include "qpid/broker/Broker.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/types/Variant.h" -#include "qmf/org/apache/qpid/ha/EventMembersUpdate.h" -#include "qmf/org/apache/qpid/ha/HaBroker.h" -#include -#include -#include - -namespace qpid { -namespace ha { - -namespace _qmf = ::qmf::org::apache::qpid::ha; - -using sys::Mutex; -using types::Variant; - -Membership::Membership(const BrokerInfo& info, HaBroker& b) - : haBroker(b), self(info.getSystemId()) -{ - brokers[self] = info; - setPrefix(); - oldStatus = info.getStatus(); -} - -void Membership::setPrefix() { - haBroker.logPrefix = Msg() << shortStr(brokers[self].getSystemId()) - << "(" << printable(brokers[self].getStatus()) << ") "; -} -void Membership::clear() { - Mutex::ScopedLock l(lock); - BrokerInfo me = brokers[self]; - brokers.clear(); - brokers[self] = me; -} - -void Membership::add(const BrokerInfo& b) { - Mutex::ScopedLock l(lock); - assert(b.getSystemId() != self); - brokers[b.getSystemId()] = b; - update(true, l); -} - - -void Membership::remove(const types::Uuid& id) { - Mutex::ScopedLock l(lock); - if (id == self) return; // Never remove myself - BrokerInfo::Map::iterator i = brokers.find(id); - if (i != brokers.end()) { - brokers.erase(i); - update(true, l); - } -} - -bool Membership::contains(const types::Uuid& id) { - Mutex::ScopedLock l(lock); - return brokers.find(id) != brokers.end(); -} - -void Membership::assign(const types::Variant::List& list) { - Mutex::ScopedLock l(lock); - clear(); - for (types::Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { - BrokerInfo b(i->asMap()); - brokers[b.getSystemId()] = b; - } - update(true, l); -} - -types::Variant::List Membership::asList() const { - Mutex::ScopedLock l(lock); - return asList(l); -} - -types::Variant::List Membership::asList(sys::Mutex::ScopedLock&) const { - types::Variant::List list; - for (BrokerInfo::Map::const_iterator i = brokers.begin(); i != brokers.end(); ++i) - list.push_back(i->second.asMap()); - return list; -} - -BrokerInfo::Set Membership::otherBackups() const { - Mutex::ScopedLock l(lock); - BrokerInfo::Set result; - for (BrokerInfo::Map::const_iterator i = brokers.begin(); i != brokers.end(); ++i) - if (i->second.getStatus() == READY && i->second.getSystemId() != self) - result.insert(i->second); - 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); - if (i == brokers.end()) return false; - result = i->second; - return true; -} - -namespace { -bool checkTransition(BrokerStatus from, BrokerStatus to) { - // Legal state transitions. Initial state is JOINING, ACTIVE is terminal. - static const BrokerStatus TRANSITIONS[][2] = { - { STANDALONE, JOINING }, // Initialization of backup broker - { JOINING, CATCHUP }, // Connected to primary - { JOINING, RECOVERING }, // Chosen as initial primary. - { CATCHUP, READY }, // Caught up all queues, ready to take over. - { READY, RECOVERING }, // Chosen as new primary - { READY, CATCHUP }, // Timed out failing over, demoted to catch-up. - { RECOVERING, ACTIVE } // All expected backups are ready - }; - static const size_t N = sizeof(TRANSITIONS)/sizeof(TRANSITIONS[0]); - for (size_t i = 0; i < N; ++i) { - if (TRANSITIONS[i][0] == from && TRANSITIONS[i][1] == to) - return true; - } - return false; -} -} // namespace - -void Membership::update(bool log, Mutex::ScopedLock& l) { - // Update managment and send update event. - BrokerStatus newStatus = getStatus(l); - Variant::List brokerList = asList(l); - if (mgmtObject) { - mgmtObject->set_status(printable(newStatus).str()); - mgmtObject->set_members(brokerList); - } - haBroker.getBroker().getManagementAgent()->raiseEvent( - _qmf::EventMembersUpdate(brokerList)); - - // Update link client properties - framing::FieldTable linkProperties = haBroker.getBroker().getLinkClientProperties(); - if (isBackup(newStatus)) { - // Set backup tag on outgoing link properties. - linkProperties.setTable( - ConnectionObserver::BACKUP_TAG, brokers[types::Uuid(self)].asFieldTable()); - haBroker.getBroker().setLinkClientProperties(linkProperties); - } else { - // Remove backup tag property from outgoing link properties. - linkProperties.erase(ConnectionObserver::BACKUP_TAG); - haBroker.getBroker().setLinkClientProperties(linkProperties); - } - - // Check status transitions - if (oldStatus != newStatus) { - QPID_LOG(info, haBroker.logPrefix << "Status change: " - << printable(oldStatus) << " -> " << printable(newStatus)); - if (!checkTransition(oldStatus, newStatus)) { - haBroker.shutdown(QPID_MSG("Illegal state transition: " << printable(oldStatus) - << " -> " << printable(newStatus))); - } - oldStatus = newStatus; - setPrefix(); - if (newStatus == READY) QPID_LOG(notice, haBroker.logPrefix << "Backup is ready"); - } - if (log) QPID_LOG(info, haBroker.logPrefix << "Membership update: " << brokers); -} - -void Membership::setMgmtObject(boost::shared_ptr<_qmf::HaBroker> mo) { - Mutex::ScopedLock l(lock); - mgmtObject = mo; - update(false, l); -} - - -void Membership::setStatus(BrokerStatus newStatus) { - Mutex::ScopedLock l(lock); - brokers[self].setStatus(newStatus); - update(false, l); -} - -BrokerStatus Membership::getStatus() const { - Mutex::ScopedLock l(lock); - return getStatus(l); -} - -BrokerStatus Membership::getStatus(sys::Mutex::ScopedLock&) const { - BrokerInfo::Map::const_iterator i = brokers.find(self); - assert(i != brokers.end()); - return i->second.getStatus(); -} - -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::setSelfAddress(const Address& a) { - Mutex::ScopedLock l(lock); - brokers[self].setAddress(a); - update(false, l); -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/Membership.h b/qpid/cpp/src/qpid/ha/Membership.h deleted file mode 100644 index 5590d255fa..0000000000 --- a/qpid/cpp/src/qpid/ha/Membership.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef QPID_HA_MEMBERSHIP_H -#define QPID_HA_MEMBERSHIP_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 "BrokerInfo.h" -#include "types.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Time.h" -#include "qpid/types/Variant.h" -#include -#include -#include -#include - -namespace qmf { namespace org { namespace apache { namespace qpid { namespace ha { -class HaBroker; -}}}}} - -namespace qpid { - -namespace broker { -class Broker; -} - -namespace types { -class Uuid; -} - -namespace ha { -class HaBroker; - -/** - * Keep track of the brokers in the membership. - * Send management when events on membership changes. - * THREAD SAFE - */ -class Membership -{ - public: - Membership(const BrokerInfo& info, HaBroker&); - - void setMgmtObject(boost::shared_ptr); - - void clear(); ///< Clear all but self. - void add(const BrokerInfo& b); - void remove(const types::Uuid& id); - bool contains(const types::Uuid& id); - - /** 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; - - BrokerInfo getSelf() const; - BrokerStatus getStatus() const; - void setStatus(BrokerStatus s); - - void setSelfAddress(const Address&); - - private: - void setPrefix(); - void update(bool log, sys::Mutex::ScopedLock&); - BrokerStatus getStatus(sys::Mutex::ScopedLock&) const; - types::Variant::List asList(sys::Mutex::ScopedLock&) const; - - mutable sys::Mutex lock; - HaBroker& haBroker; - boost::shared_ptr mgmtObject; - const types::Uuid self; - BrokerInfo::Map brokers; - BrokerStatus oldStatus; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_MEMBERSHIP_H*/ diff --git a/qpid/cpp/src/qpid/ha/Primary.cpp b/qpid/cpp/src/qpid/ha/Primary.cpp deleted file mode 100644 index 3a9c9a86d9..0000000000 --- a/qpid/cpp/src/qpid/ha/Primary.cpp +++ /dev/null @@ -1,439 +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 "Backup.h" -#include "HaBroker.h" -#include "Primary.h" -#include "ReplicationTest.h" -#include "IdSetter.h" -#include "ReplicatingSubscription.h" -#include "RemoteBackup.h" -#include "ConnectionObserver.h" -#include "QueueReplicator.h" -#include "qpid/assert.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/BrokerObserver.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/amqp_0_10/Connection.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/SessionHandlerObserver.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/log/Statement.h" -#include "qpid/types/Uuid.h" -#include "qpid/types/Variant.h" -#include "qpid/sys/Timer.h" -#include -#include -#include - -namespace qpid { -namespace ha { - -using sys::Mutex; -using boost::shared_ptr; -using boost::intrusive_ptr; -using namespace std; -using namespace framing; - -namespace { - -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); - -class PrimaryConnectionObserver : public broker::ConnectionObserver -{ - public: - PrimaryConnectionObserver(Primary& p) : primary(p) {} - void opened(broker::Connection& c) { primary.opened(c); } - void closed(broker::Connection& c) { primary.closed(c); } - private: - Primary& primary; -}; - -class PrimaryBrokerObserver : public broker::BrokerObserver -{ - public: - 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: - Primary& primary; -}; - -class ExpectedBackupTimerTask : public sys::TimerTask { - public: - ExpectedBackupTimerTask(Primary& p, sys::AbsTime deadline) - : TimerTask(deadline, "ExpectedBackupTimerTask"), primary(p) {} - void fire() { primary.timeoutExpectedBackups(); } - private: - Primary& primary; -}; - -class PrimaryErrorListener : public broker::SessionHandler::ErrorListener { - public: - PrimaryErrorListener(const LogPrefix& lp) : logPrefix(lp) {} - - void connectionException(framing::connection::CloseCode code, const std::string& msg) { - QPID_LOG(debug, logPrefix << framing::createConnectionException(code, msg).what()); - } - void channelException(framing::session::DetachCode code, const std::string& msg) { - QPID_LOG(debug, logPrefix << framing::createChannelException(code, msg).what()); - } - void executionException(framing::execution::ErrorCode code, const std::string& msg) { - QPID_LOG(debug, logPrefix << framing::createSessionException(code, msg).what()); - } - void incomingExecutionException(framing::execution::ErrorCode code, const std::string& msg) { - QPID_LOG(debug, logPrefix << "Incoming " << framing::createSessionException(code, msg).what()); - } - void detach() {} - - private: - const LogPrefix& logPrefix; -}; - -class PrimarySessionHandlerObserver : public broker::SessionHandlerObserver { - public: - PrimarySessionHandlerObserver(const LogPrefix& logPrefix) - : errorListener(new PrimaryErrorListener(logPrefix)) {} - void newSessionHandler(broker::SessionHandler& sh) { - BrokerInfo info; - // Suppress error logging for backup connections - // TODO aconway 2014-01-31: Be more selective, suppress only expected errors? - if (ha::ConnectionObserver::getBrokerInfo(sh.getConnection(), info)) { - sh.setErrorListener(errorListener); - } - } - private: - boost::shared_ptr errorListener; -}; - - -} // namespace - -Primary::Primary(HaBroker& hb, const BrokerInfo::Set& expect) : - haBroker(hb), membership(hb.getMembership()), - logPrefix(hb.logPrefix), active(false), - replicationTest(hb.getSettings().replicateDefault.get()), - sessionHandlerObserver(new PrimarySessionHandlerObserver(logPrefix)), - queueLimits(logPrefix, hb.getBroker().getQueues(), replicationTest) -{ - // Note that at this point, we are still rejecting client connections. - // So we are safe from client interference while we set up the primary. - - hb.getMembership().setStatus(RECOVERING); - QPID_LOG(notice, logPrefix << "Promoted to primary"); - - // Process all QueueReplicators, handles auto-delete queues. - QueueReplicator::Vector qrs; - QueueReplicator::copy(hb.getBroker().getExchanges(), qrs); - std::for_each(qrs.begin(), qrs.end(), boost::bind(&QueueReplicator::promoted, _1)); - - if (!expect.empty()) { - // 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 << "Recovering backups: " << expect); - for (BrokerInfo::Set::const_iterator i = expect.begin(); i != expect.end(); ++i) { - boost::shared_ptr backup(new RemoteBackup(*i, 0, haBroker.logPrefix)); - backups[i->getSystemId()] = backup; - if (!backup->isReady()) expectedBackups.insert(backup); - setCatchupQueues(backup, true); // Create guards - } - // Set timeout for expected brokers to connect and become ready. - sys::AbsTime deadline(sys::now(), hb.getSettings().backupTimeout); - timerTask = new ExpectedBackupTimerTask(*this, deadline); - hb.getBroker().getTimer().add(timerTask); - } - brokerObserver.reset(new PrimaryBrokerObserver(*this)); - haBroker.getBroker().getBrokerObservers().add(brokerObserver); - haBroker.getBroker().getSessionHandlerObservers().add(sessionHandlerObserver); - - checkReady(); // Outside lock - - // Allow client connections - connectionObserver.reset(new PrimaryConnectionObserver(*this)); - haBroker.getObserver()->setObserver(connectionObserver); -} - -Primary::~Primary() { - if (timerTask) timerTask->cancel(); - haBroker.getBroker().getBrokerObservers().remove(brokerObserver); - haBroker.getBroker().getSessionHandlerObservers().remove(sessionHandlerObserver); - haBroker.getObserver()->reset(); -} - -void Primary::checkReady() { - bool activate = false; - { - Mutex::ScopedLock l(lock); - if (!active && expectedBackups.empty()) - activate = active = true; - } - if (activate) { - membership.setStatus(ACTIVE); // Outside of lock. - QPID_LOG(notice, logPrefix << "All backups recovered."); - } -} - -void Primary::checkReady(boost::shared_ptr backup) { - bool ready = false; - { - Mutex::ScopedLock l(lock); - if (backup->reportReady()) { - BrokerInfo info = backup->getBrokerInfo(); - info.setStatus(READY); - membership.add(info); - if (expectedBackups.erase(backup)) { - QPID_LOG(info, logPrefix << "Recovering backup is ready: " << info); - ready = true; - } - else - QPID_LOG(info, logPrefix << "New backup is ready: " << info); - } - } - if (ready) checkReady(); // Outside lock -} - -void Primary::timeoutExpectedBackups() { - try { - sys::Mutex::ScopedLock l(lock); - if (active) return; // Already activated - // Remove records for any expectedBackups that are not yet connected - // Allow backups that are connected to continue becoming ready. - for (BackupSet::iterator i = expectedBackups.begin(); i != expectedBackups.end();) - { - // This loop erases elements of backups in backupDisconnect, so - // save and increment the iterator. - BackupSet::iterator j = i++; - boost::shared_ptr backup = *j; - if (!backup->getConnection()) { - BrokerInfo info = backup->getBrokerInfo(); - QPID_LOG(error, logPrefix << "Recovering backup timed out: " << info); - backupDisconnect(backup, l); // Calls erase(j) - // Keep broker in membership but downgrade status to CATCHUP. - // The broker will get this status change when it eventually connects. - info.setStatus(CATCHUP); - membership.add(info); - } - } - } - catch(const std::exception& e) { - QPID_LOG(error, logPrefix << "Error timing out backups: " << e.what()); - // No-where for this exception to go. - } - checkReady(); -} - -void Primary::readyReplica(const ReplicatingSubscription& rs) { - shared_ptr backup; - { - sys::Mutex::ScopedLock l(lock); - BackupMap::iterator i = backups.find(rs.getBrokerInfo().getSystemId()); - if (i != backups.end()) { - backup = i->second; - backup->ready(rs.getQueue()); - } - } - if (backup) checkReady(backup); -} - -// NOTE: Called with queue registry lock held. -void Primary::queueCreate(const QueuePtr& q) { - // Set replication argument. - ReplicateLevel level = replicationTest.useLevel(*q); - q->addArgument(QPID_REPLICATE, printable(level).str()); - if (level) { - QPID_LOG(debug, logPrefix << "Created queue " << q->getName() - << " replication: " << printable(level)); - // Give each queue a unique id. Used by backups to avoid confusion of - // same-named queues. - q->addArgument(QPID_HA_UUID, types::Variant(Uuid(true))); - { - Mutex::ScopedLock l(lock); - queueLimits.addQueue(q); // Throws if limit exceeded - for (BackupMap::iterator i = backups.begin(); i != backups.end(); ++i) - i->second->queueCreate(q); - } - checkReady(); // Outside lock - } -} - -// NOTE: Called with queue registry lock held. -void Primary::queueDestroy(const QueuePtr& q) { - if (replicationTest.useLevel(*q)) { - QPID_LOG(debug, logPrefix << "Destroyed queue " << q->getName()); - { - Mutex::ScopedLock l(lock); - queueLimits.removeQueue(q); - for (BackupMap::iterator i = backups.begin(); i != backups.end(); ++i) - i->second->queueDestroy(q); - } - checkReady(); // Outside lock - } -} - -// NOTE: Called with exchange registry lock held. -void Primary::exchangeCreate(const ExchangePtr& ex) { - ReplicateLevel level = replicationTest.useLevel(*ex); - FieldTable args = ex->getArgs(); - args.setString(QPID_REPLICATE, printable(level).str()); // Set replication arg. - if (level) { - 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).data()))); - } - ex->setArgs(args); -} - -// NOTE: Called with exchange registry lock held. -void Primary::exchangeDestroy(const ExchangePtr& ex) { - if (replicationTest.useLevel(*ex)) { - QPID_LOG(debug, logPrefix << "Destroyed exchange " << ex->getName()); - // Do nothing - } - } - -// New backup connected -shared_ptr Primary::backupConnect( - const BrokerInfo& info, broker::Connection& connection, Mutex::ScopedLock&) -{ - shared_ptr backup(new RemoteBackup(info, &connection, haBroker.logPrefix)); - queueLimits.addBackup(backup); - backups[info.getSystemId()] = backup; - return backup; -} - -// Remove a backup. Caller should not release the shared pointer returend till -// outside the lock. -void Primary::backupDisconnect(shared_ptr backup, Mutex::ScopedLock&) { - queueLimits.addBackup(backup); - types::Uuid id = backup->getBrokerInfo().getSystemId(); - backup->cancel(); - expectedBackups.erase(backup); - backups.erase(id); - membership.remove(id); -} - - -void Primary::opened(broker::Connection& connection) { - BrokerInfo info; - shared_ptr backup; - if (ha::ConnectionObserver::getBrokerInfo(connection, info)) { - Mutex::ScopedLock l(lock); - BackupMap::iterator i = backups.find(info.getSystemId()); - if (info.getStatus() == JOINING) { - info.setStatus(CATCHUP); - membership.add(info); - } - if (i == backups.end()) { - if (info.getStatus() == JOINING) { - info.setStatus(CATCHUP); - membership.add(info); - } - QPID_LOG(info, logPrefix << "New backup connection: " << info); - backup = backupConnect(info, connection, l); - } - else if (i->second->getConnection()) { - // The backup is failing over before we recieved the closed() call - // for its previous connection. Remove the old entry and create a new one. - QPID_LOG(error, logPrefix << "Known backup reconnect before disconnection: " << info); - backupDisconnect(i->second, l); - backup = backupConnect(info, connection, l); - } else { - QPID_LOG(info, logPrefix << "Known backup reconnection: " << info); - i->second->setConnection(&connection); - backup = i->second; - } - } - else { - const types::Variant::Map& properties = connection.getClientProperties(); - std::ostringstream pinfo; - types::Variant::Map::const_iterator i = properties.find(CLIENT_PROCESS_NAME); - // FIXME aconway 2014-08-13: Conditional on logging. - if (i != properties.end()) { - pinfo << " " << i->second; - i = properties.find(CLIENT_PID); - if (i != properties.end()) - pinfo << "(" << i->second << ")"; - } - QPID_LOG(info, logPrefix << "Accepted client connection " << connection.getMgmtId() << pinfo.str()); - } - - // Outside lock - if (backup) { - setCatchupQueues(backup, false); - checkReady(backup); - } - checkReady(); -} - -void Primary::closed(broker::Connection& connection) { - BrokerInfo info; - shared_ptr backup; - if (ha::ConnectionObserver::getBrokerInfo(connection, info)) { - Mutex::ScopedLock l(lock); - BackupMap::iterator i = backups.find(info.getSystemId()); - // NOTE: It is possible for a backup connection to be rejected while we - // are a backup, but closed() is called after we have become primary. - // Checking isConnected() lets us ignore such spurious closes. - if (i == backups.end()) { - QPID_LOG(info, logPrefix << "Disconnect from unknown backup " << info); - } - else if (i->second->getConnection() != &connection) { - QPID_LOG(info, logPrefix << "Late disconnect from backup " << info); - } - else { - QPID_LOG(info, logPrefix << "Disconnect from " - << (i->second->getConnection() ? "" : "disconnected ") - << "backup " << info); - // Assign to shared_ptr so it will be deleted after we release the lock. - backup = i->second; - backupDisconnect(backup, l); - } - } - checkReady(); -} - -boost::shared_ptr Primary::getGuard(const QueuePtr& q, const BrokerInfo& info) -{ - Mutex::ScopedLock l(lock); - BackupMap::iterator i = backups.find(info.getSystemId()); - return i == backups.end() ? boost::shared_ptr() : i->second->guard(q); -} - -Role* Primary::promote() { - QPID_LOG(info, logPrefix << "Ignoring promotion, already primary"); - return 0; -} - -void Primary::setCatchupQueues(const RemoteBackupPtr& backup, bool createGuards) { - // Do queue iteration outside the lock to avoid deadlocks with QueueRegistry. - haBroker.getBroker().getQueues().eachQueue( - boost::bind(&RemoteBackup::catchupQueue, backup, _1, createGuards)); - backup->startCatchup(); -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/Primary.h b/qpid/cpp/src/qpid/ha/Primary.h deleted file mode 100644 index 8ca36b35ac..0000000000 --- a/qpid/cpp/src/qpid/ha/Primary.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef QPID_HA_PRIMARY_H -#define QPID_HA_PRIMARY_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 "hash.h" -#include "BrokerInfo.h" -#include "LogPrefix.h" -#include "PrimaryQueueLimits.h" -#include "ReplicationTest.h" -#include "Role.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/unordered_map.h" -#include -#include -#include -#include - -namespace qpid { - -namespace broker { -class Queue; -class Connection; -class ConnectionObserver; -class BrokerObserver; -class SessionHandlerObserver; -} - -namespace sys { -class TimerTask; -} - -namespace ha { -class HaBroker; -class ReplicatingSubscription; -class RemoteBackup; -class QueueGuard; -class Membership; - -/** - * State associated with a primary broker: - * - sets queue guards and tracks readiness of initial backups till active. - * - sets queue guards on new queues for each backup. - * - * THREAD SAFE: called concurrently in arbitrary connection threads. - * - * Locking rules: BrokerObserver create/destroy functions are called with - * the QueueRegistry lock held. Functions holding Primary::lock *must not* - * directly or indirectly call on the queue registry. - */ -class Primary : public Role -{ - public: - typedef boost::shared_ptr QueuePtr; - typedef boost::shared_ptr ExchangePtr; - typedef boost::shared_ptr RemoteBackupPtr; - - Primary(HaBroker& hb, const BrokerInfo::Set& expectedBackups); - ~Primary(); - - // Role implementation - Role* promote(); - void setBrokerUrl(const Url&) {} - - void readyReplica(const ReplicatingSubscription&); - - // Called via BrokerObserver - void queueCreate(const QueuePtr&); - void queueDestroy(const QueuePtr&); - void exchangeCreate(const ExchangePtr&); - void exchangeDestroy(const ExchangePtr&); - - // Called via ConnectionObserver - void opened(broker::Connection& connection); - void closed(broker::Connection& connection); - - boost::shared_ptr getGuard(const QueuePtr& q, const BrokerInfo&); - - // Called in timer thread when the deadline for expected backups expires. - void timeoutExpectedBackups(); - - private: - typedef sys::unordered_map< - types::Uuid, RemoteBackupPtr, Hasher > BackupMap; - - typedef std::set BackupSet; - - typedef std::pair > UuidQueue; - - RemoteBackupPtr backupConnect(const BrokerInfo&, broker::Connection&, sys::Mutex::ScopedLock&); - void backupDisconnect(RemoteBackupPtr, sys::Mutex::ScopedLock&); - - void checkReady(); - void checkReady(RemoteBackupPtr); - void setCatchupQueues(const RemoteBackupPtr&, bool createGuards); - void deduplicate(); - - mutable sys::Mutex lock; - HaBroker& haBroker; - Membership& membership; - const LogPrefix& logPrefix; - bool active; - ReplicationTest replicationTest; - - /** - * Set of expected backups that must be ready before we declare ourselves - * active. These are backups that were known and ready before the primary - * crashed. As new primary we expect them to re-connect. - */ - BackupSet expectedBackups; - /** - * Map of all the expected backups plus all connected backups. - */ - BackupMap backups; - boost::shared_ptr connectionObserver; - boost::shared_ptr brokerObserver; - boost::shared_ptr sessionHandlerObserver; - boost::intrusive_ptr timerTask; - PrimaryQueueLimits queueLimits; -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_PRIMARY_H*/ diff --git a/qpid/cpp/src/qpid/ha/PrimaryQueueLimits.h b/qpid/cpp/src/qpid/ha/PrimaryQueueLimits.h deleted file mode 100644 index 6d0c55736a..0000000000 --- a/qpid/cpp/src/qpid/ha/PrimaryQueueLimits.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef QPID_HA_PRIMARYQUEUELIMITS_H -#define QPID_HA_PRIMARYQUEUELIMITS_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 "ReplicationTest.h" -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { -class Queue; -} - -namespace ha { -class LogPrefix; -class RemoteBackup; - -/** - * Track queue limits on the primary, ensure the primary does not attempt to - * replicate more queues than the backups can handle. - * - * THREAD UNSAFE: Protected by Primary::lock - */ -class PrimaryQueueLimits -{ - public: - // FIXME aconway 2014-01-24: hardcoded maxQueues, use negotiated channel-max - PrimaryQueueLimits(const LogPrefix& lp, - broker::QueueRegistry& qr, - const ReplicationTest& rt - ) : - logPrefix(lp), maxQueues(framing::CHANNEL_MAX-100), queues(0) - { - // Get initial count of replicated queues - qr.eachQueue(boost::bind(&PrimaryQueueLimits::addQueueIfReplicated, this, _1, rt)); - } - - /** Add a replicated queue - *@exception ResourceLimitExceededException if this would exceed the limit. - */ - void addQueue(const boost::shared_ptr& q) { - if (queues >= maxQueues) { - QPID_LOG(error, logPrefix << "Cannot create replicated queue " << q->getName() - << " exceeds limit of " << maxQueues - << " replicated queues."); - throw framing::ResourceLimitExceededException( - Msg() << "Exceeded replicated queue limit " << queues << " >= " << maxQueues); - } - else ++queues; - } - - void addQueueIfReplicated(const boost::shared_ptr& q, const ReplicationTest& rt) { - if(rt.useLevel(*q)) addQueue(q); - } - - /** Remove a replicated queue. - * @pre Was previously added with addQueue - */ - void removeQueue(const boost::shared_ptr&) { - assert(queues != 0); - --queues; - } - - // TODO aconway 2014-01-24: Currently replication links always use the - // hard-coded framing::CHANNEL_MAX. In future (e.g. when we support AMQP1.0 - // on replication links) we may need to check the actual channel max on each - // link and update maxQueues to the smallest value. addBackup and removeBackup - // are placeholders for that. - - /** Add a backup */ - void addBackup(const boost::shared_ptr&) {} - - /** Remove a backup */ - void removeBackup(const boost::shared_ptr&) {} - - private: - const LogPrefix& logPrefix; - uint64_t maxQueues; - uint64_t queues; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_PRIMARYQUEUELIMITS_H*/ diff --git a/qpid/cpp/src/qpid/ha/QueueGuard.cpp b/qpid/cpp/src/qpid/ha/QueueGuard.cpp deleted file mode 100644 index b6b6037b6f..0000000000 --- a/qpid/cpp/src/qpid/ha/QueueGuard.cpp +++ /dev/null @@ -1,123 +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 "QueueGuard.h" -#include "BrokerInfo.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/log/Statement.h" -#include -#include - -namespace qpid { -namespace ha { - -using namespace broker; -using sys::Mutex; - -class QueueGuard::QueueObserver : public broker::QueueObserver -{ - public: - QueueObserver(QueueGuard& g) : guard(g) {} - void enqueued(const broker::Message& m) { guard.enqueued(m); } - void dequeued(const broker::Message& m) { guard.dequeued(m); } - void acquired(const broker::Message&) {} - void requeued(const broker::Message&) {} - private: - QueueGuard& guard; -}; - - - -QueueGuard::QueueGuard(broker::Queue& q, const BrokerInfo& info, const LogPrefix& lp) - : cancelled(false), logPrefix(lp), queue(q) -{ - std::ostringstream os; - os << "Guard of " << queue.getName() << " at "; - info.printId(os) << ": "; - logPrefix = os.str(); - observer.reset(new QueueObserver(*this)); - queue.getObservers().add(observer); - // Set first after adding the observer so we know that the back of the - // queue+1 is (or will be) a guarded position. - QueuePosition front, back; - q.getRange(front, back, broker::REPLICATOR); - first = back + 1; - QPID_LOG(debug, logPrefix << "Guarded: front " << front - << ", back " << back - << ", guarded " << first); -} - -QueueGuard::~QueueGuard() { cancel(); } - -// NOTE: Called with message lock held. -void QueueGuard::enqueued(const Message& m) { - // Delay completion - ReplicationId id = m.getReplicationId(); - Mutex::ScopedLock l(lock); - if (cancelled) return; // Don't record enqueues after we are cancelled. - QPID_LOG(trace, logPrefix << "Delayed completion of " << logMessageId(queue, m)); - delayed[id] = m.getIngressCompletion(); - m.getIngressCompletion()->startCompleter(); -} - -// NOTE: Called with message lock held. -void QueueGuard::dequeued(const Message& m) { - ReplicationId id = m.getReplicationId(); - QPID_LOG(trace, logPrefix << "Dequeued " << logMessageId(queue, m)); - Mutex::ScopedLock l(lock); - complete(id, l); -} - -void QueueGuard::cancel() { - queue.getObservers().remove(observer); - Mutex::ScopedLock l(lock); - if (cancelled) return; - QPID_LOG(debug, logPrefix << "Cancelled"); - cancelled = true; - while (!delayed.empty()) complete(delayed.begin(), l); -} - -bool QueueGuard::complete(ReplicationId id) { - Mutex::ScopedLock l(lock); - return complete(id, l); -} - -bool QueueGuard::complete(ReplicationId id, Mutex::ScopedLock& l) { - // The same message can be completed twice, by - // ReplicatingSubscription::acknowledged and dequeued. Remove it - // from the map so we only call finishCompleter() once - Delayed::iterator i = delayed.find(id); - if (i != delayed.end()) { - complete(i, l); - return true; - } - return false; -} - -void QueueGuard::complete(Delayed::iterator i, Mutex::ScopedLock&) { - QPID_LOG(trace, logPrefix << "Completed " << queue.getName() << " =" << i->first); - i->second->finishCompleter(); - delayed.erase(i); -} - - -}} // namespaces qpid::ha diff --git a/qpid/cpp/src/qpid/ha/QueueGuard.h b/qpid/cpp/src/qpid/ha/QueueGuard.h deleted file mode 100644 index 9bf61f31da..0000000000 --- a/qpid/cpp/src/qpid/ha/QueueGuard.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef QPID_HA_QUEUEGUARD_H -#define QPID_HA_QUEUEGUARD_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 "hash.h" -#include "LogPrefix.h" -#include "qpid/types/Uuid.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/unordered_map.h" -#include -#include -#include -#include - -namespace qpid { -namespace broker { -class Queue; -struct QueuedMessage; -class Message; -class AsyncCompletion; -} - -namespace ha { -class BrokerInfo; -class ReplicatingSubscription; - -/** - * A queue guard is a QueueObserver that delays completion of new messages - * arriving on a queue. It works as part of a ReplicatingSubscription to ensure - * messages are not acknowledged till they have been replicated. - * - * The guard can be created before the ReplicatingSubscription to protect - * messages arriving before the creation of the subscription. - * - * THREAD SAFE: Concurrent calls: - * - enqueued() via QueueObserver in arbitrary connection threads. - * - cancel(), complete() from ReplicatingSubscription in subscription thread. - * - */ -class QueueGuard { - public: - QueueGuard(broker::Queue& q, const BrokerInfo&, const LogPrefix&); - ~QueueGuard(); - - /** QueueObserver override. Delay completion of the message. - * NOTE: Called under the queues message lock. - */ - void enqueued(const broker::Message&); - - /** QueueObserver override: Complete a delayed message. - * NOTE: Called under the queues message lock. - */ - void dequeued(const broker::Message&); - - /** Complete a delayed message. - *@return true if the ID was delayed - */ - bool complete(ReplicationId); - - /** Complete all delayed messages. */ - void cancel(); - - /** Return the first known guarded position on the queue. It is possible - * that the guard has seen a few messages before this point. - */ - QueuePosition getFirst() const { return first; } // Thread safe: Immutable. - - private: - class QueueObserver; - typedef qpid::sys::unordered_map, - Hasher > Delayed; - - bool complete(ReplicationId, sys::Mutex::ScopedLock &); - void complete(Delayed::iterator, sys::Mutex::ScopedLock &); - - sys::Mutex lock; - QueuePosition first; - bool cancelled; - LogPrefix2 logPrefix; - broker::Queue& queue; - Delayed delayed; - boost::shared_ptr observer; -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_QUEUEGUARD_H*/ diff --git a/qpid/cpp/src/qpid/ha/QueueReplicator.cpp b/qpid/cpp/src/qpid/ha/QueueReplicator.cpp deleted file mode 100644 index c0d2689685..0000000000 --- a/qpid/cpp/src/qpid/ha/QueueReplicator.cpp +++ /dev/null @@ -1,414 +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 "Event.h" -#include "HaBroker.h" -#include "IdSetter.h" -#include "LogPrefix.h" -#include "QueueReplicator.h" -#include "QueueSnapshot.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" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/SessionHandler.h" -#include "qpid/broker/SessionState.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/log/Statement.h" -#include "qpid/Msg.h" -#include "qpid/assert.h" -#include -#include -#include - - -namespace qpid { -namespace ha { -using namespace broker; -using namespace framing; -using namespace framing::execution; -using namespace std; -using std::exception; -using sys::Mutex; -using boost::shared_ptr; - -const std::string QueueReplicator::QPID_SYNC_FREQUENCY("qpid.sync_frequency"); - -std::string QueueReplicator::replicatorName(const std::string& queueName) { - return QUEUE_REPLICATOR_PREFIX + queueName; -} - -bool QueueReplicator::isReplicatorName(const std::string& name) { - return startsWith(name, QUEUE_REPLICATOR_PREFIX); -} - -namespace { -void pushIfQr(QueueReplicator::Vector& v, const shared_ptr& ex) { - shared_ptr qr = boost::dynamic_pointer_cast(ex); - if (qr) v.push_back(qr); -} -} - -void QueueReplicator::copy(ExchangeRegistry& registry, Vector& result) { - registry.eachExchange(boost::bind(&pushIfQr, boost::ref(result), _1)); -} - -// Debug log expected exceptions on queue replicator, check incoming execution -// exceptions for "deleted on primary" conditions. -class QueueReplicator::ErrorListener : public SessionHandler::ErrorListener { - public: - ErrorListener(const boost::shared_ptr& qr) - : queueReplicator(qr), logPrefix(qr->logPrefix.prePrefix, qr->logPrefix.get()) {} - - void connectionException(framing::connection::CloseCode code, const std::string& msg) { - QPID_LOG(error, logPrefix << "Outgoing " << framing::createConnectionException(code, msg).what()); - } - void channelException(framing::session::DetachCode code, const std::string& msg) { - QPID_LOG(error, logPrefix << "Outgoing " << framing::createChannelException(code, msg).what()); - } - void executionException(framing::execution::ErrorCode code, const std::string& msg) { - QPID_LOG(error, logPrefix << "Outgoing " << framing::createSessionException(code, msg).what()); - } - void incomingExecutionException(ErrorCode code, const std::string& msg) { - boost::shared_ptr qr = queueReplicator.lock(); - if (!(qr && qr->deletedOnPrimary(code, msg))) - QPID_LOG(error, logPrefix << "Incoming " << framing::createSessionException(code, msg).what()); - } - void detach() {} - - private: - boost::weak_ptr queueReplicator; - LogPrefix2 logPrefix; -}; - -class QueueReplicator::QueueObserver : public broker::QueueObserver { - public: - typedef boost::shared_ptr Ptr; - QueueObserver(Ptr qr) : queueReplicator(qr) {} - - void enqueued(const Message& m) { - Ptr qr = queueReplicator.lock(); - if (qr) qr->enqueued(m); - } - - void dequeued(const Message& m) { - Ptr qr = queueReplicator.lock(); - if (qr) qr->dequeued(m); - } - - void acquired(const Message&) {} - void requeued(const Message&) {} - void consumerAdded( const Consumer& ) {} - void consumerRemoved( const Consumer& ) {} - // Queue observer is destroyed when the queue is. - void destroy() { - Ptr qr = queueReplicator.lock(); - if (qr) qr->destroy(); - } - - private: - boost::weak_ptr queueReplicator; -}; - - -boost::shared_ptr QueueReplicator::create( - HaBroker& hb, boost::shared_ptr q, boost::shared_ptr l) -{ - boost::shared_ptr qr(new QueueReplicator(hb, q, l)); - qr->initialize(); - return qr; -} - -QueueReplicator::QueueReplicator(HaBroker& hb, - boost::shared_ptr q, - boost::shared_ptr l) - : Exchange(replicatorName(q->getName()), 0, q->getBroker()), - haBroker(hb), - brokerInfo(hb.getBrokerInfo()), - link(l), - queue(q), - sessionHandler(0), - logPrefix(hb.logPrefix, "Backup of "+q->getName()+": "), - subscribed(false), - settings(hb.getSettings()), - nextId(0), maxId(0) -{ - QPID_LOG(debug, logPrefix << "Created"); - // The QueueReplicator will take over setting replication IDs. - boost::shared_ptr setter = - q->getMessageInterceptors().findType(); - if (setter) q->getMessageInterceptors().remove(setter); - - args.setString(QPID_REPLICATE, printable(NONE).str()); - Uuid uuid(true); - bridgeName = replicatorName(q->getName()) + std::string(".") + uuid.str(); - framing::FieldTable args = getArgs(); - args.setString(QPID_REPLICATE, printable(NONE).str()); - setArgs(args); - // Don't allow backup queues to auto-delete, primary decides when to delete. - if (q->isAutoDelete()) q->markInUse(false); - - dispatch[DequeueEvent::KEY] = - boost::bind(&QueueReplicator::dequeueEvent, this, _1, _2); - dispatch[IdEvent::KEY] = - boost::bind(&QueueReplicator::idEvent, this, _1, _2); -} - -QueueReplicator::~QueueReplicator() {} - -void QueueReplicator::initialize() { - Mutex::ScopedLock l(lock); - if (!queue) return; // Already destroyed - - // Enable callback to route() - if (!getBroker()->getExchanges().registerExchange(shared_from_this())) - throw Exception(QPID_MSG("Duplicate queue replicator " << getName())); - - // Enable callback to initializeBridge - boost::shared_ptr b = queue->getBroker()->getLinks().declare( - bridgeName, - *link, - false, // durable - queue->getName(), // src - getName(), // dest - "", // key - false, // isQueue - false, // isLocal - "", // id/tag - "", // excludes - false, // dynamic - 0, // sync? - LinkRegistry::INFINITE_CREDIT, - // Include shared_ptr to self to ensure we are not deleted - // before initializeBridge is called. - boost::bind(&QueueReplicator::initializeBridge, shared_from_this(), _1, _2) - ).first; - b->setErrorListener( - boost::shared_ptr(new ErrorListener(shared_from_this()))); - bridge = b; // bridge is a weak_ptr to avoid a cycle. - - // Enable callback to destroy() - queue->getObservers().add( - boost::shared_ptr(new QueueObserver(shared_from_this()))); -} - -void QueueReplicator::disconnect() { - Mutex::ScopedLock l(lock); - sessionHandler = 0; -} - -// Called from Queue::destroyed() -void QueueReplicator::destroy() { - QPID_LOG(debug, logPrefix << "Destroyed"); - boost::shared_ptr bridge2; // To call outside of lock - { - Mutex::ScopedLock l(lock); - if (!queue) return; // Already destroyed - bridge2 = bridge.lock(); // !call close outside the lock. - destroy(l); - } - if (bridge2) bridge2->close(); // Outside of lock, avoid deadlock. -} - -void QueueReplicator::destroy(Mutex::ScopedLock&) { - // Need to drop shared pointers to avoid pointer cycles keeping this in memory. - queue.reset(); - bridge.reset(); - getBroker()->getExchanges().destroy(getName()); -} - - -// 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_) { - Mutex::ScopedLock l(lock); - if (!queue) return; // Already destroyed - sessionHandler = &sessionHandler_; - if (sessionHandler->getSession()) { - // Don't overwrite the exchange property set on the primary. - sessionHandler->getSession()->getMessageBuilder().setCopyExchange(false); - } - AMQP_ServerProxy peer(sessionHandler->out); - const qmf::org::apache::qpid::broker::ArgsLinkBridge& args(bridge.getArgs()); - FieldTable arguments; - arguments.setString(ReplicatingSubscription::QPID_REPLICATING_SUBSCRIPTION, getType()); - arguments.setInt(QPID_SYNC_FREQUENCY, 1); // TODO aconway 2012-05-22: optimize? - arguments.setTable(ReplicatingSubscription::QPID_BROKER_INFO, brokerInfo.asFieldTable()); - boost::shared_ptr qs = queue->getObservers().findType(); - ReplicationIdSet snapshot; - if (qs) { - snapshot = qs->getSnapshot(); - arguments.set( - ReplicatingSubscription::QPID_ID_SET, - FieldTable::ValuePtr(new Var32Value(encodeStr(snapshot), TYPE_CODE_VBIN32))); - } - try { - peer.getMessage().subscribe( - args.i_src, args.i_dest, 0/*accept-explicit*/, 1/*not-acquired*/, - false/*exclusive*/, "", 0, arguments); - peer.getMessage().setFlowMode(getName(), 1); // Window - peer.getMessage().flow(getName(), 0, settings.getFlowMessages()); - peer.getMessage().flow(getName(), 1, settings.getFlowBytes()); - } - catch(const exception& e) { - QPID_LOG(error, logPrefix << "Cannot connect to primary: " << e.what()); - throw; - } - qpid::Address primary; - link->getRemoteAddress(primary); - QPID_LOG(debug, logPrefix << "Connected to " << primary << " snapshot=" << snapshot << " bridge=" << bridgeName); - QPID_LOG(trace, logPrefix << "Subscription arguments: " << arguments); -} - -namespace { -template T decodeContent(Message& m) { - std::string content = m.getContent(); - Buffer buffer(const_cast(content.c_str()), content.size()); - T result; - result.decode(buffer); - return result; -} -} - -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 = e.ids.begin(); i != e.ids.end(); ++i) { - QueuePosition position; - { - Mutex::ScopedLock l(lock); - PositionMap::iterator j = positions.find(*i); - if (j == positions.end()) continue; - position = j->second; - } - queue->dequeueMessageAt(position); // Outside lock, will call dequeued(). - // positions will be cleaned up in dequeued() - } -} - -// Called in connection thread of the queues bridge to primary. -void QueueReplicator::route(Deliverable& deliverable) -{ - try { - broker::Message& message(deliverable.getMessage()); - { - Mutex::ScopedLock l(lock); - if (!queue) return; // Already destroyed - string key(message.getRoutingKey()); - if (isEventKey(key)) { - DispatchMap::iterator i = dispatch.find(key); - if (i == dispatch.end()) { - QPID_LOG(info, logPrefix << "Ignoring unknown event: " << key); - } else { - (i->second)(message.getContent(), l); - } - return; - } - ReplicationId id = nextId++; - message.setReplicationId(id); - PositionMap::iterator i = positions.find(id); - if (i != positions.end()) { - QPID_LOG(trace, logPrefix << "Already on queue: " << logMessageId(*queue, message)); - return; - } - QPID_LOG(trace, logPrefix << "Received: " << logMessageId(*queue, message)); - } - deliver(message); // Outside lock, will call enqueued() - } - catch (const std::exception& e) { - haBroker.shutdown(QPID_MSG(logPrefix << "Replication failed: " << e.what())); - } - -} - -void QueueReplicator::deliver(const broker::Message& m) { - queue->deliver(m); -} - -// Called via QueueObserver when message is enqueued. Could be as part of deliver() -// or in a different thread if a message is enqueued via a transaction. -// -void QueueReplicator::enqueued(const broker::Message& m) { - Mutex::ScopedLock l(lock); - maxId = std::max(maxId, ReplicationId(m.getReplicationId())); - positions[m.getReplicationId()] = m.getSequence(); - QPID_LOG(trace, logPrefix << "Enqueued " << logMessageId(*queue, m)); -} - -// Called via QueueObserver -void QueueReplicator::dequeued(const broker::Message& m) { - Mutex::ScopedLock l(lock); - positions.erase(m.getReplicationId()); -} - -void QueueReplicator::idEvent(const string& data, Mutex::ScopedLock&) { - nextId = decodeStr(data).id; -} - -bool QueueReplicator::deletedOnPrimary(ErrorCode e, const std::string& msg) { - if (e == ERROR_CODE_NOT_FOUND || e == ERROR_CODE_RESOURCE_DELETED) { - // If the queue is destroyed at the same time we are subscribing, we may - // get a not-found or resource-deleted exception before the - // BrokerReplicator gets the queue-delete event. Shut down the bridge by - // calling destroy(), we can let the BrokerReplicator delete the queue - // when the queue-delete arrives. - QPID_LOG(debug, logPrefix << "Deleted on primary: " - << framing::createSessionException(e, msg).what()); - destroy(); - return true; - } - return false; -} - -// Unused Exchange methods. -bool QueueReplicator::bind(boost::shared_ptr, const std::string&, const FieldTable*) { return false; } -bool QueueReplicator::unbind(boost::shared_ptr, const std::string&, const FieldTable*) { return false; } -bool QueueReplicator::isBound(boost::shared_ptr, const std::string* const, const FieldTable* const) { return false; } -bool QueueReplicator::hasBindings() { return false; } -std::string QueueReplicator::getType() const { return ReplicatingSubscription::QPID_QUEUE_REPLICATOR; } - -void QueueReplicator::promoted() { - if (queue) { - // On primary QueueReplicator no longer sets IDs, start an IdSetter. - QPID_LOG(debug, logPrefix << "Promoted, first replication-id " << maxId+1) - queue->getMessageInterceptors().add( - boost::shared_ptr(new IdSetter(logPrefix, queue->getName(), maxId+1))); - // Process auto-deletes - if (queue->isAutoDelete()) { - // Make a temporary shared_ptr to prevent premature deletion of queue. - // Otherwise scheduleAutoDelete can call this->destroy, which resets this->queue - // which could delete the queue while it's still running it's destroyed logic. - boost::shared_ptr q(queue); - // See markInUse in ctor: release but don't delete if never used. - q->releaseFromUse(false/*controller*/, subscribed/*doDelete*/); - } - } -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/ha/QueueReplicator.h b/qpid/cpp/src/qpid/ha/QueueReplicator.h deleted file mode 100644 index a4b31b6c9a..0000000000 --- a/qpid/cpp/src/qpid/ha/QueueReplicator.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef QPID_HA_QUEUEREPLICATOR_H -#define QPID_HA_QUEUEREPLICATOR_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 "BrokerInfo.h" -#include "LogPrefix.h" -#include "hash.h" -#include "qpid/broker/Exchange.h" -#include -#include -#include - -namespace qpid { - -namespace broker { -class Bridge; -class Link; -class Queue; -class QueueRegistry; -class SessionHandler; -class Deliverable; -class ExchangeRegistry; -} - -namespace ha { -class HaBroker; -class Settings; - -/** - * Exchange created on a backup broker to receive replicated messages and - * replication events from a queue on the primary. It subscribes to the primary - * queue via a ReplicatingSubscription on the primary by passing special - * arguments to the subscribe command. - * - * It puts replicated messages on the local replica queue and handles dequeue - * events by removing local messages. - * - * THREAD SAFE: Called in different connection threads. - */ -class QueueReplicator : public broker::Exchange, - public boost::enable_shared_from_this -{ - public: - static const std::string QPID_SYNC_FREQUENCY; - static const std::string REPLICATOR_PREFIX; - typedef std::vector > Vector; - - static std::string replicatorName(const std::string& queueName); - static bool isReplicatorName(const std::string&); - /*** Copy QueueReplicators from the registry */ - static void copy(broker::ExchangeRegistry&, Vector& result); - - static boost::shared_ptr create( - HaBroker&, boost::shared_ptr q, boost::shared_ptr l); - - ~QueueReplicator(); - - void disconnect(); // Called when we are disconnected from the primary. - - virtual std::string getType() const; - - void route(broker::Deliverable&); - - // Called via QueueObserver - void enqueued(const broker::Message&); - void dequeued(const broker::Message&); - - // Set if the queue has ever been subscribed to, used for auto-delete cleanup. - void setSubscribed() { subscribed = true; } - - boost::shared_ptr getQueue() const { return queue; } - - // No-op unused Exchange virtual functions. - bool bind(boost::shared_ptr, const std::string&, const framing::FieldTable*); - bool unbind(boost::shared_ptr, const std::string&, const framing::FieldTable*); - bool isBound(boost::shared_ptr, const std::string* const, const framing::FieldTable* const); - bool hasBindings(); - - void promoted(); - - protected: - typedef boost::function DispatchFn; - typedef qpid::sys::unordered_map DispatchMap; - - QueueReplicator( - HaBroker&, boost::shared_ptr, boost::shared_ptr); - - void initialize(); // Called as part of create() - - virtual void deliver(const broker::Message&); - - virtual void destroy(); // Called when the queue is destroyed. - virtual void destroy(sys::Mutex::ScopedLock&); - - sys::Mutex lock; - HaBroker& haBroker; - const BrokerInfo brokerInfo; - DispatchMap dispatch; - boost::shared_ptr link; - boost::weak_ptr bridge; - boost::shared_ptr queue; - broker::SessionHandler* sessionHandler; - - private: - typedef qpid::sys::unordered_map< - ReplicationId, QueuePosition, Hasher > PositionMap; - class ErrorListener; - class QueueObserver; - - void initializeBridge(broker::Bridge& bridge, broker::SessionHandler& sessionHandler); - - // Dispatch functions - void dequeueEvent(const std::string& data, sys::Mutex::ScopedLock&); - void idEvent(const std::string& data, sys::Mutex::ScopedLock&); - - bool deletedOnPrimary(framing::execution::ErrorCode e, const std::string& msg); - - LogPrefix2 logPrefix; - std::string bridgeName; - - bool subscribed; - const Settings& settings; - PositionMap positions; - ReplicationIdSet idSet; // Set of replicationIds on the queue. - ReplicationId nextId; // ID for next message to arrive. - ReplicationId maxId; // Max ID used so far. - - friend class ErrorListener; -}; - - -}} // namespace qpid::ha - -#endif /*!QPID_HA_QUEUEREPLICATOR_H*/ diff --git a/qpid/cpp/src/qpid/ha/QueueSnapshot.h b/qpid/cpp/src/qpid/ha/QueueSnapshot.h deleted file mode 100644 index 577bd96ef7..0000000000 --- a/qpid/cpp/src/qpid/ha/QueueSnapshot.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_HA_IDSETOBSERVER_H -#define QPID_HA_IDSETOBSERVER_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/broker/QueueObserver.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace ha { - -/** - * A QueueObserver that maintains a ReplicationIdSet of the ReplicationIds of - * the messages on the queue. - * - * THREAD SAFE: Note that QueueObserver methods are called under the Queues messageLock. - * - */ -class QueueSnapshot : public broker::QueueObserver -{ - public: - void enqueued(const broker::Message& m) { - sys::Mutex::ScopedLock l(lock); - set += m.getReplicationId(); - } - - void dequeued(const broker::Message& m) { - sys::Mutex::ScopedLock l(lock); - set -= m.getReplicationId(); - } - - void acquired(const broker::Message&) {} - - void requeued(const broker::Message&) {} - - ReplicationIdSet getSnapshot() { - sys::Mutex::ScopedLock l(lock); - return set; - } - - private: - sys::Mutex lock; - ReplicationIdSet set; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_IDSETOBSERVER_H*/ diff --git a/qpid/cpp/src/qpid/ha/README.h b/qpid/cpp/src/qpid/ha/README.h deleted file mode 100644 index 9e8eda7e0d..0000000000 --- a/qpid/cpp/src/qpid/ha/README.h +++ /dev/null @@ -1,149 +0,0 @@ -// This header file provides an overview of the ha module for doxygen. - -namespace qpid { -namespace ha { // Auto-links for names in the ha namespace. - -/** \defgroup ha-module - \brief High Availability Module - -This is a brief overview of how HA replication works, intended as a starting -point to understand the code. You should _first_ read the HA chapter of the "C++ -broker book" at http://qpid.apache.org/documentation.html for a general -understanding of the active/passive, hot-standby strategy. - -Class names without a prefix are in the qpid::ha namespace. See the -documentation of individual classes for more detail. - -## Overview of HA classes. ## - -HaBroker is the main container for HA code, it holds a Role which can be Primary -or Backup. It is responsible for implementing QMF management functions. - -Backup implements the back-up Role. It holds a BrokerReplicator which subscribes -to management events on the primary e.g. create/delete queue/exchange/binding. -It uses a ReplicationTest to check if an object is configured for replication. -For replicated objects it creates corresponding broker::Queue, broker::Exchange -etc. on the local broker. - -For replicated queues the BrokerReplicator also creates a QueueReplicator. The -QueueReplicator subscribes to the primary queue with arguments to tell the -primary to use a ReplicatingSubscription. See "Queue Replication" below for -more on the ReplicatingSubscription/QueueReplicator interaction. - -Primary implements the primary Role. For each replicated queue it creates an -IdSetter to set replication IDs on messages delivered to the queue. Each backup -that connects is tracked by a RemoteBackup. - -For each (queue,backup) pair, the Primary creates a ReplicatingSubscription and -a QueueGuard. The QueueGuard delays completion of messages delivered to the -queue until they are replicated to and acknowledged by the backup. - -When the primary fails, one of the backups is promoted by an external cluster -resource manager. The other backups fail-over to the new primary. See "Queue -Fail Over" below. - -## Locating the Primary ## - -Clients connect to the cluster via one of: -- a virtual IP address that is assigned to the primary broker -- a list of addresses for all brokers. - -If the connection fails the client re-tries its address or list of addresses -till it re-connects. Backup brokers have a ConnectionObserver that rejects -client connections by aborting the connection, causing the client to re-try. - -## Message Identifiers ## - -Replication IDs are sequence numbers assigned to a message *before* it is -enqueued. We use the IDs to: -- identify messages to dequeue on a backup. -- remove extra messages from backup on failover. -- avoid downloading messages already on backup on failover. - -Aside: Originally the queue position number was used as the ID, but that was -insufficient for two reasons: -- We sometimes need to identify messages that are not yet enqueued, for example messages in an open transaction. -- We don't want to require maintaining identical message sequences on every broker e.g. so transactions can be committed independently by each broker. - -## At-least-once and delayed completion. ## - -We guarantee no message loss, aka at-least-once delivery. Any message received -_and acknowledged_ by the primary will not be lost. Clients must keep sent -messages until they are acknowledged. In a failure the client re-connects and -re-sends all unacknowledged (or "in-doubt") messages. - -This ensures no messages are lost, but it is possible for in-doubt messages to -be duplicated if the broker did receive them but failed before sending the -acknowledgment. It is up to the application to handle duplicates correctly. - -We implement the broker's side of the bargain using _delayed completion_. When -the primary receives a message it does not complete (acknowledge) the message -until the message is replicated to and acknowledged by all the backups. In the -case of persistent messages, that includes writing the message to persistent -store. - -## Queue Replication ## - -Life-cycle of a message on a replicated queue, on the primary: - -Record: Received for primary queue. -- IdSetter sets a replication ID. - -Enqueue: Published to primary queue. -- QueueGuard delays completion (increments completion count). - -Deliver: Backup is ready to receive data. -- ReplicatingSubscription sends message to backup QueueReplicator - -Acknowledge: Received from backup QueueReplicator. -- ReplicatingSubscription completes (decrements completion count). - -Dequeue: Removed from queue -- QueueGuard completes if not already completed by ReplicatingSubscription. -- ReplicatingSubscription sends dequeued message ID to backup QueueReplicator. - -There is a simple protocol between ReplicatingSubscription and QueueReplicator -(see Event sub-classes) so ReplicatingSubscription can send -- replication IDs of messages as they are replicated. -- replication IDs of messages that have been dequeued on the primary. - -## Queue Failover ## - -On failover, for each queue, the backup gets the QueueSnapshot of messages on -the queue and sends it with the subscription to the primary queue. The primary -responds with its own snapshot. - -Both parties use this information to determine: - -- Messages that are on the backup and don't need to be replicated again. -- Messages that are dequeued on the primary and can be discarded by the backup. -- Queue position for the QueueGuard to start delaying completion. -- Queue position for the ReplicatingSubscription to start replicating from. - -After that handshake queue replication as described above begins. - -## Standalone replication ## - -The HA module supports ad-hoc replication between standalone brokers that are -not in a cluster, using the same basic queue replication techniques. - -## Queue and Backup "ready" ## - -A QueueGuard is set on the queue when a backup first subscribes or when a backup -fails over to a new primary. Messages before the _first guarded position_ cannot -be delayed because they may have already been acknowledged to clients. - -A backup sends a set of acknowledged message ids when subscribing, messages that -are already on the backup and therefore safe. - -A ReplicatingSubscription is _ready_ when all messages are safe or delayed. We -know this is the case when both the following conditions hold: - -- The ReplicatingSubscription has reached the position preceding the first guarded position AND -- All messages prior to the first guarded position are safe. - - -*/ -/** \namespace qpid::ha \brief High Availability \ingroup ha-module */ -}} // namespace qpid::ha - diff --git a/qpid/cpp/src/qpid/ha/RemoteBackup.cpp b/qpid/cpp/src/qpid/ha/RemoteBackup.cpp deleted file mode 100644 index cbf00d0a8f..0000000000 --- a/qpid/cpp/src/qpid/ha/RemoteBackup.cpp +++ /dev/null @@ -1,115 +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 "RemoteBackup.h" -#include "QueueGuard.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { -namespace ha { - -using sys::Mutex; -using boost::bind; - -RemoteBackup::RemoteBackup( - const BrokerInfo& info, broker::Connection* c, const LogPrefix& lp -) : logPrefix(lp), brokerInfo(info), replicationTest(NONE), - started(false), connection(c), reportedReady(false) -{ - std::ostringstream oss; - oss << "Remote backup at " << info << ": "; - logPrefix = oss.str(); -} - -RemoteBackup::~RemoteBackup() { - // Don't cancel here, cancel must be called explicitly in a locked context - // where we know the connection pointer is still good. -} - -void RemoteBackup::cancel() { - QPID_LOG(debug, logPrefix << "Cancelled " << (connection? "connected":"disconnected") - << " backup: " << brokerInfo); - for (GuardMap::iterator i = guards.begin(); i != guards.end(); ++i) - i->second->cancel(); - guards.clear(); - if (connection) { - connection->abort(); - connection = 0; - } -} - -bool RemoteBackup::isReady() { - return started && connection && catchupQueues.empty(); -} - -void RemoteBackup::catchupQueue(const QueuePtr& q, bool createGuard) { - if (replicationTest.getLevel(*q) == ALL) { - QPID_LOG(debug, logPrefix << "Catch-up queue" - << (createGuard ? " and guard" : "") << ": " << q->getName()); - catchupQueues.insert(q); - if (createGuard) guards[q].reset(new QueueGuard(*q, brokerInfo, logPrefix.prePrefix)); - } -} - -RemoteBackup::GuardPtr RemoteBackup::guard(const QueuePtr& q) { - GuardMap::iterator i = guards.find(q); - GuardPtr guard; - if (i != guards.end()) { - guard = i->second; - guards.erase(i); - } - return guard; -} - -void RemoteBackup::ready(const QueuePtr& q) { - catchupQueues.erase(q); -} - -// 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, logPrefix.prePrefix)); -} - -// Called via BrokerObserver -void RemoteBackup::queueDestroy(const QueuePtr& q) { - catchupQueues.erase(q); - GuardMap::iterator i = guards.find(q); - if (i != guards.end()) { - i->second->cancel(); - guards.erase(i); - } -} - -bool RemoteBackup::reportReady() { - if (!reportedReady && isReady()) { - if (catchupQueues.empty()) QPID_LOG(debug, logPrefix << "Caught up."); - reportedReady = true; - return true; - } - return false; -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/RemoteBackup.h b/qpid/cpp/src/qpid/ha/RemoteBackup.h deleted file mode 100644 index 77c493d27e..0000000000 --- a/qpid/cpp/src/qpid/ha/RemoteBackup.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef QPID_HA_REMOTEBACKUP_H -#define QPID_HA_REMOTEBACKUP_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 "LogPrefix.h" -#include "ReplicationTest.h" -#include "BrokerInfo.h" -#include "types.h" -#include "hash.h" -#include "qpid/sys/unordered_map.h" -#include - -namespace qpid { - -namespace broker { -class Queue; -class QueueRegistry; -class Connection; -} - -namespace ha { -class QueueGuard; - -/** - * Track readiness for a remote broker. - * Creates queue guards on behalf of the remote broker to keep - * queues safe till the ReplicatingSubscription is ready. - * - * THREAD UNSAFE: Caller must serialize. - */ -class RemoteBackup -{ - public: - typedef boost::shared_ptr GuardPtr; - typedef boost::shared_ptr QueuePtr; - - /** Note: isReady() can be true after construction - *@param connected true if the backup is already connected. - */ - RemoteBackup(const BrokerInfo&, broker::Connection*, const LogPrefix&); - ~RemoteBackup(); - - /** Return guard associated with a queue. Used to create ReplicatingSubscription. */ - GuardPtr guard(const QueuePtr&); - - /** Is the remote backup connected? */ - void setConnection(broker::Connection* c) { connection = c; } - broker::Connection* getConnection() const { return connection; } - - /** ReplicatingSubscription associated with queue is ready. - * Note: may set isReady() - */ - void ready(const QueuePtr& queue); - - /** Called via BrokerObserver */ - void queueCreate(const QueuePtr&); - - /** Called via BrokerObserver. Note: may set isReady() */ - void queueDestroy(const QueuePtr&); - - /**@return true when all catch-up queues for this backup are ready. */ - bool isReady(); - - /**@return true if isReady() and this is the first call to reportReady */ - bool reportReady(); - - /**Cancel all queue guards, called if we are timed out. */ - void cancel(); - - /** Set a catch-up queue for this backup. - *@createGuard if true create a guard immediately. - */ - void catchupQueue(const QueuePtr&, bool createGuard); - - BrokerInfo getBrokerInfo() const { return brokerInfo; } - - void startCatchup() { started = true; } - - private: - typedef qpid::sys::unordered_map< - QueuePtr, GuardPtr, Hasher > - > GuardMap; - - typedef std::set QueueSet; - - LogPrefix2 logPrefix; - BrokerInfo brokerInfo; - ReplicationTest replicationTest; - GuardMap guards; - QueueSet catchupQueues; - bool started; - broker::Connection* connection; - bool reportedReady; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_REMOTEBACKUP_H*/ diff --git a/qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp b/qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp deleted file mode 100644 index 64fdae121c..0000000000 --- a/qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp +++ /dev/null @@ -1,324 +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 "Event.h" -#include "IdSetter.h" -#include "QueueGuard.h" -#include "QueueSnapshot.h" -#include "ReplicatingSubscription.h" -#include "Primary.h" -#include "HaBroker.h" -#include "qpid/assert.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/types/Uuid.h" -#include - - -namespace qpid { -namespace ha { - -using namespace framing; -using namespace broker; -using namespace std; -using sys::Mutex; -using broker::amqp_0_10::MessageTransfer; -namespace { const string QPID_HA(QPID_HA_PREFIX); } -const string ReplicatingSubscription::QPID_REPLICATING_SUBSCRIPTION(QPID_HA+"repsub"); -const string ReplicatingSubscription::QPID_BROKER_INFO(QPID_HA+"info"); -const string ReplicatingSubscription::QPID_ID_SET(QPID_HA+"ids"); -const string ReplicatingSubscription::QPID_QUEUE_REPLICATOR(QPID_HA+"qrep"); - -/* Called by SemanticState::consume to create a consumer */ -boost::shared_ptr -ReplicatingSubscription::Factory::create( - SemanticState* parent, - const string& name, - Queue::shared_ptr queue, - bool ack, - bool acquire, - bool exclusive, - const string& tag, - const string& resumeId, - uint64_t resumeTtl, - const framing::FieldTable& arguments -) { - boost::shared_ptr rs; - std::string type = arguments.getAsString(QPID_REPLICATING_SUBSCRIPTION); - if (type == QPID_QUEUE_REPLICATOR) { - rs.reset(new ReplicatingSubscription( - haBroker, - parent, name, queue, ack, acquire, exclusive, tag, - resumeId, resumeTtl, arguments)); - } - if (rs) rs->initialize(); - return rs; -} - -ReplicatingSubscription::ReplicatingSubscription( - HaBroker& hb, - SemanticState* parent, - const string& name, - Queue::shared_ptr queue_, - bool ack, - bool /*acquire*/, - bool exclusive, - const string& tag, - const string& resumeId, - uint64_t resumeTtl, - const framing::FieldTable& arguments -) : ConsumerImpl(parent, name, queue_, ack, REPLICATOR, exclusive, tag, - resumeId, resumeTtl, arguments), - logPrefix(hb.logPrefix), - position(0), wasStopped(false), ready(false), cancelled(false), - haBroker(hb), - primary(boost::dynamic_pointer_cast(haBroker.getRole())) -{} - -// Called in subscription's connection thread when the subscription is created. -// Separate from ctor because we need to use shared_from_this -// -void ReplicatingSubscription::initialize() { - try { - FieldTable ft; - if (!getArguments().getTable(ReplicatingSubscription::QPID_BROKER_INFO, ft)) - throw InvalidArgumentException( - logPrefix.get()+"Can't subscribe, no broker info: "+getTag()); - info.assign(ft); - - // Set a log prefix message that identifies the remote broker. - ostringstream os; - os << "Subscription to " << queue->getName() << " at "; - info.printId(os) << ": "; - logPrefix = os.str(); - - // If there's already a guard (we are in failover) use it, else create one. - if (primary) guard = primary->getGuard(queue, info); - if (!guard) guard.reset(new QueueGuard(*queue, info, logPrefix.prePrefix)); - - // NOTE: Once the observer is attached we can have concurrent - // calls to dequeued so we need to lock use of this->dequeues. - // - // However we must attach the observer _before_ we snapshot for - // initial dequeues to be sure we don't miss any dequeues - // between the snapshot and attaching the observer. - queue->getObservers().add( - boost::dynamic_pointer_cast(shared_from_this())); - boost::shared_ptr snapshot = queue->getObservers().findType(); - // There may be no snapshot if the queue is being deleted concurrently. - if (!snapshot) { - queue->getObservers().remove( - boost::dynamic_pointer_cast(shared_from_this())); - throw ResourceDeletedException(logPrefix.get()+"Can't subscribe, queue deleted"); - } - ReplicationIdSet primaryIds = snapshot->getSnapshot(); - std::string backupStr = getArguments().getAsString(ReplicatingSubscription::QPID_ID_SET); - ReplicationIdSet backupIds; - if (!backupStr.empty()) backupIds = decodeStr(backupStr); - - // Initial dequeues are messages on backup but not on 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. - skipEnqueue = 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; - - QPID_LOG(debug, logPrefix << "Subscribed: primary [" - << front << "," << back << "]=" << primaryIds - << ", guarded " << guard->getFirst() - << ", backup (keep " << skipEnqueue << ", drop " << initDequeues << ")"); - checkReady(l); - } - 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. - sendDequeueEvent(l); - } - catch (const std::exception& e) { - QPID_LOG(error, logPrefix << "Subscribe failed: " << e.what()); - throw; - } -} - -ReplicatingSubscription::~ReplicatingSubscription() {} - -void ReplicatingSubscription::stopped() { - Mutex::ScopedLock l(lock); - // We have reached the last available message on the queue. - // - // Note that if messages have been removed out-of-order this may not be the - // head of the queue. We may not even have reached the guard - // position. However there are no more messages to protect and we will not - // be advanced any further, so we should consider ourselves guarded for - // purposes of readiness. - wasStopped = true; - checkReady(l); -} - -// True if the next position for the ReplicatingSubscription is a guarded position. -bool ReplicatingSubscription::isGuarded(sys::Mutex::ScopedLock&) { - // See comment in stopped() - return wasStopped || (position+1 >= guard->getFirst()); -} - -// Message is delivered in the subscription's connection thread. -bool ReplicatingSubscription::deliver( - const qpid::broker::QueueCursor& c, const qpid::broker::Message& m) -{ - Mutex::ScopedLock l(lock); - ReplicationId id = m.getReplicationId(); - position = m.getSequence(); - try { - bool result = false; - if (skipEnqueue.contains(id)) { - QPID_LOG(trace, logPrefix << "Skip " << logMessageId(*getQueue(), m)); - skipEnqueue -= id; - guard->complete(id); // This will never be acknowledged. - notify(); - result = true; - } - else { - QPID_LOG(trace, logPrefix << "Replicated " << logMessageId(*getQueue(), m)); - if (!ready && !isGuarded(l)) unready += id; - sendIdEvent(id, l); - result = ConsumerImpl::deliver(c, m); - } - checkReady(l); - return result; - } catch (const std::exception& e) { - QPID_LOG(critical, logPrefix << "Error replicating " << logMessageId(*getQueue(), m) - << ": " << e.what()); - throw; - } -} - -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. - if (position+1 >= guard->getFirst()) { - QPID_LOG(debug, logPrefix << "Caught up at " << position); - } else { - QPID_LOG(debug, logPrefix << "Caught up at " << position << "short of guard at " << guard->getFirst()); - } - - if (primary) primary->readyReplica(*this); - } -} - -// Called in the subscription's connection thread. -void ReplicatingSubscription::cancel() -{ - { - Mutex::ScopedLock l(lock); - if (cancelled) return; - cancelled = true; - } - QPID_LOG(debug, logPrefix << "Cancelled"); - getQueue()->getObservers().remove( - boost::dynamic_pointer_cast(shared_from_this())); - guard->cancel(); - ConsumerImpl::cancel(); -} - -// Consumer override, called on primary in the backup's IO thread. -void ReplicatingSubscription::acknowledged(const broker::DeliveryRecord& r) { - // Finish completion of message, it has been acknowledged by the backup. - ReplicationId id = r.getReplicationId(); - QPID_LOG(trace, logPrefix << "Acknowledged " << - logMessageId(*getQueue(), r.getMessageId(), id)); - guard->complete(id); - { - Mutex::ScopedLock l(lock); - unready -= id; - checkReady(l); - } - ConsumerImpl::acknowledged(r); -} - -// Called with lock held. Called in subscription's connection thread. -void ReplicatingSubscription::sendDequeueEvent(Mutex::ScopedLock& l) -{ - if (dequeues.empty()) return; - QPID_LOG(trace, logPrefix << "Sending dequeues " << dequeues); - DequeueEvent d(dequeues); - dequeues.clear(); - sendEvent(d, l); -} - -// Called after the message has been removed -// from the deque and under the messageLock in the queue. Called in -// arbitrary connection threads. -void ReplicatingSubscription::dequeued(const broker::Message& m) -{ - ReplicationId id = m.getReplicationId(); - QPID_LOG(trace, logPrefix << "Dequeued ID " << id); - { - Mutex::ScopedLock l(lock); - dequeues.add(id); - } - notify(); // Ensure a call to doDispatch -} - - -// Called with lock held. Called in subscription's connection thread. -void ReplicatingSubscription::sendIdEvent(ReplicationId pos, Mutex::ScopedLock& l) -{ - sendEvent(IdEvent(pos), l); -} - -void ReplicatingSubscription::sendEvent(const Event& event, Mutex::ScopedLock&) -{ - Mutex::ScopedUnlock u(lock); - // 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(), event.message(), boost::shared_ptr()); -} - -// Called in subscription's connection thread. -bool ReplicatingSubscription::doDispatch() -{ - { - Mutex::ScopedLock l(lock); - if (!dequeues.empty()) sendDequeueEvent(l); - } - try { - return ConsumerImpl::doDispatch(); - } - catch (const std::exception& e) { - QPID_LOG(warning, logPrefix << " exception in dispatch: " << e.what()); - return false; - } -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/ReplicatingSubscription.h b/qpid/cpp/src/qpid/ha/ReplicatingSubscription.h deleted file mode 100644 index c2e51971cc..0000000000 --- a/qpid/cpp/src/qpid/ha/ReplicatingSubscription.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef QPID_BROKER_REPLICATINGSUBSCRIPTION_H -#define QPID_BROKER_REPLICATINGSUBSCRIPTION_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 "BrokerInfo.h" -#include "LogPrefix.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/broker/ConsumerFactory.h" -#include "qpid/broker/QueueObserver.h" -#include -#include - -namespace qpid { - -namespace broker { -class Message; -class Queue; -struct QueuedMessage; -class OwnershipToken; -} - -namespace framing { -class Buffer; -} - -namespace ha { -class QueueGuard; -class HaBroker; -class Event; -class Primary; - -/** - * A susbcription that replicates to a remote backup. - * - * Runs on the primary. In conjunction with a QueueGuard, delays completion of - * messages till the backup has acknowledged, informs backup of locally dequeued - * messages. - * - * A ReplicatingSubscription is "ready" when all the messages on the queue have - * either been acknowledged by the backup, or are protected by the queue guard. - * On a primary broker the ReplicatingSubscription calls Primary::readyReplica - * when it is ready. - * - * THREAD SAFE: Called in subscription's connection thread but also in arbitrary - * connection threads via dequeued. - * - * Lifecycle: broker::Queue holds shared_ptrs to this as a consumer. - * - * ReplicatingSubscription makes calls on QueueGuard, but not vice-versa. - */ -class ReplicatingSubscription : - public broker::SemanticState::ConsumerImpl, - public broker::QueueObserver -{ - public: - typedef broker::SemanticState::ConsumerImpl ConsumerImpl; - - class Factory : public broker::ConsumerFactory { - public: - Factory(HaBroker& hb) : haBroker(hb) {} - - HaBroker& getHaBroker() const { return haBroker; } - - boost::shared_ptr create( - broker::SemanticState* parent, - const std::string& name, boost::shared_ptr , - bool ack, bool acquire, bool exclusive, const std::string& tag, - const std::string& resumeId, uint64_t resumeTtl, - const framing::FieldTable& arguments); - private: - HaBroker& haBroker; - }; - - // Argument names for consume command. - static const std::string QPID_REPLICATING_SUBSCRIPTION; - static const std::string QPID_BROKER_INFO; - static const std::string QPID_ID_SET; - // Replicator types: argument values for QPID_REPLICATING_SUBSCRIPTION argument. - static const std::string QPID_QUEUE_REPLICATOR; - - ReplicatingSubscription(HaBroker& haBroker, - broker::SemanticState* parent, - const std::string& name, boost::shared_ptr , - bool ack, bool acquire, bool exclusive, const std::string& tag, - const std::string& resumeId, uint64_t resumeTtl, - const framing::FieldTable& arguments); - - ~ReplicatingSubscription(); - - - // Consumer overrides. - bool deliver(const broker::QueueCursor& cursor, const broker::Message& msg); - void cancel(); - void acknowledged(const broker::DeliveryRecord&); - bool browseAcquired() const { return true; } - void stopped(); - - // Hide the "queue deleted" error for a ReplicatingSubscription when a - // queue is deleted, this is normal and not an error. - bool hideDeletedError() { return true; } - - // QueueObserver overrides - void enqueued(const broker::Message&) {} - void dequeued(const broker::Message&); - void acquired(const broker::Message&) {} - void requeued(const broker::Message&) {} - - /** A ReplicatingSubscription is a passive observer, not counted for auto - * deletion and immediate message purposes. - */ - bool isCounted() { return false; } - - /** Initialization that must be done separately from construction - * because it requires a shared_ptr to this to exist. - */ - void initialize(); - - BrokerInfo getBrokerInfo() const { return info; } - - protected: - bool doDispatch(); - - private: - LogPrefix2 logPrefix; - QueuePosition position; - ReplicationIdSet dequeues; // Dequeues to be sent in next dequeue event. - ReplicationIdSet skipEnqueue; // Enqueues to skip: messages already on backup. - ReplicationIdSet unready; // Unguarded, replicated and un-acknowledged. - bool wasStopped; - bool ready; - bool cancelled; - BrokerInfo info; - boost::shared_ptr guard; - HaBroker& haBroker; - boost::shared_ptr primary; - - bool isGuarded(sys::Mutex::ScopedLock&); - void dequeued(ReplicationId); - void sendDequeueEvent(sys::Mutex::ScopedLock&); - void sendIdEvent(ReplicationId, sys::Mutex::ScopedLock&); - void sendEvent(const Event&, sys::Mutex::ScopedLock&); - void checkReady(sys::Mutex::ScopedLock&); - friend class Factory; -}; - - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_REPLICATINGSUBSCRIPTION_H*/ diff --git a/qpid/cpp/src/qpid/ha/ReplicationTest.cpp b/qpid/cpp/src/qpid/ha/ReplicationTest.cpp deleted file mode 100644 index d2152363fe..0000000000 --- a/qpid/cpp/src/qpid/ha/ReplicationTest.cpp +++ /dev/null @@ -1,75 +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 "ReplicationTest.h" -#include "qpid/log/Statement.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" - -namespace qpid { -namespace ha { - -using types::Variant; - -ReplicateLevel ReplicationTest::getLevel(const std::string& str) const { - Enum rl(replicateDefault); - if (!str.empty()) rl.parse(str); - return rl.get(); -} - -ReplicateLevel ReplicationTest::getLevel(const framing::FieldTable& f) const { - if (f.isSet(QPID_REPLICATE)) - return getLevel(f.getAsString(QPID_REPLICATE)); - else - return replicateDefault; -} - -ReplicateLevel ReplicationTest::getLevel(const Variant::Map& m) const { - Variant::Map::const_iterator i = m.find(QPID_REPLICATE); - if (i != m.end()) - return getLevel(i->second.asString()); - else - return replicateDefault; -} - -ReplicateLevel ReplicationTest::getLevel(const broker::Queue& q) const { - const Variant::Map& qmap(q.getSettings().original); - Variant::Map::const_iterator i = qmap.find(QPID_REPLICATE); - if (i != qmap.end()) - return getLevel(i->second.asString()); - else - return getLevel(q.getSettings().storeSettings); -} - -ReplicateLevel ReplicationTest::getLevel(const broker::Exchange& ex) const { - return getLevel(ex.getArgs()); -} - -ReplicateLevel ReplicationTest::useLevel(const broker::Queue& q) const { - return q.getSettings().isTemporary ? ReplicationTest(NONE).getLevel(q) : getLevel(q); -} - -ReplicateLevel ReplicationTest::useLevel(const broker::Exchange& ex) const { - return ReplicationTest::getLevel(ex); -} - - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/ReplicationTest.h b/qpid/cpp/src/qpid/ha/ReplicationTest.h deleted file mode 100644 index 8b19dc2ee0..0000000000 --- a/qpid/cpp/src/qpid/ha/ReplicationTest.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef QPID_HA_REPLICATIONTEST_H -#define QPID_HA_REPLICATIONTEST_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/types/Variant.h" -#include - -namespace qpid { - -namespace broker { -class Queue; -class Exchange; -} - -namespace framing { -class FieldTable; -} - -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 -{ - public: - ReplicationTest(ReplicateLevel replicateDefault_) : - replicateDefault(replicateDefault_) {} - - // Get the replication level set on an object, or default if not set. - ReplicateLevel getLevel(const std::string& str) const; - ReplicateLevel getLevel(const framing::FieldTable& f) const; - ReplicateLevel getLevel(const types::Variant::Map& m) const; - ReplicateLevel getLevel(const broker::Queue&) const; - ReplicateLevel getLevel(const broker::Exchange&) const; - - // Calculate level for objects that may not have replication set, - // including auto-delete/exclusive settings. - ReplicateLevel useLevel(const broker::Queue&) const; - ReplicateLevel useLevel(const broker::Exchange&) const; - - private: - ReplicateLevel replicateDefault; -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_REPLICATIONTEST_H*/ diff --git a/qpid/cpp/src/qpid/ha/Role.h b/qpid/cpp/src/qpid/ha/Role.h deleted file mode 100644 index 5392ce1fff..0000000000 --- a/qpid/cpp/src/qpid/ha/Role.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_HA_ROLE_H -#define QPID_HA_ROLE_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 - -namespace qpid { -struct Url; - -namespace ha { - -/** - * A HaBroker has a role, e.g. Primary, Backup, StandAlone. - * Role subclasses define the actions of the broker in each role. - * The Role interface allows the HaBroker to pass management actions - * to be implemented by the role. - */ -class Role -{ - public: - virtual ~Role() {} - - /** QMF promote method handler. - * @return The new role if promoted, 0 if not. Caller takes ownership. - */ - virtual Role* promote() = 0; - - virtual void setBrokerUrl(const Url& url) = 0; - - private: -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_ROLE_H*/ diff --git a/qpid/cpp/src/qpid/ha/Settings.h b/qpid/cpp/src/qpid/ha/Settings.h deleted file mode 100644 index 9d5a5e6ae0..0000000000 --- a/qpid/cpp/src/qpid/ha/Settings.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_HA_SETTINGS_H -#define QPID_HA_SETTINGS_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/sys/Time.h" -#include "qpid/sys/IntegerTypes.h" -#include - -namespace qpid { -namespace ha { - -/** - * Configurable settings for HA. - */ -class Settings -{ - public: - Settings() : cluster(false), queueReplication(false), - replicateDefault(NONE), backupTimeout(10*sys::TIME_SEC), - flowMessages(1000), flowBytes(0) - {} - - bool cluster; // True if we are a cluster member. - bool queueReplication; // True if enabled. - std::string publicUrl; - std::string brokerUrl; - Enum replicateDefault; - std::string username, password, mechanism; - sys::Duration backupTimeout; - - uint32_t flowMessages, flowBytes; - - static const uint32_t NO_LIMIT=0xFFFFFFFF; - static uint32_t flowValue(uint32_t n) { return n ? n : NO_LIMIT; } - uint32_t getFlowMessages() const { return flowValue(flowMessages); } - uint32_t getFlowBytes() const { return flowValue(flowBytes); } -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_SETTINGS_H*/ diff --git a/qpid/cpp/src/qpid/ha/StandAlone.h b/qpid/cpp/src/qpid/ha/StandAlone.h deleted file mode 100644 index 01bcf1a0b3..0000000000 --- a/qpid/cpp/src/qpid/ha/StandAlone.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef QPID_HA_STANDALONE_H -#define QPID_HA_STANDALONE_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 { -struct Url; - -namespace ha { - -/** - * Stand-alone role: acts as a stand-alone broker, no clustering. - * HA module needed to setting up replication via QMF methods. - */ -class StandAlone : public Role -{ - public: - Role* promote() { return 0; } - void setBrokerUrl(const Url&) {} -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_STANDALONE_H*/ diff --git a/qpid/cpp/src/qpid/ha/StatusCheck.cpp b/qpid/cpp/src/qpid/ha/StatusCheck.cpp deleted file mode 100644 index e1c8df5e56..0000000000 --- a/qpid/cpp/src/qpid/ha/StatusCheck.cpp +++ /dev/null @@ -1,159 +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 "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" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/ProtocolRegistry.h" -#include "qpid/types/Variant.h" - -namespace qpid { -namespace ha { - -using namespace qpid::messaging; -using namespace qpid::types; -using namespace std; -using namespace sys; - -const string HA_BROKER = "org.apache.qpid.ha:habroker:ha-broker"; - -class StatusCheckThread : public sys::Runnable { - public: - StatusCheckThread(StatusCheck& sc, const qpid::Address& addr) - : url(addr), statusCheck(sc) {} - void run(); - private: - Url url; - StatusCheck& statusCheck; -}; - -void StatusCheckThread::run() { - string logPrefix("Status check " + url.str() + ": "); - Connection c; - try { - // Check for self connections - Variant::Map options, clientProperties; - clientProperties[ConnectionObserver::ADMIN_TAG] = 1; // Allow connection to backups - clientProperties[ConnectionObserver::ADDRESS_TAG] = url.str(); - clientProperties[ConnectionObserver::BACKUP_TAG] = statusCheck.brokerInfo.asMap(); - - // Set connection options - const Settings& settings = statusCheck.settings; - 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.heartbeat/sys::TIME_SEC; - - c = Connection(url.str(), options); - c.open(); - Session session = c.createSession(); - messaging::Address responses("#;{create:always,node:{x-declare:{exclusive:True,auto-delete:True,arguments:{'qpid.replicate':none}}}}"); - Receiver r = session.createReceiver(responses); - Sender s = session.createSender("qmf.default.direct/broker"); - Message request; - request.setReplyTo(responses); - request.setContentType("amqp/map"); - request.setProperty("x-amqp-0-10.app-id", "qmf2"); - request.setProperty("qmf.opcode", "_query_request"); - Variant::Map oid; - oid["_object_name"] = HA_BROKER; - Variant::Map content; - content["_what"] = "OBJECT"; - content["_object_id"] = oid; - encode(content, request); - s.send(request); - messaging::Duration timeout(statusCheck.heartbeat/sys::TIME_MSEC); - Message response = r.fetch(timeout); - session.acknowledge(); - Variant::List contentIn; - decode(response, contentIn); - 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.noPromote(); - QPID_LOG(info, logPrefix << "Joining established cluster"); - } - } - else - QPID_LOG(error, logPrefix << "Invalid response " << response.getContent()); - } catch(const std::exception& e) { - QPID_LOG(info, logPrefix << e.what()); - } - try { c.close(); } catch(...) {} - statusCheck.endThread(); - delete this; -} - -// Note: Don't use hb outside of the constructor, it may be deleted. -StatusCheck::StatusCheck(HaBroker& hb) : - promote(true), - settings(hb.getSettings()), - heartbeat(hb.getBroker().getLinkHeartbeatInterval()), - brokerInfo(hb.getBrokerInfo()) -{} - -StatusCheck::~StatusCheck() { - // In case canPromote was never called. - for (size_t i = 0; i < threads.size(); ++i) threads[i].join(); -} - -void StatusCheck::setUrl(const Url& url) { - Mutex::ScopedLock l(lock); - threadCount = url.size(); - for (size_t i = 0; i < url.size(); ++i) - threads.push_back(Thread(new StatusCheckThread(*this, url[i]))); -} - -void StatusCheck::endThread() { - // Shut down the client poller ASAP to avoid conflict with the broker's poller. - // See https://issues.apache.org/jira/browse/QPID-7149 - if (--threadCount == 0) { - messaging::ProtocolRegistry::shutdown(); - } -} - -bool StatusCheck::canPromote() { - Mutex::ScopedLock l(lock); - while (!threads.empty()) { - Thread t = threads.back(); - threads.pop_back(); - Mutex::ScopedUnlock u(lock); - t.join(); - } - return promote; -} - -void StatusCheck::noPromote() { - Mutex::ScopedLock l(lock); - promote = false; -} - -}} // namespace qpid::ha diff --git a/qpid/cpp/src/qpid/ha/StatusCheck.h b/qpid/cpp/src/qpid/ha/StatusCheck.h deleted file mode 100644 index 2ff6f1ffba..0000000000 --- a/qpid/cpp/src/qpid/ha/StatusCheck.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef QPID_HA_STATUSCHECK_H -#define QPID_HA_STATUSCHECK_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 "BrokerInfo.h" -#include "Settings.h" -#include "qpid/Url.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Time.h" -#include - -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. -// - -/** - * Check whether a JOINING broker can be promoted . - * - * A JOINING broker can be promoted as long as all the other brokers are also - * JOINING. If there are READY brokers in the cluster the JOINING broker should - * refuse to promote so that one of the READY brokers can. This situation - * only comes about if the primary is dead and no new primary has been promoted. - * - * THREAD SAFE: setUrl and canPromote are called in arbitrary management threads. - */ -class StatusCheck -{ - public: - StatusCheck(HaBroker&); - ~StatusCheck(); - void setUrl(const Url&); - bool canPromote(); - - private: - void noPromote(); - void endThread(); - - sys::Mutex lock; - std::vector threads; - sys::AtomicValue threadCount; - bool promote; - const Settings settings; - const sys::Duration heartbeat; - const BrokerInfo brokerInfo; - - friend class StatusCheckThread; -}; -}} // namespace qpid::ha - -#endif /*!QPID_HA_STATUSCHECK_H*/ diff --git a/qpid/cpp/src/qpid/ha/hash.h b/qpid/cpp/src/qpid/ha/hash.h deleted file mode 100644 index 17f99fb666..0000000000 --- a/qpid/cpp/src/qpid/ha/hash.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef QPID_HA_HASH_H -#define QPID_HA_HASH_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/types/Uuid.h" -#include -#include - -namespace qpid { -namespace ha { - -// 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(v); } -inline std::size_t hashValue(char v) { return static_cast(v); } -inline std::size_t hashValue(unsigned char v) { return static_cast(v); } -inline std::size_t hashValue(signed char v) { return static_cast(v); } -inline std::size_t hashValue(short v) { return static_cast(v); } -inline std::size_t hashValue(unsigned short v) { return static_cast(v); } -inline std::size_t hashValue(int v) { return static_cast(v); } -inline std::size_t hashValue(unsigned int v) { return static_cast(v); } -inline std::size_t hashValue(long v) { return static_cast(v); } -inline std::size_t hashValue(unsigned long v) { return static_cast(v); } - -inline std::size_t hashValue(const types::Uuid& v) { return v.hash(); } - -template inline std::size_t hashValue(T* v) { - std::size_t x = static_cast(reinterpret_cast(v)); - return x + (x >> 3); -} - -template inline std::size_t hashValue(boost::shared_ptr v) { - return hashValue(v.get()); -} - -template inline void hashCombine(std::size_t& seed, const T& v) { - seed ^= hashValue(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); -} - -template inline size_t hashValue(const std::pair& v) { - std::size_t seed = 0; - hashCombine(seed, v.first); - hashCombine(seed, v.second); - return seed; -} - -template struct Hasher { - size_t operator()(const T& v) const { return hashValue(v); } -}; - -}} // namespace qpid::ha - -#endif /*!QPID_HA_HASH_H*/ diff --git a/qpid/cpp/src/qpid/ha/management-schema.xml b/qpid/cpp/src/qpid/ha/management-schema.xml deleted file mode 100644 index 3da482e732..0000000000 --- a/qpid/cpp/src/qpid/ha/management-schema.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qpid/cpp/src/qpid/ha/types.cpp b/qpid/cpp/src/qpid/ha/types.cpp deleted file mode 100644 index 3088661c95..0000000000 --- a/qpid/cpp/src/qpid/ha/types.cpp +++ /dev/null @@ -1,138 +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 "types.h" -#include "qpid/Msg.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/Exception.h" -#include -#include -#include -#include - -namespace qpid { -namespace ha { - -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:"; - -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]; -} - -void EnumBase::parse(const string& s) { - if (!parseNoThrow(s)) - throw Exception(QPID_MSG("Invalid " << name << " value: " << s)); -} - -bool EnumBase::parseNoThrow(const string& s) { - const char** i = find(names, names+count, s); - value = i - names; - return value < count; -} - -template <> const char* Enum::NAME = "replication"; -template <> const char* Enum::NAMES[] = { "none", "configuration", "all" }; -template <> const size_t Enum::N = 3; - -template <> const char* Enum::NAME = "HA broker status"; - -// NOTE: Changing status names will have an impact on qpid-ha and -// the qpidd-primary init script. -// Don't change them unless you are going to update all dependent code. -// -template <> const char* Enum::NAMES[] = { - "joining", "catchup", "ready", "recovering", "active", "standalone" -}; -template <> const size_t Enum::N = 6; - -ostream& operator<<(ostream& o, EnumBase e) { - return o << e.str(); -} - -istream& operator>>(istream& i, EnumBase& e) { - string s; - i >> s; - e.parse(s); - return i; -} - -ostream& operator<<(ostream& o, const UuidSet& ids) { - ostream_iterator out(o, " "); - o << "{ "; - for (UuidSet::const_iterator i = ids.begin(); i != ids.end(); ++i) - o << shortStr(*i) << " "; - o << "}"; - return o; -} - - -std::string logMessageId(const std::string& q, QueuePosition pos, ReplicationId id) { - return Msg() << q << "[" << pos << "]" << "=" << id; -} -std::string logMessageId(const std::string& q, ReplicationId id) { - return Msg() << q << "[]" << "=" << id; -} -std::string logMessageId(const std::string& q, const broker::Message& m) { - return logMessageId(q, m.getSequence(), m.getReplicationId()); -} -std::string logMessageId(const broker::Queue& q, QueuePosition pos, ReplicationId id) { - return logMessageId(q.getName(), pos, id); -} -std::string logMessageId(const broker::Queue& q, ReplicationId id) { - return logMessageId(q.getName(), id); -} -std::string logMessageId(const broker::Queue& q, const broker::Message& m) { - return logMessageId(q.getName(), m); -} - -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(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 deleted file mode 100644 index ae4b948dfc..0000000000 --- a/qpid/cpp/src/qpid/ha/types.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef QPID_HA_ENUM_H -#define QPID_HA_ENUM_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/types/Variant.h" -#include "qpid/types/Uuid.h" -#include "qpid/framing/SequenceSet.h" - -#include - -#include -#include -#include - -namespace qpid { - -namespace broker { -class Message; -class Queue; -} -namespace framing { -class FieldTable; -} - -namespace ha { - -/** Base class for enums with string conversion */ -class EnumBase { - public: - EnumBase(const char* name_, const char* names_[], size_t count_, unsigned value) - : name(name_), names(names_), count(count_), value(value) {} - - /** Convert to string */ - std::string str() const; - /** Parse from string, throw if unsuccessful */ - void parse(const std::string&); - /** Parse from string, return false if unsuccessful. */ - bool parseNoThrow(const std::string&); - - protected: - const char* name; - const char** names; - size_t count; - unsigned value; -}; - -std::ostream& operator<<(std::ostream&, EnumBase); -std::istream& operator>>(std::istream&, EnumBase&); - -/** Wrapper template for enums with string conversion */ -template class Enum : public EnumBase { - public: - Enum(T x=T()) : EnumBase(NAME, NAMES, N, x) {} - T get() const { return T(value); } - void operator=(T x) { value = x; } - - private: - static const size_t N; // Number of enum values. - static const char* NAMES[]; // Names of enum values. - static const char* NAME; // Descriptive name for the enum type. -}; - -/** To print an enum x: o << printable(x) */ -template Enum printable(T x) { return Enum(x); } - -enum ReplicateLevel { - NONE, ///< Nothing is replicated - CONFIGURATION, ///< Wiring is replicated but not messages - ALL ///< Everything is replicated -}; - -/** State of a broker: see HaBroker::setStatus for state diagram */ -enum BrokerStatus { - JOINING, ///< New broker, looking for primary - CATCHUP, ///< Backup: Connected to primary, catching up on state. - READY, ///< Backup: Caught up, ready to take over. - RECOVERING, ///< Primary: waiting for backups to connect & sync - ACTIVE, ///< Primary: actively serving clients. - STANDALONE ///< Not part of a cluster. -}; - -inline bool isPrimary(BrokerStatus s) { - return s == RECOVERING || s == ACTIVE || s == STANDALONE; -} - -inline bool isBackup(BrokerStatus s) { return !isPrimary(s); } - -// String constants, defined as char* to avoid initialization order problems. -extern const std::string QPID_REPLICATE; -extern const std::string QPID_HA_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; - -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 { - 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; -typedef framing::SequenceNumber ReplicationId; -typedef framing::SequenceSet QueuePositionSet; -typedef framing::SequenceSet ReplicationIdSet; - -/** Helpers for logging message ID */ -std::string logMessageId(const std::string& q, QueuePosition pos, ReplicationId id); -std::string logMessageId(const std::string& q, ReplicationId id); -std::string logMessageId(const std::string& q, const broker::Message& m); -std::string logMessageId(const broker::Queue& q, QueuePosition pos, ReplicationId id); -std::string logMessageId(const broker::Queue& q, ReplicationId id); -std::string logMessageId(const broker::Queue& q, const broker::Message& m); - -/** 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/BindingDbt.cpp b/qpid/cpp/src/qpid/legacystore/BindingDbt.cpp deleted file mode 100644 index a48c156e71..0000000000 --- a/qpid/cpp/src/qpid/legacystore/BindingDbt.cpp +++ /dev/null @@ -1,50 +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/legacystore/BindingDbt.h" - -namespace mrg { -namespace msgstore { - -BindingDbt::BindingDbt(const qpid::broker::PersistableExchange& e, const qpid::broker::PersistableQueue& q, const std::string& k, const qpid::framing::FieldTable& a) - : data(new char[encodedSize(e, q, k, a)]), - buffer(data, encodedSize(e, q, k, a)) -{ - buffer.putLongLong(q.getPersistenceId()); - buffer.putShortString(q.getName()); - buffer.putShortString(k); - buffer.put(a); - - set_data(data); - set_size(encodedSize(e, q, k, a)); -} - -BindingDbt::~BindingDbt() -{ - delete [] data; -} - -uint32_t BindingDbt::encodedSize(const qpid::broker::PersistableExchange& /*not used*/, const qpid::broker::PersistableQueue& q, const std::string& k, const qpid::framing::FieldTable& a) -{ - return 8 /*queue id*/ + q.getName().size() + 1 + k.size() + 1 + a.encodedSize(); -} - -}} diff --git a/qpid/cpp/src/qpid/legacystore/BindingDbt.h b/qpid/cpp/src/qpid/legacystore/BindingDbt.h deleted file mode 100644 index 63c7cd144e..0000000000 --- a/qpid/cpp/src/qpid/legacystore/BindingDbt.h +++ /dev/null @@ -1,56 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_BINDINGDBT_H -#define QPID_LEGACYSTORE_BINDINGDBT_H - -#include "db-inc.h" -#include "qpid/broker/PersistableExchange.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldTable.h" - -namespace mrg{ -namespace msgstore{ - -class BindingDbt : public Dbt -{ - char* data; - qpid::framing::Buffer buffer; - - static uint32_t encodedSize(const qpid::broker::PersistableExchange& e, - const qpid::broker::PersistableQueue& q, - const std::string& k, - const qpid::framing::FieldTable& a); - -public: - BindingDbt(const qpid::broker::PersistableExchange& e, - const qpid::broker::PersistableQueue& q, - const std::string& k, - const qpid::framing::FieldTable& a); - - virtual ~BindingDbt(); - -}; - -}} - -#endif // ifndef QPID_LEGACYSTORE_BINDINGDBT_H diff --git a/qpid/cpp/src/qpid/legacystore/BufferValue.cpp b/qpid/cpp/src/qpid/legacystore/BufferValue.cpp deleted file mode 100644 index fb2c471cd7..0000000000 --- a/qpid/cpp/src/qpid/legacystore/BufferValue.cpp +++ /dev/null @@ -1,56 +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/legacystore/BufferValue.h" - -namespace mrg { -namespace msgstore { - - - -BufferValue::BufferValue(u_int32_t size, u_int64_t offset) - : data(new char[size]), - buffer(data, size) -{ - set_data(data); - set_size(size); - set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); - set_doff(offset); - set_dlen(size); - set_ulen(size); -} - -BufferValue::BufferValue(const qpid::broker::Persistable& p) - : data(new char[p.encodedSize()]), - buffer(data, p.encodedSize()) -{ - p.encode(buffer); - - set_data(data); - set_size(p.encodedSize()); -} - -BufferValue::~BufferValue() -{ - delete [] data; -} - -}} diff --git a/qpid/cpp/src/qpid/legacystore/BufferValue.h b/qpid/cpp/src/qpid/legacystore/BufferValue.h deleted file mode 100644 index 527fbcf577..0000000000 --- a/qpid/cpp/src/qpid/legacystore/BufferValue.h +++ /dev/null @@ -1,46 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_BUFFERVALUE_H -#define QPID_LEGACYSTORE_BUFFERVALUE_H - -#include "db-inc.h" -#include "qpid/broker/Persistable.h" -#include "qpid/framing/Buffer.h" - -namespace mrg{ -namespace msgstore{ - -class BufferValue : public Dbt -{ - char* data; - -public: - qpid::framing::Buffer buffer; - - BufferValue(u_int32_t size, u_int64_t offset); - BufferValue(const qpid::broker::Persistable& p); - virtual ~BufferValue(); -}; - -}} - -#endif // ifndef QPID_LEGACYSTORE_BUFFERVALUE_H diff --git a/qpid/cpp/src/qpid/legacystore/Cursor.h b/qpid/cpp/src/qpid/legacystore/Cursor.h deleted file mode 100644 index 0c869c29a0..0000000000 --- a/qpid/cpp/src/qpid/legacystore/Cursor.h +++ /dev/null @@ -1,50 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_CURSOR_H -#define QPID_LEGACYSTORE_CURSOR_H - -#include -#include "db-inc.h" - -namespace mrg{ -namespace msgstore{ - -class Cursor -{ - Dbc* cursor; -public: - typedef boost::shared_ptr db_ptr; - - Cursor() : cursor(0) {} - virtual ~Cursor() { if(cursor) cursor->close(); } - - void open(db_ptr db, DbTxn* txn, u_int32_t flags = 0) { db->cursor(txn, &cursor, flags); } - void close() { if(cursor) cursor->close(); cursor = 0; } - Dbc* get() { return cursor; } - Dbc* operator->() { return cursor; } - bool next(Dbt& key, Dbt& value) { return cursor->get(&key, &value, DB_NEXT) == 0; } - bool current(Dbt& key, Dbt& value) { return cursor->get(&key, &value, DB_CURRENT) == 0; } -}; - -}} - -#endif // ifndef QPID_LEGACYSTORE_CURSOR_H diff --git a/qpid/cpp/src/qpid/legacystore/DataTokenImpl.cpp b/qpid/cpp/src/qpid/legacystore/DataTokenImpl.cpp deleted file mode 100644 index 796d4c02f0..0000000000 --- a/qpid/cpp/src/qpid/legacystore/DataTokenImpl.cpp +++ /dev/null @@ -1,28 +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/legacystore/DataTokenImpl.h" - -using namespace mrg::msgstore; - -DataTokenImpl::DataTokenImpl():data_tok() {} - -DataTokenImpl::~DataTokenImpl() {} diff --git a/qpid/cpp/src/qpid/legacystore/DataTokenImpl.h b/qpid/cpp/src/qpid/legacystore/DataTokenImpl.h deleted file mode 100644 index e01d471e1b..0000000000 --- a/qpid/cpp/src/qpid/legacystore/DataTokenImpl.h +++ /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. - * - */ - -#ifndef QPID_LEGACYSTORE_DATATOKENIMPL_H -#define QPID_LEGACYSTORE_DATATOKENIMPL_H - -#include "qpid/legacystore/jrnl/data_tok.h" -#include "qpid/broker/PersistableMessage.h" -#include - -namespace mrg { -namespace msgstore { - -class DataTokenImpl : public journal::data_tok, public qpid::RefCounted -{ - private: - boost::intrusive_ptr sourceMsg; - public: - DataTokenImpl(); - virtual ~DataTokenImpl(); - - inline boost::intrusive_ptr& getSourceMessage() { return sourceMsg; } - inline void setSourceMessage(const boost::intrusive_ptr& msg) { sourceMsg = msg; } -}; - -} // namespace msgstore -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_DATATOKENIMPL_H diff --git a/qpid/cpp/src/qpid/legacystore/IdDbt.cpp b/qpid/cpp/src/qpid/legacystore/IdDbt.cpp deleted file mode 100644 index d9edaf80e6..0000000000 --- a/qpid/cpp/src/qpid/legacystore/IdDbt.cpp +++ /dev/null @@ -1,42 +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/legacystore/IdDbt.h" - -using namespace mrg::msgstore; - -IdDbt::IdDbt() : id(0) -{ - init(); -} - -IdDbt::IdDbt(u_int64_t _id) : id(_id) -{ - init(); -} - -void IdDbt::init() -{ - set_data(&id); - set_size(sizeof(u_int64_t)); - set_ulen(sizeof(u_int64_t)); - set_flags(DB_DBT_USERMEM); -} diff --git a/qpid/cpp/src/qpid/legacystore/IdDbt.h b/qpid/cpp/src/qpid/legacystore/IdDbt.h deleted file mode 100644 index ecf5922963..0000000000 --- a/qpid/cpp/src/qpid/legacystore/IdDbt.h +++ /dev/null @@ -1,42 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_IDDBT_H -#define QPID_LEGACYSTORE_IDDBT_H - -#include "db-inc.h" - -namespace mrg{ -namespace msgstore{ - -class IdDbt : public Dbt -{ - void init(); -public: - u_int64_t id; - - IdDbt(u_int64_t id); - IdDbt(); -}; - -}} - -#endif // ifndef QPID_LEGACYSTORE_IDDBT_H diff --git a/qpid/cpp/src/qpid/legacystore/IdSequence.cpp b/qpid/cpp/src/qpid/legacystore/IdSequence.cpp deleted file mode 100644 index 975b1107e7..0000000000 --- a/qpid/cpp/src/qpid/legacystore/IdSequence.cpp +++ /dev/null @@ -1,40 +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/legacystore/IdSequence.h" - -using namespace mrg::msgstore; -using qpid::sys::Mutex; - -IdSequence::IdSequence() : id(1) {} - -u_int64_t IdSequence::next() -{ - Mutex::ScopedLock guard(lock); - if (!id) id++; // avoid 0 when folding around - return id++; -} - -void IdSequence::reset(uint64_t value) -{ - //deliberately not threadsafe, used only on recovery - id = value; -} diff --git a/qpid/cpp/src/qpid/legacystore/IdSequence.h b/qpid/cpp/src/qpid/legacystore/IdSequence.h deleted file mode 100644 index 11d7ff61ca..0000000000 --- a/qpid/cpp/src/qpid/legacystore/IdSequence.h +++ /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. - * - */ - -#ifndef QPID_LEGACYSTORE_IDSEQUENCE_H -#define QPID_LEGACYSTORE_IDSEQUENCE_H - -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Mutex.h" -#include - -namespace mrg{ -namespace msgstore{ - -class IdSequence -{ - qpid::sys::Mutex lock; - uint64_t id; -public: - IdSequence(); - uint64_t next(); - void reset(uint64_t value); -}; - -}} - -#endif // ifndef QPID_LEGACYSTORE_IDSEQUENCE_H diff --git a/qpid/cpp/src/qpid/legacystore/JournalImpl.cpp b/qpid/cpp/src/qpid/legacystore/JournalImpl.cpp deleted file mode 100644 index ba3f2aecae..0000000000 --- a/qpid/cpp/src/qpid/legacystore/JournalImpl.cpp +++ /dev/null @@ -1,633 +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/legacystore/JournalImpl.h" - -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/legacystore/ArgsJournalExpand.h" -#include "qmf/org/apache/qpid/legacystore/EventCreated.h" -#include "qmf/org/apache/qpid/legacystore/EventEnqThresholdExceeded.h" -#include "qmf/org/apache/qpid/legacystore/EventFull.h" -#include "qmf/org/apache/qpid/legacystore/EventRecovered.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Timer.h" -#include "qpid/legacystore/StoreException.h" - -using namespace mrg::msgstore; -using namespace mrg::journal; -using qpid::management::ManagementAgent; -namespace _qmf = qmf::org::apache::qpid::legacystore; - -InactivityFireEvent::InactivityFireEvent(JournalImpl* p, const qpid::sys::Duration timeout): - qpid::sys::TimerTask(timeout, "JournalInactive:"+p->id()), _parent(p) {} - -void InactivityFireEvent::fire() { qpid::sys::Mutex::ScopedLock sl(_ife_lock); if (_parent) _parent->flushFire(); } - -GetEventsFireEvent::GetEventsFireEvent(JournalImpl* p, const qpid::sys::Duration timeout): - qpid::sys::TimerTask(timeout, "JournalGetEvents:"+p->id()), _parent(p) {} - -void GetEventsFireEvent::fire() { qpid::sys::Mutex::ScopedLock sl(_gefe_lock); if (_parent) _parent->getEventsFire(); } - -JournalImpl::JournalImpl(qpid::sys::Timer& timer_, - const std::string& journalId, - const std::string& journalDirectory, - const std::string& journalBaseFilename, - const qpid::sys::Duration getEventsTimeout, - const qpid::sys::Duration flushTimeout, - qpid::management::ManagementAgent* a, - DeleteCallback onDelete): - jcntl(journalId, journalDirectory, journalBaseFilename), - timer(timer_), - getEventsTimerSetFlag(false), - lastReadRid(0), - writeActivityFlag(false), - flushTriggeredFlag(true), - _xidp(0), - _datap(0), - _dlen(0), - _dtok(), - _external(false), - deleteCallback(onDelete) -{ - getEventsFireEventsPtr = new GetEventsFireEvent(this, getEventsTimeout); - inactivityFireEventPtr = new InactivityFireEvent(this, flushTimeout); - { - timer.start(); - timer.add(inactivityFireEventPtr); - } - - initManagement(a); - - log(LOG_NOTICE, "Created"); - std::ostringstream oss; - oss << "Journal directory = \"" << journalDirectory << "\"; Base file name = \"" << journalBaseFilename << "\""; - log(LOG_DEBUG, oss.str()); -} - -JournalImpl::~JournalImpl() -{ - if (deleteCallback) deleteCallback(*this); - if (_init_flag && !_stop_flag){ - try { stop(true); } // NOTE: This will *block* until all outstanding disk aio calls are complete! - catch (const jexception& e) { log(LOG_ERROR, e.what()); } - } - getEventsFireEventsPtr->cancel(); - inactivityFireEventPtr->cancel(); - free_read_buffers(); - - if (_mgmtObject.get() != 0) { - _mgmtObject->resourceDestroy(); - _mgmtObject.reset(); - } - - log(LOG_NOTICE, "Destroyed"); -} - -void -JournalImpl::initManagement(qpid::management::ManagementAgent* a) -{ - _agent = a; - if (_agent != 0) - { - _mgmtObject = _qmf::Journal::shared_ptr ( - new _qmf::Journal(_agent, this)); - - _mgmtObject->set_name(_jid); - _mgmtObject->set_directory(_jdir.dirname()); - _mgmtObject->set_baseFileName(_base_filename); - _mgmtObject->set_readPageSize(JRNL_RMGR_PAGE_SIZE * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE); - _mgmtObject->set_readPages(JRNL_RMGR_PAGES); - - // The following will be set on initialize(), but being properties, these must be set to 0 in the meantime - _mgmtObject->set_initialFileCount(0); - _mgmtObject->set_dataFileSize(0); - _mgmtObject->set_currentFileCount(0); - _mgmtObject->set_writePageSize(0); - _mgmtObject->set_writePages(0); - - _agent->addObject(_mgmtObject, 0, true); - } -} - - -void -JournalImpl::initialize(const u_int16_t num_jfiles, - const bool auto_expand, - const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, - const u_int16_t wcache_num_pages, - const u_int32_t wcache_pgsize_sblks, - mrg::journal::aio_callback* const cbp) -{ - std::ostringstream oss; - oss << "Initialize; num_jfiles=" << num_jfiles << " jfsize_sblks=" << jfsize_sblks; - oss << " wcache_pgsize_sblks=" << wcache_pgsize_sblks; - oss << " wcache_num_pages=" << wcache_num_pages; - log(LOG_DEBUG, oss.str()); - jcntl::initialize(num_jfiles, auto_expand, ae_max_jfiles, jfsize_sblks, wcache_num_pages, wcache_pgsize_sblks, cbp); - log(LOG_DEBUG, "Initialization complete"); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->set_initialFileCount(_lpmgr.num_jfiles()); - _mgmtObject->set_autoExpand(_lpmgr.is_ae()); - _mgmtObject->set_currentFileCount(_lpmgr.num_jfiles()); - _mgmtObject->set_maxFileCount(_lpmgr.ae_max_jfiles()); - _mgmtObject->set_dataFileSize(_jfsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE); - _mgmtObject->set_writePageSize(wcache_pgsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE); - _mgmtObject->set_writePages(wcache_num_pages); - } - if (_agent != 0) - _agent->raiseEvent(qmf::org::apache::qpid::legacystore::EventCreated(_jid, _jfsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE, _lpmgr.num_jfiles()), - qpid::management::ManagementAgent::SEV_NOTE); -} - -void -JournalImpl::recover(const u_int16_t num_jfiles, - const bool auto_expand, - const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, - const u_int16_t wcache_num_pages, - const u_int32_t wcache_pgsize_sblks, - mrg::journal::aio_callback* const cbp, - boost::ptr_list* prep_tx_list_ptr, - u_int64_t& highest_rid, - u_int64_t queue_id) -{ - std::ostringstream oss1; - oss1 << "Recover; num_jfiles=" << num_jfiles << " jfsize_sblks=" << jfsize_sblks; - oss1 << " queue_id = 0x" << std::hex << queue_id << std::dec; - oss1 << " wcache_pgsize_sblks=" << wcache_pgsize_sblks; - oss1 << " wcache_num_pages=" << wcache_num_pages; - log(LOG_DEBUG, oss1.str()); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->set_initialFileCount(_lpmgr.num_jfiles()); - _mgmtObject->set_autoExpand(_lpmgr.is_ae()); - _mgmtObject->set_currentFileCount(_lpmgr.num_jfiles()); - _mgmtObject->set_maxFileCount(_lpmgr.ae_max_jfiles()); - _mgmtObject->set_dataFileSize(_jfsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE); - _mgmtObject->set_writePageSize(wcache_pgsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE); - _mgmtObject->set_writePages(wcache_num_pages); - } - - if (prep_tx_list_ptr) { - // Create list of prepared xids - std::vector prep_xid_list; - for (msgstore::PreparedTransaction::list::iterator i = prep_tx_list_ptr->begin(); i != prep_tx_list_ptr->end(); i++) { - prep_xid_list.push_back(i->xid); - } - - jcntl::recover(num_jfiles, auto_expand, ae_max_jfiles, jfsize_sblks, wcache_num_pages, wcache_pgsize_sblks, - cbp, &prep_xid_list, highest_rid); - } else { - jcntl::recover(num_jfiles, auto_expand, ae_max_jfiles, jfsize_sblks, wcache_num_pages, wcache_pgsize_sblks, - cbp, 0, highest_rid); - } - - // Populate PreparedTransaction lists from _tmap - if (prep_tx_list_ptr) - { - for (msgstore::PreparedTransaction::list::iterator i = prep_tx_list_ptr->begin(); i != prep_tx_list_ptr->end(); i++) { - txn_data_list tdl = _tmap.get_tdata_list(i->xid); // tdl will be empty if xid not found - for (tdl_itr tdl_itr = tdl.begin(); tdl_itr < tdl.end(); tdl_itr++) { - if (tdl_itr->_enq_flag) { // enqueue op - i->enqueues->add(queue_id, tdl_itr->_rid); - } else { // dequeue op - i->dequeues->add(queue_id, tdl_itr->_drid); - } - } - } - } - std::ostringstream oss2; - oss2 << "Recover phase 1 complete; highest rid found = 0x" << std::hex << highest_rid; - oss2 << std::dec << "; emap.size=" << _emap.size() << "; tmap.size=" << _tmap.size(); - oss2 << "; journal now read-only."; - log(LOG_DEBUG, oss2.str()); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->inc_recordDepth(_emap.size()); - _mgmtObject->inc_enqueues(_emap.size()); - _mgmtObject->inc_txn(_tmap.size()); - _mgmtObject->inc_txnEnqueues(_tmap.enq_cnt()); - _mgmtObject->inc_txnDequeues(_tmap.deq_cnt()); - } -} - -void -JournalImpl::recover_complete() -{ - jcntl::recover_complete(); - log(LOG_DEBUG, "Recover phase 2 complete; journal now writable."); - if (_agent != 0) - _agent->raiseEvent(qmf::org::apache::qpid::legacystore::EventRecovered(_jid, _jfsize_sblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE, _lpmgr.num_jfiles(), - _emap.size(), _tmap.size(), _tmap.enq_cnt(), _tmap.deq_cnt()), qpid::management::ManagementAgent::SEV_NOTE); -} - -//#define MAX_AIO_SLEEPS 1000000 // tot: ~10 sec -//#define AIO_SLEEP_TIME_US 10 // 0.01 ms -// Return true if content is recovered from store; false if content is external and must be recovered from an external store. -// Throw exception for all errors. -bool -JournalImpl::loadMsgContent(u_int64_t rid, std::string& data, size_t length, size_t offset) -{ - qpid::sys::Mutex::ScopedLock sl(_read_lock); - if (_dtok.rid() != rid) - { - // Free any previous msg - free_read_buffers(); - - // Last read encountered out-of-order rids, check if this rid is in that list - bool oooFlag = false; - for (std::vector::const_iterator i=oooRidList.begin(); i!=oooRidList.end() && !oooFlag; i++) { - if (*i == rid) { - oooFlag = true; - } - } - - // TODO: This is a brutal approach - very inefficient and slow. Rather introduce a system of remembering - // jumpover points and allow the read to jump back to the first known jumpover point - but this needs - // a mechanism in rrfc to accomplish it. Also helpful is a struct containing a journal address - a - // combination of lid/offset. - // NOTE: The second part of the if stmt (rid < lastReadRid) is required to handle browsing. - if (oooFlag || rid < lastReadRid) { - _rmgr.invalidate(); - oooRidList.clear(); - } - _dlen = 0; - _dtok.reset(); - _dtok.set_wstate(DataTokenImpl::ENQ); - _dtok.set_rid(0); - _external = false; - size_t xlen = 0; - bool transient = false; - bool done = false; - bool rid_found = false; - while (!done) { - iores res = read_data_record(&_datap, _dlen, &_xidp, xlen, transient, _external, &_dtok); - switch (res) { - case mrg::journal::RHM_IORES_SUCCESS: - if (_dtok.rid() != rid) { - // Check if this is an out-of-order rid that may impact next read - if (_dtok.rid() > rid) - oooRidList.push_back(_dtok.rid()); - free_read_buffers(); - // Reset data token for next read - _dlen = 0; - _dtok.reset(); - _dtok.set_wstate(DataTokenImpl::ENQ); - _dtok.set_rid(0); - } else { - rid_found = _dtok.rid() == rid; - lastReadRid = rid; - done = true; - } - break; - case mrg::journal::RHM_IORES_PAGE_AIOWAIT: - if (get_wr_events(&_aio_cmpl_timeout) == journal::jerrno::AIO_TIMEOUT) { - std::stringstream ss; - ss << "read_data_record() returned " << mrg::journal::iores_str(res); - ss << "; timed out waiting for page to be processed."; - throw jexception(mrg::journal::jerrno::JERR__TIMEOUT, ss.str().c_str(), "JournalImpl", - "loadMsgContent"); - } - break; - default: - std::stringstream ss; - ss << "read_data_record() returned " << mrg::journal::iores_str(res); - throw jexception(mrg::journal::jerrno::JERR__UNEXPRESPONSE, ss.str().c_str(), "JournalImpl", - "loadMsgContent"); - } - } - if (!rid_found) { - std::stringstream ss; - ss << "read_data_record() was unable to find rid 0x" << std::hex << rid << std::dec; - ss << " (" << rid << "); last rid found was 0x" << std::hex << _dtok.rid() << std::dec; - ss << " (" << _dtok.rid() << ")"; - throw jexception(mrg::journal::jerrno::JERR__RECNFOUND, ss.str().c_str(), "JournalImpl", "loadMsgContent"); - } - } - - if (_external) return false; - - u_int32_t hdr_offs = qpid::framing::Buffer(static_cast(_datap), sizeof(u_int32_t)).getLong() + sizeof(u_int32_t); - if (hdr_offs + offset + length > _dlen) { - data.append((const char*)_datap + hdr_offs + offset, _dlen - hdr_offs - offset); - } else { - data.append((const char*)_datap + hdr_offs + offset, length); - } - return true; -} - -void -JournalImpl::enqueue_data_record(const void* const data_buff, const size_t tot_data_len, - const size_t this_data_len, data_tok* dtokp, const bool transient) -{ - handleIoResult(jcntl::enqueue_data_record(data_buff, tot_data_len, this_data_len, dtokp, transient)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->inc_enqueues(); - _mgmtObject->inc_recordDepth(); - } -} - -void -JournalImpl::enqueue_extern_data_record(const size_t tot_data_len, data_tok* dtokp, - const bool transient) -{ - handleIoResult(jcntl::enqueue_extern_data_record(tot_data_len, dtokp, transient)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->inc_enqueues(); - _mgmtObject->inc_recordDepth(); - } -} - -void -JournalImpl::enqueue_txn_data_record(const void* const data_buff, const size_t tot_data_len, - const size_t this_data_len, data_tok* dtokp, const std::string& xid, const bool transient) -{ - bool txn_incr = _mgmtObject.get() != 0 ? _tmap.in_map(xid) : false; - - handleIoResult(jcntl::enqueue_txn_data_record(data_buff, tot_data_len, this_data_len, dtokp, xid, transient)); - - if (_mgmtObject.get() != 0) - { - if (!txn_incr) // If this xid was not in _tmap, it will be now... - _mgmtObject->inc_txn(); - _mgmtObject->inc_enqueues(); - _mgmtObject->inc_txnEnqueues(); - _mgmtObject->inc_recordDepth(); - } -} - -void -JournalImpl::enqueue_extern_txn_data_record(const size_t tot_data_len, data_tok* dtokp, - const std::string& xid, const bool transient) -{ - bool txn_incr = _mgmtObject.get() != 0 ? _tmap.in_map(xid) : false; - - handleIoResult(jcntl::enqueue_extern_txn_data_record(tot_data_len, dtokp, xid, transient)); - - if (_mgmtObject.get() != 0) - { - if (!txn_incr) // If this xid was not in _tmap, it will be now... - _mgmtObject->inc_txn(); - _mgmtObject->inc_enqueues(); - _mgmtObject->inc_txnEnqueues(); - _mgmtObject->inc_recordDepth(); - } -} - -void -JournalImpl::dequeue_data_record(data_tok* const dtokp, const bool txn_coml_commit) -{ - handleIoResult(jcntl::dequeue_data_record(dtokp, txn_coml_commit)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->inc_dequeues(); - _mgmtObject->inc_txnDequeues(); - _mgmtObject->dec_recordDepth(); - } -} - -void -JournalImpl::dequeue_txn_data_record(data_tok* const dtokp, const std::string& xid, const bool txn_coml_commit) -{ - bool txn_incr = _mgmtObject.get() != 0 ? _tmap.in_map(xid) : false; - - handleIoResult(jcntl::dequeue_txn_data_record(dtokp, xid, txn_coml_commit)); - - if (_mgmtObject.get() != 0) - { - if (!txn_incr) // If this xid was not in _tmap, it will be now... - _mgmtObject->inc_txn(); - _mgmtObject->inc_dequeues(); - _mgmtObject->inc_txnDequeues(); - _mgmtObject->dec_recordDepth(); - } -} - -void -JournalImpl::txn_abort(data_tok* const dtokp, const std::string& xid) -{ - handleIoResult(jcntl::txn_abort(dtokp, xid)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->dec_txn(); - _mgmtObject->inc_txnAborts(); - } -} - -void -JournalImpl::txn_commit(data_tok* const dtokp, const std::string& xid) -{ - handleIoResult(jcntl::txn_commit(dtokp, xid)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->dec_txn(); - _mgmtObject->inc_txnCommits(); - } -} - -void -JournalImpl::stop(bool block_till_aio_cmpl) -{ - InactivityFireEvent* ifep = dynamic_cast(inactivityFireEventPtr.get()); - assert(ifep); // dynamic_cast can return null if the cast fails - ifep->cancel(); - jcntl::stop(block_till_aio_cmpl); - - if (_mgmtObject.get() != 0) { - _mgmtObject->resourceDestroy(); - _mgmtObject.reset(); - } -} - -iores -JournalImpl::flush(const bool block_till_aio_cmpl) -{ - const iores res = jcntl::flush(block_till_aio_cmpl); - { - qpid::sys::Mutex::ScopedLock sl(_getf_lock); - if (_wmgr.get_aio_evt_rem() && !getEventsTimerSetFlag) { setGetEventTimer(); } - } - return res; -} - -void -JournalImpl::log(mrg::journal::log_level ll, const std::string& log_stmt) const -{ - log(ll, log_stmt.c_str()); -} - -void -JournalImpl::log(mrg::journal::log_level ll, const char* const log_stmt) const -{ - switch (ll) - { - case LOG_TRACE: QPID_LOG(trace, "Journal \"" << _jid << "\": " << log_stmt); break; - case LOG_DEBUG: QPID_LOG(debug, "Journal \"" << _jid << "\": " << log_stmt); break; - case LOG_INFO: QPID_LOG(info, "Journal \"" << _jid << "\": " << log_stmt); break; - case LOG_NOTICE: QPID_LOG(notice, "Journal \"" << _jid << "\": " << log_stmt); break; - case LOG_WARN: QPID_LOG(warning, "Journal \"" << _jid << "\": " << log_stmt); break; - case LOG_ERROR: QPID_LOG(error, "Journal \"" << _jid << "\": " << log_stmt); break; - case LOG_CRITICAL: QPID_LOG(critical, "Journal \"" << _jid << "\": " << log_stmt); break; - } -} - -void -JournalImpl::getEventsFire() -{ - qpid::sys::Mutex::ScopedLock sl(_getf_lock); - getEventsTimerSetFlag = false; - if (_wmgr.get_aio_evt_rem()) { jcntl::get_wr_events(0); } - if (_wmgr.get_aio_evt_rem()) { setGetEventTimer(); } -} - -void -JournalImpl::flushFire() -{ - if (writeActivityFlag) { - writeActivityFlag = false; - flushTriggeredFlag = false; - } else { - if (!flushTriggeredFlag) { - flush(); - flushTriggeredFlag = true; - } - } - inactivityFireEventPtr->setupNextFire(); - { - timer.add(inactivityFireEventPtr); - } -} - -void -JournalImpl::wr_aio_cb(std::vector& dtokl) -{ - for (std::vector::const_iterator i=dtokl.begin(); i!=dtokl.end(); i++) - { - DataTokenImpl* dtokp = static_cast(*i); - if (/*!is_stopped() &&*/ dtokp->getSourceMessage()) - { - switch (dtokp->wstate()) - { - case data_tok::ENQ: - dtokp->getSourceMessage()->enqueueComplete(); - break; - case data_tok::DEQ: -/* Don't need to signal until we have a way to ack completion of dequeue in AMQP - dtokp->getSourceMessage()->dequeueComplete(); - if ( dtokp->getSourceMessage()->isDequeueComplete() ) // clear id after last dequeue - dtokp->getSourceMessage()->setPersistenceId(0); -*/ - break; - default: ; - } - } - dtokp->release(); - } -} - -void -JournalImpl::rd_aio_cb(std::vector& /*pil*/) -{} - -void -JournalImpl::free_read_buffers() -{ - if (_xidp) { - ::free(_xidp); - _xidp = 0; - _datap = 0; - } else if (_datap) { - ::free(_datap); - _datap = 0; - } -} - -void -JournalImpl::handleIoResult(const iores r) -{ - writeActivityFlag = true; - switch (r) - { - case mrg::journal::RHM_IORES_SUCCESS: - return; - case mrg::journal::RHM_IORES_ENQCAPTHRESH: - { - std::ostringstream oss; - oss << "Enqueue capacity threshold exceeded on queue \"" << _jid << "\"."; - log(LOG_WARN, oss.str()); - if (_agent != 0) - _agent->raiseEvent(qmf::org::apache::qpid::legacystore::EventEnqThresholdExceeded(_jid, "Journal enqueue capacity threshold exceeded"), - qpid::management::ManagementAgent::SEV_WARN); - THROW_STORE_FULL_EXCEPTION(oss.str()); - } - case mrg::journal::RHM_IORES_FULL: - { - std::ostringstream oss; - oss << "Journal full on queue \"" << _jid << "\"."; - log(LOG_CRITICAL, oss.str()); - if (_agent != 0) - _agent->raiseEvent(qmf::org::apache::qpid::legacystore::EventFull(_jid, "Journal full"), qpid::management::ManagementAgent::SEV_ERROR); - THROW_STORE_FULL_EXCEPTION(oss.str()); - } - default: - { - std::ostringstream oss; - oss << "Unexpected I/O response (" << mrg::journal::iores_str(r) << ") on queue " << _jid << "\"."; - log(LOG_ERROR, oss.str()); - THROW_STORE_FULL_EXCEPTION(oss.str()); - } - } -} - -qpid::management::Manageable::status_t JournalImpl::ManagementMethod (uint32_t methodId, - qpid::management::Args& /*args*/, - std::string& /*text*/) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - switch (methodId) - { - case _qmf::Journal::METHOD_EXPAND : - //_qmf::ArgsJournalExpand& eArgs = (_qmf::ArgsJournalExpand&) args; - - // Implement "expand" using eArgs.i_by (expand-by argument) - - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } - - return status; -} diff --git a/qpid/cpp/src/qpid/legacystore/JournalImpl.h b/qpid/cpp/src/qpid/legacystore/JournalImpl.h deleted file mode 100644 index 7227b2ffd4..0000000000 --- a/qpid/cpp/src/qpid/legacystore/JournalImpl.h +++ /dev/null @@ -1,265 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_JOURNALIMPL_H -#define QPID_LEGACYSTORE_JOURNALIMPL_H - -#include -#include "qpid/legacystore/jrnl/enums.h" -#include "qpid/legacystore/jrnl/jcntl.h" -#include "qpid/legacystore/DataTokenImpl.h" -#include "qpid/legacystore/PreparedTransaction.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/Time.h" -#include -#include -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/legacystore/Journal.h" - -namespace qpid { namespace sys { -class Timer; -}} - -namespace mrg { -namespace msgstore { - -class JournalImpl; - -class InactivityFireEvent : public qpid::sys::TimerTask -{ - JournalImpl* _parent; - qpid::sys::Mutex _ife_lock; - - public: - InactivityFireEvent(JournalImpl* p, const qpid::sys::Duration timeout); - virtual ~InactivityFireEvent() {} - void fire(); - inline void cancel() { qpid::sys::Mutex::ScopedLock sl(_ife_lock); _parent = 0; } -}; - -class GetEventsFireEvent : public qpid::sys::TimerTask -{ - JournalImpl* _parent; - qpid::sys::Mutex _gefe_lock; - - public: - GetEventsFireEvent(JournalImpl* p, const qpid::sys::Duration timeout); - virtual ~GetEventsFireEvent() {} - void fire(); - inline void cancel() { qpid::sys::Mutex::ScopedLock sl(_gefe_lock); _parent = 0; } -}; - -class JournalImpl : public qpid::broker::ExternalQueueStore, public mrg::journal::jcntl, public mrg::journal::aio_callback -{ - public: - typedef boost::function DeleteCallback; - - private: -// static qpid::sys::Mutex _static_lock; -// static u_int32_t cnt; - - qpid::sys::Timer& timer; - bool getEventsTimerSetFlag; - boost::intrusive_ptr getEventsFireEventsPtr; - qpid::sys::Mutex _getf_lock; - qpid::sys::Mutex _read_lock; - - u_int64_t lastReadRid; // rid of last read msg for loadMsgContent() - detects out-of-order read requests - std::vector oooRidList; // list of out-of-order rids (greater than current rid) encountered during read sequence - - bool writeActivityFlag; - bool flushTriggeredFlag; - boost::intrusive_ptr inactivityFireEventPtr; - - // temp local vars for loadMsgContent below - void* _xidp; - void* _datap; - size_t _dlen; - mrg::journal::data_tok _dtok; - bool _external; - - qpid::management::ManagementAgent* _agent; - qmf::org::apache::qpid::legacystore::Journal::shared_ptr _mgmtObject; - DeleteCallback deleteCallback; - - public: - - JournalImpl(qpid::sys::Timer& timer, - const std::string& journalId, - const std::string& journalDirectory, - const std::string& journalBaseFilename, - const qpid::sys::Duration getEventsTimeout, - const qpid::sys::Duration flushTimeout, - qpid::management::ManagementAgent* agent, - DeleteCallback deleteCallback=DeleteCallback() ); - - virtual ~JournalImpl(); - - void initManagement(qpid::management::ManagementAgent* agent); - - void initialize(const u_int16_t num_jfiles, - const bool auto_expand, - const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, - const u_int16_t wcache_num_pages, - const u_int32_t wcache_pgsize_sblks, - mrg::journal::aio_callback* const cbp); - - inline void initialize(const u_int16_t num_jfiles, - const bool auto_expand, - const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, - const u_int16_t wcache_num_pages, - const u_int32_t wcache_pgsize_sblks) { - initialize(num_jfiles, auto_expand, ae_max_jfiles, jfsize_sblks, wcache_num_pages, wcache_pgsize_sblks, - this); - } - - void recover(const u_int16_t num_jfiles, - const bool auto_expand, - const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, - const u_int16_t wcache_num_pages, - const u_int32_t wcache_pgsize_sblks, - mrg::journal::aio_callback* const cbp, - boost::ptr_list* prep_tx_list_ptr, - u_int64_t& highest_rid, - u_int64_t queue_id); - - inline void recover(const u_int16_t num_jfiles, - const bool auto_expand, - const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, - const u_int16_t wcache_num_pages, - const u_int32_t wcache_pgsize_sblks, - boost::ptr_list* prep_tx_list_ptr, - u_int64_t& highest_rid, - u_int64_t queue_id) { - recover(num_jfiles, auto_expand, ae_max_jfiles, jfsize_sblks, wcache_num_pages, wcache_pgsize_sblks, - this, prep_tx_list_ptr, highest_rid, queue_id); - } - - void recover_complete(); - - // Temporary fn to read and save last msg read from journal so it can be assigned - // in chunks. To be replaced when coding to do this direct from the journal is ready. - // Returns true if the record is extern, false if local. - bool loadMsgContent(u_int64_t rid, std::string& data, size_t length, size_t offset = 0); - - // Overrides for write inactivity timer - void enqueue_data_record(const void* const data_buff, const size_t tot_data_len, - const size_t this_data_len, mrg::journal::data_tok* dtokp, - const bool transient = false); - - void enqueue_extern_data_record(const size_t tot_data_len, mrg::journal::data_tok* dtokp, - const bool transient = false); - - void enqueue_txn_data_record(const void* const data_buff, const size_t tot_data_len, - const size_t this_data_len, mrg::journal::data_tok* dtokp, const std::string& xid, - const bool transient = false); - - void enqueue_extern_txn_data_record(const size_t tot_data_len, mrg::journal::data_tok* dtokp, - const std::string& xid, const bool transient = false); - - void dequeue_data_record(mrg::journal::data_tok* const dtokp, const bool txn_coml_commit = false); - - void dequeue_txn_data_record(mrg::journal::data_tok* const dtokp, const std::string& xid, const bool txn_coml_commit = false); - - void txn_abort(mrg::journal::data_tok* const dtokp, const std::string& xid); - - void txn_commit(mrg::journal::data_tok* const dtokp, const std::string& xid); - - void stop(bool block_till_aio_cmpl = false); - - // Logging - void log(mrg::journal::log_level level, const std::string& log_stmt) const; - void log(mrg::journal::log_level level, const char* const log_stmt) const; - - // Overrides for get_events timer - mrg::journal::iores flush(const bool block_till_aio_cmpl = false); - - // TimerTask callback - void getEventsFire(); - void flushFire(); - - // AIO callbacks - virtual void wr_aio_cb(std::vector& dtokl); - virtual void rd_aio_cb(std::vector& pil); - - qpid::management::ManagementObject::shared_ptr GetManagementObject (void) const - { return _mgmtObject; } - - qpid::management::Manageable::status_t ManagementMethod (uint32_t, - qpid::management::Args&, - std::string&); - - void resetDeleteCallback() { deleteCallback = DeleteCallback(); } - - private: - void free_read_buffers(); - - inline void setGetEventTimer() - { - getEventsFireEventsPtr->setupNextFire(); - timer.add(getEventsFireEventsPtr); - getEventsTimerSetFlag = true; - } - void handleIoResult(const mrg::journal::iores r); - - // Management instrumentation callbacks overridden from jcntl - inline void instr_incr_outstanding_aio_cnt() { - if (_mgmtObject.get() != 0) _mgmtObject->inc_outstandingAIOs(); - } - inline void instr_decr_outstanding_aio_cnt() { - if (_mgmtObject.get() != 0) _mgmtObject->dec_outstandingAIOs(); - } - -}; // class JournalImpl - -class TplJournalImpl : public JournalImpl -{ - public: - TplJournalImpl(qpid::sys::Timer& timer, - const std::string& journalId, - const std::string& journalDirectory, - const std::string& journalBaseFilename, - const qpid::sys::Duration getEventsTimeout, - const qpid::sys::Duration flushTimeout, - qpid::management::ManagementAgent* agent) : - JournalImpl(timer, journalId, journalDirectory, journalBaseFilename, getEventsTimeout, flushTimeout, agent) - {} - - virtual ~TplJournalImpl() {} - - // Special version of read_data_record that ignores transactions - needed when reading the TPL - inline mrg::journal::iores read_data_record(void** const datapp, std::size_t& dsize, - void** const xidpp, std::size_t& xidsize, bool& transient, bool& external, - mrg::journal::data_tok* const dtokp) { - return JournalImpl::read_data_record(datapp, dsize, xidpp, xidsize, transient, external, dtokp, true); - } - inline void read_reset() { _rmgr.invalidate(); } -}; // class TplJournalImpl - -} // namespace msgstore -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JOURNALIMPL_H diff --git a/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp b/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp deleted file mode 100644 index 7a1fea95d5..0000000000 --- a/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp +++ /dev/null @@ -1,1730 +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/legacystore/MessageStoreImpl.h" - -#include "db-inc.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/legacystore/BindingDbt.h" -#include "qpid/legacystore/BufferValue.h" -#include "qpid/legacystore/IdDbt.h" -#include "qpid/legacystore/jrnl/txn_map.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/log/Statement.h" -#include "qmf/org/apache/qpid/legacystore/Package.h" -#include "qpid/legacystore/StoreException.h" -#include - -#define MAX_AIO_SLEEPS 100000 // tot: ~1 sec -#define AIO_SLEEP_TIME_US 10 // 0.01 ms - -namespace _qmf = qmf::org::apache::qpid::legacystore; - -namespace mrg { -namespace msgstore { - - -const std::string MessageStoreImpl::storeTopLevelDir("rhm"); // Sets the top-level store dir name -// FIXME aconway 2010-03-09: was 10 -qpid::sys::Duration MessageStoreImpl::defJournalGetEventsTimeout(1 * qpid::sys::TIME_MSEC); // 10ms -qpid::sys::Duration MessageStoreImpl::defJournalFlushTimeout(500 * qpid::sys::TIME_MSEC); // 0.5s -qpid::sys::Mutex TxnCtxt::globalSerialiser; - -MessageStoreImpl::TplRecoverStruct::TplRecoverStruct(const u_int64_t _rid, - const bool _deq_flag, - const bool _commit_flag, - const bool _tpc_flag) : - rid(_rid), - deq_flag(_deq_flag), - commit_flag(_commit_flag), - tpc_flag(_tpc_flag) -{} - -MessageStoreImpl::MessageStoreImpl(qpid::broker::Broker* broker_, const char* envpath) : - numJrnlFiles(0), - autoJrnlExpand(false), - autoJrnlExpandMaxFiles(0), - jrnlFsizeSblks(0), - truncateFlag(false), - wCachePgSizeSblks(0), - wCacheNumPages(0), - tplNumJrnlFiles(0), - tplJrnlFsizeSblks(0), - tplWCachePgSizeSblks(0), - tplWCacheNumPages(0), - highestRid(0), - isInit(false), - envPath(envpath), - broker(broker_), - mgmtObject(), - agent(0) -{} - -u_int16_t MessageStoreImpl::chkJrnlNumFilesParam(const u_int16_t param, const std::string paramName) -{ - if (param < JRNL_MIN_NUM_FILES || param > JRNL_MAX_NUM_FILES) { - std::ostringstream oss; - oss << "Parameter " << paramName << ": Illegal number of store journal files (" << param << "), must be " << JRNL_MIN_NUM_FILES << " to " << JRNL_MAX_NUM_FILES << " inclusive."; - THROW_STORE_EXCEPTION(oss.str()); - } - return param; -} - -u_int32_t MessageStoreImpl::chkJrnlFileSizeParam(const u_int32_t param, const std::string paramName, const u_int32_t wCachePgSizeSblks) -{ - if (param < (JRNL_MIN_FILE_SIZE / JRNL_RMGR_PAGE_SIZE) || (param > JRNL_MAX_FILE_SIZE / JRNL_RMGR_PAGE_SIZE)) { - std::ostringstream oss; - oss << "Parameter " << paramName << ": Illegal store journal file size (" << param << "), must be " << JRNL_MIN_FILE_SIZE / JRNL_RMGR_PAGE_SIZE << " to " << JRNL_MAX_FILE_SIZE / JRNL_RMGR_PAGE_SIZE << " inclusive."; - THROW_STORE_EXCEPTION(oss.str()); - } - if (wCachePgSizeSblks > param * JRNL_RMGR_PAGE_SIZE) { - std::ostringstream oss; - oss << "Cannot create store with file size less than write page cache size. [file size = " << param << " (" << (param * JRNL_RMGR_PAGE_SIZE / 2) << " kB); write page cache = " << (wCachePgSizeSblks / 2) << " kB]"; - THROW_STORE_EXCEPTION(oss.str()); - } - return param; -} - -u_int32_t MessageStoreImpl::chkJrnlWrPageCacheSize(const u_int32_t param, const std::string paramName, const u_int16_t jrnlFsizePgs) -{ - u_int32_t p = param; - - if (jrnlFsizePgs == 1 && p > 64 ) { - p = 64; - QPID_LOG(warning, "parameter " << paramName << " (" << param << ") cannot set a page size greater than the journal file size; changing this parameter to the journal file size (" << p << ")"); - } - else if (p == 0) { - // For zero value, use default - p = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE / 1024; - QPID_LOG(warning, "parameter " << paramName << " (" << param << ") must be a power of 2 between 1 and 128; changing this parameter to default value (" << p << ")"); - } else if ( p > 128 || (p & (p-1)) ) { - // For any positive value that is not a power of 2, use closest value - if (p < 6) p = 4; - else if (p < 12) p = 8; - else if (p < 24) p = 16; - else if (p < 48) p = 32; - else if (p < 96) p = 64; - else p = 128; - QPID_LOG(warning, "parameter " << paramName << " (" << param << ") must be a power of 2 between 1 and 128; changing this parameter to closest allowable value (" << p << ")"); - } - return p; -} - -u_int16_t MessageStoreImpl::getJrnlWrNumPages(const u_int32_t wrPageSizeKib) -{ - u_int32_t wrPageSizeSblks = wrPageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks - u_int32_t defTotWCacheSize = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_WMGR_DEF_PAGES; // in sblks. Currently 2014 sblks (1 MiB). - switch (wrPageSizeKib) - { - case 1: - case 2: - case 4: - // 256 KiB total cache - return defTotWCacheSize / wrPageSizeSblks / 4; - case 8: - case 16: - // 512 KiB total cache - return defTotWCacheSize / wrPageSizeSblks / 2; - default: // 32, 64, 128 - // 1 MiB total cache - return defTotWCacheSize / wrPageSizeSblks; - } -} - -void MessageStoreImpl::chkJrnlAutoExpandOptions(const StoreOptions* opts, - bool& autoJrnlExpand, - u_int16_t& autoJrnlExpandMaxFiles, - const std::string& autoJrnlExpandMaxFilesParamName, - const u_int16_t numJrnlFiles, - const std::string& numJrnlFilesParamName) -{ - if (!opts->autoJrnlExpand) { - // auto-expand disabled - autoJrnlExpand = false; - autoJrnlExpandMaxFiles = 0; - return; - } - u_int16_t p = opts->autoJrnlExpandMaxFiles; - if (numJrnlFiles == JRNL_MAX_NUM_FILES) { - // num-jfiles at max; disable auto-expand - autoJrnlExpand = false; - autoJrnlExpandMaxFiles = 0; - QPID_LOG(warning, "parameter " << autoJrnlExpandMaxFilesParamName << " (" << p << ") must be higher than parameter " - << numJrnlFilesParamName << " (" << numJrnlFiles << ") which is at the maximum allowable value; disabling auto-expand."); - return; - } - if (p > JRNL_MAX_NUM_FILES) { - // auto-expand-max-jfiles higher than max allowable, adjust - autoJrnlExpand = true; - autoJrnlExpandMaxFiles = JRNL_MAX_NUM_FILES; - QPID_LOG(warning, "parameter " << autoJrnlExpandMaxFilesParamName << " (" << p << ") is above allowable maximum (" - << JRNL_MAX_NUM_FILES << "); changing this parameter to maximum value."); - return; - } - if (p && p == defAutoJrnlExpandMaxFiles && numJrnlFiles != defTplNumJrnlFiles) { - // num-jfiles is different from the default AND max-auto-expand-jfiles is still at default - // change value of max-auto-expand-jfiles - autoJrnlExpand = true; - if (2 * numJrnlFiles <= JRNL_MAX_NUM_FILES) { - autoJrnlExpandMaxFiles = 2 * numJrnlFiles <= JRNL_MAX_NUM_FILES ? 2 * numJrnlFiles : JRNL_MAX_NUM_FILES; - QPID_LOG(warning, "parameter " << autoJrnlExpandMaxFilesParamName << " adjusted from its default value (" - << defAutoJrnlExpandMaxFiles << ") to twice that of parameter " << numJrnlFilesParamName << " (" << autoJrnlExpandMaxFiles << ")."); - } else { - autoJrnlExpandMaxFiles = 2 * numJrnlFiles <= JRNL_MAX_NUM_FILES ? 2 * numJrnlFiles : JRNL_MAX_NUM_FILES; - QPID_LOG(warning, "parameter " << autoJrnlExpandMaxFilesParamName << " adjusted from its default to maximum allowable value (" - << JRNL_MAX_NUM_FILES << ") because of the value of " << numJrnlFilesParamName << " (" << numJrnlFiles << ")."); - } - return; - } - // No adjustments req'd, set values - autoJrnlExpand = true; - autoJrnlExpandMaxFiles = p; -} - -void MessageStoreImpl::initManagement () -{ - if (broker != 0) { - agent = broker->getManagementAgent(); - if (agent != 0) { - _qmf::Package packageInitializer(agent); - mgmtObject = _qmf::Store::shared_ptr ( - new _qmf::Store(agent, this, broker)); - - mgmtObject->set_location(storeDir); - mgmtObject->set_defaultInitialFileCount(numJrnlFiles); - mgmtObject->set_defaultDataFileSize(jrnlFsizeSblks / JRNL_RMGR_PAGE_SIZE); - mgmtObject->set_tplIsInitialized(false); - mgmtObject->set_tplDirectory(getTplBaseDir()); - mgmtObject->set_tplWritePageSize(tplWCachePgSizeSblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE); - mgmtObject->set_tplWritePages(tplWCacheNumPages); - mgmtObject->set_tplInitialFileCount(tplNumJrnlFiles); - mgmtObject->set_tplDataFileSize(tplJrnlFsizeSblks * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE); - mgmtObject->set_tplCurrentFileCount(tplNumJrnlFiles); - - agent->addObject(mgmtObject, 0, true); - - // Initialize all existing queues (ie those recovered before management was initialized) - for (JournalListMapItr i=journalList.begin(); i!=journalList.end(); i++) { - i->second->initManagement(agent); - } - } - } -} - -bool MessageStoreImpl::init(const qpid::Options* options) -{ - // Extract and check options - const StoreOptions* opts = static_cast(options); - u_int16_t numJrnlFiles = chkJrnlNumFilesParam(opts->numJrnlFiles, "num-jfiles"); - u_int32_t jrnlFsizePgs = chkJrnlFileSizeParam(opts->jrnlFsizePgs, "jfile-size-pgs"); - u_int32_t jrnlWrCachePageSizeKib = chkJrnlWrPageCacheSize(opts->wCachePageSizeKib, "wcache-page-size", jrnlFsizePgs); - u_int16_t tplNumJrnlFiles = chkJrnlNumFilesParam(opts->tplNumJrnlFiles, "tpl-num-jfiles"); - u_int32_t tplJrnlFSizePgs = chkJrnlFileSizeParam(opts->tplJrnlFsizePgs, "tpl-jfile-size-pgs"); - u_int32_t tplJrnlWrCachePageSizeKib = chkJrnlWrPageCacheSize(opts->tplWCachePageSizeKib, "tpl-wcache-page-size", tplJrnlFSizePgs); - bool autoJrnlExpand; - u_int16_t autoJrnlExpandMaxFiles; - chkJrnlAutoExpandOptions(opts, autoJrnlExpand, autoJrnlExpandMaxFiles, "auto-expand-max-jfiles", numJrnlFiles, "num-jfiles"); - - // Pass option values to init(...) - return init(opts->storeDir, numJrnlFiles, jrnlFsizePgs, opts->truncateFlag, jrnlWrCachePageSizeKib, tplNumJrnlFiles, tplJrnlFSizePgs, tplJrnlWrCachePageSizeKib, autoJrnlExpand, autoJrnlExpandMaxFiles); -} - -// These params, taken from options, are assumed to be correct and verified -bool MessageStoreImpl::init(const std::string& dir, - u_int16_t jfiles, - u_int32_t jfileSizePgs, - const bool truncateFlag, - u_int32_t wCachePageSizeKib, - u_int16_t tplJfiles, - u_int32_t tplJfileSizePgs, - u_int32_t tplWCachePageSizeKib, - bool autoJExpand, - u_int16_t autoJExpandMaxFiles) -{ - if (isInit) return true; - - // Set geometry members (converting to correct units where req'd) - numJrnlFiles = jfiles; - jrnlFsizeSblks = jfileSizePgs * JRNL_RMGR_PAGE_SIZE; - wCachePgSizeSblks = wCachePageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks - wCacheNumPages = getJrnlWrNumPages(wCachePageSizeKib); - tplNumJrnlFiles = tplJfiles; - tplJrnlFsizeSblks = tplJfileSizePgs * JRNL_RMGR_PAGE_SIZE; - tplWCachePgSizeSblks = tplWCachePageSizeKib * 1024 / JRNL_DBLK_SIZE / JRNL_SBLK_SIZE; // convert from KiB to number sblks - tplWCacheNumPages = getJrnlWrNumPages(tplWCachePageSizeKib); - autoJrnlExpand = autoJExpand; - autoJrnlExpandMaxFiles = autoJExpandMaxFiles; - if (dir.size()>0) storeDir = dir; - - if (truncateFlag) - truncateInit(false); - else - init(); - - QPID_LOG(notice, "Store module initialized; store-dir=" << dir); - QPID_LOG(info, "> Default files per journal: " << jfiles); -// TODO: Uncomment these lines when auto-expand is enabled. -// QPID_LOG(info, "> Auto-expand " << (autoJrnlExpand ? "enabled" : "disabled")); -// if (autoJrnlExpand) QPID_LOG(info, "> Max auto-expand journal files: " << autoJrnlExpandMaxFiles); - QPID_LOG(info, "> Default journal file size: " << jfileSizePgs << " (wpgs)"); - QPID_LOG(info, "> Default write cache page size: " << wCachePageSizeKib << " (KiB)"); - QPID_LOG(info, "> Default number of write cache pages: " << wCacheNumPages); - QPID_LOG(info, "> TPL files per journal: " << tplNumJrnlFiles); - QPID_LOG(info, "> TPL journal file size: " << tplJfileSizePgs << " (wpgs)"); - QPID_LOG(info, "> TPL write cache page size: " << tplWCachePageSizeKib << " (KiB)"); - QPID_LOG(info, "> TPL number of write cache pages: " << tplWCacheNumPages); - - return isInit; -} - -void MessageStoreImpl::init() -{ - const int retryMax = 3; - int bdbRetryCnt = 0; - do { - if (bdbRetryCnt++ > 0) - { - closeDbs(); - ::usleep(1000000); // 1 sec delay - QPID_LOG(error, "Previoius BDB store initialization failed, retrying (" << bdbRetryCnt << " of " << retryMax << ")..."); - } - - try { - journal::jdir::create_dir(getBdbBaseDir()); - - dbenv.reset(new DbEnv(0)); - dbenv->set_errpfx("msgstore"); - dbenv->set_lg_regionmax(256000); // default = 65000 - dbenv->open(getBdbBaseDir().c_str(), DB_THREAD | DB_CREATE | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_USE_ENVIRON | DB_RECOVER, 0); - - // Databases are constructed here instead of the constructor so that the DB_RECOVER flag can be used - // against the database environment. Recover can only be performed if no databases have been created - // against the environment at the time of recovery, as recovery invalidates the environment. - queueDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(queueDb); - configDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(configDb); - exchangeDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(exchangeDb); - mappingDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(mappingDb); - bindingDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(bindingDb); - generalDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(generalDb); - - TxnCtxt txn; - txn.begin(dbenv.get(), false); - try { - open(queueDb, txn.get(), "queues.db", false); - open(configDb, txn.get(), "config.db", false); - open(exchangeDb, txn.get(), "exchanges.db", false); - open(mappingDb, txn.get(), "mappings.db", true); - open(bindingDb, txn.get(), "bindings.db", true); - open(generalDb, txn.get(), "general.db", false); - txn.commit(); - } catch (...) { txn.abort(); throw; } - // NOTE: during normal initialization, agent == 0 because the store is initialized before the management infrastructure. - // However during a truncated initialization in a cluster, agent != 0. We always pass 0 as the agent for the - // TplStore to keep things consistent in a cluster. See https://bugzilla.redhat.com/show_bug.cgi?id=681026 - tplStorePtr.reset(new TplJournalImpl(broker->getTimer(), "TplStore", getTplBaseDir(), "tpl", defJournalGetEventsTimeout, defJournalFlushTimeout, 0)); - isInit = true; - } catch (const DbException& e) { - if (e.get_errno() == DB_VERSION_MISMATCH) - { - QPID_LOG(error, "Database environment mismatch: This version of db4 does not match that which created the store database.: " << e.what()); - THROW_STORE_EXCEPTION_2("Database environment mismatch: This version of db4 does not match that which created the store database. " - "(If recovery is not important, delete the contents of the store directory. Otherwise, try upgrading the database using " - "db_upgrade or using db_recover - but the db4-utils package must also be installed to use these utilities.)", e); - } - QPID_LOG(error, "BDB exception occurred while initializing store: " << e.what()); - if (bdbRetryCnt >= retryMax) - THROW_STORE_EXCEPTION_2("BDB exception occurred while initializing store", e); - } catch (const StoreException&) { - throw; - } catch (const journal::jexception& e) { - QPID_LOG(error, "Journal Exception occurred while initializing store: " << e); - THROW_STORE_EXCEPTION_2("Journal Exception occurred while initializing store", e.what()); - } catch (...) { - QPID_LOG(error, "Unknown exception occurred while initializing store."); - throw; - } - } while (!isInit); -} - -void MessageStoreImpl::finalize() -{ - if (tplStorePtr.get() && tplStorePtr->is_ready()) tplStorePtr->stop(true); - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - for (JournalListMapItr i = journalList.begin(); i != journalList.end(); i++) - { - JournalImpl* jQueue = i->second; - jQueue->resetDeleteCallback(); - if (jQueue->is_ready()) jQueue->stop(true); - } - } - - if (mgmtObject.get() != 0) { - mgmtObject->resourceDestroy(); - mgmtObject.reset(); - } -} - -void MessageStoreImpl::truncateInit(const bool saveStoreContent) -{ - if (isInit) { - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - if (journalList.size()) { // check no queues exist - std::ostringstream oss; - oss << "truncateInit() called with " << journalList.size() << " queues still in existence"; - THROW_STORE_EXCEPTION(oss.str()); - } - } - closeDbs(); - dbs.clear(); - if (tplStorePtr->is_ready()) tplStorePtr->stop(true); - dbenv->close(0); - isInit = false; - } - std::ostringstream oss; - oss << storeDir << "/" << storeTopLevelDir; - if (saveStoreContent) { - std::string dir = mrg::journal::jdir::push_down(storeDir, storeTopLevelDir, "cluster"); - QPID_LOG(notice, "Store directory " << oss.str() << " was pushed down (saved) into directory " << dir << "."); - } else { - mrg::journal::jdir::delete_dir(oss.str().c_str()); - QPID_LOG(notice, "Store directory " << oss.str() << " was truncated."); - } - init(); -} - -void MessageStoreImpl::chkTplStoreInit() -{ - // Prevent multiple threads from late-initializing the TPL - qpid::sys::Mutex::ScopedLock sl(tplInitLock); - if (!tplStorePtr->is_ready()) { - journal::jdir::create_dir(getTplBaseDir()); - tplStorePtr->initialize(tplNumJrnlFiles, false, 0, tplJrnlFsizeSblks, tplWCacheNumPages, tplWCachePgSizeSblks); - if (mgmtObject.get() != 0) mgmtObject->set_tplIsInitialized(true); - } -} - -void MessageStoreImpl::open(db_ptr db, - DbTxn* txn, - const char* file, - bool dupKey) -{ - if(dupKey) db->set_flags(DB_DUPSORT); - db->open(txn, file, 0, DB_BTREE, DB_CREATE | DB_THREAD, 0); -} - -void MessageStoreImpl::closeDbs() -{ - for (std::list::iterator i = dbs.begin(); i != dbs.end(); i++) { - (*i)->close(0); - } - dbs.clear(); -} - -MessageStoreImpl::~MessageStoreImpl() -{ - if (mgmtObject.get() != 0) - mgmtObject->debugStats("destroying"); - finalize(); - try { - closeDbs(); - } catch (const DbException& e) { - QPID_LOG(error, "Error closing BDB databases: " << e.what()); - } catch (const journal::jexception& e) { - QPID_LOG(error, "Error: " << e.what()); - } catch (const std::exception& e) { - QPID_LOG(error, "Error: " << e.what()); - } catch (...) { - QPID_LOG(error, "Unknown error in MessageStoreImpl::~MessageStoreImpl()"); - } - - if (mgmtObject.get() != 0) { - mgmtObject->resourceDestroy(); - mgmtObject.reset(); - } -} - -void MessageStoreImpl::create(qpid::broker::PersistableQueue& queue, - const qpid::framing::FieldTable& args) -{ - checkInit(); - if (queue.getPersistenceId()) { - THROW_STORE_EXCEPTION("Queue already created: " + queue.getName()); - } - JournalImpl* jQueue = 0; - qpid::framing::FieldTable::ValuePtr value; - - u_int16_t localFileCount = numJrnlFiles; - bool localAutoExpandFlag = autoJrnlExpand; - u_int16_t localAutoExpandMaxFileCount = autoJrnlExpandMaxFiles; - u_int32_t localFileSizeSblks = jrnlFsizeSblks; - - value = args.get("qpid.file_count"); - if (value.get() != 0 && !value->empty() && value->convertsTo()) - localFileCount = chkJrnlNumFilesParam((u_int16_t) value->get(), "qpid.file_count"); - - value = args.get("qpid.file_size"); - if (value.get() != 0 && !value->empty() && value->convertsTo()) - localFileSizeSblks = chkJrnlFileSizeParam((u_int32_t) value->get(), "qpid.file_size", wCachePgSizeSblks) * JRNL_RMGR_PAGE_SIZE; - - if (queue.getName().size() == 0) - { - QPID_LOG(error, "Cannot create store for empty (null) queue name - ignoring and attempting to continue."); - return; - } - - jQueue = new JournalImpl(broker->getTimer(), queue.getName(), getJrnlDir(queue), std::string("JournalData"), - defJournalGetEventsTimeout, defJournalFlushTimeout, agent, - boost::bind(&MessageStoreImpl::journalDeleted, this, _1)); - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - journalList[queue.getName()]=jQueue; - } - - value = args.get("qpid.auto_expand"); - if (value.get() != 0 && !value->empty() && value->convertsTo()) - localAutoExpandFlag = (bool) value->get(); - - value = args.get("qpid.auto_expand_max_jfiles"); - if (value.get() != 0 && !value->empty() && value->convertsTo()) - localAutoExpandMaxFileCount = (u_int16_t) value->get(); - - queue.setExternalQueueStore(dynamic_cast(jQueue)); - try { - // init will create the deque's for the init... - jQueue->initialize(localFileCount, localAutoExpandFlag, localAutoExpandMaxFileCount, localFileSizeSblks, wCacheNumPages, wCachePgSizeSblks); - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() + ": create() failed: " + e.what()); - } - try { - if (!create(queueDb, queueIdSequence, queue)) { - THROW_STORE_EXCEPTION("Queue already exists: " + queue.getName()); - } - } catch (const DbException& e) { - THROW_STORE_EXCEPTION_2("Error creating queue named " + queue.getName(), e); - } -} - -void MessageStoreImpl::destroy(qpid::broker::PersistableQueue& queue) -{ - checkInit(); - destroy(queueDb, queue); - deleteBindingsForQueue(queue); - qpid::broker::ExternalQueueStore* eqs = queue.getExternalQueueStore(); - if (eqs) { - JournalImpl* jQueue = static_cast(eqs); - jQueue->delete_jrnl_files(); - queue.setExternalQueueStore(0); // will delete the journal if exists - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - journalList.erase(queue.getName()); - } - } -} - -void MessageStoreImpl::create(const qpid::broker::PersistableExchange& exchange, - const qpid::framing::FieldTable& /*args*/) -{ - checkInit(); - if (exchange.getPersistenceId()) { - THROW_STORE_EXCEPTION("Exchange already created: " + exchange.getName()); - } - try { - if (!create(exchangeDb, exchangeIdSequence, exchange)) { - THROW_STORE_EXCEPTION("Exchange already exists: " + exchange.getName()); - } - } catch (const DbException& e) { - THROW_STORE_EXCEPTION_2("Error creating exchange named " + exchange.getName(), e); - } -} - -void MessageStoreImpl::destroy(const qpid::broker::PersistableExchange& exchange) -{ - checkInit(); - destroy(exchangeDb, exchange); - //need to also delete bindings - IdDbt key(exchange.getPersistenceId()); - bindingDb->del(0, &key, DB_AUTO_COMMIT); -} - -void MessageStoreImpl::create(const qpid::broker::PersistableConfig& general) -{ - checkInit(); - if (general.getPersistenceId()) { - THROW_STORE_EXCEPTION("General configuration item already created"); - } - try { - if (!create(generalDb, generalIdSequence, general)) { - THROW_STORE_EXCEPTION("General configuration already exists"); - } - } catch (const DbException& e) { - THROW_STORE_EXCEPTION_2("Error creating general configuration", e); - } -} - -void MessageStoreImpl::destroy(const qpid::broker::PersistableConfig& general) -{ - checkInit(); - destroy(generalDb, general); -} - -bool MessageStoreImpl::create(db_ptr db, - IdSequence& seq, - const qpid::broker::Persistable& p) -{ - u_int64_t id (seq.next()); - Dbt key(&id, sizeof(id)); - BufferValue value (p); - - int status; - TxnCtxt txn; - txn.begin(dbenv.get(), true); - try { - status = db->put(txn.get(), &key, &value, DB_NOOVERWRITE); - txn.commit(); - } catch (...) { - txn.abort(); - throw; - } - if (status == DB_KEYEXIST) { - return false; - } else { - p.setPersistenceId(id); - return true; - } -} - -void MessageStoreImpl::destroy(db_ptr db, const qpid::broker::Persistable& p) -{ - qpid::sys::Mutex::ScopedLock sl(bdbLock); - IdDbt key(p.getPersistenceId()); - db->del(0, &key, DB_AUTO_COMMIT); -} - - -void MessageStoreImpl::bind(const qpid::broker::PersistableExchange& e, - const qpid::broker::PersistableQueue& q, - const std::string& k, - const qpid::framing::FieldTable& a) -{ - checkInit(); - IdDbt key(e.getPersistenceId()); - BindingDbt value(e, q, k, a); - TxnCtxt txn; - txn.begin(dbenv.get(), true); - try { - put(bindingDb, txn.get(), key, value); - txn.commit(); - } catch (...) { - txn.abort(); - throw; - } -} - -void MessageStoreImpl::unbind(const qpid::broker::PersistableExchange& e, - const qpid::broker::PersistableQueue& q, - const std::string& k, - const qpid::framing::FieldTable&) -{ - checkInit(); - deleteBinding(e, q, k); -} - -void MessageStoreImpl::recover(qpid::broker::RecoveryManager& registry) -{ - checkInit(); - txn_list prepared; - recoverLockedMappings(prepared); - - queue_index queues;//id->queue - exchange_index exchanges;//id->exchange - message_index messages;//id->message - - TxnCtxt txn; - txn.begin(dbenv.get(), false); - try { - //read all queues, calls recoversMessages - recoverQueues(txn, registry, queues, prepared, messages); - - //recover exchange & bindings: - recoverExchanges(txn, registry, exchanges); - recoverBindings(txn, exchanges, queues); - - //recover general-purpose configuration - recoverGeneral(txn, registry); - - txn.commit(); - } catch (const DbException& e) { - txn.abort(); - THROW_STORE_EXCEPTION_2("Error on recovery", e); - } catch (...) { - txn.abort(); - throw; - } - - //recover transactions: - for (txn_list::iterator i = prepared.begin(); i != prepared.end(); i++) { - const PreparedTransaction pt = *i; - if (mgmtObject.get() != 0) { - mgmtObject->inc_tplTransactionDepth(); - mgmtObject->inc_tplTxnPrepares(); - } - - std::string xid = pt.xid; - - // Restore data token state in TxnCtxt - TplRecoverMapCitr citr = tplRecoverMap.find(xid); - if (citr == tplRecoverMap.end()) THROW_STORE_EXCEPTION("XID not found in tplRecoverMap"); - - // If a record is found that is dequeued but not committed/aborted from tplStore, then a complete() call - // was interrupted part way through committing/aborting the impacted queues. Complete this process. - bool incomplTplTxnFlag = citr->second.deq_flag; - - if (citr->second.tpc_flag) { - // Dtx (2PC) transaction - TPCTxnCtxt* tpcc = new TPCTxnCtxt(xid, &messageIdSequence); - std::auto_ptr txn(tpcc); - tpcc->recoverDtok(citr->second.rid, xid); - tpcc->prepare(tplStorePtr.get()); - - qpid::broker::RecoverableTransaction::shared_ptr dtx; - if (!incomplTplTxnFlag) dtx = registry.recoverTransaction(xid, txn); - if (pt.enqueues.get()) { - for (LockedMappings::iterator j = pt.enqueues->begin(); j != pt.enqueues->end(); j++) { - tpcc->addXidRecord(queues[j->first]->getExternalQueueStore()); - if (!incomplTplTxnFlag) dtx->enqueue(queues[j->first], messages[j->second]); - } - } - if (pt.dequeues.get()) { - for (LockedMappings::iterator j = pt.dequeues->begin(); j != pt.dequeues->end(); j++) { - tpcc->addXidRecord(queues[j->first]->getExternalQueueStore()); - if (!incomplTplTxnFlag) dtx->dequeue(queues[j->first], messages[j->second]); - } - } - - if (incomplTplTxnFlag) { - tpcc->complete(citr->second.commit_flag); - } - } else { - // Local (1PC) transaction - boost::shared_ptr opcc(new TxnCtxt(xid, &messageIdSequence)); - opcc->recoverDtok(citr->second.rid, xid); - opcc->prepare(tplStorePtr.get()); - - if (pt.enqueues.get()) { - for (LockedMappings::iterator j = pt.enqueues->begin(); j != pt.enqueues->end(); j++) { - opcc->addXidRecord(queues[j->first]->getExternalQueueStore()); - } - } - if (pt.dequeues.get()) { - for (LockedMappings::iterator j = pt.dequeues->begin(); j != pt.dequeues->end(); j++) { - opcc->addXidRecord(queues[j->first]->getExternalQueueStore()); - } - } - if (incomplTplTxnFlag) { - opcc->complete(citr->second.commit_flag); - } else { - completed(*opcc.get(), citr->second.commit_flag); - } - } - } - registry.recoveryComplete(); -} - -void MessageStoreImpl::recoverQueues(TxnCtxt& txn, - qpid::broker::RecoveryManager& registry, - queue_index& queue_index, - txn_list& prepared, - message_index& messages) -{ - Cursor queues; - queues.open(queueDb, txn.get()); - - u_int64_t maxQueueId(1); - - IdDbt key; - Dbt value; - //read all queues - while (queues.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - //create a Queue instance - qpid::broker::RecoverableQueue::shared_ptr queue = registry.recoverQueue(buffer); - //set the persistenceId and update max as required - queue->setPersistenceId(key.id); - - const std::string queueName = queue->getName().c_str(); - JournalImpl* jQueue = 0; - if (queueName.size() == 0) - { - QPID_LOG(error, "Cannot recover empty (null) queue name - ignoring and attempting to continue."); - break; - } - jQueue = new JournalImpl(broker->getTimer(), queueName, getJrnlHashDir(queueName), std::string("JournalData"), - defJournalGetEventsTimeout, defJournalFlushTimeout, agent, - boost::bind(&MessageStoreImpl::journalDeleted, this, _1)); - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - journalList[queueName] = jQueue; - } - queue->setExternalQueueStore(dynamic_cast(jQueue)); - - try - { - long rcnt = 0L; // recovered msg count - long idcnt = 0L; // in-doubt msg count - u_int64_t thisHighestRid = 0ULL; - jQueue->recover(numJrnlFiles, autoJrnlExpand, autoJrnlExpandMaxFiles, jrnlFsizeSblks, wCacheNumPages, wCachePgSizeSblks, &prepared, thisHighestRid, key.id); // start recovery - - // Check for changes to queue store settings qpid.file_count and qpid.file_size resulting - // from recovery of a store that has had its size changed externally by the resize utility. - // If so, update the queue store settings so that QMF queries will reflect the new values. - const qpid::framing::FieldTable& storeargs = queue->getSettings().storeSettings; - qpid::framing::FieldTable::ValuePtr value; - value = storeargs.get("qpid.file_count"); - if (value.get() != 0 && !value->empty() && value->convertsTo() && (u_int16_t)value->get() != jQueue->num_jfiles()) { - queue->addArgument("qpid.file_count", jQueue->num_jfiles()); - } - value = storeargs.get("qpid.file_size"); - if (value.get() != 0 && !value->empty() && value->convertsTo() && (u_int32_t)value->get() != jQueue->jfsize_sblks()/JRNL_RMGR_PAGE_SIZE) { - queue->addArgument("qpid.file_size", jQueue->jfsize_sblks()/JRNL_RMGR_PAGE_SIZE); - } - - if (highestRid == 0ULL) - highestRid = thisHighestRid; - else if (thisHighestRid - highestRid < 0x8000000000000000ULL) // RFC 1982 comparison for unsigned 64-bit - highestRid = thisHighestRid; - recoverMessages(txn, registry, queue, prepared, messages, rcnt, idcnt); - QPID_LOG(info, "Recovered queue \"" << queueName << "\": " << rcnt << " messages recovered; " << idcnt << " messages in-doubt."); - jQueue->recover_complete(); // start journal. - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queueName + ": recoverQueues() failed: " + e.what()); - } - //read all messages: done on a per queue basis if using Journal - - queue_index[key.id] = queue; - maxQueueId = std::max(key.id, maxQueueId); - } - - // NOTE: highestRid is set by both recoverQueues() and recoverTplStore() as - // the messageIdSequence is used for both queue journals and the tpl journal. - messageIdSequence.reset(highestRid + 1); - QPID_LOG(info, "Most recent persistence id found: 0x" << std::hex << highestRid << std::dec); - - queueIdSequence.reset(maxQueueId + 1); -} - - -void MessageStoreImpl::recoverExchanges(TxnCtxt& txn, - qpid::broker::RecoveryManager& registry, - exchange_index& index) -{ - //TODO: this is a copy&paste from recoverQueues - refactor! - Cursor exchanges; - exchanges.open(exchangeDb, txn.get()); - - u_int64_t maxExchangeId(1); - IdDbt key; - Dbt value; - //read all exchanges - while (exchanges.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - //create a Exchange instance - qpid::broker::RecoverableExchange::shared_ptr exchange = registry.recoverExchange(buffer); - if (exchange) { - //set the persistenceId and update max as required - exchange->setPersistenceId(key.id); - index[key.id] = exchange; - QPID_LOG(info, "Recovered exchange \"" << exchange->getName() << '"'); - } - maxExchangeId = std::max(key.id, maxExchangeId); - } - exchangeIdSequence.reset(maxExchangeId + 1); -} - -void MessageStoreImpl::recoverBindings(TxnCtxt& txn, - exchange_index& exchanges, - queue_index& queues) -{ - Cursor bindings; - bindings.open(bindingDb, txn.get()); - - IdDbt key; - Dbt value; - while (bindings.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - if (buffer.available() < 8) { - QPID_LOG(error, "Not enough data for binding: " << buffer.available()); - THROW_STORE_EXCEPTION("Not enough data for binding"); - } - uint64_t queueId = buffer.getLongLong(); - std::string queueName; - std::string routingkey; - qpid::framing::FieldTable args; - buffer.getShortString(queueName); - buffer.getShortString(routingkey); - buffer.get(args); - exchange_index::iterator exchange = exchanges.find(key.id); - queue_index::iterator queue = queues.find(queueId); - if (exchange != exchanges.end() && queue != queues.end()) { - //could use the recoverable queue here rather than the name... - exchange->second->bind(queueName, routingkey, args); - QPID_LOG(info, "Recovered binding exchange=" << exchange->second->getName() - << " key=" << routingkey - << " queue=" << queueName); - } else { - //stale binding, delete it - QPID_LOG(warning, "Deleting stale binding"); - bindings->del(0); - } - } -} - -void MessageStoreImpl::recoverGeneral(TxnCtxt& txn, - qpid::broker::RecoveryManager& registry) -{ - Cursor items; - items.open(generalDb, txn.get()); - - u_int64_t maxGeneralId(1); - IdDbt key; - Dbt value; - //read all items - while (items.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - //create instance - qpid::broker::RecoverableConfig::shared_ptr config = registry.recoverConfig(buffer); - //set the persistenceId and update max as required - config->setPersistenceId(key.id); - maxGeneralId = std::max(key.id, maxGeneralId); - } - generalIdSequence.reset(maxGeneralId + 1); -} - -void MessageStoreImpl::recoverMessages(TxnCtxt& /*txn*/, - qpid::broker::RecoveryManager& recovery, - qpid::broker::RecoverableQueue::shared_ptr& queue, - txn_list& prepared, - message_index& messages, - long& rcnt, - long& idcnt) -{ - size_t preambleLength = sizeof(u_int32_t)/*header size*/; - - JournalImpl* jc = static_cast(queue->getExternalQueueStore()); - DataTokenImpl dtok; - size_t readSize = 0; - unsigned msg_count = 0; - - // TODO: This optimization to skip reading if there are no enqueued messages to read - // breaks the python system test in phase 6 with "Exception: Cannot write lock file" - // Figure out what is breaking. - //bool read = jc->get_enq_cnt() > 0; - bool read = true; - - void* dbuff = NULL; size_t dbuffSize = 0; - void* xidbuff = NULL; size_t xidbuffSize = 0; - bool transientFlag = false; - bool externalFlag = false; - - dtok.set_wstate(DataTokenImpl::ENQ); - - // Read the message from the Journal. - try { - unsigned aio_sleep_cnt = 0; - while (read) { - mrg::journal::iores res = jc->read_data_record(&dbuff, dbuffSize, &xidbuff, xidbuffSize, transientFlag, externalFlag, &dtok); - readSize = dtok.dsize(); - - switch (res) - { - case mrg::journal::RHM_IORES_SUCCESS: { - msg_count++; - qpid::broker::RecoverableMessage::shared_ptr msg; - char* data = (char*)dbuff; - - unsigned headerSize; - if (externalFlag) { - msg = getExternMessage(recovery, dtok.rid(), headerSize); // large message external to jrnl - } else { - headerSize = qpid::framing::Buffer(data, preambleLength).getLong(); - qpid::framing::Buffer headerBuff(data+ preambleLength, headerSize); /// do we want read size or header size ???? - msg = recovery.recoverMessage(headerBuff); - } - msg->setPersistenceId(dtok.rid()); - // At some future point if delivery attempts are stored, then this call would - // become optional depending on that information. - msg->setRedelivered(); - // Reset the TTL for the recovered message - msg->computeExpiration(); - - u_int32_t contentOffset = headerSize + preambleLength; - u_int64_t contentSize = readSize - contentOffset; - if (msg->loadContent(contentSize) && !externalFlag) { - //now read the content - qpid::framing::Buffer contentBuff(data + contentOffset, contentSize); - msg->decodeContent(contentBuff); - } - - PreparedTransaction::list::iterator i = PreparedTransaction::getLockedPreparedTransaction(prepared, queue->getPersistenceId(), dtok.rid()); - if (i == prepared.end()) { // not in prepared list - rcnt++; - queue->recover(msg); - } else { - u_int64_t rid = dtok.rid(); - std::string xid(i->xid); - TplRecoverMapCitr citr = tplRecoverMap.find(xid); - if (citr == tplRecoverMap.end()) THROW_STORE_EXCEPTION("XID not found in tplRecoverMap"); - - // deq present in prepared list: this xid is part of incomplete txn commit/abort - // or this is a 1PC txn that must be rolled forward - if (citr->second.deq_flag || !citr->second.tpc_flag) { - if (jc->is_enqueued(rid, true)) { - // Enqueue is non-tx, dequeue tx - assert(jc->is_locked(rid)); // This record MUST be locked by a txn dequeue - if (!citr->second.commit_flag) { - rcnt++; - queue->recover(msg); // recover message in abort case only - } - } else { - // Enqueue and/or dequeue tx - journal::txn_map& tmap = jc->get_txn_map(); - journal::txn_data_list txnList = tmap.get_tdata_list(xid); // txnList will be empty if xid not found - bool enq = false; - bool deq = false; - for (journal::tdl_itr j = txnList.begin(); j_enq_flag && j->_rid == rid) enq = true; - else if (!j->_enq_flag && j->_drid == rid) deq = true; - } - if (enq && !deq && citr->second.commit_flag) { - rcnt++; - queue->recover(msg); // recover txn message in commit case only - } - } - } else { - idcnt++; - messages[rid] = msg; - } - } - - dtok.reset(); - dtok.set_wstate(DataTokenImpl::ENQ); - - if (xidbuff) - ::free(xidbuff); - else if (dbuff) - ::free(dbuff); - aio_sleep_cnt = 0; - break; - } - case mrg::journal::RHM_IORES_PAGE_AIOWAIT: - if (++aio_sleep_cnt > MAX_AIO_SLEEPS) - THROW_STORE_EXCEPTION("Timeout waiting for AIO in MessageStoreImpl::recoverMessages()"); - ::usleep(AIO_SLEEP_TIME_US); - break; - case mrg::journal::RHM_IORES_EMPTY: - read = false; - break; // done with all messages. (add call in jrnl to test that _emap is empty.) - default: - std::ostringstream oss; - oss << "recoverMessages(): Queue: " << queue->getName() << ": Unexpected return from journal read: " << mrg::journal::iores_str(res); - THROW_STORE_EXCEPTION(oss.str()); - } // switch - } // while - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queue->getName() + ": recoverMessages() failed: " + e.what()); - } -} - -qpid::broker::RecoverableMessage::shared_ptr MessageStoreImpl::getExternMessage(qpid::broker::RecoveryManager& /*recovery*/, - uint64_t /*messageId*/, - unsigned& /*headerSize*/) -{ - throw mrg::journal::jexception(mrg::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "getExternMessage"); -} - -int MessageStoreImpl::enqueueMessage(TxnCtxt& txn, - IdDbt& msgId, - qpid::broker::RecoverableMessage::shared_ptr& msg, - queue_index& index, - txn_list& prepared, - message_index& messages) -{ - Cursor mappings; - mappings.open(mappingDb, txn.get()); - - IdDbt value; - - int count(0); - for (int status = mappings->get(&msgId, &value, DB_SET); status == 0; status = mappings->get(&msgId, &value, DB_NEXT_DUP)) { - if (index.find(value.id) == index.end()) { - QPID_LOG(warning, "Recovered message for queue that no longer exists"); - mappings->del(0); - } else { - qpid::broker::RecoverableQueue::shared_ptr queue = index[value.id]; - if (PreparedTransaction::isLocked(prepared, value.id, msgId.id)) { - messages[msgId.id] = msg; - } else { - queue->recover(msg); - } - count++; - } - } - mappings.close(); - return count; -} - -void MessageStoreImpl::readTplStore() -{ - tplRecoverMap.clear(); - journal::txn_map& tmap = tplStorePtr->get_txn_map(); - DataTokenImpl dtok; - void* dbuff = NULL; size_t dbuffSize = 0; - void* xidbuff = NULL; size_t xidbuffSize = 0; - bool transientFlag = false; - bool externalFlag = false; - bool done = false; - try { - unsigned aio_sleep_cnt = 0; - while (!done) { - dtok.reset(); - dtok.set_wstate(DataTokenImpl::ENQ); - mrg::journal::iores res = tplStorePtr->read_data_record(&dbuff, dbuffSize, &xidbuff, xidbuffSize, transientFlag, externalFlag, &dtok); - switch (res) { - case mrg::journal::RHM_IORES_SUCCESS: { - // Every TPL record contains both data and an XID - assert(dbuffSize>0); - assert(xidbuffSize>0); - std::string xid(static_cast(xidbuff), xidbuffSize); - bool is2PC = *(static_cast(dbuff)) != 0; - - // Check transaction details; add to recover map - journal::txn_data_list txnList = tmap.get_tdata_list(xid); // txnList will be empty if xid not found - if (!txnList.empty()) { // xid found in tmap - unsigned enqCnt = 0; - unsigned deqCnt = 0; - u_int64_t rid = 0; - - // Assume commit (roll forward) in cases where only prepare has been called - ie only enqueue record exists. - // Note: will apply to both 1PC and 2PC transactions. - bool commitFlag = true; - - for (journal::tdl_itr j = txnList.begin(); j_enq_flag) { - rid = j->_rid; - enqCnt++; - } else { - commitFlag = j->_commit_flag; - deqCnt++; - } - } - assert(enqCnt == 1); - assert(deqCnt <= 1); - tplRecoverMap.insert(TplRecoverMapPair(xid, TplRecoverStruct(rid, deqCnt == 1, commitFlag, is2PC))); - } - - ::free(xidbuff); - aio_sleep_cnt = 0; - break; - } - case mrg::journal::RHM_IORES_PAGE_AIOWAIT: - if (++aio_sleep_cnt > MAX_AIO_SLEEPS) - THROW_STORE_EXCEPTION("Timeout waiting for AIO in MessageStoreImpl::recoverTplStore()"); - ::usleep(AIO_SLEEP_TIME_US); - break; - case mrg::journal::RHM_IORES_EMPTY: - done = true; - break; // done with all messages. (add call in jrnl to test that _emap is empty.) - default: - std::ostringstream oss; - oss << "readTplStore(): Unexpected result from journal read: " << mrg::journal::iores_str(res); - THROW_STORE_EXCEPTION(oss.str()); - } // switch - } - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("TPL recoverTplStore() failed: ") + e.what()); - } -} - -void MessageStoreImpl::recoverTplStore() -{ - if (journal::jdir::exists(tplStorePtr->jrnl_dir() + tplStorePtr->base_filename() + ".jinf")) { - u_int64_t thisHighestRid = 0ULL; - tplStorePtr->recover(tplNumJrnlFiles, false, 0, tplJrnlFsizeSblks, tplWCachePgSizeSblks, tplWCacheNumPages, 0, thisHighestRid, 0); - if (highestRid == 0ULL) - highestRid = thisHighestRid; - else if (thisHighestRid - highestRid < 0x8000000000000000ULL) // RFC 1982 comparison for unsigned 64-bit - highestRid = thisHighestRid; - - // Load tplRecoverMap by reading the TPL store - readTplStore(); - - tplStorePtr->recover_complete(); // start journal. - } -} - -void MessageStoreImpl::recoverLockedMappings(txn_list& txns) -{ - if (!tplStorePtr->is_ready()) - recoverTplStore(); - - // Abort unprepared xids and populate the locked maps - for (TplRecoverMapCitr i = tplRecoverMap.begin(); i != tplRecoverMap.end(); i++) { - LockedMappings::shared_ptr enq_ptr; - enq_ptr.reset(new LockedMappings); - LockedMappings::shared_ptr deq_ptr; - deq_ptr.reset(new LockedMappings); - txns.push_back(new PreparedTransaction(i->first, enq_ptr, deq_ptr)); - } -} - -void MessageStoreImpl::collectPreparedXids(std::set& xids) -{ - if (tplStorePtr->is_ready()) { - tplStorePtr->read_reset(); - readTplStore(); - } else { - recoverTplStore(); - } - for (TplRecoverMapCitr i = tplRecoverMap.begin(); i != tplRecoverMap.end(); i++) { - // Discard all txns that are to be rolled forward/back and 1PC transactions - if (!i->second.deq_flag && i->second.tpc_flag) - xids.insert(i->first); - } -} - -void MessageStoreImpl::stage(const boost::intrusive_ptr& /*msg*/) -{ - throw mrg::journal::jexception(mrg::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "stage"); -} - -void MessageStoreImpl::destroy(qpid::broker::PersistableMessage& /*msg*/) -{ - throw mrg::journal::jexception(mrg::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "destroy"); -} - -void MessageStoreImpl::appendContent(const boost::intrusive_ptr& /*msg*/, - const std::string& /*data*/) -{ - throw mrg::journal::jexception(mrg::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "appendContent"); -} - -void MessageStoreImpl::loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - u_int64_t offset, - u_int32_t length) -{ - checkInit(); - u_int64_t messageId (msg->getPersistenceId()); - - if (messageId != 0) { - try { - JournalImpl* jc = static_cast(queue.getExternalQueueStore()); - if (jc && jc->is_enqueued(messageId) ) { - if (!jc->loadMsgContent(messageId, data, length, offset)) { - std::ostringstream oss; - oss << "Queue " << queue.getName() << ": loadContent() failed: Message " << messageId << " is extern"; - THROW_STORE_EXCEPTION(oss.str()); - } - } else { - std::ostringstream oss; - oss << "Queue " << queue.getName() << ": loadContent() failed: Message " << messageId << " not enqueued"; - THROW_STORE_EXCEPTION(oss.str()); - } - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() + ": loadContent() failed: " + e.what()); - } - } else { - THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!"); - } -} - -void MessageStoreImpl::flush(const qpid::broker::PersistableQueue& queue) -{ - if (queue.getExternalQueueStore() == 0) return; - checkInit(); - std::string qn = queue.getName(); - try { - JournalImpl* jc = static_cast(queue.getExternalQueueStore()); - if (jc) { - // TODO: check if this result should be used... - /*mrg::journal::iores res =*/ jc->flush(); - } - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + qn + ": flush() failed: " + e.what() ); - } -} - -void MessageStoreImpl::enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue) -{ - checkInit(); - u_int64_t queueId (queue.getPersistenceId()); - u_int64_t messageId (msg->getPersistenceId()); - if (queueId == 0) { - THROW_STORE_EXCEPTION("Queue not created: " + queue.getName()); - } - - TxnCtxt implicit; - TxnCtxt* txn = 0; - if (ctxt) { - txn = check(ctxt); - } else { - txn = &implicit; - } - - bool newId = false; - if (messageId == 0) { - messageId = messageIdSequence.next(); - msg->setPersistenceId(messageId); - newId = true; - } - store(&queue, txn, msg, newId); - - // add queue* to the txn map.. - if (ctxt) txn->addXidRecord(queue.getExternalQueueStore()); -} - -u_int64_t MessageStoreImpl::msgEncode(std::vector& buff, const boost::intrusive_ptr& message) -{ - u_int32_t headerSize = message->encodedHeaderSize(); - u_int64_t size = message->encodedSize() + sizeof(u_int32_t); - try { buff = std::vector(size); } // long + headers + content - catch (const std::exception& e) { - std::ostringstream oss; - oss << "Unable to allocate memory for encoding message; requested size: " << size << "; error: " << e.what(); - THROW_STORE_EXCEPTION(oss.str()); - } - qpid::framing::Buffer buffer(&buff[0],size); - buffer.putLong(headerSize); - message->encode(buffer); - return size; -} - -void MessageStoreImpl::store(const qpid::broker::PersistableQueue* queue, - TxnCtxt* txn, - const boost::intrusive_ptr& message, - bool /*newId*/) -{ - std::vector buff; - u_int64_t size = msgEncode(buff, message); - - try { - if (queue) { - boost::intrusive_ptr dtokp(new DataTokenImpl); - dtokp->addRef(); - dtokp->setSourceMessage(message); - dtokp->set_external_rid(true); - dtokp->set_rid(message->getPersistenceId()); // set the messageID into the Journal header (record-id) - - JournalImpl* jc = static_cast(queue->getExternalQueueStore()); - if (txn->getXid().empty()) { - jc->enqueue_data_record(&buff[0], size, size, dtokp.get(), !message->isPersistent()); - } else { - jc->enqueue_txn_data_record(&buff[0], size, size, dtokp.get(), txn->getXid(), !message->isPersistent()); - } - } else { - THROW_STORE_EXCEPTION(std::string("MessageStoreImpl::store() failed: queue NULL.")); - } - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queue->getName() + ": MessageStoreImpl::store() failed: " + - e.what()); - } -} - -void MessageStoreImpl::dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue) -{ - checkInit(); - u_int64_t queueId (queue.getPersistenceId()); - u_int64_t messageId (msg->getPersistenceId()); - if (queueId == 0) { - THROW_STORE_EXCEPTION("Queue \"" + queue.getName() + "\" has null queue Id (has not been created)"); - } - if (messageId == 0) { - THROW_STORE_EXCEPTION("Queue \"" + queue.getName() + "\": Dequeuing message with null persistence Id."); - } - - TxnCtxt implicit; - TxnCtxt* txn = 0; - if (ctxt) { - txn = check(ctxt); - } else { - txn = &implicit; - } - - // add queue* to the txn map.. - if (ctxt) txn->addXidRecord(queue.getExternalQueueStore()); - async_dequeue(ctxt, msg, queue); - - msg->dequeueComplete(); -} - -void MessageStoreImpl::async_dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue) -{ - boost::intrusive_ptr ddtokp(new DataTokenImpl); - ddtokp->setSourceMessage(msg); - ddtokp->set_external_rid(true); - ddtokp->set_rid(messageIdSequence.next()); - ddtokp->set_dequeue_rid(msg->getPersistenceId()); - ddtokp->set_wstate(DataTokenImpl::ENQ); - std::string tid; - if (ctxt) { - TxnCtxt* txn = check(ctxt); - tid = txn->getXid(); - } - // Manually increase the ref count, as raw pointers are used beyond this point - ddtokp->addRef(); - try { - JournalImpl* jc = static_cast(queue.getExternalQueueStore()); - if (tid.empty()) { - jc->dequeue_data_record(ddtokp.get()); - } else { - jc->dequeue_txn_data_record(ddtokp.get(), tid); - } - } catch (const journal::jexception& e) { - ddtokp->release(); - THROW_STORE_EXCEPTION(std::string("Queue ") + queue.getName() + ": async_dequeue() failed: " + e.what()); - } -} - -u_int32_t MessageStoreImpl::outstandingQueueAIO(const qpid::broker::PersistableQueue& /*queue*/) -{ - checkInit(); - return 0; -} - -void MessageStoreImpl::completed(TxnCtxt& txn, - bool commit) -{ - try { - chkTplStoreInit(); // Late initialize (if needed) - - // Nothing to do if not prepared - if (txn.getDtok()->is_enqueued()) { - txn.incrDtokRef(); - DataTokenImpl* dtokp = txn.getDtok(); - dtokp->set_dequeue_rid(dtokp->rid()); - dtokp->set_rid(messageIdSequence.next()); - tplStorePtr->dequeue_txn_data_record(txn.getDtok(), txn.getXid(), commit); - } - txn.complete(commit); - if (mgmtObject.get() != 0) { - mgmtObject->dec_tplTransactionDepth(); - if (commit) - mgmtObject->inc_tplTxnCommits(); - else - mgmtObject->inc_tplTxnAborts(); - } - } catch (const std::exception& e) { - QPID_LOG(error, "Error completing xid " << txn.getXid() << ": " << e.what()); - throw; - } -} - -std::auto_ptr MessageStoreImpl::begin() -{ - checkInit(); - // pass sequence number for c/a - return std::auto_ptr(new TxnCtxt(&messageIdSequence)); -} - -std::auto_ptr MessageStoreImpl::begin(const std::string& xid) -{ - checkInit(); - IdSequence* jtx = &messageIdSequence; - // pass sequence number for c/a - return std::auto_ptr(new TPCTxnCtxt(xid, jtx)); -} - -void MessageStoreImpl::prepare(qpid::broker::TPCTransactionContext& ctxt) -{ - checkInit(); - TxnCtxt* txn = dynamic_cast(&ctxt); - if(!txn) throw qpid::broker::InvalidTransactionContextException(); - localPrepare(txn); -} - -void MessageStoreImpl::localPrepare(TxnCtxt* ctxt) -{ - try { - chkTplStoreInit(); // Late initialize (if needed) - - // This sync is required to ensure multi-queue atomicity - ie all txn data - // must hit the disk on *all* queues before the TPL prepare (enq) is written. - ctxt->sync(); - - ctxt->incrDtokRef(); - DataTokenImpl* dtokp = ctxt->getDtok(); - dtokp->set_external_rid(true); - dtokp->set_rid(messageIdSequence.next()); - char tpcFlag = static_cast(ctxt->isTPC()); - tplStorePtr->enqueue_txn_data_record(&tpcFlag, sizeof(char), sizeof(char), dtokp, ctxt->getXid(), false); - ctxt->prepare(tplStorePtr.get()); - // make sure all the data is written to disk before returning - ctxt->sync(); - if (mgmtObject.get() != 0) { - mgmtObject->inc_tplTransactionDepth(); - mgmtObject->inc_tplTxnPrepares(); - } - } catch (const std::exception& e) { - QPID_LOG(error, "Error preparing xid " << ctxt->getXid() << ": " << e.what()); - throw; - } -} - -void MessageStoreImpl::commit(qpid::broker::TransactionContext& ctxt) -{ - checkInit(); - TxnCtxt* txn(check(&ctxt)); - if (!txn->isTPC()) { - if (txn->impactedQueuesEmpty()) return; - localPrepare(dynamic_cast(txn)); - } - completed(*dynamic_cast(txn), true); -} - -void MessageStoreImpl::abort(qpid::broker::TransactionContext& ctxt) -{ - checkInit(); - TxnCtxt* txn(check(&ctxt)); - if (!txn->isTPC()) { - if (txn->impactedQueuesEmpty()) return; - localPrepare(dynamic_cast(txn)); - } - completed(*dynamic_cast(txn), false); -} - -TxnCtxt* MessageStoreImpl::check(qpid::broker::TransactionContext* ctxt) -{ - TxnCtxt* txn = dynamic_cast(ctxt); - if(!txn) throw qpid::broker::InvalidTransactionContextException(); - return txn; -} - -void MessageStoreImpl::put(db_ptr db, - DbTxn* txn, - Dbt& key, - Dbt& value) -{ - try { - int status = db->put(txn, &key, &value, DB_NODUPDATA); - if (status == DB_KEYEXIST) { - THROW_STORE_EXCEPTION("duplicate data"); - } else if (status) { - THROW_STORE_EXCEPTION(DbEnv::strerror(status)); - } - } catch (const DbException& e) { - THROW_STORE_EXCEPTION(e.what()); - } -} - -void MessageStoreImpl::deleteBindingsForQueue(const qpid::broker::PersistableQueue& queue) -{ - TxnCtxt txn; - txn.begin(dbenv.get(), true); - try { - { - Cursor bindings; - bindings.open(bindingDb, txn.get()); - - IdDbt key; - Dbt value; - while (bindings.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - if (buffer.available() < 8) { - THROW_STORE_EXCEPTION("Not enough data for binding"); - } - uint64_t queueId = buffer.getLongLong(); - if (queue.getPersistenceId() == queueId) { - bindings->del(0); - QPID_LOG(debug, "Deleting binding for " << queue.getName() << " " << key.id << "->" << queueId); - } - } - } - txn.commit(); - } catch (const std::exception& e) { - txn.abort(); - THROW_STORE_EXCEPTION_2("Error deleting bindings", e.what()); - } catch (...) { - txn.abort(); - throw; - } - QPID_LOG(debug, "Deleted all bindings for " << queue.getName() << ":" << queue.getPersistenceId()); -} - -void MessageStoreImpl::deleteBinding(const qpid::broker::PersistableExchange& exchange, - const qpid::broker::PersistableQueue& queue, - const std::string& bkey) -{ - TxnCtxt txn; - txn.begin(dbenv.get(), true); - try { - { - Cursor bindings; - bindings.open(bindingDb, txn.get()); - - IdDbt key(exchange.getPersistenceId()); - Dbt value; - - for (int status = bindings->get(&key, &value, DB_SET); status == 0; status = bindings->get(&key, &value, DB_NEXT_DUP)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - if (buffer.available() < 8) { - THROW_STORE_EXCEPTION("Not enough data for binding"); - } - uint64_t queueId = buffer.getLongLong(); - if (queue.getPersistenceId() == queueId) { - std::string q; - std::string k; - buffer.getShortString(q); - buffer.getShortString(k); - if (bkey == k) { - bindings->del(0); - QPID_LOG(debug, "Deleting binding for " << queue.getName() << " " << key.id << "->" << queueId); - } - } - } - } - txn.commit(); - } catch (const std::exception& e) { - txn.abort(); - THROW_STORE_EXCEPTION_2("Error deleting bindings", e.what()); - } catch (...) { - txn.abort(); - throw; - } -} - -std::string MessageStoreImpl::getJrnlBaseDir() -{ - std::ostringstream dir; - dir << storeDir << "/" << storeTopLevelDir << "/jrnl/" ; - return dir.str(); -} - -std::string MessageStoreImpl::getBdbBaseDir() -{ - std::ostringstream dir; - dir << storeDir << "/" << storeTopLevelDir << "/dat/" ; - return dir.str(); -} - -std::string MessageStoreImpl::getTplBaseDir() -{ - std::ostringstream dir; - dir << storeDir << "/" << storeTopLevelDir << "/tpl/" ; - return dir.str(); -} - -std::string MessageStoreImpl::getJrnlDir(const qpid::broker::PersistableQueue& queue) //for exmaple /var/rhm/ + queueDir/ -{ - return getJrnlHashDir(queue.getName().c_str()); -} - -u_int32_t MessageStoreImpl::bHash(const std::string str) -{ - // Daniel Bernstein hash fn - u_int32_t h = 0; - for (std::string::const_iterator i = str.begin(); i < str.end(); i++) - h = 33*h + *i; - return h; -} - -std::string MessageStoreImpl::getJrnlHashDir(const std::string& queueName) //for exmaple /var/rhm/ + queueDir/ -{ - std::stringstream dir; - dir << getJrnlBaseDir() << std::hex << std::setfill('0') << std::setw(4); - dir << (bHash(queueName.c_str()) % 29); // Use a prime number for better distribution across dirs - dir << "/" << queueName << "/"; - return dir.str(); -} - -std::string MessageStoreImpl::getStoreDir() const { return storeDir; } - -void MessageStoreImpl::journalDeleted(JournalImpl& j) { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - journalList.erase(j.id()); -} - -MessageStoreImpl::StoreOptions::StoreOptions(const std::string& name) : - qpid::Options(name), - numJrnlFiles(defNumJrnlFiles), - autoJrnlExpand(defAutoJrnlExpand), - autoJrnlExpandMaxFiles(defAutoJrnlExpandMaxFiles), - jrnlFsizePgs(defJrnlFileSizePgs), - truncateFlag(defTruncateFlag), - wCachePageSizeKib(defWCachePageSize), - tplNumJrnlFiles(defTplNumJrnlFiles), - tplJrnlFsizePgs(defTplJrnlFileSizePgs), - tplWCachePageSizeKib(defTplWCachePageSize) -{ - std::ostringstream oss1; - oss1 << "Default number of files for each journal instance (queue). [Allowable values: " << - JRNL_MIN_NUM_FILES << " - " << JRNL_MAX_NUM_FILES << "]"; - std::ostringstream oss2; - oss2 << "Default size for each journal file in multiples of read pages (1 read page = 64KiB). [Allowable values: " << - JRNL_MIN_FILE_SIZE / JRNL_RMGR_PAGE_SIZE << " - " << JRNL_MAX_FILE_SIZE / JRNL_RMGR_PAGE_SIZE << "]"; - std::ostringstream oss3; - oss3 << "Number of files for transaction prepared list journal instance. [Allowable values: " << - JRNL_MIN_NUM_FILES << " - " << JRNL_MAX_NUM_FILES << "]"; - std::ostringstream oss4; - oss4 << "Size of each transaction prepared list journal file in multiples of read pages (1 read page = 64KiB) [Allowable values: " << - JRNL_MIN_FILE_SIZE / JRNL_RMGR_PAGE_SIZE << " - " << JRNL_MAX_FILE_SIZE / JRNL_RMGR_PAGE_SIZE << "]"; - addOptions() - ("store-dir", qpid::optValue(storeDir, "DIR"), - "Store directory location for persistence (instead of using --data-dir value). " - "Required if --no-data-dir is also used.") - ("num-jfiles", qpid::optValue(numJrnlFiles, "N"), oss1.str().c_str()) - ("jfile-size-pgs", qpid::optValue(jrnlFsizePgs, "N"), oss2.str().c_str()) -// TODO: Uncomment these lines when auto-expand is enabled. -// ("auto-expand", qpid::optValue(autoJrnlExpand, "yes|no"), -// "If yes|true|1, allows journal to auto-expand by adding additional journal files as needed. " -// "If no|false|0, the number of journal files will remain fixed (num-jfiles).") -// ("max-auto-expand-jfiles", qpid::optValue(autoJrnlExpandMaxFiles, "N"), -// "Maximum number of journal files allowed from auto-expanding; must be greater than --num-jfiles parameter.") - ("truncate", qpid::optValue(truncateFlag, "yes|no"), - "If yes|true|1, will truncate the store (discard any existing records). If no|false|0, will preserve " - "the existing store files for recovery.") - ("wcache-page-size", qpid::optValue(wCachePageSizeKib, "N"), - "Size of the pages in the write page cache in KiB. " - "Allowable values - powers of 2: 1, 2, 4, ... , 128. " - "Lower values decrease latency at the expense of throughput.") - ("tpl-num-jfiles", qpid::optValue(tplNumJrnlFiles, "N"), oss3.str().c_str()) - ("tpl-jfile-size-pgs", qpid::optValue(tplJrnlFsizePgs, "N"), oss4.str().c_str()) - ("tpl-wcache-page-size", qpid::optValue(tplWCachePageSizeKib, "N"), - "Size of the pages in the transaction prepared list write page cache in KiB. " - "Allowable values - powers of 2: 1, 2, 4, ... , 128. " - "Lower values decrease latency at the expense of throughput.") - ; -} - -}} diff --git a/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.h b/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.h deleted file mode 100644 index f6fa68e481..0000000000 --- a/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.h +++ /dev/null @@ -1,383 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_MESSAGESTOREIMPL_H -#define QPID_LEGACYSTORE_MESSAGESTOREIMPL_H - -#include "qpid/broker/MessageStore.h" - -#include "qpid/Options.h" -#include "qpid/broker/Broker.h" -#include "qpid/legacystore/Cursor.h" -#include "qpid/legacystore/IdDbt.h" -#include "qpid/legacystore/IdSequence.h" -#include "qpid/legacystore/JournalImpl.h" -#include "qpid/legacystore/jrnl/jcfg.h" -#include "qpid/legacystore/PreparedTransaction.h" -#include "qpid/legacystore/TxnCtxt.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/legacystore/Store.h" - -#include - -#include "db-inc.h" - -// Assume DB_VERSION_MAJOR == 4 -#if (DB_VERSION_MINOR == 2) -#include -#define DB_BUFFER_SMALL ENOMEM -#endif - -namespace qpid { namespace sys { -class Timer; -}} - -namespace mrg { -namespace msgstore { - -/** - * An implementation of the MessageStore interface based on Berkeley DB - */ -class MessageStoreImpl : public qpid::broker::MessageStore, public qpid::management::Manageable -{ - public: - typedef boost::shared_ptr db_ptr; - typedef boost::shared_ptr dbEnv_ptr; - - struct StoreOptions : public qpid::Options { - StoreOptions(const std::string& name="Store Options"); - std::string clusterName; - std::string storeDir; - u_int16_t numJrnlFiles; - bool autoJrnlExpand; - u_int16_t autoJrnlExpandMaxFiles; - u_int32_t jrnlFsizePgs; - bool truncateFlag; - u_int32_t wCachePageSizeKib; - u_int16_t tplNumJrnlFiles; - u_int32_t tplJrnlFsizePgs; - u_int32_t tplWCachePageSizeKib; - }; - - protected: - typedef std::map queue_index; - typedef std::map exchange_index; - typedef std::map message_index; - - typedef LockedMappings::map txn_lock_map; - typedef boost::ptr_list txn_list; - - // Structs for Transaction Recover List (TPL) recover state - struct TplRecoverStruct { - u_int64_t rid; // rid of TPL record - bool deq_flag; - bool commit_flag; - bool tpc_flag; - TplRecoverStruct(const u_int64_t _rid, const bool _deq_flag, const bool _commit_flag, const bool _tpc_flag); - }; - typedef TplRecoverStruct TplRecover; - typedef std::pair TplRecoverMapPair; - typedef std::map TplRecoverMap; - typedef TplRecoverMap::const_iterator TplRecoverMapCitr; - - typedef std::map JournalListMap; - typedef JournalListMap::iterator JournalListMapItr; - - // Default store settings - static const u_int16_t defNumJrnlFiles = 8; - static const u_int32_t defJrnlFileSizePgs = 24; - static const bool defTruncateFlag = false; - static const u_int32_t defWCachePageSize = JRNL_WMGR_DEF_PAGE_SIZE * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE / 1024; - static const u_int16_t defTplNumJrnlFiles = 8; - static const u_int32_t defTplJrnlFileSizePgs = 24; - static const u_int32_t defTplWCachePageSize = defWCachePageSize / 8; - // TODO: set defAutoJrnlExpand to true and defAutoJrnlExpandMaxFiles to 16 when auto-expand comes on-line - static const bool defAutoJrnlExpand = false; - static const u_int16_t defAutoJrnlExpandMaxFiles = 0; - - static const std::string storeTopLevelDir; - static qpid::sys::Duration defJournalGetEventsTimeout; - static qpid::sys::Duration defJournalFlushTimeout; - - std::list dbs; - dbEnv_ptr dbenv; - db_ptr queueDb; - db_ptr configDb; - db_ptr exchangeDb; - db_ptr mappingDb; - db_ptr bindingDb; - db_ptr generalDb; - - // Pointer to Transaction Prepared List (TPL) journal instance - boost::shared_ptr tplStorePtr; - TplRecoverMap tplRecoverMap; - qpid::sys::Mutex tplInitLock; - JournalListMap journalList; - qpid::sys::Mutex journalListLock; - qpid::sys::Mutex bdbLock; - - IdSequence queueIdSequence; - IdSequence exchangeIdSequence; - IdSequence generalIdSequence; - IdSequence messageIdSequence; - std::string storeDir; - u_int16_t numJrnlFiles; - bool autoJrnlExpand; - u_int16_t autoJrnlExpandMaxFiles; - u_int32_t jrnlFsizeSblks; - bool truncateFlag; - u_int32_t wCachePgSizeSblks; - u_int16_t wCacheNumPages; - u_int16_t tplNumJrnlFiles; - u_int32_t tplJrnlFsizeSblks; - u_int32_t tplWCachePgSizeSblks; - u_int16_t tplWCacheNumPages; - u_int64_t highestRid; - bool isInit; - const char* envPath; - qpid::broker::Broker* broker; - - qmf::org::apache::qpid::legacystore::Store::shared_ptr mgmtObject; - qpid::management::ManagementAgent* agent; - - - // Parameter validation and calculation - static u_int16_t chkJrnlNumFilesParam(const u_int16_t param, - const std::string paramName); - static u_int32_t chkJrnlFileSizeParam(const u_int32_t param, - const std::string paramName, - const u_int32_t wCachePgSizeSblks = 0); - static u_int32_t chkJrnlWrPageCacheSize(const u_int32_t param, - const std::string paramName, - const u_int16_t jrnlFsizePgs); - static u_int16_t getJrnlWrNumPages(const u_int32_t wrPageSizeKib); - void chkJrnlAutoExpandOptions(const MessageStoreImpl::StoreOptions* opts, - bool& autoJrnlExpand, - u_int16_t& autoJrnlExpandMaxFiles, - const std::string& autoJrnlExpandMaxFilesParamName, - const u_int16_t numJrnlFiles, - const std::string& numJrnlFilesParamName); - - void init(); - - void recoverQueues(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery, - queue_index& index, - txn_list& locked, - message_index& messages); - void recoverMessages(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery, - queue_index& index, - txn_list& locked, - message_index& prepared); - void recoverMessages(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery, - qpid::broker::RecoverableQueue::shared_ptr& queue, - txn_list& locked, - message_index& prepared, - long& rcnt, - long& idcnt); - qpid::broker::RecoverableMessage::shared_ptr getExternMessage(qpid::broker::RecoveryManager& recovery, - uint64_t mId, - unsigned& headerSize); - void recoverExchanges(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery, - exchange_index& index); - void recoverBindings(TxnCtxt& txn, - exchange_index& exchanges, - queue_index& queues); - void recoverGeneral(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery); - int enqueueMessage(TxnCtxt& txn, - IdDbt& msgId, - qpid::broker::RecoverableMessage::shared_ptr& msg, - queue_index& index, - txn_list& locked, - message_index& prepared); - void readTplStore(); - void recoverTplStore(); - void recoverLockedMappings(txn_list& txns); - TxnCtxt* check(qpid::broker::TransactionContext* ctxt); - u_int64_t msgEncode(std::vector& buff, const boost::intrusive_ptr& message); - void store(const qpid::broker::PersistableQueue* queue, - TxnCtxt* txn, - const boost::intrusive_ptr& message, - bool newId); - void async_dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue); - void destroy(db_ptr db, - const qpid::broker::Persistable& p); - bool create(db_ptr db, - IdSequence& seq, - const qpid::broker::Persistable& p); - void completed(TxnCtxt& txn, - bool commit); - void deleteBindingsForQueue(const qpid::broker::PersistableQueue& queue); - void deleteBinding(const qpid::broker::PersistableExchange& exchange, - const qpid::broker::PersistableQueue& queue, - const std::string& key); - - void put(db_ptr db, - DbTxn* txn, - Dbt& key, - Dbt& value); - void open(db_ptr db, - DbTxn* txn, - const char* file, - bool dupKey); - void closeDbs(); - - // journal functions - void createJrnlQueue(const qpid::broker::PersistableQueue& queue); - u_int32_t bHash(const std::string str); - std::string getJrnlDir(const qpid::broker::PersistableQueue& queue); //for exmaple /var/rhm/ + queueDir/ - std::string getJrnlHashDir(const std::string& queueName); - std::string getJrnlBaseDir(); - std::string getBdbBaseDir(); - std::string getTplBaseDir(); - inline void checkInit() { - // TODO: change the default dir to ~/.qpidd - if (!isInit) { init("/tmp"); isInit = true; } - } - void chkTplStoreInit(); - - // debug aid for printing XIDs that may contain non-printable chars - static std::string xid2str(const std::string xid) { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - for (unsigned i=0; i shared_ptr; - - MessageStoreImpl(qpid::broker::Broker* broker, const char* envpath = 0); - - virtual ~MessageStoreImpl(); - - bool init(const qpid::Options* options); - - bool init(const std::string& dir, - u_int16_t jfiles = defNumJrnlFiles, - u_int32_t jfileSizePgs = defJrnlFileSizePgs, - const bool truncateFlag = false, - u_int32_t wCachePageSize = defWCachePageSize, - u_int16_t tplJfiles = defTplNumJrnlFiles, - u_int32_t tplJfileSizePgs = defTplJrnlFileSizePgs, - u_int32_t tplWCachePageSize = defTplWCachePageSize, - bool autoJExpand = defAutoJrnlExpand, - u_int16_t autoJExpandMaxFiles = defAutoJrnlExpandMaxFiles); - - void truncateInit(const bool saveStoreContent = false); - - void initManagement (); - - void finalize(); - - void create(qpid::broker::PersistableQueue& queue, - const qpid::framing::FieldTable& args); - - void destroy(qpid::broker::PersistableQueue& queue); - - void create(const qpid::broker::PersistableExchange& queue, - const qpid::framing::FieldTable& args); - - void destroy(const qpid::broker::PersistableExchange& queue); - - void bind(const qpid::broker::PersistableExchange& exchange, - const qpid::broker::PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - void unbind(const qpid::broker::PersistableExchange& exchange, - const qpid::broker::PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - void create(const qpid::broker::PersistableConfig& config); - - void destroy(const qpid::broker::PersistableConfig& config); - - void recover(qpid::broker::RecoveryManager& queues); - - void stage(const boost::intrusive_ptr& msg); - - void destroy(qpid::broker::PersistableMessage& msg); - - void appendContent(const boost::intrusive_ptr& msg, - const std::string& data); - - void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - void enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue); - - void dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue); - - void flush(const qpid::broker::PersistableQueue& queue); - - u_int32_t outstandingQueueAIO(const qpid::broker::PersistableQueue& queue); - - void collectPreparedXids(std::set& xids); - - std::auto_ptr begin(); - - std::auto_ptr begin(const std::string& xid); - - void prepare(qpid::broker::TPCTransactionContext& ctxt); - - void localPrepare(TxnCtxt* ctxt); - - void commit(qpid::broker::TransactionContext& ctxt); - - void abort(qpid::broker::TransactionContext& ctxt); - - qpid::management::ManagementObject::shared_ptr GetManagementObject (void) const - { return mgmtObject; } - - inline qpid::management::Manageable::status_t ManagementMethod (u_int32_t, qpid::management::Args&, std::string&) - { return qpid::management::Manageable::STATUS_OK; } - - std::string getStoreDir() const; - - private: - void journalDeleted(JournalImpl&); - -}; // class MessageStoreImpl - -} // namespace msgstore -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_MESSAGESTOREIMPL_H diff --git a/qpid/cpp/src/qpid/legacystore/PreparedTransaction.cpp b/qpid/cpp/src/qpid/legacystore/PreparedTransaction.cpp deleted file mode 100644 index 50b81e2824..0000000000 --- a/qpid/cpp/src/qpid/legacystore/PreparedTransaction.cpp +++ /dev/null @@ -1,81 +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/legacystore/PreparedTransaction.h" -#include - -using namespace mrg::msgstore; -using std::string; - -void LockedMappings::add(queue_id queue, message_id message) -{ - locked.push_back(std::make_pair(queue, message)); -} - -bool LockedMappings::isLocked(queue_id queue, message_id message) -{ - idpair op( std::make_pair(queue, message) ); - return find(locked.begin(), locked.end(), op) != locked.end(); -} - -void LockedMappings::add(LockedMappings::map& map, std::string& key, queue_id queue, message_id message) -{ - LockedMappings::map::iterator i = map.find(key); - if (i == map.end()) { - LockedMappings::shared_ptr ptr(new LockedMappings()); - i = map.insert(std::make_pair(key, ptr)).first; - } - i->second->add(queue, message); -} - -bool PreparedTransaction::isLocked(queue_id queue, message_id message) -{ - return (enqueues.get() && enqueues->isLocked(queue, message)) - || (dequeues.get() && dequeues->isLocked(queue, message)); -} - - -bool PreparedTransaction::isLocked(PreparedTransaction::list& txns, queue_id queue, message_id message) -{ - for (PreparedTransaction::list::iterator i = txns.begin(); i != txns.end(); i++) { - if (i->isLocked(queue, message)) { - return true; - } - } - return false; -} - -PreparedTransaction::list::iterator PreparedTransaction::getLockedPreparedTransaction(PreparedTransaction::list& txns, queue_id queue, message_id message) -{ - for (PreparedTransaction::list::iterator i = txns.begin(); i != txns.end(); i++) { - if (i->isLocked(queue, message)) { - return i; - } - } - return txns.end(); -} - -PreparedTransaction::PreparedTransaction(const std::string& _xid, - LockedMappings::shared_ptr _enqueues, - LockedMappings::shared_ptr _dequeues) - - : xid(_xid), enqueues(_enqueues), dequeues(_dequeues) {} - diff --git a/qpid/cpp/src/qpid/legacystore/PreparedTransaction.h b/qpid/cpp/src/qpid/legacystore/PreparedTransaction.h deleted file mode 100644 index c5f7b9458a..0000000000 --- a/qpid/cpp/src/qpid/legacystore/PreparedTransaction.h +++ /dev/null @@ -1,74 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_PREPAREDTRANSACTION_H -#define QPID_LEGACYSTORE_PREPAREDTRANSACTION_H - -#include -#include -#include -#include -#include -#include - -namespace mrg{ -namespace msgstore{ - -typedef u_int64_t queue_id; -typedef u_int64_t message_id; - -class LockedMappings -{ -public: - typedef boost::shared_ptr shared_ptr; - typedef std::map map; - typedef std::pair idpair; - typedef std::list::iterator iterator; - - void add(queue_id queue, message_id message); - bool isLocked(queue_id queue, message_id message); - std::size_t size() { return locked.size(); } - iterator begin() { return locked.begin(); } - iterator end() { return locked.end(); } - - static void add(LockedMappings::map& map, std::string& key, queue_id queue, message_id message); - -private: - std::list locked; -}; - -struct PreparedTransaction -{ - typedef boost::ptr_list list; - - const std::string xid; - const LockedMappings::shared_ptr enqueues; - const LockedMappings::shared_ptr dequeues; - - PreparedTransaction(const std::string& xid, LockedMappings::shared_ptr enqueues, LockedMappings::shared_ptr dequeues); - bool isLocked(queue_id queue, message_id message); - static bool isLocked(PreparedTransaction::list& txns, queue_id queue, message_id message); - static PreparedTransaction::list::iterator getLockedPreparedTransaction(PreparedTransaction::list& txns, queue_id queue, message_id message); -}; - -}} - -#endif // ifndef QPID_LEGACYSTORE_PREPAREDTRANSACTION_H diff --git a/qpid/cpp/src/qpid/legacystore/StoreException.h b/qpid/cpp/src/qpid/legacystore/StoreException.h deleted file mode 100644 index 6624aafd5a..0000000000 --- a/qpid/cpp/src/qpid/legacystore/StoreException.h +++ /dev/null @@ -1,56 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_STOREEXCEPTION_H -#define QPID_LEGACYSTORE_STOREEXCEPTION_H - -#include "qpid/legacystore/IdDbt.h" -#include - -namespace mrg{ -namespace msgstore{ - -class StoreException : public std::exception -{ - std::string text; -public: - StoreException(const std::string& _text) : text(_text) {} - StoreException(const std::string& _text, const DbException& cause) : text(_text + ": " + cause.what()) {} - virtual ~StoreException() throw() {} - virtual const char* what() const throw() { return text.c_str(); } -}; - -class StoreFullException : public StoreException -{ -public: - StoreFullException(const std::string& _text) : StoreException(_text) {} - StoreFullException(const std::string& _text, const DbException& cause) : StoreException(_text, cause) {} - virtual ~StoreFullException() throw() {} - -}; - -#define THROW_STORE_EXCEPTION(MESSAGE) throw StoreException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__)) -#define THROW_STORE_EXCEPTION_2(MESSAGE, EXCEPTION) throw StoreException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__), EXCEPTION) -#define THROW_STORE_FULL_EXCEPTION(MESSAGE) throw StoreFullException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__)) - -}} - -#endif // ifndef QPID_LEGACYSTORE_STOREEXCEPTION_H diff --git a/qpid/cpp/src/qpid/legacystore/StorePlugin.cpp b/qpid/cpp/src/qpid/legacystore/StorePlugin.cpp deleted file mode 100644 index 5cba10d0f9..0000000000 --- a/qpid/cpp/src/qpid/legacystore/StorePlugin.cpp +++ /dev/null @@ -1,81 +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/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/DataDir.h" -#include "qpid/log/Statement.h" -#include "qpid/legacystore/MessageStoreImpl.h" - -using mrg::msgstore::MessageStoreImpl; - -namespace qpid { -namespace broker { - -using namespace std; - -struct StorePlugin : public Plugin { - - MessageStoreImpl::StoreOptions options; - boost::shared_ptr store; - - Options* getOptions() { return &options; } - - void earlyInitialize (Plugin::Target& target) - { - Broker* broker = dynamic_cast(&target); - if (!broker) return; - store.reset(new MessageStoreImpl(broker)); - const DataDir& dataDir = broker->getDataDir (); - if (options.storeDir.empty ()) - { - if (!dataDir.isEnabled ()) - throw Exception ("msgstore: If --data-dir is blank or --no-data-dir is specified, --store-dir must be present."); - - options.storeDir = dataDir.getPath (); - } - store->init(&options); - boost::shared_ptr brokerStore(store); - broker->setStore(brokerStore); - target.addFinalizer(boost::bind(&StorePlugin::finalize, this)); - } - - void initialize(Plugin::Target& target) - { - Broker* broker = dynamic_cast(&target); - if (!broker) return; - if (!store) return; - QPID_LOG(info, "Enabling management instrumentation for the store."); - store->initManagement(); - } - - void finalize() - { - store.reset(); - } - - const char* id() {return "StorePlugin";} -}; - -static StorePlugin instance; // Static initialization. - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/legacystore/TxnCtxt.cpp b/qpid/cpp/src/qpid/legacystore/TxnCtxt.cpp deleted file mode 100644 index b02b5e887f..0000000000 --- a/qpid/cpp/src/qpid/legacystore/TxnCtxt.cpp +++ /dev/null @@ -1,184 +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/legacystore/TxnCtxt.h" - -#include - -#include "qpid/legacystore/jrnl/jexception.h" -#include "qpid/legacystore/StoreException.h" - -namespace mrg { -namespace msgstore { - -void TxnCtxt::completeTxn(bool commit) { - sync(); - for (ipqItr i = impactedQueues.begin(); i != impactedQueues.end(); i++) { - commitTxn(static_cast(*i), commit); - } - impactedQueues.clear(); - if (preparedXidStorePtr) - commitTxn(preparedXidStorePtr, commit); -} - -void TxnCtxt::commitTxn(JournalImpl* jc, bool commit) { - if (jc && loggedtx) { /* if using journal */ - boost::intrusive_ptr dtokp(new DataTokenImpl); - dtokp->addRef(); - dtokp->set_external_rid(true); - dtokp->set_rid(loggedtx->next()); - try { - if (commit) { - jc->txn_commit(dtokp.get(), getXid()); - sync(); - } else { - jc->txn_abort(dtokp.get(), getXid()); - } - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Error commit") + e.what()); - } - } -} - -// static -qpid::sys::uuid_t TxnCtxt::uuid; - -// static -IdSequence TxnCtxt::uuidSeq; - -// static -bool TxnCtxt::staticInit = TxnCtxt::setUuid(); - -// static -bool TxnCtxt::setUuid() { - qpid::sys::uuid_generate(uuid); - return true; -} - -TxnCtxt::TxnCtxt(IdSequence* _loggedtx) : loggedtx(_loggedtx), dtokp(new DataTokenImpl), preparedXidStorePtr(0), txn(0) { - if (loggedtx) { -// // Human-readable tid: 53 bytes -// // uuit_t is a char[16] -// tid.reserve(53); -// u_int64_t* u1 = (u_int64_t*)uuid; -// u_int64_t* u2 = (u_int64_t*)(uuid + sizeof(u_int64_t)); -// std::stringstream s; -// s << "tid:" << std::hex << std::setfill('0') << std::setw(16) << uuidSeq.next() << ":" << std::setw(16) << *u1 << std::setw(16) << *u2; -// tid.assign(s.str()); - - // Binary tid: 24 bytes - tid.reserve(24); - u_int64_t c = uuidSeq.next(); - tid.append((char*)&c, sizeof(c)); - tid.append((char*)&uuid, sizeof(uuid)); - } -} - -TxnCtxt::TxnCtxt(std::string _tid, IdSequence* _loggedtx) : loggedtx(_loggedtx), dtokp(new DataTokenImpl), preparedXidStorePtr(0), tid(_tid), txn(0) {} - -TxnCtxt::~TxnCtxt() { abort(); } - -void TxnCtxt::sync() { - if (loggedtx) { - try { - for (ipqItr i = impactedQueues.begin(); i != impactedQueues.end(); i++) - jrnl_flush(static_cast(*i)); - if (preparedXidStorePtr) - jrnl_flush(preparedXidStorePtr); - for (ipqItr i = impactedQueues.begin(); i != impactedQueues.end(); i++) - jrnl_sync(static_cast(*i), &journal::jcntl::_aio_cmpl_timeout); - if (preparedXidStorePtr) - jrnl_sync(preparedXidStorePtr, &journal::jcntl::_aio_cmpl_timeout); - } catch (const journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Error during txn sync: ") + e.what()); - } - } -} - -void TxnCtxt::jrnl_flush(JournalImpl* jc) { - if (jc && !(jc->is_txn_synced(getXid()))) - jc->flush(); -} - -void TxnCtxt::jrnl_sync(JournalImpl* jc, timespec* timeout) { - if (!jc || jc->is_txn_synced(getXid())) - return; - while (jc->get_wr_aio_evt_rem()) { - if (jc->get_wr_events(timeout) == journal::jerrno::AIO_TIMEOUT && timeout) - THROW_STORE_EXCEPTION(std::string("Error: timeout waiting for TxnCtxt::jrnl_sync()")); - } -} - -void TxnCtxt::begin(DbEnv* env, bool sync) { - int err; - try { err = env->txn_begin(0, &txn, 0); } - catch (const DbException&) { txn = 0; throw; } - if (err != 0) { - std::ostringstream oss; - oss << "Error: Env::txn_begin() returned error code: " << err; - THROW_STORE_EXCEPTION(oss.str()); - } - if (sync) - globalHolder = AutoScopedLock(new qpid::sys::Mutex::ScopedLock(globalSerialiser)); -} - -void TxnCtxt::commit() { - if (txn) { - txn->commit(0); - txn = 0; - globalHolder.reset(); - } -} - -void TxnCtxt::abort(){ - if (txn) { - txn->abort(); - txn = 0; - globalHolder.reset(); - } -} - -DbTxn* TxnCtxt::get() { return txn; } - -bool TxnCtxt::isTPC() { return false; } - -const std::string& TxnCtxt::getXid() { return tid; } - -void TxnCtxt::addXidRecord(qpid::broker::ExternalQueueStore* queue) { impactedQueues.insert(queue); } - -void TxnCtxt::complete(bool commit) { completeTxn(commit); } - -bool TxnCtxt::impactedQueuesEmpty() { return impactedQueues.empty(); } - -DataTokenImpl* TxnCtxt::getDtok() { return dtokp.get(); } - -void TxnCtxt::incrDtokRef() { dtokp->addRef(); } - -void TxnCtxt::recoverDtok(const u_int64_t rid, const std::string xid) { - dtokp->set_rid(rid); - dtokp->set_wstate(DataTokenImpl::ENQ); - dtokp->set_xid(xid); - dtokp->set_external_rid(true); -} - -TPCTxnCtxt::TPCTxnCtxt(const std::string& _xid, IdSequence* _loggedtx) : TxnCtxt(_loggedtx), xid(_xid) {} - -}} diff --git a/qpid/cpp/src/qpid/legacystore/TxnCtxt.h b/qpid/cpp/src/qpid/legacystore/TxnCtxt.h deleted file mode 100644 index 85f0226cdc..0000000000 --- a/qpid/cpp/src/qpid/legacystore/TxnCtxt.h +++ /dev/null @@ -1,117 +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. - * - */ - -#ifndef QPID_LEGACYSTORE_TXNCTXT_H -#define QPID_LEGACYSTORE_TXNCTXT_H - -#include "db-inc.h" -#include -#include -#include - -#include "qpid/legacystore/DataTokenImpl.h" -#include "qpid/legacystore/IdSequence.h" -#include "qpid/legacystore/JournalImpl.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/uuid.h" - -#include - -namespace mrg { -namespace msgstore { - -class TxnCtxt : public qpid::broker::TransactionContext -{ - protected: - static qpid::sys::Mutex globalSerialiser; - - static qpid::sys::uuid_t uuid; - static IdSequence uuidSeq; - static bool staticInit; - static bool setUuid(); - - typedef std::set ipqdef; - typedef ipqdef::iterator ipqItr; - typedef std::auto_ptr AutoScopedLock; - - ipqdef impactedQueues; // list of Queues used in the txn - IdSequence* loggedtx; - boost::intrusive_ptr dtokp; - AutoScopedLock globalHolder; - JournalImpl* preparedXidStorePtr; - - /** - * local txn id, if non XA. - */ - std::string tid; - DbTxn* txn; - - virtual void completeTxn(bool commit); - void commitTxn(JournalImpl* jc, bool commit); - void jrnl_flush(JournalImpl* jc); - void jrnl_sync(JournalImpl* jc, timespec* timeout); - - public: - TxnCtxt(IdSequence* _loggedtx=NULL); - TxnCtxt(std::string _tid, IdSequence* _loggedtx); - virtual ~TxnCtxt(); - - /** - * Call to make sure all the data for this txn is written to safe store - * - *@return if the data successfully synced. - */ - void sync(); - void begin(DbEnv* env, bool sync = false); - void commit(); - void abort(); - DbTxn* get(); - virtual bool isTPC(); - virtual const std::string& getXid(); - - void addXidRecord(qpid::broker::ExternalQueueStore* queue); - inline void prepare(JournalImpl* _preparedXidStorePtr) { preparedXidStorePtr = _preparedXidStorePtr; } - void complete(bool commit); - bool impactedQueuesEmpty(); - DataTokenImpl* getDtok(); - void incrDtokRef(); - void recoverDtok(const u_int64_t rid, const std::string xid); -}; - - -class TPCTxnCtxt : public TxnCtxt, public qpid::broker::TPCTransactionContext -{ - protected: - const std::string xid; - - public: - TPCTxnCtxt(const std::string& _xid, IdSequence* _loggedtx); - inline virtual bool isTPC() { return true; } - inline virtual const std::string& getXid() { return xid; } -}; - -}} - -#endif // ifndef QPID_LEGACYSTORE_TXNCTXT_H - - diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/aio.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/aio.cpp deleted file mode 100644 index ffbddd887e..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/aio.cpp +++ /dev/null @@ -1,41 +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. - * - */ - -/** - * \file aio.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::aio (libaio interface - * encapsulation). See comments in file aio.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/aio.h" - -namespace mrg -{ -namespace journal -{ - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/aio.h b/qpid/cpp/src/qpid/legacystore/jrnl/aio.h deleted file mode 100644 index b1de5f79f7..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/aio.h +++ /dev/null @@ -1,153 +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. - * - */ - -/** - * \file aio.h - * - * Qpid asynchronous store plugin library - * - * This file contains an encapsulation of the libaio interface used - * by the journal. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_AIO_H -#define QPID_LEGACYSTORE_JRNL_AIO_H - -#include -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - -typedef iocb aio_cb; -typedef io_event aio_event; - -/** - * \brief This class is a C++ wrapper class for the libaio functions used by the journal. Note that only those - * functions used by the journal are included here. This is not a complete implementation of all libaio functions. - */ -class aio -{ -public: - static inline int queue_init(int maxevents, io_context_t* ctxp) - { - return ::io_queue_init(maxevents, ctxp); - } - - static inline int queue_release(io_context_t ctx) - { - return ::io_queue_release(ctx); - } - - static inline int submit(io_context_t ctx, long nr, aio_cb* aios[]) - { - return ::io_submit(ctx, nr, aios); - } - - static inline int getevents(io_context_t ctx, long min_nr, long nr, aio_event* events, timespec* const timeout) - { - return ::io_getevents(ctx, min_nr, nr, events, timeout); - } - - /** - * \brief This function allows iocbs to be initialized with a pointer that can be re-used. This prepares an - * aio_cb struct for read use. (This is a wrapper for libaio's ::io_prep_pread() function.) - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for read. - * \param buf Pointer to buffer in which read data is to be placed. - * \param count Number of bytes to read - buffer must be large enough. - * \param offset Offset within file from which data will be read. - */ - static inline void prep_pread(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - ::io_prep_pread(aiocbp, fd, buf, count, offset); - } - - /** - * \brief Special version of libaio's io_prep_pread() which preserves the value of the data pointer. This allows - * iocbs to be initialized with a pointer that can be re-used. This prepares a aio_cb struct for read use. - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for read. - * \param buf Pointer to buffer in which read data is to be placed. - * \param count Number of bytes to read - buffer must be large enough. - * \param offset Offset within file from which data will be read. - */ - static inline void prep_pread_2(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - std::memset((void*) ((char*) aiocbp + sizeof(void*)), 0, sizeof(aio_cb) - sizeof(void*)); - aiocbp->aio_fildes = fd; - aiocbp->aio_lio_opcode = IO_CMD_PREAD; - aiocbp->aio_reqprio = 0; - aiocbp->u.c.buf = buf; - aiocbp->u.c.nbytes = count; - aiocbp->u.c.offset = offset; - } - - /** - * \brief This function allows iocbs to be initialized with a pointer that can be re-used. This function prepares - * an aio_cb struct for write use. (This is a wrapper for libaio's ::io_prep_pwrite() function.) - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for write. - * \param buf Pointer to buffer in which data to be written is located. - * \param count Number of bytes to write. - * \param offset Offset within file to which data will be written. - */ - static inline void prep_pwrite(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - ::io_prep_pwrite(aiocbp, fd, buf, count, offset); - } - - /** - * \brief Special version of libaio's io_prep_pwrite() which preserves the value of the data pointer. This allows - * iocbs to be initialized with a pointer that can be re-used. This function prepares an aio_cb struct for write - * use. - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for write. - * \param buf Pointer to buffer in which data to be written is located. - * \param count Number of bytes to write. - * \param offset Offset within file to which data will be written. - */ - static inline void prep_pwrite_2(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - std::memset((void*) ((char*) aiocbp + sizeof(void*)), 0, sizeof(aio_cb) - sizeof(void*)); - aiocbp->aio_fildes = fd; - aiocbp->aio_lio_opcode = IO_CMD_PWRITE; - aiocbp->aio_reqprio = 0; - aiocbp->u.c.buf = buf; - aiocbp->u.c.nbytes = count; - aiocbp->u.c.offset = offset; - } -}; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_AIO_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/aio_callback.h b/qpid/cpp/src/qpid/legacystore/jrnl/aio_callback.h deleted file mode 100644 index 90249278a5..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/aio_callback.h +++ /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. - * - */ - -/** - * \file aio_callback.h - * - * Qpid asynchronous store plugin library - * - * This file contains the definition for the AIO callback function - * pointer. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_AIO_CALLBACK_H -#define QPID_LEGACYSTORE_JRNL_AIO_CALLBACK_H - -#include -#include - -namespace mrg -{ -namespace journal -{ - - class data_tok; - - class aio_callback - { - public: - virtual ~aio_callback() {} - virtual void wr_aio_cb(std::vector& dtokl) = 0; - virtual void rd_aio_cb(std::vector& pil) = 0; - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_AIO_CALLBACK_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/cvar.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/cvar.cpp deleted file mode 100644 index e4010bf91f..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/cvar.cpp +++ /dev/null @@ -1,33 +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. - * - */ - -/** - * \file cvar.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::cvar (condition variable). See - * comments in file cvar.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/cvar.h" diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/cvar.h b/qpid/cpp/src/qpid/legacystore/jrnl/cvar.h deleted file mode 100644 index 0498e743a2..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/cvar.h +++ /dev/null @@ -1,87 +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. - * - */ - -/** - * \file cvar.h - * - * Qpid asynchronous store plugin library - * - * This file contains a posix condition variable class. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_CVAR_H -#define QPID_LEGACYSTORE_JRNL_CVAR_H - -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include "qpid/legacystore/jrnl/smutex.h" -#include "qpid/legacystore/jrnl/time_ns.h" -#include -#include - -namespace mrg -{ -namespace journal -{ - - // Ultra-simple thread condition variable class - class cvar - { - private: - const smutex& _sm; - pthread_cond_t _c; - public: - inline cvar(const smutex& sm) : _sm(sm) { ::pthread_cond_init(&_c, 0); } - inline ~cvar() { ::pthread_cond_destroy(&_c); } - inline void wait() - { - PTHREAD_CHK(::pthread_cond_wait(&_c, _sm.get()), "::pthread_cond_wait", "cvar", "wait"); - } - inline void timedwait(timespec& ts) - { - PTHREAD_CHK(::pthread_cond_timedwait(&_c, _sm.get(), &ts), "::pthread_cond_timedwait", "cvar", "timedwait"); - } - inline bool waitintvl(const long intvl_ns) - { - time_ns t; t.now(); t+=intvl_ns; - int ret = ::pthread_cond_timedwait(&_c, _sm.get(), &t); - if (ret == ETIMEDOUT) - return true; - PTHREAD_CHK(ret, "::pthread_cond_timedwait", "cvar", "waitintvl"); - return false; - } - inline void signal() - { - PTHREAD_CHK(::pthread_cond_signal(&_c), "::pthread_cond_signal", "cvar", "notify"); - } - inline void broadcast() - { - PTHREAD_CHK(::pthread_cond_broadcast(&_c), "::pthread_cond_broadcast", "cvar", "broadcast"); - } - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_CVAR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/data_tok.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/data_tok.cpp deleted file mode 100644 index ce7206d80d..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/data_tok.cpp +++ /dev/null @@ -1,194 +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. - * - */ - -/** - * \file data_tok.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::data_tok (data block token). - * See comments in file data_tok.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/data_tok.h" - -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include "qpid/legacystore/jrnl/slock.h" -#include - -namespace mrg -{ -namespace journal -{ - -// Static members - -u_int64_t data_tok::_cnt = 0; -smutex data_tok::_mutex; - -data_tok::data_tok(): - _wstate(NONE), - _rstate(UNREAD), - _dsize(0), - _dblks_written(0), - _dblks_read(0), - _pg_cnt(0), - _fid(0), - _rid(0), - _xid(), - _dequeue_rid(0), - _external_rid(false) -{ - slock s(_mutex); - _icnt = _cnt++; -} - -data_tok::~data_tok() {} - -const char* -data_tok::wstate_str() const -{ - return wstate_str(_wstate); -} - -const char* -data_tok::wstate_str(write_state wstate) -{ - switch (wstate) - { - case NONE: - return "NONE"; - case ENQ_CACHED: - return "ENQ_CACHED"; - case ENQ_PART: - return "ENQ_PART"; - case ENQ_SUBM: - return "ENQ_SUBM"; - case ENQ: - return "ENQ"; - case DEQ_CACHED: - return "DEQ_CACHED"; - case DEQ_PART: - return "DEQ_PART"; - case DEQ_SUBM: - return "DEQ_SUBM"; - case DEQ: - return "DEQ"; - case ABORT_CACHED: - return "ABORT_CACHED"; - case ABORT_PART: - return "ABORT_PART"; - case ABORT_SUBM: - return "ABORT_SUBM"; - case ABORTED: - return "ABORTED"; - case COMMIT_CACHED: - return "COMMIT_CACHED"; - case COMMIT_PART: - return "COMMIT_PART"; - case COMMIT_SUBM: - return "COMMIT_SUBM"; - case COMMITTED: - return "COMMITTED"; - } - // Not using default: forces compiler to ensure all cases are covered. - return ""; -} - -const char* -data_tok::rstate_str() const -{ - return rstate_str(_rstate); -} - -const char* -data_tok::rstate_str(read_state rstate) -{ - switch (rstate) - { - case NONE: - return "NONE"; - case READ_PART: - return "READ_PART"; - case SKIP_PART: - return "SKIP_PART"; - case READ: - return "READ"; - // Not using default: forces compiler to ensure all cases are covered. - } - return ""; -} - -void -data_tok::set_rstate(const read_state rstate) -{ - if (_wstate != ENQ && rstate != UNREAD) - { - std::ostringstream oss; - oss << "Attempted to change read state to " << rstate_str(rstate); - oss << " while write state is not enqueued (wstate ENQ); wstate=" << wstate_str() << "."; - throw jexception(jerrno::JERR_DTOK_ILLEGALSTATE, oss.str(), "data_tok", - "set_rstate"); - } - _rstate = rstate; -} - -void -data_tok::reset() -{ - _wstate = NONE; - _rstate = UNREAD; - _dsize = 0; - _dblks_written = 0; - _dblks_read = 0; - _pg_cnt = 0; - _fid = 0; - _rid = 0; - _xid.clear(); -} - -// debug aid -std::string -data_tok::status_str() const -{ - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "dtok id=0x" << _icnt << "; ws=" << wstate_str() << "; rs=" << rstate_str(); - oss << "; fid=0x" << _fid << "; rid=0x" << _rid << "; xid="; - for (unsigned i=0; i<_xid.size(); i++) - { - if (isprint(_xid[i])) - oss << _xid[i]; - else - oss << "/" << std::setw(2) << (int)((char)_xid[i]); - } - oss << "; drid=0x" << _dequeue_rid << " extrid=" << (_external_rid?"T":"F"); - oss << "; ds=0x" << _dsize << "; dw=0x" << _dblks_written << "; dr=0x" << _dblks_read; - oss << " pc=0x" << _pg_cnt; - return oss.str(); -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/data_tok.h b/qpid/cpp/src/qpid/legacystore/jrnl/data_tok.h deleted file mode 100644 index e35f069399..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/data_tok.h +++ /dev/null @@ -1,172 +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. - * - */ - -/** - * \file data_tok.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::data_tok (data block token). - * See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_DATA_TOK_H -#define QPID_LEGACYSTORE_JRNL_DATA_TOK_H - -namespace mrg -{ -namespace journal -{ -class data_tok; -} -} - -#include -#include -#include "qpid/legacystore/jrnl/smutex.h" -#include -#include -#include - -namespace mrg -{ - -namespace journal -{ - - /** - * \class data_tok - * \brief Data block token (data_tok) used to track wstate of a data block through asynchronous - * I/O process - */ - class data_tok - { - public: - // TODO: Fix this, separate write state from operation - // ie: wstate = NONE, CACHED, PART, SUBM, COMPL - // op = ENQUEUE, DEQUEUE, ABORT, COMMIT - enum write_state - { - NONE, ///< Data block not sent to journal - ENQ_CACHED, ///< Data block enqueue written to page cache - ENQ_PART, ///< Data block part-submitted to AIO, waiting for page buffer to free up - ENQ_SUBM, ///< Data block enqueue submitted to AIO - ENQ, ///< Data block enqueue AIO write complete (enqueue complete) - DEQ_CACHED, ///< Data block dequeue written to page cache - DEQ_PART, ///< Data block part-submitted to AIO, waiting for page buffer to free up - DEQ_SUBM, ///< Data block dequeue submitted to AIO - DEQ, ///< Data block dequeue AIO write complete (dequeue complete) - ABORT_CACHED, - ABORT_PART, - ABORT_SUBM, - ABORTED, - COMMIT_CACHED, - COMMIT_PART, - COMMIT_SUBM, - COMMITTED - }; - - enum read_state - { - UNREAD, ///< Data block not read - READ_PART, ///< Data block is part-read; waiting for page buffer to fill - SKIP_PART, ///< Prev. dequeued dblock is part-skipped; waiting for page buffer to fill - READ ///< Data block is fully read - }; - - protected: - static smutex _mutex; - static u_int64_t _cnt; - u_int64_t _icnt; - write_state _wstate; ///< Enqueued / dequeued state of data - read_state _rstate; ///< Read state of data - std::size_t _dsize; ///< Data size in bytes - u_int32_t _dblks_written; ///< Data blocks read/written - u_int32_t _dblks_read; ///< Data blocks read/written - u_int32_t _pg_cnt; ///< Page counter - incr for each page containing part of data - u_int16_t _fid; ///< FID containing header of enqueue record - u_int64_t _rid; ///< RID of data set by enqueue operation - std::string _xid; ///< XID set by enqueue operation - u_int64_t _dequeue_rid; ///< RID of data set by dequeue operation - bool _external_rid; ///< Flag to indicate external setting of rid - - public: - data_tok(); - virtual ~data_tok(); - - inline u_int64_t id() const { return _icnt; } - inline write_state wstate() const { return _wstate; } - const char* wstate_str() const; - static const char* wstate_str(write_state wstate); - inline read_state rstate() const { return _rstate; } - const char* rstate_str() const; - static const char* rstate_str(read_state rstate); - inline bool is_writable() const { return _wstate == NONE || _wstate == ENQ_PART; } - inline bool is_enqueued() const { return _wstate == ENQ; } - inline bool is_readable() const { return _wstate == ENQ; } - inline bool is_read() const { return _rstate == READ; } - inline bool is_dequeueable() const { return _wstate == ENQ || _wstate == DEQ_PART; } - inline void set_wstate(const write_state wstate) { _wstate = wstate; } - void set_rstate(const read_state rstate); - inline std::size_t dsize() const { return _dsize; } - inline void set_dsize(std::size_t dsize) { _dsize = dsize; } - - inline u_int32_t dblocks_written() const { return _dblks_written; } - inline void incr_dblocks_written(u_int32_t dblks_written) - { _dblks_written += dblks_written; } - inline void set_dblocks_written(u_int32_t dblks_written) { _dblks_written = dblks_written; } - - inline u_int32_t dblocks_read() const { return _dblks_read; } - inline void incr_dblocks_read(u_int32_t dblks_read) { _dblks_read += dblks_read; } - inline void set_dblocks_read(u_int32_t dblks_read) { _dblks_read = dblks_read; } - - inline u_int32_t pg_cnt() const { return _pg_cnt; } - inline u_int32_t incr_pg_cnt() { return ++_pg_cnt; } - inline u_int32_t decr_pg_cnt() { assert(_pg_cnt != 0); return --_pg_cnt; } - - inline u_int16_t fid() const { return _fid; } - inline void set_fid(const u_int16_t fid) { _fid = fid; } - inline u_int64_t rid() const { return _rid; } - inline void set_rid(const u_int64_t rid) { _rid = rid; } - inline u_int64_t dequeue_rid() const {return _dequeue_rid; } - inline void set_dequeue_rid(const u_int64_t rid) { _dequeue_rid = rid; } - inline bool external_rid() const { return _external_rid; } - inline void set_external_rid(const bool external_rid) { _external_rid = external_rid; } - - inline bool has_xid() const { return !_xid.empty(); } - inline const std::string& xid() const { return _xid; } - inline void clear_xid() { _xid.clear(); } - inline void set_xid(const std::string& xid) { _xid.assign(xid); } - inline void set_xid(const void* xidp, const std::size_t xid_len) - { _xid.assign((const char*)xidp, xid_len); } - - void reset(); - - // debug aid - std::string status_str() const; - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_DATA_TOK_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/deq_hdr.h b/qpid/cpp/src/qpid/legacystore/jrnl/deq_hdr.h deleted file mode 100644 index ae7081eac1..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/deq_hdr.h +++ /dev/null @@ -1,141 +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. - * - */ - -/** - * \file deq_hdr.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::deq_hdr (dequeue record), - * used to dequeue a previously enqueued record. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_DEQ_HDR_H -#define QPID_LEGACYSTORE_JRNL_DEQ_HDR_H - -#include -#include "qpid/legacystore/jrnl/rec_hdr.h" - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for dequeue record. - * - * Struct for dequeue record. If this record has a non-zero xidsize field (i.e., there is a - * valid XID), then this header is followed by the XID of xidsize bytes and a rec_tail. If, - * on the other hand, this record has a zero xidsize (i.e., there is no XID), then the rec_tail - * is absent. - * - * Note that this record had its own rid distinct from the rid of the record it is dequeueing. - * The rid field below is the rid of the dequeue record itself; the deq-rid field is the rid of a - * previous enqueue record being dequeued by this record. - * - * Record header info in binary format (32 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+  -+
-    * |     magic     | v | e | flags |   |
-    * +---+---+---+---+---+---+---+---+   | struct hdr
-    * |              rid              |   |
-    * +---+---+---+---+---+---+---+---+  -+
-    * |            deq-rid            |
-    * +---+---+---+---+---+---+---+---+
-    * |            xidsize            |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct deq_hdr : rec_hdr - { - u_int64_t _deq_rid; ///< Record ID of dequeued record -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _xidsize; ///< XID size -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t -#endif - static const u_int16_t DEQ_HDR_TXNCMPLCOMMIT_MASK = 0x10; - - /** - * \brief Default constructor, which sets all values to 0. - */ - inline deq_hdr(): rec_hdr(), _deq_rid(0), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(0) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler0(0) -#endif - {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline deq_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const u_int64_t deq_rid, const std::size_t xidsize, const bool owi, - const bool txn_coml_commit = false): - rec_hdr(magic, version, rid, owi), _deq_rid(deq_rid), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(xidsize) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler0(0) -#endif - { set_txn_coml_commit(txn_coml_commit); } - - - inline bool is_txn_coml_commit() const { return _uflag & DEQ_HDR_TXNCMPLCOMMIT_MASK; } - - inline void set_txn_coml_commit(const bool commit) - { - _uflag = commit ? _uflag | DEQ_HDR_TXNCMPLCOMMIT_MASK : - _uflag & (~DEQ_HDR_TXNCMPLCOMMIT_MASK); - } - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(deq_hdr); } - }; - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_DEQ_HDR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.cpp deleted file mode 100644 index 270ebdd69e..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.cpp +++ /dev/null @@ -1,461 +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. - * - */ - -/** - * \file deq_rec.cpp - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::deq_rec (journal dequeue - * record) class. See comments in file deq_rec.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/deq_rec.h" - -#include -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include - -namespace mrg -{ -namespace journal -{ - -deq_rec::deq_rec(): - _deq_hdr(RHM_JDAT_DEQ_MAGIC, RHM_JDAT_VERSION, 0, 0, 0, false), - _xidp(0), - _buff(0), - _deq_tail(_deq_hdr) -{} - -deq_rec::deq_rec(const u_int64_t rid, const u_int64_t drid, const void* const xidp, - const std::size_t xidlen, const bool owi, const bool txn_coml_commit): - _deq_hdr(RHM_JDAT_DEQ_MAGIC, RHM_JDAT_VERSION, rid, drid, xidlen, owi, txn_coml_commit), - _xidp(xidp), - _buff(0), - _deq_tail(_deq_hdr) -{} - -deq_rec::~deq_rec() -{ - clean(); -} - -void -deq_rec::reset() -{ - _deq_hdr._rid = 0; - _deq_hdr.set_owi(false); - _deq_hdr.set_txn_coml_commit(false); - _deq_hdr._deq_rid = 0; - _deq_hdr._xidsize = 0; - _deq_tail._rid = 0; - _xidp = 0; - _buff = 0; -} - -void -deq_rec::reset(const u_int64_t rid, const u_int64_t drid, const void* const xidp, - const std::size_t xidlen, const bool owi, const bool txn_coml_commit) -{ - _deq_hdr._rid = rid; - _deq_hdr.set_owi(owi); - _deq_hdr.set_txn_coml_commit(txn_coml_commit); - _deq_hdr._deq_rid = drid; - _deq_hdr._xidsize = xidlen; - _deq_tail._rid = rid; - _xidp = xidp; - _buff = 0; -} - -u_int32_t -deq_rec::encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks) -{ - assert(wptr != 0); - assert(max_size_dblks > 0); - if (_xidp == 0) - assert(_deq_hdr._xidsize == 0); - - std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - std::size_t rem = max_size_dblks * JRNL_DBLK_SIZE; - std::size_t wr_cnt = 0; - if (rec_offs_dblks) // Continuation of split dequeue record (over 2 or more pages) - { - if (size_dblks(rec_size()) - rec_offs_dblks > max_size_dblks) // Further split required - { - rec_offs -= sizeof(_deq_hdr); - std::size_t wsize = _deq_hdr._xidsize > rec_offs ? _deq_hdr._xidsize - rec_offs : 0; - std::size_t wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= _deq_hdr._xidsize - wsize2; - if (rem) - { - wsize = sizeof(_deq_tail) > rec_offs ? sizeof(_deq_tail) - rec_offs : 0; - wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy((char*)wptr + wr_cnt, (char*)&_deq_tail + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= sizeof(_deq_tail) - wsize2; - } - assert(rem == 0); - assert(rec_offs == 0); - } - else // No further split required - { - rec_offs -= sizeof(_deq_hdr); - std::size_t wsize = _deq_hdr._xidsize > rec_offs ? _deq_hdr._xidsize - rec_offs : 0; - if (wsize) - { - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - } - rec_offs -= _deq_hdr._xidsize - wsize; - wsize = sizeof(_deq_tail) > rec_offs ? sizeof(_deq_tail) - rec_offs : 0; - if (wsize) - { - std::memcpy((char*)wptr + wr_cnt, (char*)&_deq_tail + rec_offs, wsize); - wr_cnt += wsize; -#ifdef RHM_CLEAN - std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - std::size_t dblk_rec_size = size_dblks(rec_size() - rec_offs) * JRNL_DBLK_SIZE; - std::memset((char*)wptr + wr_cnt, RHM_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - rec_offs -= sizeof(_deq_tail) - wsize; - assert(rec_offs == 0); - } - } - else // Start at beginning of data record - { - // Assumption: the header will always fit into the first dblk - std::memcpy(wptr, (void*)&_deq_hdr, sizeof(_deq_hdr)); - wr_cnt = sizeof(_deq_hdr); - if (size_dblks(rec_size()) > max_size_dblks) // Split required - can only occur with xid - { - std::size_t wsize; - rem -= sizeof(_deq_hdr); - if (rem) - { - wsize = rem >= _deq_hdr._xidsize ? _deq_hdr._xidsize : rem; - std::memcpy((char*)wptr + wr_cnt, _xidp, wsize); - wr_cnt += wsize; - rem -= wsize; - } - if (rem) - { - wsize = rem >= sizeof(_deq_tail) ? sizeof(_deq_tail) : rem; - std::memcpy((char*)wptr + wr_cnt, (void*)&_deq_tail, wsize); - wr_cnt += wsize; - rem -= wsize; - } - assert(rem == 0); - } - else // No split required - { - if (_deq_hdr._xidsize) - { - std::memcpy((char*)wptr + wr_cnt, _xidp, _deq_hdr._xidsize); - wr_cnt += _deq_hdr._xidsize; - std::memcpy((char*)wptr + wr_cnt, (void*)&_deq_tail, sizeof(_deq_tail)); - wr_cnt += sizeof(_deq_tail); - } -#ifdef RHM_CLEAN - std::size_t dblk_rec_size = size_dblks(rec_size()) * JRNL_DBLK_SIZE; - std::memset((char*)wptr + wr_cnt, RHM_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - } - return size_dblks(wr_cnt); -} - -u_int32_t -deq_rec::decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks) -{ - assert(rptr != 0); - assert(max_size_dblks > 0); - - std::size_t rd_cnt = 0; - if (rec_offs_dblks) // Continuation of record on new page - { - const u_int32_t hdr_xid_dblks = size_dblks(deq_hdr::size() + _deq_hdr._xidsize); - const u_int32_t hdr_xid_tail_dblks = size_dblks(deq_hdr::size() + _deq_hdr._xidsize + - rec_tail::size()); - const std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - - if (hdr_xid_tail_dblks - rec_offs_dblks <= max_size_dblks) - { - // Remainder of xid fits within this page - if (rec_offs - deq_hdr::size() < _deq_hdr._xidsize) - { - // Part of xid still outstanding, copy remainder of xid and tail - const std::size_t xid_offs = rec_offs - deq_hdr::size(); - const std::size_t xid_rem = _deq_hdr._xidsize - xid_offs; - std::memcpy((char*)_buff + xid_offs, rptr, xid_rem); - rd_cnt = xid_rem; - std::memcpy((void*)&_deq_tail, ((char*)rptr + rd_cnt), sizeof(_deq_tail)); - chk_tail(); - rd_cnt += sizeof(_deq_tail); - } - else - { - // Tail or part of tail only outstanding, complete tail - const std::size_t tail_offs = rec_offs - deq_hdr::size() - _deq_hdr._xidsize; - const std::size_t tail_rem = rec_tail::size() - tail_offs; - std::memcpy((char*)&_deq_tail + tail_offs, rptr, tail_rem); - chk_tail(); - rd_cnt = tail_rem; - } - } - else if (hdr_xid_dblks - rec_offs_dblks <= max_size_dblks) - { - // Remainder of xid fits within this page, tail split - const std::size_t xid_offs = rec_offs - deq_hdr::size(); - const std::size_t xid_rem = _deq_hdr._xidsize - xid_offs; - std::memcpy((char*)_buff + xid_offs, rptr, xid_rem); - rd_cnt += xid_rem; - const std::size_t tail_rem = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - if (tail_rem) - { - std::memcpy((void*)&_deq_tail, ((char*)rptr + xid_rem), tail_rem); - rd_cnt += tail_rem; - } - } - else - { - // Remainder of xid split - const std::size_t xid_cp_size = (max_size_dblks * JRNL_DBLK_SIZE); - std::memcpy((char*)_buff + rec_offs - deq_hdr::size(), rptr, xid_cp_size); - rd_cnt += xid_cp_size; - } - } - else // Start of record - { - // Get and check header - _deq_hdr.hdr_copy(h); - rd_cnt = sizeof(rec_hdr); - //_deq_hdr._deq_rid = *(u_int64_t*)((char*)rptr + rd_cnt); - std::memcpy((void*)&_deq_hdr._deq_rid, (char*)rptr + rd_cnt, sizeof(u_int64_t)); - rd_cnt += sizeof(u_int64_t); -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - rd_cnt += sizeof(u_int32_t); // Filler 0 -#endif - //_deq_hdr._xidsize = *(std::size_t*)((char*)rptr + rd_cnt); - std::memcpy((void*)&_deq_hdr._xidsize, (char*)rptr + rd_cnt, sizeof(std::size_t)); - rd_cnt = _deq_hdr.size(); - chk_hdr(); - if (_deq_hdr._xidsize) - { - _buff = std::malloc(_deq_hdr._xidsize); - MALLOC_CHK(_buff, "_buff", "deq_rec", "decode"); - const u_int32_t hdr_xid_dblks = size_dblks(deq_hdr::size() + _deq_hdr._xidsize); - const u_int32_t hdr_xid_tail_dblks = size_dblks(deq_hdr::size() + _deq_hdr._xidsize + - rec_tail::size()); - - // Check if record (header + xid + tail) fits within this page, we can check the - // tail before the expense of copying data to memory - if (hdr_xid_tail_dblks <= max_size_dblks) - { - // Entire header, xid and tail fits within this page - std::memcpy(_buff, (char*)rptr + rd_cnt, _deq_hdr._xidsize); - rd_cnt += _deq_hdr._xidsize; - std::memcpy((void*)&_deq_tail, (char*)rptr + rd_cnt, sizeof(_deq_tail)); - rd_cnt += sizeof(_deq_tail); - chk_tail(); - } - else if (hdr_xid_dblks <= max_size_dblks) - { - // Entire header and xid fit within this page, tail split - std::memcpy(_buff, (char*)rptr + rd_cnt, _deq_hdr._xidsize); - rd_cnt += _deq_hdr._xidsize; - const std::size_t tail_rem = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - if (tail_rem) - { - std::memcpy((void*)&_deq_tail, (char*)rptr + rd_cnt, tail_rem); - rd_cnt += tail_rem; - } - } - else - { - // Header fits within this page, xid split - const std::size_t xid_cp_size = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - std::memcpy(_buff, (char*)rptr + rd_cnt, xid_cp_size); - rd_cnt += xid_cp_size; - } - } - } - return size_dblks(rd_cnt); -} - -bool -deq_rec::rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs) -{ - if (rec_offs == 0) - { - _deq_hdr.hdr_copy(h); - ifsp->read((char*)&_deq_hdr._deq_rid, sizeof(u_int64_t)); -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - ifsp->ignore(sizeof(u_int32_t)); // _filler0 -#endif - ifsp->read((char*)&_deq_hdr._xidsize, sizeof(std::size_t)); -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - ifsp->ignore(sizeof(u_int32_t)); // _filler0 -#endif - rec_offs = sizeof(_deq_hdr); - // Read header, allocate (if req'd) for xid - if (_deq_hdr._xidsize) - { - _buff = std::malloc(_deq_hdr._xidsize); - MALLOC_CHK(_buff, "_buff", "enq_rec", "rcv_decode"); - } - } - if (rec_offs < sizeof(_deq_hdr) + _deq_hdr._xidsize) - { - // Read xid (or continue reading xid) - std::size_t offs = rec_offs - sizeof(_deq_hdr); - ifsp->read((char*)_buff + offs, _deq_hdr._xidsize - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < _deq_hdr._xidsize - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - if (rec_offs < sizeof(_deq_hdr) + - (_deq_hdr._xidsize ? _deq_hdr._xidsize + sizeof(rec_tail) : 0)) - { - // Read tail (or continue reading tail) - std::size_t offs = rec_offs - sizeof(_deq_hdr) - _deq_hdr._xidsize; - ifsp->read((char*)&_deq_tail + offs, sizeof(rec_tail) - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < sizeof(rec_tail) - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - ifsp->ignore(rec_size_dblks() * JRNL_DBLK_SIZE - rec_size()); - if (_deq_hdr._xidsize) - chk_tail(); // Throws if tail invalid or record incomplete - assert(!ifsp->fail() && !ifsp->bad()); - return true; -} - -std::size_t -deq_rec::get_xid(void** const xidpp) -{ - if (!_buff) - { - *xidpp = 0; - return 0; - } - *xidpp = _buff; - return _deq_hdr._xidsize; -} - -std::string& -deq_rec::str(std::string& str) const -{ - std::ostringstream oss; - oss << "deq_rec: m=" << _deq_hdr._magic; - oss << " v=" << (int)_deq_hdr._version; - oss << " rid=" << _deq_hdr._rid; - oss << " drid=" << _deq_hdr._deq_rid; - if (_xidp) - oss << " xid=\"" << _xidp << "\""; - str.append(oss.str()); - return str; -} - -std::size_t -deq_rec::xid_size() const -{ - return _deq_hdr._xidsize; -} - -std::size_t -deq_rec::rec_size() const -{ - return deq_hdr::size() + (_deq_hdr._xidsize ? _deq_hdr._xidsize + rec_tail::size() : 0); -} - -void -deq_rec::chk_hdr() const -{ - jrec::chk_hdr(_deq_hdr); - if (_deq_hdr._magic != RHM_JDAT_DEQ_MAGIC) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "deq magic: rid=0x" << std::setw(16) << _deq_hdr._rid; - oss << ": expected=0x" << std::setw(8) << RHM_JDAT_DEQ_MAGIC; - oss << " read=0x" << std::setw(2) << (int)_deq_hdr._magic; - throw jexception(jerrno::JERR_JREC_BADRECHDR, oss.str(), "deq_rec", "chk_hdr"); - } -} - -void -deq_rec::chk_hdr(u_int64_t rid) const -{ - chk_hdr(); - jrec::chk_rid(_deq_hdr, rid); -} - -void -deq_rec::chk_tail() const -{ - jrec::chk_tail(_deq_tail, _deq_hdr); -} - -void -deq_rec::clean() -{ - // clean up allocated memory here -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.h b/qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.h deleted file mode 100644 index d870b658da..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/deq_rec.h +++ /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. - * - */ - -/** - * \file deq_rec.h - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::deq_rec (journal dequeue - * record) class. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_DEQ_REQ_H -#define QPID_LEGACYSTORE_JRNL_DEQ_REQ_H - -namespace mrg -{ -namespace journal -{ -class deq_rec; -} -} - -#include -#include "qpid/legacystore/jrnl/deq_hdr.h" -#include "qpid/legacystore/jrnl/jrec.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \class deq_rec - * \brief Class to handle a single journal dequeue record. - */ - class deq_rec : public jrec - { - private: - deq_hdr _deq_hdr; ///< Dequeue header - const void* _xidp; ///< xid pointer for encoding (writing to disk) - void* _buff; ///< Pointer to buffer to receive data read from disk - rec_tail _deq_tail; ///< Record tail, only encoded if XID is present - - public: - // constructor used for read operations and xid will have memory allocated - deq_rec(); - // constructor used for write operations, where xid already exists - deq_rec(const u_int64_t rid, const u_int64_t drid, const void* const xidp, - const std::size_t xidlen, const bool owi, const bool txn_coml_commit); - virtual ~deq_rec(); - - // Prepare instance for use in reading data from journal - void reset(); - // Prepare instance for use in writing data to journal - void reset(const u_int64_t rid, const u_int64_t drid, const void* const xidp, - const std::size_t xidlen, const bool owi, const bool txn_coml_commit); - u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); - u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks); - // Decode used for recover - bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); - - inline bool is_txn_coml_commit() const { return _deq_hdr.is_txn_coml_commit(); } - inline u_int64_t rid() const { return _deq_hdr._rid; } - inline u_int64_t deq_rid() const { return _deq_hdr._deq_rid; } - std::size_t get_xid(void** const xidpp); - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return 0; } // This record never carries data - std::size_t xid_size() const; - std::size_t rec_size() const; - - private: - virtual void chk_hdr() const; - virtual void chk_hdr(u_int64_t rid) const; - virtual void chk_tail() const; - virtual void clean(); - }; // class deq_rec - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_DEQ_REQ_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/enq_hdr.h b/qpid/cpp/src/qpid/legacystore/jrnl/enq_hdr.h deleted file mode 100644 index 0d1e6116be..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/enq_hdr.h +++ /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. - * - */ - -/** - * \file enq_hdr.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::enq_hdr (enueue header), - * used to start an enqueue record in the journal. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_ENQ_HDR_H -#define QPID_LEGACYSTORE_JRNL_ENQ_HDR_H - -#include -#include "qpid/legacystore/jrnl/rec_hdr.h" - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for enqueue record. - * - * Struct for enqueue record. In addition to the common data, this header includes both the - * xid and data blob sizes. - * - * This header precedes all enqueue data in journal files. - * - * Record header info in binary format (32 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+  -+
-    * |     magic     | v | e | flags |   |
-    * +---+---+---+---+---+---+---+---+   | struct hdr
-    * |              rid              |   |
-    * +---+---+---+---+---+---+---+---+  -+
-    * |            xidsize            |
-    * +---+---+---+---+---+---+---+---+
-    * |             dsize             |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct enq_hdr : rec_hdr - { -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _xidsize; ///< XID size -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler1; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _dsize; ///< Record data size -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler1; ///< Little-endian filler for 32-bit size_t -#endif - static const u_int16_t ENQ_HDR_TRANSIENT_MASK = 0x10; - static const u_int16_t ENQ_HDR_EXTERNAL_MASK = 0x20; - - /** - * \brief Default constructor, which sets all values to 0. - */ - inline enq_hdr(): rec_hdr(), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(0), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif - _dsize(0) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler1(0) -#endif - {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline enq_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const std::size_t xidsize, const std::size_t dsize, const bool owi, - const bool transient = false): rec_hdr(magic, version, rid, owi), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(xidsize), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif - _dsize(dsize) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler1(0) -#endif - { set_transient(transient); } - - - inline bool is_transient() const { return _uflag & ENQ_HDR_TRANSIENT_MASK; } - - inline void set_transient(const bool transient) - { - _uflag = transient ? _uflag | ENQ_HDR_TRANSIENT_MASK : - _uflag & (~ENQ_HDR_TRANSIENT_MASK); - } - - inline bool is_external() const { return _uflag & ENQ_HDR_EXTERNAL_MASK; } - - inline void set_external(const bool external) - { - _uflag = external ? _uflag | ENQ_HDR_EXTERNAL_MASK : - _uflag & (~ENQ_HDR_EXTERNAL_MASK); - } - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(enq_hdr); } - }; - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_ENQ_HDR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/enq_map.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/enq_map.cpp deleted file mode 100644 index d024b704a7..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/enq_map.cpp +++ /dev/null @@ -1,183 +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. - * - */ - -/** - * \file enq_map.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::enq_map (enqueue map). See - * comments in file enq_map.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/enq_map.h" - -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/slock.h" -#include - - -namespace mrg -{ -namespace journal -{ - -// static return/error codes -int16_t enq_map::EMAP_DUP_RID = -3; -int16_t enq_map::EMAP_LOCKED = -2; -int16_t enq_map::EMAP_RID_NOT_FOUND = -1; -int16_t enq_map::EMAP_OK = 0; -int16_t enq_map::EMAP_FALSE = 0; -int16_t enq_map::EMAP_TRUE = 1; - -enq_map::enq_map(): - _map(), - _pfid_enq_cnt() -{} - -enq_map::~enq_map() {} - -void -enq_map::set_num_jfiles(const u_int16_t num_jfiles) -{ - _pfid_enq_cnt.resize(num_jfiles, 0); -} - - -int16_t -enq_map::insert_pfid(const u_int64_t rid, const u_int16_t pfid) -{ - return insert_pfid(rid, pfid, false); -} - -int16_t -enq_map::insert_pfid(const u_int64_t rid, const u_int16_t pfid, const bool locked) -{ - std::pair ret; - emap_data_struct rec(pfid, locked); - { - slock s(_mutex); - ret = _map.insert(emap_param(rid, rec)); - } - if (ret.second == false) - return EMAP_DUP_RID; - _pfid_enq_cnt.at(pfid)++; - return EMAP_OK; -} - -int16_t -enq_map::get_pfid(const u_int64_t rid) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - if (itr->second._lock) - return EMAP_LOCKED; - return itr->second._pfid; -} - -int16_t -enq_map::get_remove_pfid(const u_int64_t rid, const bool txn_flag) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - if (itr->second._lock && !txn_flag) // locked, but not a commit/abort - return EMAP_LOCKED; - u_int16_t pfid = itr->second._pfid; - _map.erase(itr); - _pfid_enq_cnt.at(pfid)--; - return pfid; -} - -bool -enq_map::is_enqueued(const u_int64_t rid, bool ignore_lock) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return false; - if (!ignore_lock && itr->second._lock) // locked - return false; - return true; -} - -int16_t -enq_map::lock(const u_int64_t rid) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - itr->second._lock = true; - return EMAP_OK; -} - -int16_t -enq_map::unlock(const u_int64_t rid) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - itr->second._lock = false; - return EMAP_OK; -} - -int16_t -enq_map::is_locked(const u_int64_t rid) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - return itr->second._lock ? EMAP_TRUE : EMAP_FALSE; -} - -void -enq_map::rid_list(std::vector& rv) -{ - rv.clear(); - { - slock s(_mutex); - for (emap_itr itr = _map.begin(); itr != _map.end(); itr++) - rv.push_back(itr->first); - } -} - -void -enq_map::pfid_list(std::vector& fv) -{ - fv.clear(); - { - slock s(_mutex); - for (emap_itr itr = _map.begin(); itr != _map.end(); itr++) - fv.push_back(itr->second._pfid); - } -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/enq_map.h b/qpid/cpp/src/qpid/legacystore/jrnl/enq_map.h deleted file mode 100644 index 75404afebe..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/enq_map.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file enq_map.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::enq_map (enqueue map). - * See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_ENQ_MAP_H -#define QPID_LEGACYSTORE_JRNL_ENQ_MAP_H - -namespace mrg -{ -namespace journal -{ -class enq_map; -} -} - -#include "qpid/legacystore/jrnl/jexception.h" -#include "qpid/legacystore/jrnl/smutex.h" -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class enq_map - * \brief Class for storing the physical file id (pfid) and a transaction locked flag for each enqueued - * data block using the record id (rid) as a key. This is the primary mechanism for - * deterimining the enqueue low water mark: if a pfid exists in this map, then there is - * at least one still-enqueued record in that file. (The transaction map must also be - * clear, however.) - * - * Map rids against pfid and lock status. As records are enqueued, they are added to this - * map, and as they are dequeued, they are removed. An enqueue is locked when a transactional - * dequeue is pending that has been neither committed nor aborted. - *
-    *   key      data
-    *
-    *   rid1 --- [ pfid, txn_lock ]
-    *   rid2 --- [ pfid, txn_lock ]
-    *   rid3 --- [ pfid, txn_lock ]
-    *   ...
-    * 
- */ - class enq_map - { - public: - // return/error codes - static int16_t EMAP_DUP_RID; - static int16_t EMAP_LOCKED; - static int16_t EMAP_RID_NOT_FOUND; - static int16_t EMAP_OK; - static int16_t EMAP_FALSE; - static int16_t EMAP_TRUE; - - private: - - struct emap_data_struct - { - u_int16_t _pfid; - bool _lock; - emap_data_struct(const u_int16_t pfid, const bool lock) : _pfid(pfid), _lock(lock) {} - }; - typedef std::pair emap_param; - typedef std::map emap; - typedef emap::iterator emap_itr; - - emap _map; - smutex _mutex; - std::vector _pfid_enq_cnt; - - public: - enq_map(); - virtual ~enq_map(); - - void set_num_jfiles(const u_int16_t num_jfiles); - inline u_int32_t get_enq_cnt(const u_int16_t pfid) const { return _pfid_enq_cnt.at(pfid); }; - - int16_t insert_pfid(const u_int64_t rid, const u_int16_t pfid); // 0=ok; -3=duplicate rid; - int16_t insert_pfid(const u_int64_t rid, const u_int16_t pfid, const bool locked); // 0=ok; -3=duplicate rid; - int16_t get_pfid(const u_int64_t rid); // >=0=pfid; -1=rid not found; -2=locked - int16_t get_remove_pfid(const u_int64_t rid, const bool txn_flag = false); // >=0=pfid; -1=rid not found; -2=locked - bool is_enqueued(const u_int64_t rid, bool ignore_lock = false); - int16_t lock(const u_int64_t rid); // 0=ok; -1=rid not found - int16_t unlock(const u_int64_t rid); // 0=ok; -1=rid not found - int16_t is_locked(const u_int64_t rid); // 1=true; 0=false; -1=rid not found - inline void clear() { _map.clear(); } - inline bool empty() const { return _map.empty(); } - inline u_int32_t size() const { return u_int32_t(_map.size()); } - void rid_list(std::vector& rv); - void pfid_list(std::vector& fv); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_ENQ_MAP_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.cpp deleted file mode 100644 index 94f42066a0..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.cpp +++ /dev/null @@ -1,640 +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. - * - */ - -/** - * \file enq_rec.cpp - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::enq_rec (journal enqueue - * record) class. See comments in file enq_rec.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/enq_rec.h" - -#include -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include - -namespace mrg -{ -namespace journal -{ - -// Constructor used for read operations, where buf contains preallocated space to receive data. -enq_rec::enq_rec(): - jrec(), // superclass - _enq_hdr(RHM_JDAT_ENQ_MAGIC, RHM_JDAT_VERSION, 0, 0, 0, false, false), - _xidp(0), - _data(0), - _buff(0), - _enq_tail(_enq_hdr) -{} - -// Constructor used for transactional write operations, where dbuf contains data to be written. -enq_rec::enq_rec(const u_int64_t rid, const void* const dbuf, const std::size_t dlen, - const void* const xidp, const std::size_t xidlen, const bool owi, const bool transient): - jrec(), // superclass - _enq_hdr(RHM_JDAT_ENQ_MAGIC, RHM_JDAT_VERSION, rid, xidlen, dlen, owi, transient), - _xidp(xidp), - _data(dbuf), - _buff(0), - _enq_tail(_enq_hdr) -{} - -enq_rec::~enq_rec() -{ - clean(); -} - -// Prepare instance for use in reading data from journal, where buf contains preallocated space -// to receive data. -void -enq_rec::reset() -{ - _enq_hdr._rid = 0; - _enq_hdr.set_owi(false); - _enq_hdr.set_transient(false); - _enq_hdr._xidsize = 0; - _enq_hdr._dsize = 0; - _xidp = 0; - _data = 0; - _buff = 0; - _enq_tail._rid = 0; -} - -// Prepare instance for use in writing transactional data to journal, where dbuf contains data to -// be written. -void -enq_rec::reset(const u_int64_t rid, const void* const dbuf, const std::size_t dlen, - const void* const xidp, const std::size_t xidlen, const bool owi, const bool transient, - const bool external) -{ - _enq_hdr._rid = rid; - _enq_hdr.set_owi(owi); - _enq_hdr.set_transient(transient); - _enq_hdr.set_external(external); - _enq_hdr._xidsize = xidlen; - _enq_hdr._dsize = dlen; - _xidp = xidp; - _data = dbuf; - _buff = 0; - _enq_tail._rid = rid; -} - -u_int32_t -enq_rec::encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks) -{ - assert(wptr != 0); - assert(max_size_dblks > 0); - if (_xidp == 0) - assert(_enq_hdr._xidsize == 0); - - std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - std::size_t rem = max_size_dblks * JRNL_DBLK_SIZE; - std::size_t wr_cnt = 0; - if (rec_offs_dblks) // Continuation of split data record (over 2 or more pages) - { - if (size_dblks(rec_size()) - rec_offs_dblks > max_size_dblks) // Further split required - { - rec_offs -= sizeof(_enq_hdr); - std::size_t wsize = _enq_hdr._xidsize > rec_offs ? _enq_hdr._xidsize - rec_offs : 0; - std::size_t wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt = wsize; - rem -= wsize; - } - rec_offs -= _enq_hdr._xidsize - wsize2; - if (rem && !_enq_hdr.is_external()) - { - wsize = _enq_hdr._dsize > rec_offs ? _enq_hdr._dsize - rec_offs : 0; - wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy((char*)wptr + wr_cnt, (const char*)_data + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= _enq_hdr._dsize - wsize2; - } - if (rem) - { - wsize = sizeof(_enq_tail) > rec_offs ? sizeof(_enq_tail) - rec_offs : 0; - wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy((char*)wptr + wr_cnt, (char*)&_enq_tail + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= sizeof(_enq_tail) - wsize2; - } - assert(rem == 0); - assert(rec_offs == 0); - } - else // No further split required - { - rec_offs -= sizeof(_enq_hdr); - std::size_t wsize = _enq_hdr._xidsize > rec_offs ? _enq_hdr._xidsize - rec_offs : 0; - if (wsize) - { - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - } - rec_offs -= _enq_hdr._xidsize - wsize; - wsize = _enq_hdr._dsize > rec_offs ? _enq_hdr._dsize - rec_offs : 0; - if (wsize && !_enq_hdr.is_external()) - { - std::memcpy((char*)wptr + wr_cnt, (const char*)_data + rec_offs, wsize); - wr_cnt += wsize; - } - rec_offs -= _enq_hdr._dsize - wsize; - wsize = sizeof(_enq_tail) > rec_offs ? sizeof(_enq_tail) - rec_offs : 0; - if (wsize) - { - std::memcpy((char*)wptr + wr_cnt, (char*)&_enq_tail + rec_offs, wsize); - wr_cnt += wsize; -#ifdef RHM_CLEAN - std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - std::size_t dblk_rec_size = size_dblks(rec_size() - rec_offs) * JRNL_DBLK_SIZE; - std::memset((char*)wptr + wr_cnt, RHM_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - rec_offs -= sizeof(_enq_tail) - wsize; - assert(rec_offs == 0); - } - } - else // Start at beginning of data record - { - // Assumption: the header will always fit into the first dblk - std::memcpy(wptr, (void*)&_enq_hdr, sizeof(_enq_hdr)); - wr_cnt = sizeof(_enq_hdr); - if (size_dblks(rec_size()) > max_size_dblks) // Split required - { - std::size_t wsize; - rem -= sizeof(_enq_hdr); - if (rem) - { - wsize = rem >= _enq_hdr._xidsize ? _enq_hdr._xidsize : rem; - std::memcpy((char*)wptr + wr_cnt, _xidp, wsize); - wr_cnt += wsize; - rem -= wsize; - } - if (rem && !_enq_hdr.is_external()) - { - wsize = rem >= _enq_hdr._dsize ? _enq_hdr._dsize : rem; - std::memcpy((char*)wptr + wr_cnt, _data, wsize); - wr_cnt += wsize; - rem -= wsize; - } - if (rem) - { - wsize = rem >= sizeof(_enq_tail) ? sizeof(_enq_tail) : rem; - std::memcpy((char*)wptr + wr_cnt, (void*)&_enq_tail, wsize); - wr_cnt += wsize; - rem -= wsize; - } - assert(rem == 0); - } - else // No split required - { - if (_enq_hdr._xidsize) - { - std::memcpy((char*)wptr + wr_cnt, _xidp, _enq_hdr._xidsize); - wr_cnt += _enq_hdr._xidsize; - } - if (!_enq_hdr.is_external()) - { - std::memcpy((char*)wptr + wr_cnt, _data, _enq_hdr._dsize); - wr_cnt += _enq_hdr._dsize; - } - std::memcpy((char*)wptr + wr_cnt, (void*)&_enq_tail, sizeof(_enq_tail)); - wr_cnt += sizeof(_enq_tail); -#ifdef RHM_CLEAN - std::size_t dblk_rec_size = size_dblks(rec_size()) * JRNL_DBLK_SIZE; - std::memset((char*)wptr + wr_cnt, RHM_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - } - return size_dblks(wr_cnt); -} - -u_int32_t -enq_rec::decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks) -{ - assert(rptr != 0); - assert(max_size_dblks > 0); - - std::size_t rd_cnt = 0; - if (rec_offs_dblks) // Continuation of record on new page - { - const u_int32_t hdr_xid_data_size = enq_hdr::size() + _enq_hdr._xidsize + - (_enq_hdr.is_external() ? 0 : _enq_hdr._dsize); - const u_int32_t hdr_xid_data_tail_size = hdr_xid_data_size + rec_tail::size(); - const u_int32_t hdr_data_dblks = size_dblks(hdr_xid_data_size); - const u_int32_t hdr_tail_dblks = size_dblks(hdr_xid_data_tail_size); - const std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - const std::size_t offs = rec_offs - enq_hdr::size(); - - if (hdr_tail_dblks - rec_offs_dblks <= max_size_dblks) - { - // Remainder of record fits within this page - if (offs < _enq_hdr._xidsize) - { - // some XID still outstanding, copy remainder of XID, data and tail - const std::size_t rem = _enq_hdr._xidsize + _enq_hdr._dsize - offs; - std::memcpy((char*)_buff + offs, rptr, rem); - rd_cnt += rem; - std::memcpy((void*)&_enq_tail, ((char*)rptr + rd_cnt), sizeof(_enq_tail)); - chk_tail(); - rd_cnt += sizeof(_enq_tail); - } - else if (offs < _enq_hdr._xidsize + _enq_hdr._dsize && !_enq_hdr.is_external()) - { - // some data still outstanding, copy remainder of data and tail - const std::size_t data_offs = offs - _enq_hdr._xidsize; - const std::size_t data_rem = _enq_hdr._dsize - data_offs; - std::memcpy((char*)_buff + offs, rptr, data_rem); - rd_cnt += data_rem; - std::memcpy((void*)&_enq_tail, ((char*)rptr + rd_cnt), sizeof(_enq_tail)); - chk_tail(); - rd_cnt += sizeof(_enq_tail); - } - else - { - // Tail or part of tail only outstanding, complete tail - const std::size_t tail_offs = rec_offs - enq_hdr::size() - _enq_hdr._xidsize - - _enq_hdr._dsize; - const std::size_t tail_rem = rec_tail::size() - tail_offs; - std::memcpy((char*)&_enq_tail + tail_offs, rptr, tail_rem); - chk_tail(); - rd_cnt = tail_rem; - } - } - else if (hdr_data_dblks - rec_offs_dblks <= max_size_dblks) - { - // Remainder of xid & data fits within this page; tail split - - /* - * TODO: This section needs revision. Since it is known that the end of the page falls within the - * tail record, it is only necessary to write from the current offset to the end of the page under - * all circumstances. The multiple if/else combinations may be eliminated, as well as one memcpy() - * operation. - * - * Also note that Coverity has detected a possible memory overwrite in this block. It occurs if - * both the following two if() stmsts (numbered) are false. With rd_cnt = 0, this would result in - * the value of tail_rem > sizeof(tail_rec). Practically, this could only happen if the start and - * end of a page both fall within the same tail record, in which case the tail would have to be - * (much!) larger. However, the logic here does not account for this possibility. - * - * If the optimization above is undertaken, this code would probably be removed. - */ - if (offs < _enq_hdr._xidsize) // 1 - { - // some XID still outstanding, copy remainder of XID and data - const std::size_t rem = _enq_hdr._xidsize + _enq_hdr._dsize - offs; - std::memcpy((char*)_buff + offs, rptr, rem); - rd_cnt += rem; - } - else if (offs < _enq_hdr._xidsize + _enq_hdr._dsize && !_enq_hdr.is_external()) // 2 - { - // some data still outstanding, copy remainder of data - const std::size_t data_offs = offs - _enq_hdr._xidsize; - const std::size_t data_rem = _enq_hdr._dsize - data_offs; - std::memcpy((char*)_buff + offs, rptr, data_rem); - rd_cnt += data_rem; - } - const std::size_t tail_rem = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - if (tail_rem) - { - std::memcpy((void*)&_enq_tail, ((char*)rptr + rd_cnt), tail_rem); - rd_cnt += tail_rem; - } - } - else - { - // Since xid and data are contiguous, both fit within current page - copy whole page - const std::size_t data_cp_size = (max_size_dblks * JRNL_DBLK_SIZE); - std::memcpy((char*)_buff + offs, rptr, data_cp_size); - rd_cnt += data_cp_size; - } - } - else // Start of record - { - // Get and check header - _enq_hdr.hdr_copy(h); - rd_cnt = sizeof(rec_hdr); -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - rd_cnt += sizeof(u_int32_t); // Filler 0 -#endif - //_enq_hdr._xidsize = *(std::size_t*)((char*)rptr + rd_cnt); - std::memcpy((void*)&_enq_hdr._xidsize, (char*)rptr + rd_cnt, sizeof(std::size_t)); - rd_cnt += sizeof(std::size_t); -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - rd_cnt += sizeof(u_int32_t); // Filler 0 -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - rd_cnt += sizeof(u_int32_t); // Filler 1 -#endif - //_enq_hdr._dsize = *(std::size_t*)((char*)rptr + rd_cnt); - std::memcpy((void*)&_enq_hdr._dsize, (char*)rptr + rd_cnt, sizeof(std::size_t)); - rd_cnt = _enq_hdr.size(); - chk_hdr(); - if (_enq_hdr._xidsize + (_enq_hdr.is_external() ? 0 : _enq_hdr._dsize)) - { - _buff = std::malloc(_enq_hdr._xidsize + (_enq_hdr.is_external() ? 0 : _enq_hdr._dsize)); - MALLOC_CHK(_buff, "_buff", "enq_rec", "decode"); - - const u_int32_t hdr_xid_size = enq_hdr::size() + _enq_hdr._xidsize; - const u_int32_t hdr_xid_data_size = hdr_xid_size + (_enq_hdr.is_external() ? 0 : _enq_hdr._dsize); - const u_int32_t hdr_xid_data_tail_size = hdr_xid_data_size + rec_tail::size(); - const u_int32_t hdr_xid_dblks = size_dblks(hdr_xid_size); - const u_int32_t hdr_data_dblks = size_dblks(hdr_xid_data_size); - const u_int32_t hdr_tail_dblks = size_dblks(hdr_xid_data_tail_size); - // Check if record (header + data + tail) fits within this page, we can check the - // tail before the expense of copying data to memory - if (hdr_tail_dblks <= max_size_dblks) - { - // Header, xid, data and tail fits within this page - if (_enq_hdr._xidsize) - { - std::memcpy(_buff, (char*)rptr + rd_cnt, _enq_hdr._xidsize); - rd_cnt += _enq_hdr._xidsize; - } - if (_enq_hdr._dsize && !_enq_hdr.is_external()) - { - std::memcpy((char*)_buff + _enq_hdr._xidsize, (char*)rptr + rd_cnt, - _enq_hdr._dsize); - rd_cnt += _enq_hdr._dsize; - } - std::memcpy((void*)&_enq_tail, (char*)rptr + rd_cnt, sizeof(_enq_tail)); - chk_tail(); - rd_cnt += sizeof(_enq_tail); - } - else if (hdr_data_dblks <= max_size_dblks) - { - // Header, xid and data fit within this page, tail split or separated - if (_enq_hdr._xidsize) - { - std::memcpy(_buff, (char*)rptr + rd_cnt, _enq_hdr._xidsize); - rd_cnt += _enq_hdr._xidsize; - } - if (_enq_hdr._dsize && !_enq_hdr.is_external()) - { - std::memcpy((char*)_buff + _enq_hdr._xidsize, (char*)rptr + rd_cnt, - _enq_hdr._dsize); - rd_cnt += _enq_hdr._dsize; - } - const std::size_t tail_rem = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - if (tail_rem) - { - std::memcpy((void*)&_enq_tail, (char*)rptr + rd_cnt, tail_rem); - rd_cnt += tail_rem; - } - } - else if (hdr_xid_dblks <= max_size_dblks) - { - // Header and xid fits within this page, data split or separated - if (_enq_hdr._xidsize) - { - std::memcpy(_buff, (char*)rptr + rd_cnt, _enq_hdr._xidsize); - rd_cnt += _enq_hdr._xidsize; - } - if (_enq_hdr._dsize && !_enq_hdr.is_external()) - { - const std::size_t data_cp_size = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - std::memcpy((char*)_buff + _enq_hdr._xidsize, (char*)rptr + rd_cnt, data_cp_size); - rd_cnt += data_cp_size; - } - } - else - { - // Header fits within this page, xid split or separated - const std::size_t data_cp_size = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - std::memcpy(_buff, (char*)rptr + rd_cnt, data_cp_size); - rd_cnt += data_cp_size; - } - } - } - return size_dblks(rd_cnt); -} - -bool -enq_rec::rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs) -{ - if (rec_offs == 0) - { - // Read header, allocate (if req'd) for xid - _enq_hdr.hdr_copy(h); -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - ifsp->ignore(sizeof(u_int32_t)); // _filler0 -#endif - ifsp->read((char*)&_enq_hdr._xidsize, sizeof(std::size_t)); -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - ifsp->ignore(sizeof(u_int32_t)); // _filler0 -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - ifsp->ignore(sizeof(u_int32_t)); // _filler1 -#endif - ifsp->read((char*)&_enq_hdr._dsize, sizeof(std::size_t)); -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - ifsp->ignore(sizeof(u_int32_t)); // _filler1 -#endif - rec_offs = sizeof(_enq_hdr); - if (_enq_hdr._xidsize) - { - _buff = std::malloc(_enq_hdr._xidsize); - MALLOC_CHK(_buff, "_buff", "enq_rec", "rcv_decode"); - } - } - if (rec_offs < sizeof(_enq_hdr) + _enq_hdr._xidsize) - { - // Read xid (or continue reading xid) - std::size_t offs = rec_offs - sizeof(_enq_hdr); - ifsp->read((char*)_buff + offs, _enq_hdr._xidsize - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < _enq_hdr._xidsize - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - if (!_enq_hdr.is_external()) - { - if (rec_offs < sizeof(_enq_hdr) + _enq_hdr._xidsize + _enq_hdr._dsize) - { - // Ignore data (or continue ignoring data) - std::size_t offs = rec_offs - sizeof(_enq_hdr) - _enq_hdr._xidsize; - ifsp->ignore(_enq_hdr._dsize - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < _enq_hdr._dsize - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - } - if (rec_offs < sizeof(_enq_hdr) + _enq_hdr._xidsize + - (_enq_hdr.is_external() ? 0 : _enq_hdr._dsize) + sizeof(rec_tail)) - { - // Read tail (or continue reading tail) - std::size_t offs = rec_offs - sizeof(_enq_hdr) - _enq_hdr._xidsize; - if (!_enq_hdr.is_external()) - offs -= _enq_hdr._dsize; - ifsp->read((char*)&_enq_tail + offs, sizeof(rec_tail) - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < sizeof(rec_tail) - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - ifsp->ignore(rec_size_dblks() * JRNL_DBLK_SIZE - rec_size()); - chk_tail(); // Throws if tail invalid or record incomplete - assert(!ifsp->fail() && !ifsp->bad()); - return true; -} - -std::size_t -enq_rec::get_xid(void** const xidpp) -{ - if (!_buff || !_enq_hdr._xidsize) - { - *xidpp = 0; - return 0; - } - *xidpp = _buff; - return _enq_hdr._xidsize; -} - -std::size_t -enq_rec::get_data(void** const datapp) -{ - if (!_buff) - { - *datapp = 0; - return 0; - } - if (_enq_hdr.is_external()) - *datapp = 0; - else - *datapp = (void*)((char*)_buff + _enq_hdr._xidsize); - return _enq_hdr._dsize; -} - -std::string& -enq_rec::str(std::string& str) const -{ - std::ostringstream oss; - oss << "enq_rec: m=" << _enq_hdr._magic; - oss << " v=" << (int)_enq_hdr._version; - oss << " rid=" << _enq_hdr._rid; - if (_xidp) - oss << " xid=\"" << _xidp << "\""; - oss << " len=" << _enq_hdr._dsize; - str.append(oss.str()); - return str; -} - -std::size_t -enq_rec::rec_size() const -{ - return rec_size(_enq_hdr._xidsize, _enq_hdr._dsize, _enq_hdr.is_external()); -} - -std::size_t -enq_rec::rec_size(const std::size_t xidsize, const std::size_t dsize, const bool external) -{ - if (external) - return enq_hdr::size() + xidsize + rec_tail::size(); - return enq_hdr::size() + xidsize + dsize + rec_tail::size(); -} - -void -enq_rec::set_rid(const u_int64_t rid) -{ - _enq_hdr._rid = rid; - _enq_tail._rid = rid; -} - -void -enq_rec::chk_hdr() const -{ - jrec::chk_hdr(_enq_hdr); - if (_enq_hdr._magic != RHM_JDAT_ENQ_MAGIC) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "enq magic: rid=0x" << std::setw(16) << _enq_hdr._rid; - oss << ": expected=0x" << std::setw(8) << RHM_JDAT_ENQ_MAGIC; - oss << " read=0x" << std::setw(2) << (int)_enq_hdr._magic; - throw jexception(jerrno::JERR_JREC_BADRECHDR, oss.str(), "enq_rec", "chk_hdr"); - } -} - -void -enq_rec::chk_hdr(u_int64_t rid) const -{ - chk_hdr(); - jrec::chk_rid(_enq_hdr, rid); -} - -void -enq_rec::chk_tail() const -{ - jrec::chk_tail(_enq_tail, _enq_hdr); -} - -void -enq_rec::clean() -{ - // clean up allocated memory here -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.h b/qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.h deleted file mode 100644 index 805a96a1aa..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/enq_rec.h +++ /dev/null @@ -1,116 +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. - * - */ - -/** - * \file enq_rec.h - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::enq_rec (journal enqueue - * record) class. See class documentation for details. - */ - -#ifndef QPID_LEGACYSTORE_JRNL_ENQ_REC_H -#define QPID_LEGACYSTORE_JRNL_ENQ_REC_H - -namespace mrg -{ -namespace journal -{ -class enq_rec; -} -} - -#include -#include "qpid/legacystore/jrnl/enq_hdr.h" -#include "qpid/legacystore/jrnl/jrec.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \class enq_rec - * \brief Class to handle a single journal enqueue record. - */ - class enq_rec : public jrec - { - private: - enq_hdr _enq_hdr; - const void* _xidp; ///< xid pointer for encoding (for writing to disk) - const void* _data; ///< Pointer to data to be written to disk - void* _buff; ///< Pointer to buffer to receive data read from disk - rec_tail _enq_tail; - - public: - /** - * \brief Constructor used for read operations. - */ - enq_rec(); - - /** - * \brief Constructor used for write operations, where mbuf contains data to be written. - */ - enq_rec(const u_int64_t rid, const void* const dbuf, const std::size_t dlen, - const void* const xidp, const std::size_t xidlen, const bool owi, const bool transient); - - /** - * \brief Destructor - */ - virtual ~enq_rec(); - - // Prepare instance for use in reading data from journal, xid and data will be allocated - void reset(); - // Prepare instance for use in writing data to journal - void reset(const u_int64_t rid, const void* const dbuf, const std::size_t dlen, - const void* const xidp, const std::size_t xidlen, const bool owi, const bool transient, - const bool external); - - u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); - u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks); - // Decode used for recover - bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); - - std::size_t get_xid(void** const xidpp); - std::size_t get_data(void** const datapp); - inline bool is_transient() const { return _enq_hdr.is_transient(); } - inline bool is_external() const { return _enq_hdr.is_external(); } - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return _enq_hdr._dsize; } - inline std::size_t xid_size() const { return _enq_hdr._xidsize; } - std::size_t rec_size() const; - static std::size_t rec_size(const std::size_t xidsize, const std::size_t dsize, const bool external); - inline u_int64_t rid() const { return _enq_hdr._rid; } - void set_rid(const u_int64_t rid); - - private: - void chk_hdr() const; - void chk_hdr(u_int64_t rid) const; - void chk_tail() const; - virtual void clean(); - }; // class enq_rec - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_ENQ_REC_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/enums.h b/qpid/cpp/src/qpid/legacystore/jrnl/enums.h deleted file mode 100644 index 169a13fa4d..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/enums.h +++ /dev/null @@ -1,108 +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. - * - */ - -/** - * \file enums.h - * - * Qpid asynchronous store plugin library - * - * File containing definitions for namespace mrg::journal enums. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_ENUMS_H -#define QPID_LEGACYSTORE_JRNL_ENUMS_H - -namespace mrg -{ -namespace journal -{ - - // TODO: Change this to flags, as multiple of these conditions may exist simultaneously - /** - * \brief Enumeration of possilbe return states from journal read and write operations. - */ - enum _iores - { - RHM_IORES_SUCCESS = 0, ///< Success: IO operation completed noramlly. - RHM_IORES_PAGE_AIOWAIT, ///< IO operation suspended - next page is waiting for AIO. - RHM_IORES_FILE_AIOWAIT, ///< IO operation suspended - next file is waiting for AIO. - RHM_IORES_EMPTY, ///< During read operations, nothing further is available to read. - RHM_IORES_RCINVALID, ///< Read page cache is invalid (ie obsolete or uninitialized) - RHM_IORES_ENQCAPTHRESH, ///< Enqueue capacity threshold (limit) reached. - RHM_IORES_FULL, ///< During write operations, the journal files are full. - RHM_IORES_BUSY, ///< Another blocking operation is in progress. - RHM_IORES_TXPENDING, ///< Operation blocked by pending transaction. - RHM_IORES_NOTIMPL ///< Function is not yet implemented. - }; - typedef _iores iores; - - static inline const char* iores_str(iores res) - { - switch (res) - { - case RHM_IORES_SUCCESS: return "RHM_IORES_SUCCESS"; - case RHM_IORES_PAGE_AIOWAIT: return "RHM_IORES_PAGE_AIOWAIT"; - case RHM_IORES_FILE_AIOWAIT: return "RHM_IORES_FILE_AIOWAIT"; - case RHM_IORES_EMPTY: return "RHM_IORES_EMPTY"; - case RHM_IORES_RCINVALID: return "RHM_IORES_RCINVALID"; - case RHM_IORES_ENQCAPTHRESH: return "RHM_IORES_ENQCAPTHRESH"; - case RHM_IORES_FULL: return "RHM_IORES_FULL"; - case RHM_IORES_BUSY: return "RHM_IORES_BUSY"; - case RHM_IORES_TXPENDING: return "RHM_IORES_TXPENDING"; - case RHM_IORES_NOTIMPL: return "RHM_IORES_NOTIMPL"; - } - return ""; - } - - enum _log_level - { - LOG_TRACE = 0, - LOG_DEBUG, - LOG_INFO, - LOG_NOTICE, - LOG_WARN, - LOG_ERROR, - LOG_CRITICAL - }; - typedef _log_level log_level; - - static inline const char* log_level_str(log_level ll) - { - switch (ll) - { - case LOG_TRACE: return "TRACE"; - case LOG_DEBUG: return "DEBUG"; - case LOG_INFO: return "INFO"; - case LOG_NOTICE: return "NOTICE"; - case LOG_WARN: return "WARN"; - case LOG_ERROR: return "ERROR"; - case LOG_CRITICAL: return "CRITICAL"; - } - return ""; - } - - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_ENUMS_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/fcntl.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/fcntl.cpp deleted file mode 100644 index fbb176667e..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/fcntl.cpp +++ /dev/null @@ -1,375 +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. - * - */ - -/** - * \file fcntl.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::fcntl (non-logging file - * handle), used for controlling journal log files. See comments in file - * fcntl.h for details. - */ - -#include "qpid/legacystore/jrnl/fcntl.h" - -#include -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include -#include - -namespace mrg -{ -namespace journal -{ - -fcntl::fcntl(const std::string& fbasename, const u_int16_t pfid, const u_int16_t lfid, const u_int32_t jfsize_sblks, - const rcvdat* const ro): - _fname(), - _pfid(pfid), - _lfid(lfid), - _ffull_dblks(JRNL_SBLK_SIZE * (jfsize_sblks + 1)), - _wr_fh(-1), - _rec_enqcnt(0), - _rd_subm_cnt_dblks(0), - _rd_cmpl_cnt_dblks(0), - _wr_subm_cnt_dblks(0), - _wr_cmpl_cnt_dblks(0), - _aio_cnt(0), - _fhdr_wr_aio_outstanding(false) -{ - initialize(fbasename, pfid, lfid, jfsize_sblks, ro); - open_wr_fh(); -} - -fcntl::~fcntl() -{ - close_wr_fh(); -} - -bool -fcntl::reset(const rcvdat* const ro) -{ - rd_reset(); - return wr_reset(ro); -} - -void -fcntl::rd_reset() -{ - _rd_subm_cnt_dblks = 0; - _rd_cmpl_cnt_dblks = 0; -} - -bool -fcntl::wr_reset(const rcvdat* const ro) -{ - if (ro) - { - if (!ro->_jempty) - { - if (ro->_lfid == _pfid) - { - _wr_subm_cnt_dblks = ro->_eo/JRNL_DBLK_SIZE; - _wr_cmpl_cnt_dblks = ro->_eo/JRNL_DBLK_SIZE; - } - else - { - _wr_subm_cnt_dblks = _ffull_dblks; - _wr_cmpl_cnt_dblks = _ffull_dblks; - } - _rec_enqcnt = ro->_enq_cnt_list[_pfid]; - return true; - } - } - // Journal overflow test - checks if the file to be reset still contains enqueued records - // or outstanding aios - if (_rec_enqcnt || _aio_cnt) - return false; - _wr_subm_cnt_dblks = 0; - _wr_cmpl_cnt_dblks = 0; - return true; -} - -int -fcntl::open_wr_fh() -{ - if (_wr_fh < 0) - { - _wr_fh = ::open(_fname.c_str(), O_WRONLY | O_DIRECT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // 0644 -rw-r--r-- - if (_wr_fh < 0) - { - std::ostringstream oss; - oss << "pfid=" << _pfid << " lfid=" << _lfid << " file=\"" << _fname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_FCNTL_OPENWR, oss.str(), "fcntl", "open_fh"); - } - } - return _wr_fh; -} - -void -fcntl::close_wr_fh() -{ - if (_wr_fh >= 0) - { - ::close(_wr_fh); - _wr_fh = -1; - } -} - -u_int32_t -fcntl::add_enqcnt(u_int32_t a) -{ - _rec_enqcnt += a; - return _rec_enqcnt; -} - -u_int32_t -fcntl::decr_enqcnt() -{ - if (_rec_enqcnt == 0) - { - std::ostringstream oss; - oss << "pfid=" << _pfid << " lfid=" << _lfid; - throw jexception(jerrno::JERR__UNDERFLOW, oss.str(), "fcntl", "decr_enqcnt"); - } - return --_rec_enqcnt; -} - -u_int32_t -fcntl::subtr_enqcnt(u_int32_t s) -{ - if (_rec_enqcnt < s) - { - std::ostringstream oss; - oss << "pfid=" << _pfid << " lfid=" << _lfid << " rec_enqcnt=" << _rec_enqcnt << " decr=" << s; - throw jexception(jerrno::JERR__UNDERFLOW, oss.str(), "fcntl", "subtr_enqcnt"); - } - _rec_enqcnt -= s; - return _rec_enqcnt; -} - -u_int32_t -fcntl::add_rd_subm_cnt_dblks(u_int32_t a) -{ - if (_rd_subm_cnt_dblks + a > _wr_subm_cnt_dblks) - { - std::ostringstream oss; - oss << "pfid=" << _pfid << " lfid=" << _lfid << " rd_subm_cnt_dblks=" << _rd_subm_cnt_dblks << " incr=" << a; - oss << " wr_subm_cnt_dblks=" << _wr_subm_cnt_dblks; - throw jexception(jerrno::JERR_FCNTL_RDOFFSOVFL, oss.str(), "fcntl", "add_rd_subm_cnt_dblks"); - } - _rd_subm_cnt_dblks += a; - return _rd_subm_cnt_dblks; -} - -u_int32_t -fcntl::add_rd_cmpl_cnt_dblks(u_int32_t a) -{ - if (_rd_cmpl_cnt_dblks + a > _rd_subm_cnt_dblks) - { - std::ostringstream oss; - oss << "pfid=" << _pfid << " lfid=" << _lfid << " rd_cmpl_cnt_dblks=" << _rd_cmpl_cnt_dblks << " incr=" << a; - oss << " rd_subm_cnt_dblks=" << _rd_subm_cnt_dblks; - throw jexception(jerrno::JERR_FCNTL_CMPLOFFSOVFL, oss.str(), "fcntl", "add_rd_cmpl_cnt_dblks"); - } - _rd_cmpl_cnt_dblks += a; - return _rd_cmpl_cnt_dblks; -} - -u_int32_t -fcntl::add_wr_subm_cnt_dblks(u_int32_t a) -{ - if (_wr_subm_cnt_dblks + a > _ffull_dblks) // Allow for file header - { - std::ostringstream oss; - oss << "pfid=" << _pfid << " lfid=" << _lfid << " wr_subm_cnt_dblks=" << _wr_subm_cnt_dblks << " incr=" << a; - oss << " fsize=" << _ffull_dblks << " dblks"; - throw jexception(jerrno::JERR_FCNTL_FILEOFFSOVFL, oss.str(), "fcntl", "add_wr_subm_cnt_dblks"); - } - _wr_subm_cnt_dblks += a; - return _wr_subm_cnt_dblks; -} - -u_int32_t -fcntl::add_wr_cmpl_cnt_dblks(u_int32_t a) -{ - if (_wr_cmpl_cnt_dblks + a > _wr_subm_cnt_dblks) - { - std::ostringstream oss; - oss << "pfid=" << _pfid << " lfid=" << _lfid << " wr_cmpl_cnt_dblks=" << _wr_cmpl_cnt_dblks << " incr=" << a; - oss << " wr_subm_cnt_dblks=" << _wr_subm_cnt_dblks; - throw jexception(jerrno::JERR_FCNTL_CMPLOFFSOVFL, oss.str(), "fcntl", "add_wr_cmpl_cnt_dblks"); - } - _wr_cmpl_cnt_dblks += a; - return _wr_cmpl_cnt_dblks; -} - -u_int16_t -fcntl::decr_aio_cnt() -{ - if(_aio_cnt == 0) - { - std::ostringstream oss; - oss << "pfid=" << _pfid << " lfid=" << _lfid << " Decremented aio_cnt to below zero"; - throw jexception(jerrno::JERR__UNDERFLOW, oss.str(), "fcntl", "decr_aio_cnt"); - } - return --_aio_cnt; -} - -// Debug function -const std::string -fcntl::status_str() const -{ - std::ostringstream oss; - oss << "pfid=" << _pfid << " ws=" << _wr_subm_cnt_dblks << " wc=" << _wr_cmpl_cnt_dblks; - oss << " rs=" << _rd_subm_cnt_dblks << " rc=" << _rd_cmpl_cnt_dblks; - oss << " ec=" << _rec_enqcnt << " ac=" << _aio_cnt; - return oss.str(); -} - -// Protected functions - -void -fcntl::initialize(const std::string& fbasename, const u_int16_t pfid, const u_int16_t lfid, const u_int32_t jfsize_sblks, - const rcvdat* const ro) -{ - _pfid = pfid; - _lfid = lfid; - _fname = filename(fbasename, pfid); - -#ifdef RHM_JOWRITE - // In test mode, only create file if it does not exist - struct stat s; - if (::stat(_fname.c_str(), &s)) - { -#endif - if (ro) // Recovery initialization: set counters only - { - if (!ro->_jempty) - { - // For last file only, set write counters to end of last record (the - // continuation point); for all others, set to eof. - if (ro->_lfid == _pfid) - { - _wr_subm_cnt_dblks = ro->_eo/JRNL_DBLK_SIZE; - _wr_cmpl_cnt_dblks = ro->_eo/JRNL_DBLK_SIZE; - } - else - { - _wr_subm_cnt_dblks = _ffull_dblks; - _wr_cmpl_cnt_dblks = _ffull_dblks; - } - // Set the number of enqueued records for this file. - _rec_enqcnt = ro->_enq_cnt_list[_pfid]; - } - } - else // Normal initialization: create empty journal files - create_jfile(jfsize_sblks); -#ifdef RHM_JOWRITE - } -#endif -} - -std::string -fcntl::filename(const std::string& fbasename, const u_int16_t pfid) -{ - std::ostringstream oss; - oss << fbasename << "."; - oss << std::setw(4) << std::setfill('0') << std::hex << pfid; - oss << "." << JRNL_DATA_EXTENSION; - return oss.str(); -} - -void -fcntl::clean_file(const u_int32_t jfsize_sblks) -{ - // NOTE: The journal file size is always one sblock bigger than the specified journal - // file size, which is the data content size. The extra block is for the journal file - // header which precedes all data on each file and is exactly one sblock in size. - u_int32_t nsblks = jfsize_sblks + 1; - - // TODO - look at more efficient alternatives to allocating a null block: - // 1. mmap() against /dev/zero, but can alignment for O_DIRECT be assured? - // 2. ftruncate(), but does this result in a sparse file? If so, then this is no good. - - // Create temp null block for writing - const std::size_t sblksize = JRNL_DBLK_SIZE * JRNL_SBLK_SIZE; - void* nullbuf = 0; - // Allocate no more than 2MB (4096 sblks) as a null buffer - const u_int32_t nullbuffsize_sblks = nsblks > 4096 ? 4096 : nsblks; - const std::size_t nullbuffsize = nullbuffsize_sblks * sblksize; - if (::posix_memalign(&nullbuf, sblksize, nullbuffsize)) - { - std::ostringstream oss; - oss << "posix_memalign() failed: size=" << nullbuffsize << " blk_size=" << sblksize; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__MALLOC, oss.str(), "fcntl", "clean_file"); - } - std::memset(nullbuf, 0, nullbuffsize); - - int fh = ::open(_fname.c_str(), O_WRONLY | O_CREAT | O_DIRECT, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // 0644 -rw-r--r-- - if (fh < 0) - { - std::free(nullbuf); - std::ostringstream oss; - oss << "open() failed:" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_FCNTL_OPENWR, oss.str(), "fcntl", "clean_file"); - } - - while (nsblks > 0) - { - u_int32_t this_write_sblks = nsblks >= nullbuffsize_sblks ? nullbuffsize_sblks : nsblks; - if (::write(fh, nullbuf, this_write_sblks * sblksize) == -1) - { - ::close(fh); - std::free(nullbuf); - std::ostringstream oss; - oss << "wr_size=" << (this_write_sblks * sblksize) << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_FCNTL_WRITE, oss.str(), "fcntl", "clean_file"); - } - nsblks -= this_write_sblks; - } - - // Clean up - std::free(nullbuf); - if (::close(fh)) - { - std::ostringstream oss; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_FCNTL_CLOSE, oss.str(), "fcntl", "clean_file"); - } -} - -void -fcntl::create_jfile(const u_int32_t jfsize_sblks) -{ - clean_file(jfsize_sblks); -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/fcntl.h b/qpid/cpp/src/qpid/legacystore/jrnl/fcntl.h deleted file mode 100644 index a75e3bc84d..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/fcntl.h +++ /dev/null @@ -1,156 +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. - * - */ - -/** - * \file fcntl.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::fcntl (non-logging file - * handle), used for controlling journal log files. See class documentation for - * details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_FCNTL_H -#define QPID_LEGACYSTORE_JRNL_FCNTL_H - -namespace mrg -{ -namespace journal -{ -class fcntl; -} -} - -#include -#include -#include "qpid/legacystore/jrnl/rcvdat.h" -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class fcntl - * \brief Journal file controller. There is one instance per journal file. - */ - class fcntl - { - protected: - std::string _fname; ///< File name - u_int16_t _pfid; ///< Physical file ID (file number in order of creation) - u_int16_t _lfid; ///< Logical file ID (ordinal number in ring store) - const u_int32_t _ffull_dblks; ///< File size in dblks (incl. file header) - int _wr_fh; ///< Write file handle - u_int32_t _rec_enqcnt; ///< Count of enqueued records - u_int32_t _rd_subm_cnt_dblks; ///< Read file count (data blocks) for submitted AIO - u_int32_t _rd_cmpl_cnt_dblks; ///< Read file count (data blocks) for completed AIO - u_int32_t _wr_subm_cnt_dblks; ///< Write file count (data blocks) for submitted AIO - u_int32_t _wr_cmpl_cnt_dblks; ///< Write file count (data blocks) for completed AIO - u_int16_t _aio_cnt; ///< Outstanding AIO operations on this file - bool _fhdr_wr_aio_outstanding; ///< Outstanding file header write on this file - - public: - // Constructors with implicit initialize() and open() - fcntl(const std::string& fbasename, const u_int16_t pfid, const u_int16_t lfid, const u_int32_t jfsize_sblks, - const rcvdat* const ro); - virtual ~fcntl(); - - virtual bool reset(const rcvdat* const ro = 0); - virtual void rd_reset(); - virtual bool wr_reset(const rcvdat* const ro = 0); - - virtual int open_wr_fh(); - virtual void close_wr_fh(); - inline bool is_wr_fh_open() const { return _wr_fh >= 0; } - - inline const std::string& fname() const { return _fname; } - inline u_int16_t pfid() const { return _pfid; } - inline u_int16_t lfid() const { return _lfid; } - inline void set_lfid(const u_int16_t lfid) { _lfid = lfid; } - inline int wr_fh() const { return _wr_fh; } - inline u_int32_t enqcnt() const { return _rec_enqcnt; } - inline u_int32_t incr_enqcnt() { return ++_rec_enqcnt; } - u_int32_t add_enqcnt(u_int32_t a); - u_int32_t decr_enqcnt(); - u_int32_t subtr_enqcnt(u_int32_t s); - - inline u_int32_t rd_subm_cnt_dblks() const { return _rd_subm_cnt_dblks; } - inline std::size_t rd_subm_offs() const { return _rd_subm_cnt_dblks * JRNL_DBLK_SIZE; } - u_int32_t add_rd_subm_cnt_dblks(u_int32_t a); - - inline u_int32_t rd_cmpl_cnt_dblks() const { return _rd_cmpl_cnt_dblks; } - inline std::size_t rd_cmpl_offs() const { return _rd_cmpl_cnt_dblks * JRNL_DBLK_SIZE; } - u_int32_t add_rd_cmpl_cnt_dblks(u_int32_t a); - - inline u_int32_t wr_subm_cnt_dblks() const { return _wr_subm_cnt_dblks; } - inline std::size_t wr_subm_offs() const { return _wr_subm_cnt_dblks * JRNL_DBLK_SIZE; } - u_int32_t add_wr_subm_cnt_dblks(u_int32_t a); - - inline u_int32_t wr_cmpl_cnt_dblks() const { return _wr_cmpl_cnt_dblks; } - inline std::size_t wr_cmpl_offs() const { return _wr_cmpl_cnt_dblks * JRNL_DBLK_SIZE; } - u_int32_t add_wr_cmpl_cnt_dblks(u_int32_t a); - - inline u_int16_t aio_cnt() const { return _aio_cnt; } - inline u_int16_t incr_aio_cnt() { return ++_aio_cnt; } - u_int16_t decr_aio_cnt(); - - inline bool wr_fhdr_aio_outstanding() { return _fhdr_wr_aio_outstanding; } - inline void set_wr_fhdr_aio_outstanding(const bool wfao) { _fhdr_wr_aio_outstanding = wfao; } - - // Derived helper functions - - inline bool rd_void() const { return _wr_cmpl_cnt_dblks == 0; } - inline bool rd_empty() const { return _wr_cmpl_cnt_dblks <= JRNL_SBLK_SIZE; } - inline u_int32_t rd_remaining_dblks() const { return _wr_cmpl_cnt_dblks - _rd_subm_cnt_dblks; } - inline bool is_rd_full() const { return _wr_cmpl_cnt_dblks == _rd_subm_cnt_dblks; } - inline bool is_rd_compl() const { return _wr_cmpl_cnt_dblks == _rd_cmpl_cnt_dblks; } - inline u_int32_t rd_aio_outstanding_dblks() const { return _rd_subm_cnt_dblks - _rd_cmpl_cnt_dblks; } - inline bool rd_file_rotate() const { return is_rd_full() && is_wr_compl(); } - - inline bool wr_void() const { return _wr_subm_cnt_dblks == 0; } - inline bool wr_empty() const { return _wr_subm_cnt_dblks <= JRNL_SBLK_SIZE; } - inline u_int32_t wr_remaining_dblks() const { return _ffull_dblks - _wr_subm_cnt_dblks; } - inline bool is_wr_full() const { return _ffull_dblks == _wr_subm_cnt_dblks; } - inline bool is_wr_compl() const { return _ffull_dblks == _wr_cmpl_cnt_dblks; } - inline u_int32_t wr_aio_outstanding_dblks() const { return _wr_subm_cnt_dblks - _wr_cmpl_cnt_dblks; } - inline bool wr_file_rotate() const { return is_wr_full(); } - - // Debug aid - const std::string status_str() const; - - protected: - virtual void initialize(const std::string& fbasename, const u_int16_t pfid, const u_int16_t lfid, - const u_int32_t jfsize_sblks, const rcvdat* const ro); - - static std::string filename(const std::string& fbasename, const u_int16_t pfid); - void clean_file(const u_int32_t jfsize_sblks); - void create_jfile(const u_int32_t jfsize_sblks); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_FCNTL_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/file_hdr.h b/qpid/cpp/src/qpid/legacystore/jrnl/file_hdr.h deleted file mode 100644 index db20834cbb..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/file_hdr.h +++ /dev/null @@ -1,211 +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. - * - */ - -/** - * \file file_hdr.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::file_hdr (file - * record header), used to start a journal file. It contains some - * file metadata and information to aid journal recovery. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_FILE_HDR_H -#define QPID_LEGACYSTORE_JRNL_FILE_HDR_H - -#include -#include -#include "qpid/legacystore/jrnl/rec_hdr.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for data common to the head of all journal files. In addition to - * the common data, this includes the record ID and offset of the first record in - * the file. - * - * This header precedes all data in journal files and occupies the first complete - * block in the file. The record ID and offset are updated on each overwrite of the - * file. - * - * File header info in binary format (48 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+  -+
-    * |     magic     | v | e | flags |   |
-    * +---+---+---+---+---+---+---+---+   | struct hdr
-    * |       first rid in file       |   |
-    * +---+---+---+---+---+---+---+---+  -+
-    * | pfid  | lfid  |  reserved (0) |
-    * +---+---+---+---+---+---+---+---+
-    * |              fro              |
-    * +---+---+---+---+---+---+---+---+
-    * |           timestamp (sec)     |
-    * +---+---+---+---+---+---+---+---+
-    * |           timestamp (ns)      |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * pfid = File ID (number used in naming file)
-    * lfid = Logical ID (order used in circular buffer)
-    * fro = First record offset, offset from start of file to first record header
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct file_hdr : rec_hdr - { - u_int16_t _pfid; ///< Physical file ID (pfid) - u_int16_t _lfid; ///< Logical file ID (lfid) - u_int32_t _res; ///< Reserved (for alignment/flags) -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _fro; ///< First record offset -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler1; ///< Big-endian filler for 32-bit time_t -#endif - std::time_t _ts_sec; ///< Timestamp of journal initilailization -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler1; ///< Little-endian filler for 32-bit time_t -#endif -#if defined(JRNL_BIG_ENDIAN) - u_int32_t _filler2; ///< Big endian filler for u_int32_t -#endif - u_int32_t _ts_nsec; ///< Timestamp of journal initilailization -#if defined(JRNL_LITTLE_ENDIAN) - u_int32_t _filler2; ///< Little-endian filler for u_int32_t -#endif - - /** - * \brief Default constructor, which sets all values to 0. - */ - inline file_hdr(): rec_hdr(), _pfid(0), _lfid(0), _res(0), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _fro(0), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif - _ts_sec(0), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif -#if defined(JRNL_BIG_ENDIAN) - _filler2(0), -#endif - _ts_nsec(0) -#if defined(JRNL_LITTLE_ENDIAN) - , _filler2(0) -#endif - {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline file_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const u_int16_t pfid, const u_int16_t lfid, const std::size_t fro, - const bool owi, const bool settime = false): - rec_hdr(magic, version, rid, owi), _pfid(pfid), _lfid(lfid), _res(0), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _fro(fro), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif - _ts_sec(0), -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - _filler1(0), -#endif -#if defined(JRNL_BIG_ENDIAN) - _filler2(0), -#endif - _ts_nsec(0) -#if defined(JRNL_LITTLE_ENDIAN) - , _filler2(0) -#endif - { if (settime) set_time(); } - - /** - * \brief Gets the current time from the system clock and sets the timestamp in the struct. - */ - inline void set_time() - { - // TODO: Standardize on method for getting time that does not requrie a context switch. - timespec ts; - if (::clock_gettime(CLOCK_REALTIME, &ts)) - { - std::ostringstream oss; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__RTCLOCK, oss.str(), "file_hdr", "set_time"); - } - _ts_sec = ts.tv_sec; - _ts_nsec = ts.tv_nsec; - } - - /** - * \brief Sets the timestamp in the struct to the provided value (in seconds and - * nanoseconds). - */ - inline void set_time(timespec& ts) - { - _ts_sec = ts.tv_sec; - _ts_nsec = ts.tv_nsec; - } - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(file_hdr); } - }; // struct file_hdr - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_FILE_HDR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h b/qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h deleted file mode 100644 index 01d92ee985..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h +++ /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. - * - */ - -/** - * \file jcfg.h - * - * Qpid asynchronous store plugin library - * - * This file contains \#defines that control the implementation details of - * the journal. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_JCFG_H -#define QPID_LEGACYSTORE_JRNL_JCFG_H - -#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__) || (__arm64__) /* little endian, 64 bits */ -#define JRNL_LITTLE_ENDIAN -#define JRNL_64_BIT -#elif defined(__powerpc64__) || defined(__s390x__) /* big endian, 64 bits */ -#define JRNL_BIG_ENDIAN -#define JRNL_64_BIT -#else -#error endian? -#endif - - -/** -* Rule: Data block size (JRNL_DBLK_SIZE) MUST be a power of 2 such that -*
-* JRNL_DBLK_SIZE * JRNL_SBLK_SIZE == n * 512 (n = 1,2,3...)
-* 
-* (The disk softblock size is 512 for Linux kernels >= 2.6) -*/ -#define JRNL_DBLK_SIZE 128 ///< Data block size in bytes (CANNOT BE LESS THAN 32!) -#define JRNL_SBLK_SIZE 4 ///< Disk softblock size in multiples of JRNL_DBLK_SIZE -#define JRNL_MIN_FILE_SIZE 128 ///< Min. jrnl file size in sblks (excl. file_hdr) -#define JRNL_MAX_FILE_SIZE 4194176 ///< Max. jrnl file size in sblks (excl. file_hdr) -#define JRNL_MIN_NUM_FILES 4 ///< Min. number of journal files -#define JRNL_MAX_NUM_FILES 64 ///< Max. number of journal files -#define JRNL_ENQ_THRESHOLD 80 ///< Percent full when enqueue connection will be closed - -#define JRNL_RMGR_PAGE_SIZE 128 ///< Journal page size in softblocks -#define JRNL_RMGR_PAGES 16 ///< Number of pages to use in wmgr - -#define JRNL_WMGR_DEF_PAGE_SIZE 64 ///< Journal write page size in softblocks (default) -#define JRNL_WMGR_DEF_PAGES 32 ///< Number of pages to use in wmgr (default) - -#define JRNL_WMGR_MAXDTOKPP 1024 ///< Max. dtoks (data blocks) per page in wmgr -#define JRNL_WMGR_MAXWAITUS 100 ///< Max. wait time (us) before submitting AIO - -#define JRNL_INFO_EXTENSION "jinf" ///< Extension for journal info files -#define JRNL_DATA_EXTENSION "jdat" ///< Extension for journal data files -#define RHM_JDAT_TXA_MAGIC 0x614d4852 ///< ("RHMa" in little endian) Magic for dtx abort hdrs -#define RHM_JDAT_TXC_MAGIC 0x634d4852 ///< ("RHMc" in little endian) Magic for dtx commit hdrs -#define RHM_JDAT_DEQ_MAGIC 0x644d4852 ///< ("RHMd" in little endian) Magic for deq rec hdrs -#define RHM_JDAT_ENQ_MAGIC 0x654d4852 ///< ("RHMe" in little endian) Magic for enq rec hdrs -#define RHM_JDAT_FILE_MAGIC 0x664d4852 ///< ("RHMf" in little endian) Magic for file hdrs -#define RHM_JDAT_EMPTY_MAGIC 0x784d4852 ///< ("RHMx" in little endian) Magic for empty dblk -#define RHM_JDAT_VERSION 0x01 ///< Version (of file layout) -#define RHM_CLEAN_CHAR 0xff ///< Char used to clear empty space on disk - -#define RHM_LENDIAN_FLAG 0 ///< Value of little endian flag on disk -#define RHM_BENDIAN_FLAG 1 ///< Value of big endian flag on disk - -#endif // ifndef QPID_LEGACYSTORE_JRNL_JCFG_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jcntl.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/jcntl.cpp deleted file mode 100644 index 21fcf099b4..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jcntl.cpp +++ /dev/null @@ -1,984 +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. - * - */ - -/** - * \file jcntl.cpp - * - * Qpid asynchronous store plugin library - * - * Messaging journal top-level control and interface class - * mrg::journal::jcntl. See comments in file jcntl.h for details. - * - * \author Kim van der Riet - */ - - -#include "qpid/legacystore/jrnl/jcntl.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/file_hdr.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jinf.h" -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - -#define AIO_CMPL_TIMEOUT_SEC 5 -#define AIO_CMPL_TIMEOUT_NSEC 0 -#define FINAL_AIO_CMPL_TIMEOUT_SEC 15 -#define FINAL_AIO_CMPL_TIMEOUT_NSEC 0 - -// Static -timespec jcntl::_aio_cmpl_timeout; ///< Timeout for blocking libaio returns -timespec jcntl::_final_aio_cmpl_timeout; ///< Timeout for blocking libaio returns when stopping or finalizing -bool jcntl::_init = init_statics(); -bool jcntl::init_statics() -{ - _aio_cmpl_timeout.tv_sec = AIO_CMPL_TIMEOUT_SEC; - _aio_cmpl_timeout.tv_nsec = AIO_CMPL_TIMEOUT_NSEC; - _final_aio_cmpl_timeout.tv_sec = FINAL_AIO_CMPL_TIMEOUT_SEC; - _final_aio_cmpl_timeout.tv_nsec = FINAL_AIO_CMPL_TIMEOUT_NSEC; - return true; -} - - -// Functions - -jcntl::jcntl(const std::string& jid, const std::string& jdir, const std::string& base_filename): - _jid(jid), - _jdir(jdir, base_filename), - _base_filename(base_filename), - _init_flag(false), - _stop_flag(false), - _readonly_flag(false), - _autostop(true), - _jfsize_sblks(0), - _lpmgr(), - _emap(), - _tmap(), - _rrfc(&_lpmgr), - _wrfc(&_lpmgr), - _rmgr(this, _emap, _tmap, _rrfc), - _wmgr(this, _emap, _tmap, _wrfc), - _rcvdat() -{} - -jcntl::~jcntl() -{ - if (_init_flag && !_stop_flag) - try { stop(true); } - catch (const jexception& e) { std::cerr << e << std::endl; } - _lpmgr.finalize(); -} - -void -jcntl::initialize(const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks, - aio_callback* const cbp) -{ - _init_flag = false; - _stop_flag = false; - _readonly_flag = false; - - _emap.clear(); - _tmap.clear(); - - _lpmgr.finalize(); - - // Set new file geometry parameters - assert(num_jfiles >= JRNL_MIN_NUM_FILES); - assert(num_jfiles <= JRNL_MAX_NUM_FILES); - _emap.set_num_jfiles(num_jfiles); - _tmap.set_num_jfiles(num_jfiles); - - assert(jfsize_sblks >= JRNL_MIN_FILE_SIZE); - assert(jfsize_sblks <= JRNL_MAX_FILE_SIZE); - _jfsize_sblks = jfsize_sblks; - - // Clear any existing journal files - _jdir.clear_dir(); - _lpmgr.initialize(num_jfiles, ae, ae_max_jfiles, this, &new_fcntl); - - _wrfc.initialize(_jfsize_sblks); - _rrfc.initialize(); - _rrfc.set_findex(0); - _rmgr.initialize(cbp); - _wmgr.initialize(cbp, wcache_pgsize_sblks, wcache_num_pages, JRNL_WMGR_MAXDTOKPP, JRNL_WMGR_MAXWAITUS); - - // Write info file (.jinf) to disk - write_infofile(); - - _init_flag = true; -} - -void -jcntl::recover(const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks, -// const rd_aio_cb rd_cb, const wr_aio_cb wr_cb, const std::vector* prep_txn_list_ptr, - aio_callback* const cbp, const std::vector* prep_txn_list_ptr, - u_int64_t& highest_rid) -{ - _init_flag = false; - _stop_flag = false; - _readonly_flag = false; - - _emap.clear(); - _tmap.clear(); - - _lpmgr.finalize(); - - assert(num_jfiles >= JRNL_MIN_NUM_FILES); - assert(num_jfiles <= JRNL_MAX_NUM_FILES); - assert(jfsize_sblks >= JRNL_MIN_FILE_SIZE); - assert(jfsize_sblks <= JRNL_MAX_FILE_SIZE); - _jfsize_sblks = jfsize_sblks; - - // Verify journal dir and journal files - _jdir.verify_dir(); - _rcvdat.reset(num_jfiles, ae, ae_max_jfiles); - - rcvr_janalyze(_rcvdat, prep_txn_list_ptr); - highest_rid = _rcvdat._h_rid; - if (_rcvdat._jfull) - throw jexception(jerrno::JERR_JCNTL_RECOVERJFULL, "jcntl", "recover"); - this->log(LOG_DEBUG, _rcvdat.to_log(_jid)); - - _lpmgr.recover(_rcvdat, this, &new_fcntl); - - _wrfc.initialize(_jfsize_sblks, &_rcvdat); - _rrfc.initialize(); - _rrfc.set_findex(_rcvdat.ffid()); - _rmgr.initialize(cbp); - _wmgr.initialize(cbp, wcache_pgsize_sblks, wcache_num_pages, JRNL_WMGR_MAXDTOKPP, JRNL_WMGR_MAXWAITUS, - (_rcvdat._lffull ? 0 : _rcvdat._eo)); - - _readonly_flag = true; - _init_flag = true; -} - -void -jcntl::recover_complete() -{ - if (!_readonly_flag) - throw jexception(jerrno::JERR_JCNTL_NOTRECOVERED, "jcntl", "recover_complete"); - for (u_int16_t i=0; i<_lpmgr.num_jfiles(); i++) - _lpmgr.get_fcntlp(i)->reset(&_rcvdat); - _wrfc.initialize(_jfsize_sblks, &_rcvdat); - _rrfc.initialize(); - _rrfc.set_findex(_rcvdat.ffid()); - _rmgr.recover_complete(); - _readonly_flag = false; -} - -void -jcntl::delete_jrnl_files() -{ - stop(true); // wait for AIO to complete - _jdir.delete_dir(); -} - - -iores -jcntl::enqueue_data_record(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const bool transient) -{ - iores r; - check_wstatus("enqueue_data_record"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.enqueue(data_buff, tot_data_len, this_data_len, dtokp, 0, 0, transient, false), r, - dtokp)) ; - } - return r; -} - -iores -jcntl::enqueue_extern_data_record(const std::size_t tot_data_len, data_tok* dtokp, const bool transient) -{ - iores r; - check_wstatus("enqueue_extern_data_record"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.enqueue(0, tot_data_len, 0, dtokp, 0, 0, transient, true), r, dtokp)) ; - } - return r; -} - -iores -jcntl::enqueue_txn_data_record(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const std::string& xid, - const bool transient) -{ - iores r; - check_wstatus("enqueue_tx_data_record"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.enqueue(data_buff, tot_data_len, this_data_len, dtokp, xid.data(), xid.size(), - transient, false), r, dtokp)) ; - } - return r; -} - -iores -jcntl::enqueue_extern_txn_data_record(const std::size_t tot_data_len, data_tok* dtokp, - const std::string& xid, const bool transient) -{ - iores r; - check_wstatus("enqueue_extern_txn_data_record"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.enqueue(0, tot_data_len, 0, dtokp, xid.data(), xid.size(), transient, true), r, - dtokp)) ; - } - return r; -} - -/* TODO -iores -jcntl::get_data_record(const u_int64_t& rid, const std::size_t& dsize, const std::size_t& dsize_avail, - const void** const data, bool auto_discard) -{ - check_rstatus("get_data_record"); - return _rmgr.get(rid, dsize, dsize_avail, data, auto_discard); -} */ - -/* TODO -iores -jcntl::discard_data_record(data_tok* const dtokp) -{ - check_rstatus("discard_data_record"); - return _rmgr.discard(dtokp); -} */ - -iores -jcntl::read_data_record(void** const datapp, std::size_t& dsize, void** const xidpp, std::size_t& xidsize, - bool& transient, bool& external, data_tok* const dtokp, bool ignore_pending_txns) -{ - check_rstatus("read_data"); - iores res = _rmgr.read(datapp, dsize, xidpp, xidsize, transient, external, dtokp, ignore_pending_txns); - if (res == RHM_IORES_RCINVALID) - { - get_wr_events(0); // check for outstanding write events - iores sres = _rmgr.synchronize(); // flushes all outstanding read events - if (sres != RHM_IORES_SUCCESS) - return sres; - _rmgr.wait_for_validity(&_aio_cmpl_timeout, true); // throw if timeout occurs - res = _rmgr.read(datapp, dsize, xidpp, xidsize, transient, external, dtokp, ignore_pending_txns); - } - return res; -} - -iores -jcntl::dequeue_data_record(data_tok* const dtokp, const bool txn_coml_commit) -{ - iores r; - check_wstatus("dequeue_data"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.dequeue(dtokp, 0, 0, txn_coml_commit), r, dtokp)) ; - } - return r; -} - -iores -jcntl::dequeue_txn_data_record(data_tok* const dtokp, const std::string& xid, const bool txn_coml_commit) -{ - iores r; - check_wstatus("dequeue_data"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.dequeue(dtokp, xid.data(), xid.size(), txn_coml_commit), r, dtokp)) ; - } - return r; -} - -iores -jcntl::txn_abort(data_tok* const dtokp, const std::string& xid) -{ - iores r; - check_wstatus("txn_abort"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.abort(dtokp, xid.data(), xid.size()), r, dtokp)) ; - } - return r; -} - -iores -jcntl::txn_commit(data_tok* const dtokp, const std::string& xid) -{ - iores r; - check_wstatus("txn_commit"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.commit(dtokp, xid.data(), xid.size()), r, dtokp)) ; - } - return r; -} - -bool -jcntl::is_txn_synced(const std::string& xid) -{ - slock s(_wr_mutex); - bool res = _wmgr.is_txn_synced(xid); - return res; -} - -int32_t -jcntl::get_wr_events(timespec* const timeout) -{ - stlock t(_wr_mutex); - if (!t.locked()) - return jerrno::LOCK_TAKEN; - int32_t res = _wmgr.get_events(pmgr::UNUSED, timeout); - return res; -} - -int32_t -jcntl::get_rd_events(timespec* const timeout) -{ - return _rmgr.get_events(pmgr::AIO_COMPLETE, timeout); -} - -void -jcntl::stop(const bool block_till_aio_cmpl) -{ - if (_readonly_flag) - check_rstatus("stop"); - else - check_wstatus("stop"); - _stop_flag = true; - if (!_readonly_flag) - flush(block_till_aio_cmpl); - _rrfc.finalize(); - _lpmgr.finalize(); -} - -u_int16_t -jcntl::get_earliest_fid() -{ - u_int16_t ffid = _wrfc.earliest_index(); - u_int16_t fid = _wrfc.index(); - while ( _emap.get_enq_cnt(ffid) == 0 && _tmap.get_txn_pfid_cnt(ffid) == 0 && ffid != fid) - { - if (++ffid >= _lpmgr.num_jfiles()) - ffid = 0; - } - if (!_rrfc.is_active()) - _rrfc.set_findex(ffid); - return ffid; -} - -iores -jcntl::flush(const bool block_till_aio_cmpl) -{ - if (!_init_flag) - return RHM_IORES_SUCCESS; - if (_readonly_flag) - throw jexception(jerrno::JERR_JCNTL_READONLY, "jcntl", "flush"); - iores res; - { - slock s(_wr_mutex); - res = _wmgr.flush(); - } - if (block_till_aio_cmpl) - aio_cmpl_wait(); - return res; -} - -void -jcntl::log(log_level ll, const std::string& log_stmt) const -{ - log(ll, log_stmt.c_str()); -} - -void -jcntl::log(log_level ll, const char* const log_stmt) const -{ - if (ll > LOG_INFO) - { - std::cout << log_level_str(ll) << ": Journal \"" << _jid << "\": " << log_stmt << std::endl; - } -} - -void -jcntl::chk_wr_frot() -{ - if (_wrfc.index() == _rrfc.index()) - _rmgr.invalidate(); -} - -void -jcntl::fhdr_wr_sync(const u_int16_t lid) -{ - fcntl* fcntlp = _lpmgr.get_fcntlp(lid); - while (fcntlp->wr_fhdr_aio_outstanding()) - { - if (get_wr_events(&_aio_cmpl_timeout) == jerrno::AIO_TIMEOUT) - throw jexception(jerrno::JERR_JCNTL_AIOCMPLWAIT, "jcntl", "fhdr_wr_sync"); - } -} - -fcntl* -jcntl::new_fcntl(jcntl* const jcp, const u_int16_t lid, const u_int16_t fid, const rcvdat* const rdp) -{ - if (!jcp) return 0; - std::ostringstream oss; - oss << jcp->jrnl_dir() << "/" << jcp->base_filename(); - return new fcntl(oss.str(), fid, lid, jcp->jfsize_sblks(), rdp); -} - -// Protected/Private functions - -void -jcntl::check_wstatus(const char* fn_name) const -{ - if (!_init_flag) - throw jexception(jerrno::JERR__NINIT, "jcntl", fn_name); - if (_readonly_flag) - throw jexception(jerrno::JERR_JCNTL_READONLY, "jcntl", fn_name); - if (_stop_flag) - throw jexception(jerrno::JERR_JCNTL_STOPPED, "jcntl", fn_name); -} - -void -jcntl::check_rstatus(const char* fn_name) const -{ - if (!_init_flag) - throw jexception(jerrno::JERR__NINIT, "jcntl", fn_name); - if (_stop_flag) - throw jexception(jerrno::JERR_JCNTL_STOPPED, "jcntl", fn_name); -} - -void -jcntl::write_infofile() const -{ - timespec ts; - if (::clock_gettime(CLOCK_REALTIME, &ts)) - { - std::ostringstream oss; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__RTCLOCK, oss.str(), "jcntl", "write_infofile"); - } - jinf ji(_jid, _jdir.dirname(), _base_filename, _lpmgr.num_jfiles(), _lpmgr.is_ae(), _lpmgr.ae_max_jfiles(), - _jfsize_sblks, _wmgr.cache_pgsize_sblks(), _wmgr.cache_num_pages(), ts); - ji.write(); -} - -void -jcntl::aio_cmpl_wait() -{ - //while (_wmgr.get_aio_evt_rem()) - while (true) - { - u_int32_t aer; - { - slock s(_wr_mutex); - aer = _wmgr.get_aio_evt_rem(); - } - if (aer == 0) break; // no events left - if (get_wr_events(&_aio_cmpl_timeout) == jerrno::AIO_TIMEOUT) - throw jexception(jerrno::JERR_JCNTL_AIOCMPLWAIT, "jcntl", "aio_cmpl_wait"); - } -} - -bool -jcntl::handle_aio_wait(const iores res, iores& resout, const data_tok* dtp) -{ - resout = res; - if (res == RHM_IORES_PAGE_AIOWAIT) - { - while (_wmgr.curr_pg_blocked()) - { - if (_wmgr.get_events(pmgr::UNUSED, &_aio_cmpl_timeout) == jerrno::AIO_TIMEOUT) - { - std::ostringstream oss; - oss << "get_events() returned JERR_JCNTL_AIOCMPLWAIT; wmgr_status: " << _wmgr.status_str(); - this->log(LOG_CRITICAL, oss.str()); - throw jexception(jerrno::JERR_JCNTL_AIOCMPLWAIT, "jcntl", "handle_aio_wait"); - } - } - return true; - } - else if (res == RHM_IORES_FILE_AIOWAIT) - { - while (_wmgr.curr_file_blocked()) - { - if (_wmgr.get_events(pmgr::UNUSED, &_aio_cmpl_timeout) == jerrno::AIO_TIMEOUT) - { - std::ostringstream oss; - oss << "get_events() returned JERR_JCNTL_AIOCMPLWAIT; wmgr_status: " << _wmgr.status_str(); - this->log(LOG_CRITICAL, oss.str()); - throw jexception(jerrno::JERR_JCNTL_AIOCMPLWAIT, "jcntl", "handle_aio_wait"); - } - } - _wrfc.wr_reset(); - resout = RHM_IORES_SUCCESS; - data_tok::write_state ws = dtp->wstate(); - return ws == data_tok::ENQ_PART || ws == data_tok::DEQ_PART || ws == data_tok::ABORT_PART || - ws == data_tok::COMMIT_PART; - } - return false; -} - -void -jcntl::rcvr_janalyze(rcvdat& rd, const std::vector* prep_txn_list_ptr) -{ - jinf ji(_jdir.dirname() + "/" + _base_filename + "." + JRNL_INFO_EXTENSION, true); - - // If the number of files does not tie up with the jinf file from the journal being recovered, - // use the jinf data. - if (rd._njf != ji.num_jfiles()) - { - std::ostringstream oss; - oss << "Recovery found " << ji.num_jfiles() << - " files (different from --num-jfiles value of " << rd._njf << ")."; - this->log(LOG_INFO, oss.str()); - rd._njf = ji.num_jfiles(); - _rcvdat._enq_cnt_list.resize(rd._njf); - } - _emap.set_num_jfiles(rd._njf); - _tmap.set_num_jfiles(rd._njf); - if (_jfsize_sblks != ji.jfsize_sblks()) - { - std::ostringstream oss; - oss << "Recovery found file size = " << (ji.jfsize_sblks() / JRNL_RMGR_PAGE_SIZE) << - " (different from --jfile-size-pgs value of " << - (_jfsize_sblks / JRNL_RMGR_PAGE_SIZE) << ")."; - this->log(LOG_INFO, oss.str()); - _jfsize_sblks = ji.jfsize_sblks(); - } - if (_jdir.dirname().compare(ji.jdir())) - { - std::ostringstream oss; - oss << "Journal file location change: original = \"" << ji.jdir() << - "\"; current = \"" << _jdir.dirname() << "\""; - this->log(LOG_WARN, oss.str()); - ji.set_jdir(_jdir.dirname()); - } - - try - { - rd._ffid = ji.get_first_pfid(); - rd._lfid = ji.get_last_pfid(); - rd._owi = ji.get_initial_owi(); - rd._frot = ji.get_frot(); - rd._jempty = false; - ji.get_normalized_pfid_list(rd._fid_list); // _pfid_list - } - catch (const jexception& e) - { - if (e.err_code() != jerrno::JERR_JINF_JDATEMPTY) throw; - } - - // Restore all read and write pointers and transactions - if (!rd._jempty) - { - u_int16_t fid = rd._ffid; - std::ifstream ifs; - bool lowi = rd._owi; // local copy of owi to be used during analysis - while (rcvr_get_next_record(fid, &ifs, lowi, rd)) ; - if (ifs.is_open()) ifs.close(); - - // Remove all txns from tmap that are not in the prepared list - if (prep_txn_list_ptr) - { - std::vector xid_list; - _tmap.xid_list(xid_list); - for (std::vector::iterator itr = xid_list.begin(); itr != xid_list.end(); itr++) - { - std::vector::const_iterator pitr = - std::find(prep_txn_list_ptr->begin(), prep_txn_list_ptr->end(), *itr); - if (pitr == prep_txn_list_ptr->end()) // not found in prepared list - { - txn_data_list tdl = _tmap.get_remove_tdata_list(*itr); // tdl will be empty if xid not found - // Unlock any affected enqueues in emap - for (tdl_itr i=tdl.begin(); i_enq_flag) // enq op - decrement enqueue count - rd._enq_cnt_list[i->_pfid]--; - else if (_emap.is_enqueued(i->_drid, true)) // deq op - unlock enq record - { - int16_t ret = _emap.unlock(i->_drid); - if (ret < enq_map::EMAP_OK) // fail - { - // enq_map::unlock()'s only error is enq_map::EMAP_RID_NOT_FOUND - std::ostringstream oss; - oss << std::hex << "_emap.unlock(): drid=0x\"" << i->_drid; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "jcntl", "rcvr_janalyze"); - } - } - } - } - } - } - - // Check for file full condition - add one to _jfsize_sblks to account for file header - rd._lffull = rd._eo == (1 + _jfsize_sblks) * JRNL_SBLK_SIZE * JRNL_DBLK_SIZE; - - // Check for journal full condition - u_int16_t next_wr_fid = (rd._lfid + 1) % rd._njf; - rd._jfull = rd._ffid == next_wr_fid && rd._enq_cnt_list[next_wr_fid] && rd._lffull; - } -} - -bool -jcntl::rcvr_get_next_record(u_int16_t& fid, std::ifstream* ifsp, bool& lowi, rcvdat& rd) -{ - std::size_t cum_size_read = 0; - void* xidp = 0; - rec_hdr h; - - bool hdr_ok = false; - std::streampos file_pos; - while (!hdr_ok) - { - if (!ifsp->is_open()) - { - if (!jfile_cycle(fid, ifsp, lowi, rd, true)) - return false; - } - file_pos = ifsp->tellg(); - ifsp->read((char*)&h, sizeof(rec_hdr)); - if (ifsp->gcount() == sizeof(rec_hdr)) - hdr_ok = true; - else - { - if (!jfile_cycle(fid, ifsp, lowi, rd, true)) - return false; - } - } - - switch(h._magic) - { - case RHM_JDAT_ENQ_MAGIC: - { - enq_rec er; - u_int16_t start_fid = fid; // fid may increment in decode() if record folds over file boundary - if (!decode(er, fid, ifsp, cum_size_read, h, lowi, rd, file_pos)) - return false; - if (!er.is_transient()) // Ignore transient msgs - { - rd._enq_cnt_list[start_fid]++; - if (er.xid_size()) - { - er.get_xid(&xidp); - assert(xidp != 0); - std::string xid((char*)xidp, er.xid_size()); - _tmap.insert_txn_data(xid, txn_data(h._rid, 0, start_fid, true)); - if (_tmap.set_aio_compl(xid, h._rid) < txn_map::TMAP_OK) // fail - xid or rid not found - { - std::ostringstream oss; - oss << std::hex << "_tmap.set_aio_compl: txn_enq xid=\"" << xid << "\" rid=0x" << h._rid; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "jcntl", "rcvr_get_next_record"); - } - std::free(xidp); - } - else - { - if (_emap.insert_pfid(h._rid, start_fid) < enq_map::EMAP_OK) // fail - { - // The only error code emap::insert_pfid() returns is enq_map::EMAP_DUP_RID. - std::ostringstream oss; - oss << std::hex << "rid=0x" << h._rid << " _pfid=0x" << start_fid; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "jcntl", "rcvr_get_next_record"); - } - } - } - } - break; - case RHM_JDAT_DEQ_MAGIC: - { - deq_rec dr; - u_int16_t start_fid = fid; // fid may increment in decode() if record folds over file boundary - if (!decode(dr, fid, ifsp, cum_size_read, h, lowi, rd, file_pos)) - return false; - if (dr.xid_size()) - { - // If the enqueue is part of a pending txn, it will not yet be in emap - _emap.lock(dr.deq_rid()); // ignore not found error - dr.get_xid(&xidp); - assert(xidp != 0); - std::string xid((char*)xidp, dr.xid_size()); - _tmap.insert_txn_data(xid, txn_data(dr.rid(), dr.deq_rid(), start_fid, false, - dr.is_txn_coml_commit())); - if (_tmap.set_aio_compl(xid, dr.rid()) < txn_map::TMAP_OK) // fail - xid or rid not found - { - std::ostringstream oss; - oss << std::hex << "_tmap.set_aio_compl: txn_deq xid=\"" << xid << "\" rid=0x" << dr.rid(); - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "jcntl", "rcvr_get_next_record"); - } - std::free(xidp); - } - else - { - int16_t enq_fid = _emap.get_remove_pfid(dr.deq_rid(), true); - if (enq_fid >= enq_map::EMAP_OK) // ignore not found error - rd._enq_cnt_list[enq_fid]--; - } - } - break; - case RHM_JDAT_TXA_MAGIC: - { - txn_rec ar; - if (!decode(ar, fid, ifsp, cum_size_read, h, lowi, rd, file_pos)) - return false; - // Delete this txn from tmap, unlock any locked records in emap - ar.get_xid(&xidp); - assert(xidp != 0); - std::string xid((char*)xidp, ar.xid_size()); - txn_data_list tdl = _tmap.get_remove_tdata_list(xid); // tdl will be empty if xid not found - for (tdl_itr itr = tdl.begin(); itr != tdl.end(); itr++) - { - if (itr->_enq_flag) - rd._enq_cnt_list[itr->_pfid]--; - else - _emap.unlock(itr->_drid); // ignore not found error - } - std::free(xidp); - } - break; - case RHM_JDAT_TXC_MAGIC: - { - txn_rec cr; - if (!decode(cr, fid, ifsp, cum_size_read, h, lowi, rd, file_pos)) - return false; - // Delete this txn from tmap, process records into emap - cr.get_xid(&xidp); - assert(xidp != 0); - std::string xid((char*)xidp, cr.xid_size()); - txn_data_list tdl = _tmap.get_remove_tdata_list(xid); // tdl will be empty if xid not found - for (tdl_itr itr = tdl.begin(); itr != tdl.end(); itr++) - { - if (itr->_enq_flag) // txn enqueue - { - if (_emap.insert_pfid(itr->_rid, itr->_pfid) < enq_map::EMAP_OK) // fail - { - // The only error code emap::insert_pfid() returns is enq_map::EMAP_DUP_RID. - std::ostringstream oss; - oss << std::hex << "rid=0x" << itr->_rid << " _pfid=0x" << itr->_pfid; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "jcntl", "rcvr_get_next_record"); - } - } - else // txn dequeue - { - int16_t enq_fid = _emap.get_remove_pfid(itr->_drid, true); - if (enq_fid >= enq_map::EMAP_OK) - rd._enq_cnt_list[enq_fid]--; - } - } - std::free(xidp); - } - break; - case RHM_JDAT_EMPTY_MAGIC: - { - u_int32_t rec_dblks = jrec::size_dblks(sizeof(rec_hdr)); - ifsp->ignore(rec_dblks * JRNL_DBLK_SIZE - sizeof(rec_hdr)); - assert(!ifsp->fail() && !ifsp->bad()); - if (!jfile_cycle(fid, ifsp, lowi, rd, false)) - return false; - } - break; - case 0: - check_journal_alignment(fid, file_pos, rd); - return false; - default: - // Stop as this is the overwrite boundary. - check_journal_alignment(fid, file_pos, rd); - return false; - } - return true; -} - -bool -jcntl::decode(jrec& rec, u_int16_t& fid, std::ifstream* ifsp, std::size_t& cum_size_read, - rec_hdr& h, bool& lowi, rcvdat& rd, std::streampos& file_offs) -{ - u_int16_t start_fid = fid; - std::streampos start_file_offs = file_offs; - if (!check_owi(fid, h, lowi, rd, file_offs)) - return false; - bool done = false; - while (!done) - { - try { done = rec.rcv_decode(h, ifsp, cum_size_read); } - catch (const jexception& e) - { -// TODO - review this logic and tidy up how rd._lfid is assigned. See new jinf.get_end_file() fn. -// Original -// if (e.err_code() != jerrno::JERR_JREC_BADRECTAIL || -// fid != (rd._ffid ? rd._ffid - 1 : _num_jfiles - 1)) throw; -// Tried this, but did not work -// if (e.err_code() != jerrno::JERR_JREC_BADRECTAIL || h._magic != 0) throw; - check_journal_alignment(start_fid, start_file_offs, rd); -// rd._lfid = start_fid; - return false; - } - if (!done && !jfile_cycle(fid, ifsp, lowi, rd, false)) - { - check_journal_alignment(start_fid, start_file_offs, rd); - return false; - } - } - return true; -} - -bool -jcntl::jfile_cycle(u_int16_t& fid, std::ifstream* ifsp, bool& lowi, rcvdat& rd, const bool jump_fro) -{ - if (ifsp->is_open()) - { - if (ifsp->eof() || !ifsp->good()) - { - ifsp->clear(); - rd._eo = ifsp->tellg(); // remember file offset before closing - assert(rd._eo != std::numeric_limits::max()); // Check for error code -1 - ifsp->close(); - if (++fid >= rd._njf) - { - fid = 0; - lowi = !lowi; // Flip local owi - } - if (fid == rd._ffid) // used up all journal files - return false; - } - } - if (!ifsp->is_open()) - { - std::ostringstream oss; - oss << _jdir.dirname() << "/" << _base_filename << "."; - oss << std::hex << std::setfill('0') << std::setw(4) << fid << "." << JRNL_DATA_EXTENSION; - ifsp->clear(); // clear eof flag, req'd for older versions of c++ - ifsp->open(oss.str().c_str(), std::ios_base::in | std::ios_base::binary); - if (!ifsp->good()) - throw jexception(jerrno::JERR__FILEIO, oss.str(), "jcntl", "jfile_cycle"); - - // Read file header - file_hdr fhdr; - ifsp->read((char*)&fhdr, sizeof(fhdr)); - assert(ifsp->good()); - if (fhdr._magic == RHM_JDAT_FILE_MAGIC) - { - assert(fhdr._lfid == fid); - if (!rd._fro) - rd._fro = fhdr._fro; - std::streamoff foffs = jump_fro ? fhdr._fro : JRNL_DBLK_SIZE * JRNL_SBLK_SIZE; - ifsp->seekg(foffs); - } - else - { - ifsp->close(); - return false; - } - } - return true; -} - -bool -jcntl::check_owi(const u_int16_t fid, rec_hdr& h, bool& lowi, rcvdat& rd, std::streampos& file_pos) -{ - if (rd._ffid ? h.get_owi() == lowi : h.get_owi() != lowi) // Overwrite indicator changed - { - u_int16_t expected_fid = rd._ffid ? rd._ffid - 1 : rd._njf - 1; - if (fid == expected_fid) - { - check_journal_alignment(fid, file_pos, rd); - return false; - } - std::ostringstream oss; - oss << std::hex << std::setfill('0') << "Magic=0x" << std::setw(8) << h._magic; - oss << " fid=0x" << std::setw(4) << fid << " rid=0x" << std::setw(8) << h._rid; - oss << " foffs=0x" << std::setw(8) << file_pos; - oss << " expected_fid=0x" << std::setw(4) << expected_fid; - throw jexception(jerrno::JERR_JCNTL_OWIMISMATCH, oss.str(), "jcntl", - "check_owi"); - } - if (rd._h_rid == 0) - rd._h_rid = h._rid; - else if (h._rid - rd._h_rid < 0x8000000000000000ULL) // RFC 1982 comparison for unsigned 64-bit - rd._h_rid = h._rid; - return true; -} - - -void -jcntl::check_journal_alignment(const u_int16_t fid, std::streampos& file_pos, rcvdat& rd) -{ - unsigned sblk_offs = file_pos % (JRNL_DBLK_SIZE * JRNL_SBLK_SIZE); - if (sblk_offs) - { - { - std::ostringstream oss; - oss << std::hex << "Bad record alignment found at fid=0x" << fid; - oss << " offs=0x" << file_pos << " (likely journal overwrite boundary); " << std::dec; - oss << (JRNL_SBLK_SIZE - (sblk_offs/JRNL_DBLK_SIZE)) << " filler record(s) required."; - this->log(LOG_WARN, oss.str()); - } - const u_int32_t xmagic = RHM_JDAT_EMPTY_MAGIC; - std::ostringstream oss; - oss << _jdir.dirname() << "/" << _base_filename << "."; - oss << std::hex << std::setfill('0') << std::setw(4) << fid << "." << JRNL_DATA_EXTENSION; - std::ofstream ofsp(oss.str().c_str(), - std::ios_base::in | std::ios_base::out | std::ios_base::binary); - if (!ofsp.good()) - throw jexception(jerrno::JERR__FILEIO, oss.str(), "jcntl", "check_journal_alignment"); - ofsp.seekp(file_pos); - void* buff = std::malloc(JRNL_DBLK_SIZE); - assert(buff != 0); - std::memcpy(buff, (const void*)&xmagic, sizeof(xmagic)); - // Normally, RHM_CLEAN must be set before these fills are done, but this is a recover - // situation (i.e. performance is not an issue), and it makes the location of the write - // clear should inspection of the file be required. - std::memset((char*)buff + sizeof(xmagic), RHM_CLEAN_CHAR, JRNL_DBLK_SIZE - sizeof(xmagic)); - - while (file_pos % (JRNL_DBLK_SIZE * JRNL_SBLK_SIZE)) - { - ofsp.write((const char*)buff, JRNL_DBLK_SIZE); - assert(!ofsp.fail()); - std::ostringstream oss; - oss << std::hex << "Recover phase write: Wrote filler record: fid=0x" << fid << " offs=0x" << file_pos; - this->log(LOG_NOTICE, oss.str()); - file_pos = ofsp.tellp(); - } - ofsp.close(); - std::free(buff); - rd._lfid = fid; - if (!rd._frot) - rd._ffid = (fid + 1) % rd._njf; - this->log(LOG_INFO, "Bad record alignment fixed."); - } - rd._eo = file_pos; -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jcntl.h b/qpid/cpp/src/qpid/legacystore/jrnl/jcntl.h deleted file mode 100644 index 294e9ced05..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jcntl.h +++ /dev/null @@ -1,722 +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. - * - */ - -/** - * \file jcntl.h - * - * Qpid asynchronous store plugin library - * - * Messaging journal top-level control and interface class - * mrg::journal::jcntl. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_JCNTL_H -#define QPID_LEGACYSTORE_JRNL_JCNTL_H - -namespace mrg -{ -namespace journal -{ - class jcntl; -} -} - -#include -#include -#include "qpid/legacystore/jrnl/jdir.h" -#include "qpid/legacystore/jrnl/fcntl.h" -#include "qpid/legacystore/jrnl/lpmgr.h" -#include "qpid/legacystore/jrnl/rcvdat.h" -#include "qpid/legacystore/jrnl/slock.h" -#include "qpid/legacystore/jrnl/smutex.h" -#include "qpid/legacystore/jrnl/rmgr.h" -#include "qpid/legacystore/jrnl/wmgr.h" -#include "qpid/legacystore/jrnl/wrfc.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \brief Access and control interface for the journal. This is the top-level class for the - * journal. - * - * This is the top-level journal class; one instance of this class controls one instance of the - * journal and all its files and associated control structures. Besides this class, the only - * other class that needs to be used at a higher level is the data_tok class, one instance of - * which is used per data block written to the journal, and is used to track its status through - * the AIO enqueue, read and dequeue process. - */ - class jcntl - { - protected: - /** - * \brief Journal ID - * - * This string uniquely identifies this journal instance. It will most likely be associated - * with the identity of the message queue with which it is associated. - */ - // TODO: This is not included in any files at present, add to file_hdr? - std::string _jid; - - /** - * \brief Journal directory - * - * This string stores the path to the journal directory. It may be absolute or relative, and - * should not end in a file separator character. (e.g. "/fastdisk/jdata" is correct, - * "/fastdisk/jdata/" is not.) - */ - jdir _jdir; - - /** - * \brief Base filename - * - * This string contains the base filename used for the journal files. The filenames will - * start with this base, and have various sections added to it to derive the final file names - * that will be written to disk. No file separator characters should be included here, but - * all other legal filename characters are valid. - */ - std::string _base_filename; - - /** - * \brief Initialized flag - * - * This flag starts out set to false, is set to true once this object has been initialized, - * either by calling initialize() or recover(). - */ - bool _init_flag; - - /** - * \brief Stopped flag - * - * This flag starts out false, and is set to true when stop() is called. At this point, the - * journal will no longer accept messages until either initialize() or recover() is called. - * There is no way other than through initialization to reset this flag. - */ - // TODO: It would be helpful to distinguish between states stopping and stopped. If stop(true) is called, - // then we are stopping, but must wait for all outstanding aios to return before being finally stopped. During - // this period, however, no new enqueue/dequeue/read requests may be accepted. - bool _stop_flag; - - /** - * \brief Read-only state flag used during recover. - * - * When true, this flag prevents journal write operations (enqueue and dequeue), but - * allows read to occur. It is used during recovery, and is reset when recovered() is - * called. - */ - bool _readonly_flag; - - /** - * \brief If set, calls stop() if the jouranl write pointer overruns dequeue low water - * marker. If not set, then attempts to write will throw exceptions until the journal - * file low water marker moves to the next journal file. - */ - bool _autostop; ///< Autostop flag - stops journal when overrun occurs - - // Journal control structures - u_int32_t _jfsize_sblks; ///< Journal file size in sblks - lpmgr _lpmgr; ///< LFID-PFID manager tracks inserted journal files - enq_map _emap; ///< Enqueue map for low water mark management - txn_map _tmap; ///< Transaction map open transactions - rrfc _rrfc; ///< Read journal rotating file controller - wrfc _wrfc; ///< Write journal rotating file controller - rmgr _rmgr; ///< Read page manager which manages AIO - wmgr _wmgr; ///< Write page manager which manages AIO - rcvdat _rcvdat; ///< Recovery data used for recovery - smutex _wr_mutex; ///< Mutex for journal writes - - public: - static timespec _aio_cmpl_timeout; ///< Timeout for blocking libaio returns - static timespec _final_aio_cmpl_timeout; ///< Timeout for blocking libaio returns when stopping or finalizing - - /** - * \brief Journal constructor. - * - * Constructor which sets the physical file location and base name. - * - * \param jid A unique identifier for this journal instance. - * \param jdir The directory which will contain the journal files. - * \param base_filename The string which will be used to start all journal filenames. - */ - jcntl(const std::string& jid, const std::string& jdir, const std::string& base_filename); - - /** - * \brief Destructor. - */ - virtual ~jcntl(); - - inline const std::string& id() const { return _jid; } - inline const std::string& jrnl_dir() const { return _jdir.dirname(); } - - /** - * \brief Initialize the journal for storing data. - * - * Initialize the journal by creating new journal data files and initializing internal - * control structures. When complete, the journal will be empty, and ready to store data. - * - * NOTE: Any existing journal will be ignored by this operation. To use recover - * the data from an existing journal, use recover(). - * - * NOTE: If NULL is passed to the deque pointers, they will be internally created - * and deleted. - * - * NOTE: If NULL is passed to the callbacks, internal default callbacks will be - * used. - * - * \param num_jfiles The number of journal files to be created. - * \param auto_expand If true, allows journal file auto-expansion. In this mode, the journal will automatically - * add files to the journal if it runs out of space. No more than ae_max_jfiles may be added. If false, then - * no files are added and an exception will be thrown if the journal runs out of file space. - * \param ae_max_jfiles Upper limit of journal files for auto-expand mode. When auto_expand is true, this is the - * maximum total number of files allowed in the journal (original plus those added by auto-expand mode). If - * this number of files exist and the journal runs out of space, an exception will be thrown. This number - * must be greater than the num_jfiles parameter value but cannot exceed the maximum number of files for a - * single journal; if num_jfiles is already at its maximum value, then auto-expand will be disabled. - * \param jfsize_sblks The size of each journal file expressed in softblocks. - * \param wcache_num_pages The number of write cache pages to create. - * \param wcache_pgsize_sblks The size in sblks of each write cache page. - * \param cbp Pointer to object containing callback functions for read and write operations. May be 0 (NULL). - * - * \exception TODO - */ - void initialize(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks, - aio_callback* const cbp); - - /** - * /brief Initialize journal by recovering state from previously written journal. - * - * Initialize journal by recovering state from previously written journal. The journal files - * are analyzed, and all records that have not been dequeued and that remain in the journal - * will be available for reading. The journal is placed in a read-only state until - * recovered() is called; any calls to enqueue or dequeue will fail with an exception - * in this state. - * - * NOTE: If NULL is passed to the deque pointers, they will be internally created - * and deleted. - * - * NOTE: If NULL is passed to the callbacks, internal default callbacks will be - * used. - * - * \param num_jfiles The number of journal files to be created. - * \param auto_expand If true, allows journal file auto-expansion. In this mode, the journal will automatically - * add files to the journal if it runs out of space. No more than ae_max_jfiles may be added. If false, then - * no files are added and an exception will be thrown if the journal runs out of file space. - * \param ae_max_jfiles Upper limit of journal files for auto-expand mode. When auto_expand is true, this is the - * maximum total number of files allowed in the journal (original plus those added by auto-expand mode). If - * this number of files exist and the journal runs out of space, an exception will be thrown. This number - * must be greater than the num_jfiles parameter value but cannot exceed the maximum number of files for a - * single journal; if num_jfiles is already at its maximum value, then auto-expand will be disabled. - * \param jfsize_sblks The size of each journal file expressed in softblocks. - * \param wcache_num_pages The number of write cache pages to create. - * \param wcache_pgsize_sblks The size in sblks of each write cache page. - * \param cbp Pointer to object containing callback functions for read and write operations. May be 0 (NULL). - * \param prep_txn_list_ptr - * \param highest_rid Returns the highest rid found in the journal during recover - * - * \exception TODO - */ - void recover(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks, - aio_callback* const cbp, const std::vector* prep_txn_list_ptr, u_int64_t& highest_rid); - - /** - * \brief Notification to the journal that recovery is complete and that normal operation - * may resume. - * - * This call notifies the journal that recovery is complete and that normal operation - * may resume. The read pointers are reset so that all records read as a part of recover - * may be re-read during normal operation. The read-only flag is then reset, allowing - * enqueue and dequeue operations to resume. - * - * \exception TODO - */ - void recover_complete(); - - /** - * \brief Stops journal and deletes all journal files. - * - * Clear the journal directory of all journal files matching the base filename. - * - * \exception TODO - */ - void delete_jrnl_files(); - - /** - * \brief Enqueue data. - * - * Enqueue data or part thereof. If a large data block is being written, then it may be - * enqueued in parts by setting this_data_len to the size of the data being written in this - * call. The total data size must be known in advance, however, as this is written into the - * record header on the first record write. The state of the write (i.e. how much has been - * written so far) is maintained in the data token dtokp. Partial writes will return in state - * ENQ_PART. - * - * Note that a return value of anything other than RHM_IORES_SUCCESS implies that this write - * operation did not complete successfully or was partially completed. The action taken under - * these conditions depends on the value of the return. For example, RHM_IORES_AIO_WAIT - * implies that all pages in the write page cache are waiting for AIO operations to return, - * and that the call should be remade after waiting a bit. - * - * Example: If a write of 99 kB is divided into three equal parts, then the following states - * and returns would characterize a successful operation: - *
-        *                            dtok.    dtok.   dtok.
-        * Pperation         Return   wstate() dsize() written() Comment
-        * -----------------+--------+--------+-------+---------+------------------------------------
-        *                            NONE     0       0         Value of dtok before op
-        * edr(99000, 33000) SUCCESS  ENQ_PART 99000   33000     Enqueue part 1
-        * edr(99000, 33000) AIO_WAIT ENQ_PART 99000   50000     Enqueue part 2, not completed
-        * edr(99000, 33000) SUCCESS  ENQ_PART 99000   66000     Enqueue part 2 again
-        * edr(99000, 33000) SUCCESS  ENQ      99000   99000     Enqueue part 3
-        * 
- * - * \param data_buff Pointer to data to be enqueued for this enqueue operation. - * \param tot_data_len Total data length. - * \param this_data_len Amount to be written in this enqueue operation. - * \param dtokp Pointer to data token which contains the details of the enqueue operation. - * \param transient Flag indicating transient persistence (ie, ignored on recover). - * - * \exception TODO - */ - iores enqueue_data_record(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const bool transient = false); - - iores enqueue_extern_data_record(const std::size_t tot_data_len, data_tok* dtokp, - const bool transient = false); - - /** - * \brief Enqueue data. - * - * \param data_buff Pointer to data to be enqueued for this enqueue operation. - * \param tot_data_len Total data length. - * \param this_data_len Amount to be written in this enqueue operation. - * \param dtokp Pointer to data token which contains the details of the enqueue operation. - * \param xid String containing xid. An empty string (i.e. length=0) will be considered - * non-transactional. - * \param transient Flag indicating transient persistence (ie, ignored on recover). - * - * \exception TODO - */ - iores enqueue_txn_data_record(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const std::string& xid, - const bool transient = false); - iores enqueue_extern_txn_data_record(const std::size_t tot_data_len, data_tok* dtokp, - const std::string& xid, const bool transient = false); - - /* TODO - ** - * \brief Retrieve details of next record to be read without consuming the record. - * - * Retrieve information about current read record. A pointer to the data is returned, along - * with the data size and available data size. Data is considered "available" when the AIO - * operations to fill page-cache pages from disk have returned, and is ready for consumption. - * - * If dsize_avail < dsize, then not all of the data is available or part of - * the data is in non-contiguous memory, and a subsequent call will update both the pointer - * and dsize_avail if more pages have returned from AIO. - * - * The dsize_avail parameter will return the amount of data from this record that is - * available in the page cache as contiguous memory, even if it spans page cache boundaries. - * However, if a record spans the end of the page cache and continues at the beginning, even - * if both parts are ready for consumption, then this must be divided into at least two - * get_data_record() operations, as the data is contained in at least two non-contiguous - * segments of the page cache. - * - * Once all the available data for a record is exposed, it can not be read again using - * this function. It must be consumed prior to getting the next record. This can be done by - * calling discard_data_record() or read_data_record(). However, if parameter - * auto_discard is set to true, then this record will be automatically - * consumed when the entire record has become available without having to explicitly call - * discard_next_data_record() or read_data_record(). - * - * If the current record is an open transactional record, then it cannot be read until it is - * committed. If it is aborted, it can never be read. Under this condition, get_data_record() - * will return RHM_IORES_TXPENDING, the data pointer will be set to NULL and all data - * lengths will be set to 0. - * - * Example: Read a record of 30k. Assume a read page cache of 10 pages of size 10k starting - * at address base_ptr (page0 = base_ptr, page1 = page_ptr+10k, etc.). The first 15k of - * the record falls at the end of the page cache, the remaining 15k folded to the beginning. - * The current page (page 8) containing 5k is available, the remaining pages which contain - * this record are pending AIO return: - *
-        * call       dsize
-        * no.  dsize avail data ptr     Return   Comment
-        * ----+-----+-----+------------+--------+--------------------------------------------------
-        * 1    30k   5k    base_ptr+85k SUCCESS  Initial call, read first 5k
-        * 2    30k   0k    base_ptr+90k AIO_WAIT AIO still pending; no further pages avail
-        * 3    30k   10k   base_ptr+90k SUCCESS  AIO now returned; now read till end of page cache
-        * 4    30k   15k   base_ptr     SUCCESS  data_ptr now pointing to start of page cache
-        * 
- * - * \param rid Reference that returns the record ID (rid) - * \param dsize Reference that returns the total data size of the record data . - * \param dsize_avail Reference that returns the amount of the data that is available for - * consumption. - * \param data Pointer to data pointer which will point to the first byte of the next record - * data. - * \param auto_discard If true, automatically discard the record being read if - * the entire record is available (i.e. dsize == dsize_avail). Otherwise - * discard_next_data_record() must be explicitly called. - * - * \exception TODO - * - // *** NOT YET IMPLEMENTED *** - iores get_data_record(const u_int64_t& rid, const std::size_t& dsize, - const std::size_t& dsize_avail, const void** const data, bool auto_discard = false); - */ - - /* TODO - ** - * \brief Discard (skip) next record to be read without reading or retrieving it. - * - * \exception TODO - * - // *** NOT YET IMPLEMENTED *** - iores discard_data_record(data_tok* const dtokp); - */ - - /** - * \brief Reads data from the journal. It is the responsibility of the reader to free - * the memory that is allocated through this call - see below for details. - * - * Reads the next non-dequeued data record from the journal. - * - * Note that this call allocates memory into which the data and XID are copied. It - * is the responsibility of the caller to free this memory. The memory for the data and - * XID are allocated in a single call, and the XID precedes the data in the memory space. - * Thus, where an XID exists, freeing the XID pointer will free both the XID and data memory. - * However, if an XID does not exist for the message, the XID pointer xidpp is set to NULL, - * and it is the data pointer datapp that must be freed. Should neither an XID nor data be - * present (ie an empty record), then no memory is allocated, and both pointers will be NULL. - * In this case, there is no need to free memory. - * - * TODO: Fix this lousy interface. The caller should NOT be required to clean up these - * pointers! Rather use a struct, or better still, let the data token carry the data and - * xid pointers and lengths, and have the data token both allocate and delete. - * - * \param datapp Pointer to pointer that will be set to point to memory allocated and - * containing the data. Will be set to NULL if the call fails or there is no data - * in the record. - * \param dsize Ref that will be set to the size of the data. Will be set to 0 if the call - * fails or if there is no data in the record. - * \param xidpp Pointer to pointer that will be set to point to memory allocated and - * containing the XID. Will be set to NULL if the call fails or there is no XID attached - * to this record. - * \param xidsize Ref that will be set to the size of the XID. - * \param transient Ref that will be set true if record is transient. - * \param external Ref that will be set true if record is external. In this case, the data - * pointer datapp will be set to NULL, but dsize will contain the size of the data. - * NOTE: If there is an xid, then xidpp must be freed. - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param ignore_pending_txns When false (default), if the next record to be read is locked - * by a pending transaction, the read fails with RHM_IORES_TXPENDING. However, if set - * to true, then locks are ignored. This is required for reading of the Transaction - * Prepared List (TPL) which may have its entries locked, but may be read from - * time-to-time, and needs all its records (locked and unlocked) to be available. - * - * \exception TODO - */ - iores read_data_record(void** const datapp, std::size_t& dsize, void** const xidpp, - std::size_t& xidsize, bool& transient, bool& external, data_tok* const dtokp, - bool ignore_pending_txns = false); - - /** - * \brief Dequeues (marks as no longer needed) data record in journal. - * - * Dequeues (marks as no longer needed) data record in journal. Note that it is possible - * to use the same data token instance used to enqueue this data; it contains the record ID - * needed to correctly mark this data as dequeued in the journal. Otherwise the RID of the - * record to be dequeued and the write state of ENQ must be manually set in a new or reset - * instance of data_tok. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param txn_coml_commit Only used for preparedXID journal. When used for dequeueing - * prepared XID list items, sets whether the complete() was called in commit or abort - * mode. - * - * \exception TODO - */ - iores dequeue_data_record(data_tok* const dtokp, const bool txn_coml_commit = false); - - /** - * \brief Dequeues (marks as no longer needed) data record in journal. - * - * Dequeues (marks as no longer needed) data record in journal as part of a transaction. - * Note that it is possible to use the same data token instance used to enqueue this data; - * it contains the RID needed to correctly mark this data as dequeued in the journal. - * Otherwise the RID of the record to be dequeued and the write state of ENQ must be - * manually set in a new or reset instance of data_tok. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. An empty string (i.e. length=0) will be considered - * non-transactional. - * \param txn_coml_commit Only used for preparedXID journal. When used for dequeueing - * prepared XID list items, sets whether the complete() was called in commit or abort - * mode. - * - * \exception TODO - */ - iores dequeue_txn_data_record(data_tok* const dtokp, const std::string& xid, const bool txn_coml_commit = false); - - /** - * \brief Abort the transaction for all records enqueued or dequeued with the matching xid. - * - * Abort the transaction for all records enqueued with the matching xid. All enqueued records - * are effectively deleted from the journal, and can not be read. All dequeued records remain - * as though they had never been dequeued. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. - * - * \exception TODO - */ - iores txn_abort(data_tok* const dtokp, const std::string& xid); - - /** - * \brief Commit the transaction for all records enqueued or dequeued with the matching xid. - * - * Commit the transaction for all records enqueued with the matching xid. All enqueued - * records are effectively released for reading and dequeueing. All dequeued records are - * removed and can no longer be accessed. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. - * - * \exception TODO - */ - iores txn_commit(data_tok* const dtokp, const std::string& xid); - - /** - * \brief Check whether all the enqueue records for the given xid have reached disk. - * - * \param xid String containing xid. - * - * \exception TODO - */ - bool is_txn_synced(const std::string& xid); - - /** - * \brief Forces a check for returned AIO write events. - * - * Forces a check for returned AIO write events. This is normally performed by enqueue() and - * dequeue() operations, but if these operations cease, then this call needs to be made to - * force the processing of any outstanding AIO operations. - */ - int32_t get_wr_events(timespec* const timeout); - - /** - * \brief Forces a check for returned AIO read events. - * - * Forces a check for returned AIO read events. This is normally performed by read_data() - * operations, but if these operations cease, then this call needs to be made to force the - * processing of any outstanding AIO operations. - */ - int32_t get_rd_events(timespec* const timeout); - - /** - * \brief Stop the journal from accepting any further requests to read or write data. - * - * This operation is used to stop the journal. This is the normal mechanism for bringing the - * journal to an orderly stop. Any outstanding AIO operations or partially written pages in - * the write page cache will by flushed and will complete. - * - * Note: The journal cannot be restarted without either initializing it or restoring - * it. - * - * \param block_till_aio_cmpl If true, will block the thread while waiting for all - * outstanding AIO operations to complete. - */ - void stop(const bool block_till_aio_cmpl = false); - - /** - * \brief Force a flush of the write page cache, creating a single AIO write operation. - */ - iores flush(const bool block_till_aio_cmpl = false); - - inline u_int32_t get_enq_cnt() const { return _emap.size(); } - - inline u_int32_t get_wr_aio_evt_rem() const { slock l(_wr_mutex); return _wmgr.get_aio_evt_rem(); } - - inline u_int32_t get_rd_aio_evt_rem() const { return _rmgr.get_aio_evt_rem(); } - - inline u_int32_t get_wr_outstanding_aio_dblks() const - { return _wrfc.aio_outstanding_dblks(); } - - inline u_int32_t get_wr_outstanding_aio_dblks(u_int16_t lfid) const - { return _lpmgr.get_fcntlp(lfid)->wr_aio_outstanding_dblks(); } - - inline u_int32_t get_rd_outstanding_aio_dblks() const - { return _rrfc.aio_outstanding_dblks(); } - - inline u_int32_t get_rd_outstanding_aio_dblks(u_int16_t lfid) const - { return _lpmgr.get_fcntlp(lfid)->rd_aio_outstanding_dblks(); } - - inline u_int16_t get_rd_fid() const { return _rrfc.index(); } - inline u_int16_t get_wr_fid() const { return _wrfc.index(); } - u_int16_t get_earliest_fid(); - - /** - * \brief Check if a particular rid is enqueued. Note that this function will return - * false if the rid is transactionally enqueued and is not committed, or if it is - * locked (i.e. transactionally dequeued, but the dequeue has not been committed). - */ - inline bool is_enqueued(const u_int64_t rid, bool ignore_lock = false) - { return _emap.is_enqueued(rid, ignore_lock); } - inline bool is_locked(const u_int64_t rid) - { if (_emap.is_enqueued(rid, true) < enq_map::EMAP_OK) return false; return _emap.is_locked(rid) == enq_map::EMAP_TRUE; } - inline void enq_rid_list(std::vector& rids) { _emap.rid_list(rids); } - inline void enq_xid_list(std::vector& xids) { _tmap.xid_list(xids); } - inline u_int32_t get_open_txn_cnt() const { return _tmap.size(); } - // TODO Make this a const, but txn_map must support const first. - inline txn_map& get_txn_map() { return _tmap; } - - /** - * \brief Check if the journal is stopped. - * - * \return true if the jouranl is stopped; - * false otherwise. - */ - inline bool is_stopped() { return _stop_flag; } - - /** - * \brief Check if the journal is ready to read and write data. - * - * Checks if the journal is ready to read and write data. This function will return - * true if the journal has been either initialized or restored, and the stop() - * function has not been called since the initialization. - * - * Note that the journal may also be stopped if an internal error occurs (such as running out - * of data journal file space). - * - * \return true if the journal is ready to read and write data; - * false otherwise. - */ - inline bool is_ready() const { return _init_flag && !_stop_flag; } - - inline bool is_read_only() const { return _readonly_flag; } - - /** - * \brief Get the journal directory. - * - * This returns the journal directory as set during initialization. This is the directory - * into which the journal files will be written. - */ - inline const std::string& dirname() const { return _jdir.dirname(); } - - /** - * \brief Get the journal base filename. - * - * Get the journal base filename as set during initialization. This is the prefix used in all - * journal files of this instance. Note that if more than one instance of the journal shares - * the same directory, their base filenames MUST be different or else the instances - * will overwrite one another. - */ - inline const std::string& base_filename() const { return _base_filename; } - - inline u_int16_t num_jfiles() const { return _lpmgr.num_jfiles(); } - - inline fcntl* get_fcntlp(const u_int16_t lfid) const { return _lpmgr.get_fcntlp(lfid); } - - inline u_int32_t jfsize_sblks() const { return _jfsize_sblks; } - - // Logging - virtual void log(log_level level, const std::string& log_stmt) const; - virtual void log(log_level level, const char* const log_stmt) const; - - // FIXME these are _rmgr to _wmgr interactions, remove when _rmgr contains ref to _wmgr: - void chk_wr_frot(); - inline u_int32_t unflushed_dblks() { return _wmgr.unflushed_dblks(); } - void fhdr_wr_sync(const u_int16_t lid); - inline u_int32_t wr_subm_cnt_dblks(const u_int16_t lfid) const { return _lpmgr.get_fcntlp(lfid)->wr_subm_cnt_dblks(); } - - // Management instrumentation callbacks - inline virtual void instr_incr_outstanding_aio_cnt() {} - inline virtual void instr_decr_outstanding_aio_cnt() {} - - /** - * /brief Static function for creating new fcntl objects for use with obj_arr. - */ - static fcntl* new_fcntl(jcntl* const jcp, const u_int16_t lid, const u_int16_t fid, const rcvdat* const rdp); - - protected: - static bool _init; - static bool init_statics(); - - /** - * \brief Check status of journal before allowing write operations. - */ - void check_wstatus(const char* fn_name) const; - - /** - * \brief Check status of journal before allowing read operations. - */ - void check_rstatus(const char* fn_name) const; - - /** - * \brief Write info file <basefilename>.jinf to disk - */ - void write_infofile() const; - - /** - * \brief Call that blocks while waiting for all outstanding AIOs to complete - */ - void aio_cmpl_wait(); - - /** - * \brief Call that blocks until at least one message returns; used to wait for - * AIO wait conditions to clear. - */ - bool handle_aio_wait(const iores res, iores& resout, const data_tok* dtp); - - /** - * \brief Analyze journal for recovery. - */ - void rcvr_janalyze(rcvdat& rd, const std::vector* prep_txn_list_ptr); - - bool rcvr_get_next_record(u_int16_t& fid, std::ifstream* ifsp, bool& lowi, rcvdat& rd); - - bool decode(jrec& rec, u_int16_t& fid, std::ifstream* ifsp, std::size_t& cum_size_read, - rec_hdr& h, bool& lowi, rcvdat& rd, std::streampos& rec_offset); - - bool jfile_cycle(u_int16_t& fid, std::ifstream* ifsp, bool& lowi, rcvdat& rd, - const bool jump_fro); - - bool check_owi(const u_int16_t fid, rec_hdr& h, bool& lowi, rcvdat& rd, - std::streampos& read_pos); - - void check_journal_alignment(const u_int16_t fid, std::streampos& rec_offset, rcvdat& rd); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_JCNTL_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jdir.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/jdir.cpp deleted file mode 100644 index a874c6c945..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jdir.cpp +++ /dev/null @@ -1,463 +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. - * - */ - -/** - * \file jdir.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::jdir (journal data - * directory), used for controlling and manipulating journal data - * direcories and files. See comments in file jdir.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/jdir.h" - -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/jcfg.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - -jdir::jdir(const std::string& dirname, const std::string& _base_filename): - _dirname(dirname), - _base_filename(_base_filename) -{} - -jdir::~jdir() -{} - -// === create_dir === - -void -jdir::create_dir() -{ - create_dir(_dirname); -} - - -void -jdir::create_dir(const char* dirname) -{ - create_dir(std::string(dirname)); -} - - -void -jdir::create_dir(const std::string& dirname) -{ - std::size_t fdp = dirname.find_last_of('/'); - if (fdp != std::string::npos) - { - std::string parent_dir = dirname.substr(0, fdp); - if (!exists(parent_dir)) - create_dir(parent_dir); - } - if (::mkdir(dirname.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) - { - if (errno != EEXIST) // Dir exists, ignore - { - std::ostringstream oss; - oss << "dir=\"" << dirname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_MKDIR, oss.str(), "jdir", "create_dir"); - } - } -} - - -// === clear_dir === - -void -jdir::clear_dir(const bool create_flag) -{ - clear_dir(_dirname, _base_filename, create_flag); -} - -void -jdir::clear_dir(const char* dirname, const char* base_filename, const bool create_flag) -{ - clear_dir(std::string(dirname), std::string(base_filename), create_flag); -} - - -void -jdir::clear_dir(const std::string& dirname, const std::string& -#ifndef RHM_JOWRITE - base_filename -#endif - , const bool create_flag) -{ - DIR* dir = ::opendir(dirname.c_str()); - if (!dir) - { - if (errno == 2 && create_flag) // ENOENT (No such file or dir) - { - create_dir(dirname); - return; - } - std::ostringstream oss; - oss << "dir=\"" << dirname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_OPENDIR, oss.str(), "jdir", "clear_dir"); - } -#ifndef RHM_JOWRITE - struct dirent* entry; - bool found = false; - std::string bak_dir; - while ((entry = ::readdir(dir)) != 0) - { - // Ignore . and .. - if (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) - { - if (std::strlen(entry->d_name) > base_filename.size()) - { - if (std::strncmp(entry->d_name, base_filename.c_str(), base_filename.size()) == 0) - { - if (!found) - { - bak_dir = create_bak_dir(dirname, base_filename); - found = true; - } - std::ostringstream oldname; - oldname << dirname << "/" << entry->d_name; - std::ostringstream newname; - newname << bak_dir << "/" << entry->d_name; - if (::rename(oldname.str().c_str(), newname.str().c_str())) - { - ::closedir(dir); - std::ostringstream oss; - oss << "file=\"" << oldname.str() << "\" dest=\"" << - newname.str() << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "jdir", "clear_dir"); - } - } - } - } - } -// FIXME: Find out why this fails with false alarms/errors from time to time... -// While commented out, there is no error capture from reading dir entries. -// check_err(errno, dir, dirname, "clear_dir"); -#endif - close_dir(dir, dirname, "clear_dir"); -} - -// === push_down === - -std::string -jdir::push_down(const std::string& dirname, const std::string& target_dir, const std::string& bak_dir_base) -{ - std::string bak_dir_name = create_bak_dir(dirname, bak_dir_base); - - DIR* dir = ::opendir(dirname.c_str()); - if (!dir) - { - std::ostringstream oss; - oss << "dir=\"" << dirname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_OPENDIR, oss.str(), "jdir", "push_down"); - } - // Copy contents of targetDirName into bak dir - struct dirent* entry; - while ((entry = ::readdir(dir)) != 0) - { - // Search for targetDirName in storeDirName - if (std::strcmp(entry->d_name, target_dir.c_str()) == 0) - { - std::ostringstream oldname; - oldname << dirname << "/" << target_dir; - std::ostringstream newname; - newname << bak_dir_name << "/" << target_dir; - if (::rename(oldname.str().c_str(), newname.str().c_str())) - { - ::closedir(dir); - std::ostringstream oss; - oss << "file=\"" << oldname.str() << "\" dest=\"" << newname.str() << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "jdir", "push_down"); - } - break; - } - } - close_dir(dir, dirname, "push_down"); - return bak_dir_name; -} - -// === verify_dir === - -void -jdir::verify_dir() -{ - verify_dir(_dirname, _base_filename); -} - -void -jdir::verify_dir(const char* dirname, const char* base_filename) -{ - verify_dir(std::string(dirname), std::string(base_filename)); -} - - -void -jdir::verify_dir(const std::string& dirname, const std::string& base_filename) -{ - if (!is_dir(dirname)) - { - std::ostringstream oss; - oss << "dir=\"" << dirname << "\""; - throw jexception(jerrno::JERR_JDIR_NOTDIR, oss.str(), "jdir", "verify_dir"); - } - - // Read jinf file, then verify all journal files are present - jinf ji(dirname + "/" + base_filename + "." + JRNL_INFO_EXTENSION, true); - for (u_int16_t fnum=0; fnum < ji.num_jfiles(); fnum++) - { - std::ostringstream oss; - oss << dirname << "/" << base_filename << "."; - oss << std::setw(4) << std::setfill('0') << std::hex << fnum; - oss << "." << JRNL_DATA_EXTENSION; - if (!exists(oss.str())) - throw jexception(jerrno::JERR_JDIR_NOSUCHFILE, oss.str(), "jdir", "verify_dir"); - } -} - - -// === delete_dir === - -void -jdir::delete_dir(bool children_only) -{ - delete_dir(_dirname, children_only); -} - -void -jdir::delete_dir(const char* dirname, bool children_only) -{ - delete_dir(std::string(dirname), children_only); -} - -void -jdir::delete_dir(const std::string& dirname, bool children_only) -{ - struct dirent* entry; - struct stat s; - DIR* dir = ::opendir(dirname.c_str()); - if (!dir) - { - if (errno == ENOENT) // dir does not exist. - return; - - std::ostringstream oss; - oss << "dir=\"" << dirname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_OPENDIR, oss.str(), "jdir", "delete_dir"); - } - else - { - while ((entry = ::readdir(dir)) != 0) - { - // Ignore . and .. - if (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) - { - std::string full_name(dirname + "/" + entry->d_name); - if (::lstat(full_name.c_str(), &s)) - { - ::closedir(dir); - std::ostringstream oss; - oss << "stat: file=\"" << full_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_STAT, oss.str(), "jdir", "delete_dir"); - } - if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) // This is a file or slink - { - if(::unlink(full_name.c_str())) - { - ::closedir(dir); - std::ostringstream oss; - oss << "unlink: file=\"" << entry->d_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_UNLINK, oss.str(), "jdir", "delete_dir"); - } - } - else if (S_ISDIR(s.st_mode)) // This is a dir - { - delete_dir(full_name); - } - else // all other types, throw up! - { - ::closedir(dir); - std::ostringstream oss; - oss << "file=\"" << entry->d_name << "\" is not a dir, file or slink."; - oss << " (mode=0x" << std::hex << s.st_mode << std::dec << ")"; - throw jexception(jerrno::JERR_JDIR_BADFTYPE, oss.str(), "jdir", "delete_dir"); - } - } - } - -// FIXME: Find out why this fails with false alarms/errors from time to time... -// While commented out, there is no error capture from reading dir entries. -// check_err(errno, dir, dirname, "delete_dir"); - } - // Now dir is empty, close and delete it - close_dir(dir, dirname, "delete_dir"); - - if (!children_only) - if (::rmdir(dirname.c_str())) - { - std::ostringstream oss; - oss << "dir=\"" << dirname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_RMDIR, oss.str(), "jdir", "delete_dir"); - } -} - - -std::string -jdir::create_bak_dir(const std::string& dirname, const std::string& base_filename) -{ - DIR* dir = ::opendir(dirname.c_str()); - long dir_num = 0L; - if (!dir) - { - std::ostringstream oss; - oss << "dir=\"" << dirname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_OPENDIR, oss.str(), "jdir", "create_bak_dir"); - } - struct dirent* entry; - while ((entry = ::readdir(dir)) != 0) - { - // Ignore . and .. - if (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) - { - if (std::strlen(entry->d_name) == base_filename.size() + 10) // Format: basename.bak.XXXX - { - std::ostringstream oss; - oss << "_" << base_filename << ".bak."; - if (std::strncmp(entry->d_name, oss.str().c_str(), base_filename.size() + 6) == 0) - { - long this_dir_num = std::strtol(entry->d_name + base_filename.size() + 6, 0, 16); - if (this_dir_num > dir_num) - dir_num = this_dir_num; - } - } - } - } -// FIXME: Find out why this fails with false alarms/errors from time to time... -// While commented out, there is no error capture from reading dir entries. -// check_err(errno, dir, dirname, "create_bak_dir"); - close_dir(dir, dirname, "create_bak_dir"); - - std::ostringstream dn; - dn << dirname << "/_" << base_filename << ".bak." << std::hex << std::setw(4) << - std::setfill('0') << ++dir_num; - if (::mkdir(dn.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH)) - { - std::ostringstream oss; - oss << "dir=\"" << dn.str() << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_MKDIR, oss.str(), "jdir", "create_bak_dir"); - } - return std::string(dn.str()); -} - -bool -jdir::is_dir(const char* name) -{ - struct stat s; - if (::stat(name, &s)) - { - std::ostringstream oss; - oss << "file=\"" << name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_STAT, oss.str(), "jdir", "is_dir"); - } - return S_ISDIR(s.st_mode); -} - -bool -jdir::is_dir(const std::string& name) -{ - return is_dir(name.c_str()); -} - -bool -jdir::exists(const char* name) -{ - struct stat s; - if (::stat(name, &s)) - { - if (errno == ENOENT) // No such dir or file - return false; - // Throw for any other condition - std::ostringstream oss; - oss << "file=\"" << name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_STAT, oss.str(), "jdir", "exists"); - } - return true; -} - -bool -jdir::exists(const std::string& name) -{ - return exists(name.c_str()); -} - -void -jdir::check_err(const int err_num, DIR* dir, const std::string& dir_name, const std::string& fn_name) -{ - if (err_num) - { - std::ostringstream oss; - oss << "dir=\"" << dir_name << "\"" << FORMAT_SYSERR(err_num); - ::closedir(dir); // Try to close, it makes no sense to trap errors here... - throw jexception(jerrno::JERR_JDIR_READDIR, oss.str(), "jdir", fn_name); - } -} - -void -jdir::close_dir(DIR* dir, const std::string& dir_name, const std::string& fn_name) -{ - if (::closedir(dir)) - { - std::ostringstream oss; - oss << "dir=\"" << dir_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_CLOSEDIR, oss.str(), "jdir", fn_name); - } -} - -std::ostream& -operator<<(std::ostream& os, const jdir& jdir) -{ - os << jdir._dirname; - return os; -} - -std::ostream& -operator<<(std::ostream& os, const jdir* jdirPtr) -{ - os << jdirPtr->_dirname; - return os; -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jdir.h b/qpid/cpp/src/qpid/legacystore/jrnl/jdir.h deleted file mode 100644 index e129b794d6..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jdir.h +++ /dev/null @@ -1,379 +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. - * - */ - -/** - * \file jdir.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::jdir (%journal data - * directory), used for controlling and manipulating %journal data - * directories and files. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_JDIR_H -#define QPID_LEGACYSTORE_JRNL_JDIR_H - -namespace mrg -{ -namespace journal -{ -class jdir; -} -} - -#include "qpid/legacystore/jrnl/jinf.h" -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class jdir - * \brief Class to manage the %journal directory - */ - class jdir - { - private: - std::string _dirname; - std::string _base_filename; - - public: - - /** - * \brief Sole constructor - * - * \param dirname Name of directory to be managed. - * \param base_filename Filename root used in the creation of %journal files - * and sub-directories. - */ - jdir(const std::string& dirname, const std::string& base_filename); - - virtual ~jdir(); - - - /** - * \brief Create %journal directory as set in the dirname parameter of the constructor. - * Recursive creation is supported. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - void create_dir(); - - /** - * \brief Static function to create a directory. Recursive creation is supported. - * - * \param dirname C-string containing name of directory. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - static void create_dir(const char* dirname); - - /** - * \brief Static function to create a directory. Recursive creation is supported. - * - * \param dirname String containing name of directory. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - static void create_dir(const std::string& dirname); - - - /** - * \brief Clear the %journal directory of files matching the base filename - * by moving them into a subdirectory. This fn uses the dirname and base_filename - * that were set on construction. - * - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - void clear_dir(const bool create_flag = true); - - /** - * \brief Clear the directory dirname of %journal files matching base_filename - * by moving them into a subdirectory. - * - * \param dirname C-string containing name of %journal directory. - * \param base_filename C-string containing base filename of %journal files to be matched - * for moving into subdirectory. - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void clear_dir(const char* dirname, const char* base_filename, - const bool create_flag = true); - - /** - * \brief Clear the directory dirname of %journal files matching base_filename - * by moving them into a subdirectory. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched - * for moving into subdirectory. - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void clear_dir(const std::string& dirname, const std::string& base_filename, - const bool create_flag = true); - - - - /** - * \brief Move (push down) the directory target_dir located in directory dirname into a backup directory - * named _bak_dir_base.XXXX (note prepended underscore), where XXXX is an increasing hex serial number - * starting at 0000. - * - * \param dirname Full path to directory containing directory to be pushed down. - * \param target_dir Name of directory in dirname to be pushed down. - * \param bak_dir_base Base name for backup directory to be created in dirname, into which target_dir will be moved. - * \return Name of backup dir into which target_dir was pushed. - */ - static std::string push_down(const std::string& dirname, const std::string& target_dir, const std::string& bak_dir_base); - - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - void verify_dir(); - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \param dirname C-string containing name of %journal directory. - * \param base_filename C-string containing base filename of %journal files to be matched for moving into sub-directory. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - static void verify_dir(const char* dirname, const char* base_filename); - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched for moving into sub-directory. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - static void verify_dir(const std::string& dirname, const std::string& base_filename); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - void delete_dir(bool children_only = false ); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param dirname C-string containing name of directory to be deleted. - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - static void delete_dir(const char* dirname, bool children_only = false); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param dirname String containing name of directory to be deleted. - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - static void delete_dir(const std::string& dirname, bool children_only = false); - - /** - * \brief Create bakup directory that is next in sequence and move all %journal files - * matching base_filename into it. - * - * In directory dirname, search for existing backup directory using pattern - * "_basename.bak.XXXX" where XXXX is a hexadecimal sequence, and create next directory - * based on highest number found. Move all %journal files which match the base_fileaname - * parameter into this new backup directory. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched - * for moving into subdirectory. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_MKDIR The backup directory could not be deleted. - */ - static std::string create_bak_dir(const std::string& dirname, - const std::string& base_filename); - - /** - * \brief Return the directory name as a string. - */ - inline const std::string& dirname() const { return _dirname; } - - /** - * \brief Return the %journal base filename name as a string. - */ - inline const std::string& base_filename() const { return _base_filename; } - - /** - * \brief Test whether the named file is a directory. - * - * \param name Name of file to be tested. - * \return true if the named file is a directory; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool is_dir(const char* name); - - /** - * \brief Test whether the named file is a directory. - * - * \param name Name of file to be tested. - * \return true if the named file is a directory; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool is_dir(const std::string& name); - - - /** - * \brief Test whether the named entity exists on the filesystem. - * - * If stat() fails with error ENOENT, then this will return false. If - * stat() succeeds, then true is returned, irrespective of the file type. - * If stat() fails with any other error, an exception is thrown. - * - * \param name Name of entity to be tested. - * \return true if the named entity exists; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool exists(const char* name); - - /** - * \brief Test whether the named entity exists on the filesystem. - * - * If stat() fails with error ENOENT, then this will return false. If - * stat() succeeds, then true is returned, irrespective of the file type. - * If stat() fails with any other error, an exception is thrown. - * - * \param name Name of entity to be tested. - * \return true if the named entity exists; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool exists(const std::string& name); - - /** - * \brief Stream operator - */ - friend std::ostream& operator<<(std::ostream& os, const jdir& jdir); - - /** - * \brief Stream operator - */ - friend std::ostream& operator<<(std::ostream& os, const jdir* jdirPtr); - - private: - /** - * \brief Check for error, if non-zero close DIR handle and throw JERR_JDIR_READDIR - * - * \exception jerrno::JERR_JDIR_READDIR Error while reading contents of dir. - */ - static void check_err(const int err_num, DIR* dir, const std::string& dir_name, const std::string& fn_name); - - /** - * \brief Close a DIR handle, throw JERR_JDIR_CLOSEDIR if error occurs during close - * - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void close_dir(DIR* dir, const std::string& dir_name, const std::string& fn_name); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_JDIR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jerrno.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/jerrno.cpp deleted file mode 100644 index 4962ce63ab..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jerrno.cpp +++ /dev/null @@ -1,253 +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. - * - */ - -/** - * \file jerrno.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::jerrno (journal error - * codes). See comments in file jerrno.h for details. - * - * See file jerrno.h for class details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/jerrno.h" - -namespace mrg -{ -namespace journal -{ - -std::map jerrno::_err_map; -std::map::iterator jerrno::_err_map_itr; -bool jerrno::_initialized = jerrno::__init(); - -// generic errors -const u_int32_t jerrno::JERR__MALLOC = 0x0100; -const u_int32_t jerrno::JERR__UNDERFLOW = 0x0101; -const u_int32_t jerrno::JERR__NINIT = 0x0102; -const u_int32_t jerrno::JERR__AIO = 0x0103; -const u_int32_t jerrno::JERR__FILEIO = 0x0104; -const u_int32_t jerrno::JERR__RTCLOCK = 0x0105; -const u_int32_t jerrno::JERR__PTHREAD = 0x0106; -const u_int32_t jerrno::JERR__TIMEOUT = 0x0107; -const u_int32_t jerrno::JERR__UNEXPRESPONSE = 0x0108; -const u_int32_t jerrno::JERR__RECNFOUND = 0x0109; -const u_int32_t jerrno::JERR__NOTIMPL = 0x010a; - -// class jcntl -const u_int32_t jerrno::JERR_JCNTL_STOPPED = 0x0200; -const u_int32_t jerrno::JERR_JCNTL_READONLY = 0x0201; -const u_int32_t jerrno::JERR_JCNTL_AIOCMPLWAIT = 0x0202; -const u_int32_t jerrno::JERR_JCNTL_UNKNOWNMAGIC = 0x0203; -const u_int32_t jerrno::JERR_JCNTL_NOTRECOVERED = 0x0204; -const u_int32_t jerrno::JERR_JCNTL_RECOVERJFULL = 0x0205; -const u_int32_t jerrno::JERR_JCNTL_OWIMISMATCH = 0x0206; - -// class jdir -const u_int32_t jerrno::JERR_JDIR_NOTDIR = 0x0300; -const u_int32_t jerrno::JERR_JDIR_MKDIR = 0x0301; -const u_int32_t jerrno::JERR_JDIR_OPENDIR = 0x0302; -const u_int32_t jerrno::JERR_JDIR_READDIR = 0x0303; -const u_int32_t jerrno::JERR_JDIR_CLOSEDIR = 0x0304; -const u_int32_t jerrno::JERR_JDIR_RMDIR = 0x0305; -const u_int32_t jerrno::JERR_JDIR_NOSUCHFILE = 0x0306; -const u_int32_t jerrno::JERR_JDIR_FMOVE = 0x0307; -const u_int32_t jerrno::JERR_JDIR_STAT = 0x0308; -const u_int32_t jerrno::JERR_JDIR_UNLINK = 0x0309; -const u_int32_t jerrno::JERR_JDIR_BADFTYPE = 0x030a; - -// class fcntl -const u_int32_t jerrno::JERR_FCNTL_OPENWR = 0x0400; -const u_int32_t jerrno::JERR_FCNTL_WRITE = 0x0401; -const u_int32_t jerrno::JERR_FCNTL_CLOSE = 0x0402; -const u_int32_t jerrno::JERR_FCNTL_FILEOFFSOVFL = 0x0403; -const u_int32_t jerrno::JERR_FCNTL_CMPLOFFSOVFL = 0x0404; -const u_int32_t jerrno::JERR_FCNTL_RDOFFSOVFL = 0x0405; - -// class lfmgr -const u_int32_t jerrno::JERR_LFMGR_BADAEFNUMLIM = 0x0500; -const u_int32_t jerrno::JERR_LFMGR_AEFNUMLIMIT = 0x0501; -const u_int32_t jerrno::JERR_LFMGR_AEDISABLED = 0x0502; - -// class rrfc -const u_int32_t jerrno::JERR_RRFC_OPENRD = 0x0600; - -// class jrec, enq_rec, deq_rec, txn_rec -const u_int32_t jerrno::JERR_JREC_BADRECHDR = 0x0700; -const u_int32_t jerrno::JERR_JREC_BADRECTAIL = 0x0701; - -// class wmgr -const u_int32_t jerrno::JERR_WMGR_BADPGSTATE = 0x0801; -const u_int32_t jerrno::JERR_WMGR_BADDTOKSTATE = 0x0802; -const u_int32_t jerrno::JERR_WMGR_ENQDISCONT = 0x0803; -const u_int32_t jerrno::JERR_WMGR_DEQDISCONT = 0x0804; -const u_int32_t jerrno::JERR_WMGR_DEQRIDNOTENQ = 0x0805; - -// class rmgr -const u_int32_t jerrno::JERR_RMGR_UNKNOWNMAGIC = 0x0900; -const u_int32_t jerrno::JERR_RMGR_RIDMISMATCH = 0x0901; -//const u_int32_t jerrno::JERR_RMGR_FIDMISMATCH = 0x0902; -const u_int32_t jerrno::JERR_RMGR_ENQSTATE = 0x0903; -const u_int32_t jerrno::JERR_RMGR_BADRECTYPE = 0x0904; - -// class data_tok -const u_int32_t jerrno::JERR_DTOK_ILLEGALSTATE = 0x0a00; -// const u_int32_t jerrno::JERR_DTOK_RIDNOTSET = 0x0a01; - -// class enq_map, txn_map -const u_int32_t jerrno::JERR_MAP_DUPLICATE = 0x0b00; -const u_int32_t jerrno::JERR_MAP_NOTFOUND = 0x0b01; -const u_int32_t jerrno::JERR_MAP_LOCKED = 0x0b02; - -// class jinf -const u_int32_t jerrno::JERR_JINF_CVALIDFAIL = 0x0c00; -const u_int32_t jerrno::JERR_JINF_NOVALUESTR = 0x0c01; -const u_int32_t jerrno::JERR_JINF_BADVALUESTR = 0x0c02; -const u_int32_t jerrno::JERR_JINF_JDATEMPTY = 0x0c03; -const u_int32_t jerrno::JERR_JINF_TOOMANYFILES = 0x0c04; -const u_int32_t jerrno::JERR_JINF_INVALIDFHDR = 0x0c05; -const u_int32_t jerrno::JERR_JINF_STAT = 0x0c06; -const u_int32_t jerrno::JERR_JINF_NOTREGFILE = 0x0c07; -const u_int32_t jerrno::JERR_JINF_BADFILESIZE = 0x0c08; -const u_int32_t jerrno::JERR_JINF_OWIBAD = 0x0c09; -const u_int32_t jerrno::JERR_JINF_ZEROLENFILE = 0x0c0a; - -// Negative returns for some functions -const int32_t jerrno::AIO_TIMEOUT = -1; -const int32_t jerrno::LOCK_TAKEN = -2; - - -// static initialization fn - -bool -jerrno::__init() -{ - // generic errors - _err_map[JERR__MALLOC] = "JERR__MALLOC: Buffer memory allocation failed."; - _err_map[JERR__UNDERFLOW] = "JERR__UNDERFLOW: Underflow error"; - _err_map[JERR__NINIT] = "JERR__NINIT: Operation on uninitialized class."; - _err_map[JERR__AIO] = "JERR__AIO: AIO error."; - _err_map[JERR__FILEIO] = "JERR__FILEIO: File read or write failure."; - _err_map[JERR__RTCLOCK] = "JERR__RTCLOCK: Reading real-time clock failed."; - _err_map[JERR__PTHREAD] = "JERR__PTHREAD: pthread failure."; - _err_map[JERR__TIMEOUT] = "JERR__TIMEOUT: Timeout waiting for event."; - _err_map[JERR__UNEXPRESPONSE] = "JERR__UNEXPRESPONSE: Unexpected response to call or event."; - _err_map[JERR__RECNFOUND] = "JERR__RECNFOUND: Record not found."; - _err_map[JERR__NOTIMPL] = "JERR__NOTIMPL: Not implemented"; - - // class jcntl - _err_map[JERR_JCNTL_STOPPED] = "JERR_JCNTL_STOPPED: Operation on stopped journal."; - _err_map[JERR_JCNTL_READONLY] = "JERR_JCNTL_READONLY: Write operation on read-only journal (during recovery)."; - _err_map[JERR_JCNTL_AIOCMPLWAIT] = "JERR_JCNTL_AIOCMPLWAIT: Timeout waiting for AIOs to complete."; - _err_map[JERR_JCNTL_UNKNOWNMAGIC] = "JERR_JCNTL_UNKNOWNMAGIC: Found record with unknown magic."; - _err_map[JERR_JCNTL_NOTRECOVERED] = "JERR_JCNTL_NOTRECOVERED: Operation requires recover() to be run first."; - _err_map[JERR_JCNTL_RECOVERJFULL] = "JERR_JCNTL_RECOVERJFULL: Journal data files full, cannot write."; - _err_map[JERR_JCNTL_OWIMISMATCH] = "JERR_JCNTL_OWIMISMATCH: Overwrite Indicator (OWI) change found in unexpected location."; - - // class jdir - _err_map[JERR_JDIR_NOTDIR] = "JERR_JDIR_NOTDIR: Directory name exists but is not a directory."; - _err_map[JERR_JDIR_MKDIR] = "JERR_JDIR_MKDIR: Directory creation failed."; - _err_map[JERR_JDIR_OPENDIR] = "JERR_JDIR_OPENDIR: Directory open failed."; - _err_map[JERR_JDIR_READDIR] = "JERR_JDIR_READDIR: Directory read failed."; - _err_map[JERR_JDIR_CLOSEDIR] = "JERR_JDIR_CLOSEDIR: Directory close failed."; - _err_map[JERR_JDIR_RMDIR] = "JERR_JDIR_RMDIR: Directory delete failed."; - _err_map[JERR_JDIR_NOSUCHFILE] = "JERR_JDIR_NOSUCHFILE: File does not exist."; - _err_map[JERR_JDIR_FMOVE] = "JERR_JDIR_FMOVE: File move failed."; - _err_map[JERR_JDIR_STAT] = "JERR_JDIR_STAT: File stat failed."; - _err_map[JERR_JDIR_UNLINK] = "JERR_JDIR_UNLINK: File delete failed."; - _err_map[JERR_JDIR_BADFTYPE] = "JERR_JDIR_BADFTYPE: Bad or unknown file type (stat mode)."; - - // class fcntl - _err_map[JERR_FCNTL_OPENWR] = "JERR_FCNTL_OPENWR: Unable to open file for write."; - _err_map[JERR_FCNTL_WRITE] = "JERR_FCNTL_WRITE: Unable to write to file."; - _err_map[JERR_FCNTL_CLOSE] = "JERR_FCNTL_CLOSE: File close failed."; - _err_map[JERR_FCNTL_FILEOFFSOVFL] = "JERR_FCNTL_FILEOFFSOVFL: Attempted increase file offset past file size."; - _err_map[JERR_FCNTL_CMPLOFFSOVFL] = "JERR_FCNTL_CMPLOFFSOVFL: Attempted increase completed file offset past submitted offset."; - _err_map[JERR_FCNTL_RDOFFSOVFL] = "JERR_FCNTL_RDOFFSOVFL: Attempted increase read offset past write offset."; - - // class lfmgr - _err_map[JERR_LFMGR_BADAEFNUMLIM] = "JERR_LFMGR_BADAEFNUMLIM: Auto-expand file number limit lower than initial number of journal files."; - _err_map[JERR_LFMGR_AEFNUMLIMIT] = "JERR_LFMGR_AEFNUMLIMIT: Exceeded auto-expand file number limit."; - _err_map[JERR_LFMGR_AEDISABLED] = "JERR_LFMGR_AEDISABLED: Attempted to expand with auto-expand disabled."; - - // class rrfc - _err_map[JERR_RRFC_OPENRD] = "JERR_RRFC_OPENRD: Unable to open file for read."; - - // class jrec, enq_rec, deq_rec, txn_rec - _err_map[JERR_JREC_BADRECHDR] = "JERR_JREC_BADRECHDR: Invalid data record header."; - _err_map[JERR_JREC_BADRECTAIL] = "JERR_JREC_BADRECTAIL: Invalid data record tail."; - - // class wmgr - _err_map[JERR_WMGR_BADPGSTATE] = "JERR_WMGR_BADPGSTATE: Page buffer in illegal state for operation."; - _err_map[JERR_WMGR_BADDTOKSTATE] = "JERR_WMGR_BADDTOKSTATE: Data token in illegal state for operation."; - _err_map[JERR_WMGR_ENQDISCONT] = "JERR_WMGR_ENQDISCONT: Enqueued new dtok when previous enqueue returned partly completed (state ENQ_PART)."; - _err_map[JERR_WMGR_DEQDISCONT] = "JERR_WMGR_DEQDISCONT: Dequeued new dtok when previous dequeue returned partly completed (state DEQ_PART)."; - _err_map[JERR_WMGR_DEQRIDNOTENQ] = "JERR_WMGR_DEQRIDNOTENQ: Dequeue rid is not enqueued."; - - // class rmgr - _err_map[JERR_RMGR_UNKNOWNMAGIC] = "JERR_RMGR_UNKNOWNMAGIC: Found record with unknown magic."; - _err_map[JERR_RMGR_RIDMISMATCH] = "JERR_RMGR_RIDMISMATCH: RID mismatch between current record and dtok RID"; - //_err_map[JERR_RMGR_FIDMISMATCH] = "JERR_RMGR_FIDMISMATCH: FID mismatch between emap and rrfc"; - _err_map[JERR_RMGR_ENQSTATE] = "JERR_RMGR_ENQSTATE: Attempted read when data token wstate was not ENQ"; - _err_map[JERR_RMGR_BADRECTYPE] = "JERR_RMGR_BADRECTYPE: Attempted operation on inappropriate record type"; - - // class data_tok - _err_map[JERR_DTOK_ILLEGALSTATE] = "JERR_MTOK_ILLEGALSTATE: Attempted to change to illegal state."; - //_err_map[JERR_DTOK_RIDNOTSET] = "JERR_DTOK_RIDNOTSET: Record ID not set."; - - // class enq_map, txn_map - _err_map[JERR_MAP_DUPLICATE] = "JERR_MAP_DUPLICATE: Attempted to insert record into map using duplicate key."; - _err_map[JERR_MAP_NOTFOUND] = "JERR_MAP_NOTFOUND: Key not found in map."; - _err_map[JERR_MAP_LOCKED] = "JERR_MAP_LOCKED: Record ID locked by a pending transaction."; - - // class jinf - _err_map[JERR_JINF_CVALIDFAIL] = "JERR_JINF_CVALIDFAIL: Journal compatibility validation failure."; - _err_map[JERR_JINF_NOVALUESTR] = "JERR_JINF_NOVALUESTR: No value attribute found in jinf file."; - _err_map[JERR_JINF_BADVALUESTR] = "JERR_JINF_BADVALUESTR: Bad format for value attribute in jinf file"; - _err_map[JERR_JINF_JDATEMPTY] = "JERR_JINF_JDATEMPTY: Journal data files empty."; - _err_map[JERR_JINF_TOOMANYFILES] = "JERR_JINF_TOOMANYFILES: Too many journal data files."; - _err_map[JERR_JINF_INVALIDFHDR] = "JERR_JINF_INVALIDFHDR: Invalid journal data file header"; - _err_map[JERR_JINF_STAT] = "JERR_JINF_STAT: Error while trying to stat a journal data file"; - _err_map[JERR_JINF_NOTREGFILE] = "JERR_JINF_NOTREGFILE: Target journal data file is not a regular file"; - _err_map[JERR_JINF_BADFILESIZE] = "JERR_JINF_BADFILESIZE: Journal data file is of incorrect or unexpected size"; - _err_map[JERR_JINF_OWIBAD] = "JERR_JINF_OWIBAD: Journal data files have inconsistent OWI flags; >1 transition found in non-auto-expand or min-size journal"; - _err_map[JERR_JINF_ZEROLENFILE] = "JERR_JINF_ZEROLENFILE: Journal info file zero length"; - - //_err_map[] = ""; - - return true; -} - -const char* -jerrno::err_msg(const u_int32_t err_no) throw () -{ - _err_map_itr = _err_map.find(err_no); - if (_err_map_itr == _err_map.end()) - return ""; - return _err_map_itr->second; -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jerrno.h b/qpid/cpp/src/qpid/legacystore/jrnl/jerrno.h deleted file mode 100644 index 4c8b71c423..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jerrno.h +++ /dev/null @@ -1,173 +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. - * - */ - -/** - * \file jerrno.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::jerrno (journal error - * codes). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_JERRNO_H -#define QPID_LEGACYSTORE_JRNL_JERRNO_H - -namespace mrg -{ -namespace journal -{ -class jerrno; -} -} - -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class jerrno - * \brief Class containing static error definitions and static map for error messages. - */ - class jerrno - { - static std::map _err_map; ///< Map of error messages - static std::map::iterator _err_map_itr; ///< Iterator - static bool _initialized; ///< Dummy flag, used to initialise map. - - public: - // generic errors - static const u_int32_t JERR__MALLOC; ///< Buffer memory allocation failed - static const u_int32_t JERR__UNDERFLOW; ///< Underflow error - static const u_int32_t JERR__NINIT; ///< Operation on uninitialized class - static const u_int32_t JERR__AIO; ///< AIO failure - static const u_int32_t JERR__FILEIO; ///< File read or write failure - static const u_int32_t JERR__RTCLOCK; ///< Reading real-time clock failed - static const u_int32_t JERR__PTHREAD; ///< pthread failure - static const u_int32_t JERR__TIMEOUT; ///< Timeout waiting for an event - static const u_int32_t JERR__UNEXPRESPONSE; ///< Unexpected response to call or event - static const u_int32_t JERR__RECNFOUND; ///< Record not found - static const u_int32_t JERR__NOTIMPL; ///< Not implemented - - // class jcntl - static const u_int32_t JERR_JCNTL_STOPPED; ///< Operation on stopped journal - static const u_int32_t JERR_JCNTL_READONLY; ///< Write operation on read-only journal - static const u_int32_t JERR_JCNTL_AIOCMPLWAIT; ///< Timeout waiting for AIOs to complete - static const u_int32_t JERR_JCNTL_UNKNOWNMAGIC; ///< Found record with unknown magic - static const u_int32_t JERR_JCNTL_NOTRECOVERED; ///< Req' recover() to be called first - static const u_int32_t JERR_JCNTL_RECOVERJFULL; ///< Journal data files full, cannot write - static const u_int32_t JERR_JCNTL_OWIMISMATCH; ///< OWI change found in unexpected location - - // class jdir - static const u_int32_t JERR_JDIR_NOTDIR; ///< Exists but is not a directory - static const u_int32_t JERR_JDIR_MKDIR; ///< Directory creation failed - static const u_int32_t JERR_JDIR_OPENDIR; ///< Directory open failed - static const u_int32_t JERR_JDIR_READDIR; ///< Directory read failed - static const u_int32_t JERR_JDIR_CLOSEDIR; ///< Directory close failed - static const u_int32_t JERR_JDIR_RMDIR; ///< Directory delete failed - static const u_int32_t JERR_JDIR_NOSUCHFILE; ///< File does not exist - static const u_int32_t JERR_JDIR_FMOVE; ///< File move failed - static const u_int32_t JERR_JDIR_STAT; ///< File stat failed - static const u_int32_t JERR_JDIR_UNLINK; ///< File delete failed - static const u_int32_t JERR_JDIR_BADFTYPE; ///< Bad or unknown file type (stat mode) - - // class fcntl - static const u_int32_t JERR_FCNTL_OPENWR; ///< Unable to open file for write - static const u_int32_t JERR_FCNTL_WRITE; ///< Unable to write to file - static const u_int32_t JERR_FCNTL_CLOSE; ///< File close failed - static const u_int32_t JERR_FCNTL_FILEOFFSOVFL; ///< Increased offset past file size - static const u_int32_t JERR_FCNTL_CMPLOFFSOVFL; ///< Increased cmpl offs past subm offs - static const u_int32_t JERR_FCNTL_RDOFFSOVFL; ///< Increased read offs past write offs - - // class lfmgr - static const u_int32_t JERR_LFMGR_BADAEFNUMLIM; ///< Bad auto-expand file number limit - static const u_int32_t JERR_LFMGR_AEFNUMLIMIT; ///< Exceeded auto-expand file number limit - static const u_int32_t JERR_LFMGR_AEDISABLED; ///< Attempted to expand with auto-expand disabled - - // class rrfc - static const u_int32_t JERR_RRFC_OPENRD; ///< Unable to open file for read - - // class jrec, enq_rec, deq_rec, txn_rec - static const u_int32_t JERR_JREC_BADRECHDR; ///< Invalid data record header - static const u_int32_t JERR_JREC_BADRECTAIL; ///< Invalid data record tail - - // class wmgr - static const u_int32_t JERR_WMGR_BADPGSTATE; ///< Page buffer in illegal state. - static const u_int32_t JERR_WMGR_BADDTOKSTATE; ///< Data token in illegal state. - static const u_int32_t JERR_WMGR_ENQDISCONT; ///< Enq. new dtok when previous part compl. - static const u_int32_t JERR_WMGR_DEQDISCONT; ///< Deq. new dtok when previous part compl. - static const u_int32_t JERR_WMGR_DEQRIDNOTENQ; ///< Deq. rid not enqueued - - // class rmgr - static const u_int32_t JERR_RMGR_UNKNOWNMAGIC; ///< Found record with unknown magic - static const u_int32_t JERR_RMGR_RIDMISMATCH; ///< RID mismatch between rec and dtok - //static const u_int32_t JERR_RMGR_FIDMISMATCH; ///< FID mismatch between emap and rrfc - static const u_int32_t JERR_RMGR_ENQSTATE; ///< Attempted read when wstate not ENQ - static const u_int32_t JERR_RMGR_BADRECTYPE; ///< Attempted op on incorrect rec type - - // class data_tok - static const u_int32_t JERR_DTOK_ILLEGALSTATE; ///< Attempted to change to illegal state -// static const u_int32_t JERR_DTOK_RIDNOTSET; ///< Record ID not set - - // class enq_map, txn_map - static const u_int32_t JERR_MAP_DUPLICATE; ///< Attempted to insert using duplicate key - static const u_int32_t JERR_MAP_NOTFOUND; ///< Key not found in map - static const u_int32_t JERR_MAP_LOCKED; ///< rid locked by pending txn - - // class jinf - static const u_int32_t JERR_JINF_CVALIDFAIL; ///< Compatibility validation failure - static const u_int32_t JERR_JINF_NOVALUESTR; ///< No value attr found in jinf file - static const u_int32_t JERR_JINF_BADVALUESTR; ///< Bad format for value attr in jinf file - static const u_int32_t JERR_JINF_JDATEMPTY; ///< Journal data files empty - static const u_int32_t JERR_JINF_TOOMANYFILES; ///< Too many journal data files - static const u_int32_t JERR_JINF_INVALIDFHDR; ///< Invalid file header - static const u_int32_t JERR_JINF_STAT; ///< Error while trying to stat a file - static const u_int32_t JERR_JINF_NOTREGFILE; ///< Target file is not a regular file - static const u_int32_t JERR_JINF_BADFILESIZE; ///< File is of incorrect or unexpected size - static const u_int32_t JERR_JINF_OWIBAD; ///< OWI inconsistent (>1 transition in non-ae journal) - static const u_int32_t JERR_JINF_ZEROLENFILE; ///< Journal info file is zero length (empty). - - // Negative returns for some functions - static const int32_t AIO_TIMEOUT; ///< Timeout waiting for AIO return - static const int32_t LOCK_TAKEN; ///< Attempted to take lock, but it was taken by another thread - /** - * \brief Method to access error message from known error number. - */ - static const char* err_msg(const u_int32_t err_no) throw (); - - private: - /** - * \brief Static function to initialize map. - */ - static bool __init(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_JERRNO_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jexception.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/jexception.cpp deleted file mode 100644 index 5c571020e4..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jexception.cpp +++ /dev/null @@ -1,183 +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. - * - */ - -/** - * \file jexception.cpp - * - * Qpid asynchronous store plugin library - * - * Generic journal exception class mrg::journal::jexception. See comments - * in file jexception.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/jexception.h" - -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" - -#define CATLEN(p) MAX_MSG_SIZE - std::strlen(p) - 1 - -namespace mrg -{ -namespace journal -{ - -jexception::jexception() throw (): - std::exception(), - _err_code(0) -{ - format(); -} - -jexception::jexception(const u_int32_t err_code) throw (): - std::exception(), - _err_code(err_code) -{ - format(); -} - -jexception::jexception(const char* additional_info) throw (): - std::exception(), - _err_code(0), - _additional_info(additional_info) -{ - format(); -} - -jexception::jexception(const std::string& additional_info) throw (): - std::exception(), - _err_code(0), - _additional_info(additional_info) -{ - format(); -} - -jexception::jexception(const u_int32_t err_code, const char* additional_info) throw (): - std::exception(), - _err_code(err_code), - _additional_info(additional_info) -{ - format(); -} - -jexception::jexception(const u_int32_t err_code, const std::string& additional_info) throw (): - std::exception(), - _err_code(err_code), - _additional_info(additional_info) -{ - format(); -} - -jexception::jexception(const u_int32_t err_code, const char* throwing_class, - const char* throwing_fn) throw (): - std::exception(), - _err_code(err_code), - _throwing_class(throwing_class), - _throwing_fn(throwing_fn) -{ - format(); -} - -jexception::jexception(const u_int32_t err_code, const std::string& throwing_class, - const std::string& throwing_fn) throw (): - std::exception(), - _err_code(err_code), - _throwing_class(throwing_class), - _throwing_fn(throwing_fn) -{ - format(); -} - -jexception::jexception(const u_int32_t err_code, const char* additional_info, - const char* throwing_class, const char* throwing_fn) throw (): - std::exception(), - _err_code(err_code), - _additional_info(additional_info), - _throwing_class(throwing_class), - _throwing_fn(throwing_fn) -{ - format(); -} - -jexception::jexception(const u_int32_t err_code, const std::string& additional_info, - const std::string& throwing_class, const std::string& throwing_fn) throw (): - std::exception(), - _err_code(err_code), - _additional_info(additional_info), - _throwing_class(throwing_class), - _throwing_fn(throwing_fn) -{ - format(); -} - -jexception::~jexception() throw () -{} - -void -jexception::format() -{ - const bool ai = !_additional_info.empty(); - const bool tc = !_throwing_class.empty(); - const bool tf = !_throwing_fn.empty(); - std::ostringstream oss; - oss << "jexception 0x" << std::hex << std::setfill('0') << std::setw(4) << _err_code << " "; - if (tc) - { - oss << _throwing_class; - if (tf) - oss << "::"; - else - oss << " "; - } - if (tf) - oss << _throwing_fn << "() "; - if (tc || tf) - oss << "threw " << jerrno::err_msg(_err_code); - if (ai) - oss << " (" << _additional_info << ")"; - _what.assign(oss.str()); -} - -const char* -jexception::what() const throw () -{ - return _what.c_str(); -} - -std::ostream& -operator<<(std::ostream& os, const jexception& je) -{ - os << je.what(); - return os; -} - -std::ostream& -operator<<(std::ostream& os, const jexception* jePtr) -{ - os << jePtr->what(); - return os; -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jexception.h b/qpid/cpp/src/qpid/legacystore/jrnl/jexception.h deleted file mode 100644 index 34d8373235..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jexception.h +++ /dev/null @@ -1,142 +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. - * - */ - -/** - * \file jexception.h - * - * Qpid asynchronous store plugin library - * - * Generic journal exception class mrg::journal::jexception (derived - * from class std::exception). Intended to serve as a common exception - * class for all more speicalized exceptions in the message journal. See - * class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_JEXCEPTION_H -#define QPID_LEGACYSTORE_JRNL_JEXCEPTION_H - -namespace mrg -{ -namespace journal -{ -class jexception; -} -} - -#include -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include -#include -#include - -// Macro for formatting commom system errors -#define FORMAT_SYSERR(errno) " errno=" << errno << " (" << std::strerror(errno) << ")" - -#define MALLOC_CHK(ptr, var, cls, fn) if(ptr == 0) { \ - clean(); \ - std::ostringstream oss; \ - oss << var << ": malloc() failed: " << FORMAT_SYSERR(errno); \ - throw jexception(jerrno::JERR__MALLOC, oss.str(), cls, fn); \ - } - -// TODO: The following is a temporary bug-tracking aid which forces a core. -// Replace with the commented out version below when BZ484048 is resolved. -#define PTHREAD_CHK(err, pfn, cls, fn) if(err != 0) { \ - std::ostringstream oss; \ - oss << cls << "::" << fn << "(): " << pfn; \ - errno = err; \ - ::perror(oss.str().c_str()); \ - ::abort(); \ - } -/* -#define PTHREAD_CHK(err, pfn, cls, fn) if(err != 0) { \ - std::ostringstream oss; \ - oss << pfn << " failed: " << FORMAT_SYSERR(err); \ - throw jexception(jerrno::JERR__PTHREAD, oss.str(), cls, fn); \ - } -*/ - -#define ASSERT(cond, msg) if(cond == 0) { \ - std::cerr << msg << std::endl; \ - ::abort(); \ - } - -namespace mrg -{ -namespace journal -{ - /** - * \class jexception - * \brief Generic journal exception class - */ - class jexception : public std::exception - { - private: - u_int32_t _err_code; - std::string _additional_info; - std::string _throwing_class; - std::string _throwing_fn; - std::string _what; - void format(); - - public: - jexception() throw (); - - jexception(const u_int32_t err_code) throw (); - - jexception(const char* additional_info) throw (); - jexception(const std::string& additional_info) throw (); - - jexception(const u_int32_t err_code, const char* additional_info) throw (); - jexception(const u_int32_t err_code, const std::string& additional_info) throw (); - - jexception(const u_int32_t err_code, const char* throwing_class, const char* throwing_fn) - throw (); - jexception(const u_int32_t err_code, const std::string& throwing_class, - const std::string& throwing_fn) throw (); - - jexception(const u_int32_t err_code, const char* additional_info, - const char* throwing_class, const char* throwing_fn) throw (); - jexception(const u_int32_t err_code, const std::string& additional_info, - const std::string& throwing_class, const std::string& throwing_fn) throw (); - - virtual ~jexception() throw (); - virtual const char* what() const throw (); // override std::exception::what() - - inline u_int32_t err_code() const throw () { return _err_code; } - inline const std::string additional_info() const throw () { return _additional_info; } - inline const std::string throwing_class() const throw () { return _throwing_class; } - inline const std::string throwing_fn() const throw () { return _throwing_fn; } - - friend std::ostream& operator<<(std::ostream& os, const jexception& je); - friend std::ostream& operator<<(std::ostream& os, const jexception* jePtr); - }; // class jexception - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_JEXCEPTION_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jinf.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/jinf.cpp deleted file mode 100644 index 3326005d9b..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jinf.cpp +++ /dev/null @@ -1,540 +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. - * - */ - -/** - * \file jinf.cpp - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::jinf class. - * - * See jinf.h comments for details of this class. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/jinf.h" - -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/file_hdr.h" -#include "qpid/legacystore/jrnl/jcntl.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/lp_map.h" -#include -#include - -namespace mrg -{ -namespace journal -{ - -jinf::jinf(const std::string& jinf_filename, bool validate_flag): - _jver(0), - _filename(jinf_filename), - _num_jfiles(0), - _ae(false), - _ae_max_jfiles(0), - _jfsize_sblks(0), - _sblk_size_dblks(0), - _dblk_size(0), - _wcache_pgsize_sblks(0), - _wcache_num_pages(0), - _rcache_pgsize_sblks(0), - _rcache_num_pages(0), - _tm_ptr(0), - _valid_flag(false), - _analyzed_flag(false), - _initial_owi(false), - _frot(false) -{ - read(_filename); - if (validate_flag) - validate(); -} - -jinf::jinf(const std::string& jid, const std::string& jdir, const std::string& base_filename, const u_int16_t num_jfiles, - const bool auto_expand, const u_int16_t ae_max_jfiles, const u_int32_t jfsize_sblks, - const u_int32_t wcache_pgsize_sblks, const u_int16_t wcache_num_pages, const timespec& ts): - _jver(RHM_JDAT_VERSION), - _jid(jid), - _jdir(jdir), - _base_filename(base_filename), - _ts(ts), - _num_jfiles(num_jfiles), - _ae(auto_expand), - _ae_max_jfiles(ae_max_jfiles), - _jfsize_sblks(jfsize_sblks), - _sblk_size_dblks(JRNL_SBLK_SIZE), - _dblk_size(JRNL_DBLK_SIZE), - _wcache_pgsize_sblks(wcache_pgsize_sblks), - _wcache_num_pages(wcache_num_pages), - _rcache_pgsize_sblks(JRNL_RMGR_PAGE_SIZE), - _rcache_num_pages(JRNL_RMGR_PAGES), - _tm_ptr(std::localtime(&ts.tv_sec)), - _valid_flag(false), - _analyzed_flag(false), - _initial_owi(false) -{ - set_filename(); -} - -jinf::~jinf() -{} - -void -jinf::validate() -{ - bool err = false; - std::ostringstream oss; - if (_jver != RHM_JDAT_VERSION) - { - oss << "File \"" << _filename << "\": "; - oss << "RHM_JDAT_VERSION mismatch: found=" << (int)_jver; - oss << "; required=" << RHM_JDAT_VERSION << std::endl; - err = true; - } - if (_num_jfiles < JRNL_MIN_NUM_FILES) - { - oss << "File \"" << _filename << "\": "; - oss << "Number of journal files too small: found=" << _num_jfiles; - oss << "; minimum=" << JRNL_MIN_NUM_FILES << std::endl; - err = true; - } - if (_num_jfiles > JRNL_MAX_NUM_FILES) - { - oss << "File \"" << _filename << "\": "; - oss << "Number of journal files too large: found=" << _num_jfiles; - oss << "; maximum=" << JRNL_MAX_NUM_FILES << std::endl; - err = true; - } - if (_ae) - { - if (_ae_max_jfiles < _num_jfiles) - { - oss << "File \"" << _filename << "\": "; - oss << "Number of journal files exceeds auto-expansion limit: found=" << _num_jfiles; - oss << "; maximum=" << _ae_max_jfiles; - err = true; - } - if (_ae_max_jfiles > JRNL_MAX_NUM_FILES) - { - oss << "File \"" << _filename << "\": "; - oss << "Auto-expansion file limit too large: found=" << _ae_max_jfiles; - oss << "; maximum=" << JRNL_MAX_NUM_FILES; - err = true; - } - } - if (_jfsize_sblks < JRNL_MIN_FILE_SIZE) - { - oss << "File \"" << _filename << "\": "; - oss << "Journal file size too small: found=" << _jfsize_sblks; - oss << "; minimum=" << JRNL_MIN_FILE_SIZE << " (sblks)" << std::endl; - err = true; - } - if (_sblk_size_dblks != JRNL_SBLK_SIZE) - { - oss << "File \"" << _filename << "\": "; - oss << "JRNL_SBLK_SIZE mismatch: found=" << _sblk_size_dblks; - oss << "; required=" << JRNL_SBLK_SIZE << std::endl; - err = true; - } - if (_dblk_size != JRNL_DBLK_SIZE) - { - oss << "File \"" << _filename << "\": "; - oss << "JRNL_DBLK_SIZE mismatch: found=" << _dblk_size; - oss << "; required=" << JRNL_DBLK_SIZE << std::endl; - err = true; - } - if (err) - throw jexception(jerrno::JERR_JINF_CVALIDFAIL, oss.str(), "jinf", "validate"); - _valid_flag = true; -} - -void -jinf::analyze() -{ - lp_map early_map; // map for all owi flags same as pfid 0 - lp_map late_map; // map for all owi flags opposite to pfid 0 - bool late_latch = false; // latch for owi switchover - - if (!_valid_flag) - validate(); - bool done = false; - for (u_int16_t pfid=0; pfid<_num_jfiles && !done; pfid++) - { - std::ostringstream oss; - if (_jdir.at(_jdir.size() - 1) == '/') - oss << _jdir << _base_filename << "."; - else - oss << _jdir << "/" << _base_filename << "."; - oss << std::setw(4) << std::setfill('0') << std::hex << pfid; - oss << "." << JRNL_DATA_EXTENSION; - - // Check size of each file is consistent and expected - u_int32_t fsize = get_filesize(oss.str()); - if (fsize != (_jfsize_sblks + 1) * _sblk_size_dblks * _dblk_size) - { - std::ostringstream oss1; - oss1 << "File \"" << oss.str() << "\": size=" << fsize << "; expected=" << ((_jfsize_sblks + 1) * _sblk_size_dblks * _dblk_size); - throw jexception(jerrno::JERR_JINF_BADFILESIZE, oss1.str(), "jinf", "analyze"); - } - - std::ifstream jifs(oss.str().c_str()); - if (!jifs.good()) - throw jexception(jerrno::JERR__FILEIO, oss.str(), "jinf", "analyze"); - file_hdr fhdr; - jifs.read((char*)&fhdr, sizeof(fhdr)); - if (fhdr._magic != RHM_JDAT_FILE_MAGIC) // No file header - { - if (fhdr._magic != 0) - throw jexception(jerrno::JERR_JINF_INVALIDFHDR, oss.str(), "jinf", "analyze"); - if (!pfid) // pfid 0 == lid 0 cannot be empty - throw jexception(jerrno::JERR_JINF_JDATEMPTY, oss.str(), "jinf", "analyze"); - _frot = true; - done = true; - } - else - { - assert(pfid == fhdr._pfid); - if (pfid == 0) - { - _initial_owi = fhdr.get_owi(); - early_map.insert(fhdr._lfid, pfid); - } - else - { - if (_initial_owi == fhdr.get_owi()) - { - early_map.insert(fhdr._lfid, pfid); - if (late_latch && (!_ae || _num_jfiles == JRNL_MIN_NUM_FILES)) - throw jexception(jerrno::JERR_JINF_OWIBAD, oss.str(), "jinf", "analyze"); - } - else - { - late_map.insert(fhdr._lfid, pfid); - late_latch = true; - } - } - } - jifs.close(); - } // for (pfid) - - // If this is not the first rotation, all files should be in either early or late maps - if (!_frot) assert(early_map.size() + late_map.size() == _num_jfiles); - - _pfid_list.clear(); - late_map.get_pfid_list(_pfid_list); - early_map.get_pfid_list(_pfid_list); - - // Check OWI consistency -// for (u_int16_t lfid=0; lfid<_num_jfiles && !done; lfid++) -// { -// throw jexception(jerrno::JERR_JINF_OWIBAD, oss.str(), "jinf", "analyze"); -// } - - _analyzed_flag = true; -} - -void -jinf::write() -{ - std::ostringstream oss; - oss << _jdir << "/" << _base_filename << "." << JRNL_INFO_EXTENSION; - std::ofstream of(oss.str().c_str(), std::ofstream::out | std::ofstream::trunc); - if (!of.good()) - throw jexception(jerrno::JERR__FILEIO, oss.str(), "jinf", "write"); - of << xml_str(); - of.close(); -} - -u_int16_t -jinf::incr_num_jfiles() -{ - if (_num_jfiles >= JRNL_MAX_NUM_FILES) - throw jexception(jerrno::JERR_JINF_TOOMANYFILES, "jinf", "incr_num_jfiles"); - return ++_num_jfiles; -} - -u_int16_t -jinf::get_first_pfid() -{ - if (!_analyzed_flag) - analyze(); - return *_pfid_list.begin(); -} - -u_int16_t -jinf::get_last_pfid() -{ - if (!_analyzed_flag) - analyze(); - return *_pfid_list.rbegin(); -} - -jinf::pfid_list& -jinf::get_pfid_list() -{ - if (!_analyzed_flag) - analyze(); - return _pfid_list; -} - -void -jinf::get_normalized_pfid_list(pfid_list& pfid_list) -{ - if (!_analyzed_flag) - analyze(); - pfid_list.clear(); - u_int16_t s = _pfid_list.size(); - u_int16_t iz = 0; // index of 0 value - while (_pfid_list[iz] && iz < s) - iz++; - assert(_pfid_list[iz] == 0); - for (u_int16_t i = iz; i < iz + s; i++) - pfid_list.push_back(_pfid_list[i % s]); - assert(pfid_list[0] == 0); - assert(pfid_list.size() == s); -} - -bool -jinf::get_initial_owi() -{ - if (!_analyzed_flag) - analyze(); - return _initial_owi; -} - -bool -jinf::get_frot() -{ - if (!_analyzed_flag) - analyze(); - return _frot; -} - -std::string -jinf::to_string() const -{ - std::ostringstream oss; - oss << std::setfill('0'); - oss << "Journal ID \"" << _jid << "\" initialized " << (_tm_ptr->tm_year + 1900) << "/"; - oss << std::setw(2) << (_tm_ptr->tm_mon + 1) << "/" << std::setw(2) << _tm_ptr->tm_mday << " "; - oss << std::setw(2) << _tm_ptr->tm_hour << ":" << std::setw(2) << _tm_ptr->tm_min << ":"; - oss << std::setw(2) << _tm_ptr->tm_sec << "." << std::setw(9) << _ts.tv_nsec << ":" << std::endl; - oss << " Journal directory: \"" << _jdir << "\"" << std::endl; - oss << " Journal base filename: \"" << _base_filename << "\"" << std::endl; - oss << " Journal version: " << (unsigned)_jver << std::endl; - oss << " Number of journal files: " << _num_jfiles << std::endl; -// TODO: Uncomment these lines when auto-expand is enabled. -// oss << " Auto-expand mode: " << (_ae ? "enabled" : "disabled") << std::endl; -// if (_ae) oss << " Max. number of journal files (in auto-expand mode): " << _ae_max_jfiles << std::endl; - oss << " Journal file size: " << _jfsize_sblks << " sblks" << std::endl; - oss << " Softblock size (JRNL_SBLK_SIZE): " << _sblk_size_dblks << " dblks" << std::endl; - oss << " Datablock size (JRNL_DBLK_SIZE): " << _dblk_size << " bytes" << std::endl; - oss << " Write page size: " << _wcache_pgsize_sblks << " sblks" << std::endl; - oss << " Number of write pages: " << _wcache_num_pages << std::endl; - oss << " Read page size (JRNL_RMGR_PAGE_SIZE): " << _rcache_pgsize_sblks << " sblks" << std::endl; - oss << " Number of read pages (JRNL_RMGR_PAGES): " << _rcache_num_pages << std::endl; - return oss.str(); -} - -std::string -jinf::xml_str() const -{ - // TODO: This is *not* an XML writer, rather for simplicity, it uses literals. I'm sure a more elegant way can be - // found to do this using the real thing... - - std::ostringstream oss; - oss << std::setfill('0'); - oss << "" << std::endl; - oss << "" << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " tm_year + 1900) << "/"; - oss << std::setw(2) << (_tm_ptr->tm_mon + 1) << "/" << std::setw(2) << _tm_ptr->tm_mday << " "; - oss << std::setw(2) << _tm_ptr->tm_hour << ":" << std::setw(2) << _tm_ptr->tm_min << ":"; - oss << std::setw(2) << _tm_ptr->tm_sec << "." << std::setw(9) << _ts.tv_nsec; - oss << "\" />" << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - if (_ae) oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << " " << std::endl; - oss << "" << std::endl; - return oss.str(); -} - -void -jinf::set_filename() -{ - std::ostringstream oss; - oss << _jdir << "/" << _base_filename << "." << JRNL_INFO_EXTENSION; - _filename = oss.str().c_str(); -} - -void -jinf::read(const std::string& jinf_filename) -{ - // TODO: This is *not* an XML reader, rather for simplicity, it is a brute-force line reader which relies on string - // recognition. It relies on the format of xml_str() above; it will not handle a XML restructuring. - // *** Can it be replaced cheaply by a real XML reader? Should it be, or is this sufficient? *** - - char buff[1024]; // limit of line input length - std::ifstream jinfs(jinf_filename.c_str()); - if (!jinfs.good()) - throw jexception(jerrno::JERR__FILEIO, jinf_filename.c_str(), "jinf", "read"); - u_int32_t charcnt = 0; - while (jinfs.good()) - { - jinfs.getline(buff, 1023); - charcnt += std::strlen(buff); - if (std::strstr(buff, "journal_version")) - _jver = u_int16_value(buff); - else if(std::strstr(buff, "id_string")) - string_value(_jid, buff); - else if(std::strstr(buff, "directory")) - string_value(_jdir, buff); - else if(std::strstr(buff, "base_filename")) - string_value(_base_filename, buff); - else if(std::strstr(buff, "number_jrnl_files")) - _num_jfiles = u_int16_value(buff); - else if(std::strstr(buff, "auto_expand_max_jrnl_files")) - _ae_max_jfiles = u_int16_value(buff); - else if(std::strstr(buff, "auto_expand")) - _ae = bool_value(buff); - else if(std::strstr(buff, "jrnl_file_size_sblks")) - _jfsize_sblks = u_int32_value(buff); - else if(std::strstr(buff, "JRNL_SBLK_SIZE")) - _sblk_size_dblks = u_int16_value(buff); - else if(std::strstr(buff, "JRNL_DBLK_SIZE")) - _dblk_size = u_int32_value(buff); - else if(std::strstr(buff, "wcache_pgsize_sblks")) - _wcache_pgsize_sblks = u_int32_value(buff); - else if(std::strstr(buff, "wcache_num_pages")) - _wcache_num_pages = u_int32_value(buff); - else if(std::strstr(buff, "JRNL_RMGR_PAGE_SIZE")) - _rcache_pgsize_sblks = u_int32_value(buff); - else if(std::strstr(buff, "JRNL_RMGR_PAGES")) - _rcache_num_pages = u_int32_value(buff); - else if(std::strstr(buff, "nanoseconds")) - _ts.tv_nsec = u_int32_value(buff); - else if(std::strstr(buff, "seconds")) - { - _ts.tv_sec = u_int32_value(buff); - _tm_ptr = std::localtime(&_ts.tv_sec); - } - } - jinfs.close(); - if (charcnt == 0) - throw jexception(jerrno::JERR_JINF_ZEROLENFILE, jinf_filename.c_str(), "jinf", "read"); -} - -bool -jinf::bool_value(char* line) const -{ - return std::strcmp(find_value(line), "true") == 0; -} - -u_int16_t -jinf::u_int16_value(char* line) const -{ - return std::atoi(find_value(line)); -} - -u_int32_t -jinf::u_int32_value(char* line) const -{ - return std::atol(find_value(line)); -} - -std::string& -jinf::string_value(std::string& str, char* line) const -{ - str.assign(find_value(line)); - return str; -} - -char* -jinf::find_value(char* line) const -{ - const char* target1_str = "value=\""; - int target2_char = '\"'; - char* t1 = std::strstr(line, target1_str); - if (t1 == 0) - { - std::ostringstream oss; - oss << "File \"" << _filename << "\": line=" << line; - throw jexception(jerrno::JERR_JINF_NOVALUESTR, oss.str(), "jinf", "find_value"); - } - t1 += std::strlen(target1_str); - - char* t2 = std::strchr(t1, target2_char); - if (t2 == 0) - { - std::ostringstream oss; - oss << "File \"" << _filename << "\": line=" << line; - throw jexception(jerrno::JERR_JINF_BADVALUESTR, oss.str(), "jinf", "find_value"); - } - *t2 = '\0'; - return t1; -} - -u_int32_t -jinf::get_filesize(const std::string& file_name) const -{ - struct stat s; - if (::stat(file_name.c_str(), &s)) - { - std::ostringstream oss; - oss << "stat: file=\"" << file_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JINF_STAT, oss.str(), "jinf", "get_filesize"); - } - if (!S_ISREG(s.st_mode)) // not a regular file, - { - std::ostringstream oss; - oss << "File \"" << file_name << "\" is not a regular file: mode=0x" << std::hex << s.st_mode; - throw jexception(jerrno::JERR_JINF_NOTREGFILE, oss.str(), "jinf", "get_filesize"); - } - return u_int32_t(s.st_size); -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jinf.h b/qpid/cpp/src/qpid/legacystore/jrnl/jinf.h deleted file mode 100644 index 73f5386a19..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jinf.h +++ /dev/null @@ -1,133 +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. - * - */ - -/** - * \file jinf.h - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::jinf class. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_JINF_H -#define QPID_LEGACYSTORE_JRNL_JINF_H - -#include -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - /** - * \class jinf - * \brief Class to handle the journal information file <basename>.jinf. - */ - class jinf - { - public: - typedef std::vector pfid_list; // pfids - typedef pfid_list::const_iterator pfidl_citr; - - private: - u_int8_t _jver; - std::string _jid; - std::string _jdir; - std::string _base_filename; - std::string _filename; - timespec _ts; - u_int16_t _num_jfiles; - bool _ae; - u_int32_t _ae_max_jfiles; - u_int32_t _jfsize_sblks; - u_int16_t _sblk_size_dblks; - u_int32_t _dblk_size; - u_int32_t _wcache_pgsize_sblks; - u_int16_t _wcache_num_pages; - u_int32_t _rcache_pgsize_sblks; - u_int16_t _rcache_num_pages; - std::tm* _tm_ptr; - bool _valid_flag; - bool _analyzed_flag; - pfid_list _pfid_list; - bool _initial_owi; - bool _frot; - - public: - // constructor for reading existing jinf file - jinf(const std::string& jinf_filename, bool validate_flag); - // constructor for writing jinf file - jinf(const std::string& jid, const std::string& jdir, const std::string& base_filename, - const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks, const u_int32_t wcache_pgsize_sblks, const u_int16_t wcache_num_pages, - const timespec& ts); - virtual ~jinf(); - - void validate(); - void analyze(); - void write(); - - inline u_int8_t jver() const { return _jver; } - inline const std::string& jid() const { return _jid; } - inline const std::string& jdir() const { return _jdir; } - inline void set_jdir(const std::string& jdir) { _jdir = jdir; } - inline const std::string& base_filename() const { return _base_filename; } - inline const timespec& ts() const { return _ts; } - inline u_int16_t num_jfiles() const { return _num_jfiles; } - u_int16_t incr_num_jfiles(); - inline bool is_ae() const { return _ae; } - inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; } - inline u_int32_t jfsize_sblks() const { return _jfsize_sblks; } - inline u_int16_t sblk_size_dblks() const { return _sblk_size_dblks; } - inline u_int32_t dblk_size() const { return _dblk_size; } - inline u_int32_t wcache_pgsize_sblks() const { return _wcache_pgsize_sblks; } - inline u_int16_t wcache_num_pages() const { return _wcache_num_pages; } - inline u_int32_t rcache_pgsize_sblks() const { return _rcache_pgsize_sblks; } - inline u_int16_t rcache_num_pages() const { return _rcache_num_pages; } - u_int16_t get_first_pfid(); - u_int16_t get_last_pfid(); - pfid_list& get_pfid_list(); - void get_normalized_pfid_list(pfid_list& pfid_list); - bool get_initial_owi(); - bool get_frot(); - - std::string to_string() const; - std::string xml_str() const; - - private: - void set_filename(); - void read(const std::string& jinf_filename); - bool bool_value(char* line) const; - u_int16_t u_int16_value(char* line) const; - u_int32_t u_int32_value(char* line) const; - std::string& string_value(std::string& str, char* line) const; - char* find_value(char* line) const; - u_int32_t get_filesize(const std::string& file_name) const; - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_JINF_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jrec.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/jrec.cpp deleted file mode 100644 index 61b9b6cc9b..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jrec.cpp +++ /dev/null @@ -1,119 +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. - * - */ - -/** - * \file jrec.cpp - * - * Qpid asynchronous store plugin library - * - * File containing source code for class mrg::journal::jrec (abstract journal - * jrecord). See comments in file jrec.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/jrec.h" - -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include - -namespace mrg -{ -namespace journal -{ - -jrec::jrec() {} -jrec::~jrec() {} - -void -jrec::chk_hdr(const rec_hdr& hdr) -{ - if (hdr._magic == 0) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "enq magic NULL: rid=0x" << hdr._rid; - throw jexception(jerrno::JERR_JREC_BADRECHDR, oss.str(), "jrec", "chk_hdr"); - } - if (hdr._version != RHM_JDAT_VERSION) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "version: rid=0x" << hdr._rid; - oss << ": expected=0x" << std::setw(2) << (int)RHM_JDAT_VERSION; - oss << " read=0x" << std::setw(2) << (int)hdr._version; - throw jexception(jerrno::JERR_JREC_BADRECHDR, oss.str(), "jrec", "chk_hdr"); - } -#if defined (JRNL_LITTLE_ENDIAN) - u_int8_t endian_flag = RHM_LENDIAN_FLAG; -#else - u_int8_t endian_flag = RHM_BENDIAN_FLAG; -#endif - if (hdr._eflag != endian_flag) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "endian_flag: rid=" << hdr._rid; - oss << ": expected=0x" << std::setw(2) << (int)endian_flag; - oss << " read=0x" << std::setw(2) << (int)hdr._eflag; - throw jexception(jerrno::JERR_JREC_BADRECHDR, oss.str(), "jrec", "chk_hdr"); - } -} - -void -jrec::chk_rid(const rec_hdr& hdr, const u_int64_t rid) -{ - if (hdr._rid != rid) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "rid mismatch: expected=0x" << rid; - oss << " read=0x" << hdr._rid; - throw jexception(jerrno::JERR_JREC_BADRECHDR, oss.str(), "jrec", "chk_hdr"); - } -} - -void -jrec::chk_tail(const rec_tail& tail, const rec_hdr& hdr) -{ - if (tail._xmagic != ~hdr._magic) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "magic: rid=0x" << hdr._rid; - oss << ": expected=0x" << ~hdr._magic; - oss << " read=0x" << tail._xmagic; - throw jexception(jerrno::JERR_JREC_BADRECTAIL, oss.str(), "jrec", "chk_tail"); - } - if (tail._rid != hdr._rid) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "rid: rid=0x" << hdr._rid; - oss << ": read=0x" << tail._rid; - throw jexception(jerrno::JERR_JREC_BADRECTAIL, oss.str(), "jrec", "chk_tail"); - } -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jrec.h b/qpid/cpp/src/qpid/legacystore/jrnl/jrec.h deleted file mode 100644 index 9d0771cabd..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/jrec.h +++ /dev/null @@ -1,183 +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. - * - */ - -/** - * \file jrec.h - * - * Qpid asynchronous store plugin library - * - * File containing source code for class mrg::journal::jrec (abstract journal - * jrecord). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_JREC_H -#define QPID_LEGACYSTORE_JRNL_JREC_H - -namespace mrg -{ -namespace journal -{ -class jrec; -} -} - -#include -#include -#include "qpid/legacystore/jrnl/rec_hdr.h" -#include "qpid/legacystore/jrnl/rec_tail.h" -#include -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \class jrec - * \brief Abstract class for all file jrecords, both data and log. This class establishes - * the common data format and structure for these jrecords. - */ - class jrec - { - public: - jrec(); - virtual ~jrec(); - - /** - * \brief Encode this instance of jrec into the write buffer at the disk-block-aligned - * pointer wptr starting at position rec_offs_dblks in the encoded record to a - * maximum size of max_size_dblks. - * - * This call encodes the content of the data contianed in this instance of jrec into a - * disk-softblock-aligned (defined by JRNL_SBLK_SIZE) buffer pointed to by parameter - * wptr. No more than paramter max_size_dblks data-blocks may be written to the buffer. - * The parameter rec_offs_dblks is the offset in data-blocks within the fully encoded - * data block this instance represents at which to start encoding. - * - * Encoding entails writing the record header (struct enq_hdr), the data and the record tail - * (struct enq_tail). The record must be data-block-aligned (defined by JRNL_DBLK_SIZE), - * thus any remaining space in the final data-block is ignored; the returned value is the - * number of data-blocks consumed from the page by the encode action. Provided the initial - * alignment requirements are met, records may be of arbitrary size and may span multiple - * data-blocks, disk-blocks and/or pages. - * - * Since the record size in data-blocks is known, the general usage pattern is to call - * encode() as many times as is needed to fully encode the data. Each call to encode() - * will encode as much of the record as it can to what remains of the current page cache, - * and will return the number of data-blocks actually encoded. - * - * Example: Assume that record r1 was previously written to page 0, and that this - * is an instance representing record r2. Being larger than the page size ps, r2 would span - * multiple pages as follows: - *
-        *       |<---ps--->|
-        *       +----------+----------+----------+----...
-        *       |      |r2a|   r2b    |  r2c   | |
-        *       |<-r1-><----------r2---------->  |
-        *       +----------+----------+----------+----...
-        * page:      p0         p1         p2
-        * 
- * Encoding record r2 will require multiple calls to encode; one for each page which - * is involved. Record r2 is divided logically into sections r2a, r2b and r2c at the - * points where the page boundaries intersect with the record. Assuming a page size - * of ps, the page boundary pointers are represented by their names p0, p1... and the - * sizes of the record segments are represented by their names r1, r2a, r2b..., the calls - * should be as follows: - *
-        * encode(p0+r1, 0, ps-r1); (returns r2a data-blocks)
-        * encode(p1, r2a, ps);     (returns r2b data-blocks which equals ps)
-        * encode(p2, r2a+r2b, ps); (returns r2c data-blocks)
-        * 
- * - * \param wptr Data-block-aligned pointer to position in page buffer where encoding is to - * take place. - * \param rec_offs_dblks Offset in data-blocks within record from which to start encoding. - * \param max_size_dblks Maximum number of data-blocks to write to pointer wptr. - * \returns Number of data-blocks encoded. - */ - virtual u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks) = 0; - - /** - * \brief Decode into this instance of jrec from the read buffer at the disk-block-aligned - * pointer rptr starting at position jrec_offs_dblks in the encoded record to a - * maximum size of max_size_blks. - * - * This call decodes a record in the page buffer pointed to by the data-block-aligned - * (defined by JRNL_DBLK_SIZE) parameter rptr into this instance of jrec. No more than - * paramter max_size_dblks data-blocks may be read from the buffer. The parameter - * jrec_offs_dblks is the offset in data-blocks within the encoded record at which to start - * decoding. - * - * Decoding entails reading the record header, the data and the tail. The record is - * data-block-aligned (defined by JRNL_DBLK_SIZE); the returned value is the number of - * data-blocks read from the buffer by the decode action. As the record data size is only - * known once the header is read, the number of calls required to complete reading the - * record will depend on the vlaues within this instance which are set when the - * header is decoded. - * - * A non-zero value for jrec_offs_dblks implies that this is not the first call to - * decode and the record data will be appended at this offset. - * - * \param h Reference to instance of struct hdr, already read from page buffer and used - * to determine record type - * \param rptr Data-block-aligned pointer to position in page buffer where decoding is to - * begin. - * \param rec_offs_dblks Offset within record from which to start appending the decoded - * record. - * \param max_size_dblks Maximum number of data-blocks to read from pointer rptr. - * \returns Number of data-blocks read (consumed). - */ - virtual u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks) = 0; - - virtual bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs) = 0; - - virtual std::string& str(std::string& str) const = 0; - virtual std::size_t data_size() const = 0; - virtual std::size_t xid_size() const = 0; - virtual std::size_t rec_size() const = 0; - inline virtual u_int32_t rec_size_dblks() const { return size_dblks(rec_size()); } - static inline u_int32_t size_dblks(const std::size_t size) - { return size_blks(size, JRNL_DBLK_SIZE); } - static inline u_int32_t size_sblks(const std::size_t size) - { return size_blks(size, JRNL_DBLK_SIZE * JRNL_SBLK_SIZE); } - static inline u_int32_t size_blks(const std::size_t size, const std::size_t blksize) - { return (size + blksize - 1)/blksize; } - virtual u_int64_t rid() const = 0; - - protected: - virtual void chk_hdr() const = 0; - virtual void chk_hdr(u_int64_t rid) const = 0; - virtual void chk_tail() const = 0; - static void chk_hdr(const rec_hdr& hdr); - static void chk_rid(const rec_hdr& hdr, u_int64_t rid); - static void chk_tail(const rec_tail& tail, const rec_hdr& hdr); - virtual void clean() = 0; - }; // class jrec - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_JREC_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/lp_map.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/lp_map.cpp deleted file mode 100644 index 8024ddadd2..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/lp_map.cpp +++ /dev/null @@ -1,82 +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. - * - */ - -/** - * \file lp_map.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::lp_map (logical file map). See - * comments in file lp_map.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/lp_map.h" - -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include - -namespace mrg -{ -namespace journal -{ -lp_map::lp_map() : _map() {} -lp_map::~lp_map() {} - -void -lp_map::insert(u_int16_t lfid, u_int16_t pfid) -{ - lfpair ip = lfpair(lfid, pfid); - lfret ret = _map.insert(ip); - if (ret.second == false) - { - std::ostringstream oss; - oss << std::hex << "lfid=0x" << lfid << " pfid=0x" << pfid; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "lp_map", "insert"); - } -} - -void -lp_map::get_pfid_list(std::vector& pfid_list) -{ - for (lp_map_citr_t i = _map.begin(); i != _map.end(); i++) - pfid_list.push_back(i->second); -} - -// debug aid -std::string -lp_map::to_string() -{ - std::ostringstream oss; - oss << "{lfid:pfid "; - for (lp_map_citr_t i=_map.begin(); i!=_map.end(); i++) - { - if (i != _map.begin()) oss << ", "; - oss << (*i).first << ":" << (*i).second; - } - oss << "}"; - return oss.str(); -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/lp_map.h b/qpid/cpp/src/qpid/legacystore/jrnl/lp_map.h deleted file mode 100644 index c43cbc0173..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/lp_map.h +++ /dev/null @@ -1,83 +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. - * - */ - -/** - * \file lp_map.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::lp_map (logical file map). - * See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_LP_MAP_H -#define QPID_LEGACYSTORE_JRNL_LP_MAP_H - -#include -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - /** - * \class lp_map - * \brief Maps the logical file id (lfid) to the physical file id (pfid) in the journal. - * - * NOTE: NOT THREAD SAFE - */ - class lp_map - { - public: - typedef std::map lp_map_t; - typedef lp_map_t::const_iterator lp_map_citr_t; - typedef lp_map_t::const_reverse_iterator lp_map_critr_t; - - private: - typedef std::pair lfpair; - typedef std::pair lfret; - lp_map_t _map; - - public: - lp_map(); - virtual ~lp_map(); - - void insert(u_int16_t lfid, u_int16_t pfid); - inline u_int16_t size() const { return u_int16_t(_map.size()); } - inline bool empty() const { return _map.empty(); } - inline lp_map_citr_t begin() { return _map.begin(); } - inline lp_map_citr_t end() { return _map.end(); } - inline lp_map_critr_t rbegin() { return _map.rbegin(); } - inline lp_map_critr_t rend() { return _map.rend(); } - void get_pfid_list(std::vector& pfid_list); - - // debug aid - std::string to_string(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_LP_MAP_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.cpp deleted file mode 100644 index d7b0c9f516..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.cpp +++ /dev/null @@ -1,226 +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. - * - */ - -/** - * \file lpmgr.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::lpmgr (non-logging file - * handle), used for controlling journal log files. See comments in file - * lpmgr.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/lpmgr.h" - -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - -lpmgr::lpmgr() : _ae(false), _ae_max_jfiles(0) -{} - -lpmgr::~lpmgr() -{ - finalize(); -} - -void -lpmgr::initialize(const u_int16_t num_jfiles, - const bool ae, - const u_int16_t ae_max_jfiles, - jcntl* const jcp, - new_obj_fn_ptr fp) -{ - assert(jcp != 0); - finalize(); - - // Validate params - if (ae && ae_max_jfiles > 0 && ae_max_jfiles <= num_jfiles) - { - std::ostringstream oss; - oss << "ae_max_jfiles (" << ae_max_jfiles << ") <= num_jfiles (" << num_jfiles << ")"; - throw jexception(jerrno::JERR_LFMGR_BADAEFNUMLIM, oss.str(), "lpmgr", "initialize"); - } - _ae = ae; - _ae_max_jfiles = ae_max_jfiles; - - const std::size_t num_res_files = ae - ? (ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES) - : num_jfiles; - _fcntl_arr.reserve(num_res_files); - append(jcp, fp, num_jfiles); -} - -void -lpmgr::recover(const rcvdat& rd, - jcntl* const jcp, - new_obj_fn_ptr fp) -{ - assert(jcp != 0); - finalize(); - - // Validate rd params - if (rd._aemjf > 0 && rd._aemjf <= rd._njf) - { - std::ostringstream oss; - oss << "ae_max_jfiles (" << rd._aemjf << ") <= num_jfiles (" << rd._njf << ")"; - throw jexception(jerrno::JERR_LFMGR_BADAEFNUMLIM, oss.str(), "lpmgr", "recover"); - } - _ae = rd._ae; - _ae_max_jfiles = rd._aemjf; - - const std::size_t num_res_files = rd._ae - ? (rd._aemjf ? rd._aemjf : JRNL_MAX_NUM_FILES) - : rd._njf; - _fcntl_arr.reserve(num_res_files); - _fcntl_arr.assign(rd._njf, 0); - std::vector lfid_list(rd._fid_list.size(), 0); - for (std::size_t lid = 0; lid < rd._fid_list.size(); lid++) - lfid_list[rd._fid_list[lid]] = lid; - // NOTE: rd._fid_list may be smaller than rd._njf (journal may be empty or not yet file-cycled) - for (std::size_t pfid = 0; pfid < rd._njf; pfid++) - if (pfid < rd._fid_list.size()) - _fcntl_arr[lfid_list[pfid]] = fp(jcp, lfid_list[pfid], pfid, &rd); - else - _fcntl_arr[pfid] = fp(jcp, pfid, pfid, &rd); -} - -void -lpmgr::insert(const u_int16_t after_lfid, - jcntl* const jcp, - new_obj_fn_ptr fp, - const u_int16_t num_jfiles) -{ - assert(jcp != 0); - assert(after_lfid < _fcntl_arr.size()); - if (!_ae) throw jexception(jerrno::JERR_LFMGR_AEDISABLED, "lpmgr", "insert"); - if (num_jfiles == 0) return; - std::size_t pfid = _fcntl_arr.size(); - const u_int16_t eff_ae_max_jfiles = _ae_max_jfiles ? _ae_max_jfiles : JRNL_MAX_NUM_FILES; - if (pfid + num_jfiles > eff_ae_max_jfiles) - { - std::ostringstream oss; - oss << "num_files=" << pfid << " incr=" << num_jfiles << " limit=" << _ae_max_jfiles; - throw jexception(jerrno::JERR_LFMGR_AEFNUMLIMIT, oss.str(), "lpmgr", "insert"); - } - for (std::size_t lid = after_lfid + 1; lid <= after_lfid + num_jfiles; lid++, pfid++) - _fcntl_arr.insert(_fcntl_arr.begin() + lid, fp(jcp, lid, pfid, 0)); - for (std::size_t lid = after_lfid + num_jfiles + 1; lid < _fcntl_arr.size(); lid++) - { - fcntl* p = _fcntl_arr[lid]; - assert(p != 0); - p->set_lfid(p->lfid() + num_jfiles); - } -} - -void -lpmgr::finalize() -{ - for (u_int32_t i = 0; i < _fcntl_arr.size(); i++) - delete _fcntl_arr[i]; - _fcntl_arr.clear(); - _ae = false; - _ae_max_jfiles = 0; -} - -void -lpmgr::set_ae(const bool ae) -{ - if (ae && _ae_max_jfiles > 0 && _ae_max_jfiles <= _fcntl_arr.size()) - { - std::ostringstream oss; - oss << "ae_max_jfiles (" << _ae_max_jfiles << ") <= _fcntl_arr.size (" << _fcntl_arr.size() << ")"; - throw jexception(jerrno::JERR_LFMGR_BADAEFNUMLIM, oss.str(), "lpmgr", "set_ae"); - } - if (ae && _fcntl_arr.max_size() < _ae_max_jfiles) - _fcntl_arr.reserve(_ae_max_jfiles ? _ae_max_jfiles : JRNL_MAX_NUM_FILES); - _ae = ae; -} - -void -lpmgr::set_ae_max_jfiles(const u_int16_t ae_max_jfiles) -{ - if (_ae && ae_max_jfiles > 0 && ae_max_jfiles <= _fcntl_arr.size()) - { - std::ostringstream oss; - oss << "ae_max_jfiles (" << _ae_max_jfiles << ") <= _fcntl_arr.size() (" << _fcntl_arr.size() << ")"; - throw jexception(jerrno::JERR_LFMGR_BADAEFNUMLIM, oss.str(), "lpmgr", "set_ae_max_jfiles"); - } - if (_ae && _fcntl_arr.max_size() < ae_max_jfiles) - _fcntl_arr.reserve(ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES); - _ae_max_jfiles = ae_max_jfiles; -} - -u_int16_t -lpmgr::ae_jfiles_rem() const -{ - if (_ae_max_jfiles > _fcntl_arr.size()) return _ae_max_jfiles - _fcntl_arr.size(); - if (_ae_max_jfiles == 0) return JRNL_MAX_NUM_FILES - _fcntl_arr.size(); - return 0; -} - -// Testing functions - -void -lpmgr::get_pfid_list(std::vector& pfid_list) const -{ - pfid_list.clear(); - for (std::size_t i = 0; i < _fcntl_arr.size(); i++) - pfid_list.push_back(_fcntl_arr[i]->pfid()); -} - -void -lpmgr::get_lfid_list(std::vector& lfid_list) const -{ - lfid_list.clear(); - lfid_list.assign(_fcntl_arr.size(), 0); - for (std::size_t i = 0; i < _fcntl_arr.size(); i++) - lfid_list[_fcntl_arr[i]->pfid()] = i; -} - -// === protected fns === - -void -lpmgr::append(jcntl* const jcp, - new_obj_fn_ptr fp, - const u_int16_t num_jfiles) -{ - std::size_t s = _fcntl_arr.size(); - if (_ae_max_jfiles && s + num_jfiles > _ae_max_jfiles) - { - std::ostringstream oss; - oss << "num_files=" << s << " incr=" << num_jfiles << " limit=" << _ae_max_jfiles; - throw jexception(jerrno::JERR_LFMGR_AEFNUMLIMIT, oss.str(), "lpmgr", "append"); - } - for (std::size_t i = s; i < s + num_jfiles; i++) - _fcntl_arr.push_back(fp(jcp, i, i, 0)); -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.h b/qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.h deleted file mode 100644 index be5c4494cc..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/lpmgr.h +++ /dev/null @@ -1,303 +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. - * - */ - -/** - * \file lpmgr.h - * - * Qpid asynchronous store plugin library - * - * Class mrg::journal::lpmgr. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_LPMGR_H -#define QPID_LEGACYSTORE_JRNL_LPMGR_H - -namespace mrg -{ -namespace journal -{ - class jcntl; - class lpmgr; -} -} - -#include "qpid/legacystore/jrnl/fcntl.h" -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \brief LFID-PFID manager. This class maps the logical file id (lfid) to the physical file id (pfid) so that files - * may be inserted into the file ring buffer in (nearly) arbitrary logical locations while the physical ids continue - * to be appended. NOTE: NOT THREAD SAFE. - * - * The entire functionality of the LFID-PFID manager is to maintain an array of pointers to fcntl objects which have - * a one-to-one relationship to the physical %journal files. The logical file id (lfid) is used as an index to the - * array to read the mapped physical file id (pfid). By altering the order of these pointers within the array, the - * mapping of logical to physical files may be altered. This can be used to allow for the logical insertion of - * %journal files into a ring buffer, even though the physical file ids must be appended to those that preceded them. - * - * Since the insert() operation uses after-lfid as its position parameter, it is not possible to insert before lfid - * 0 - i.e. It is only possible to insert after an existing lfid. Consequently, lfid 0 and pfid 0 are always - * coincident in a %journal. Note, however, that inserting before lfid 0 is logically equivilent to inserting after - * the last lfid. - * - * When one or more files are inserted after a particular lfid, the lfids of the following files are incremented. The - * pfids of the inserted files follow those of all existing files, thus leading to a lfid-pfid discreppancy (ie no - * longer a one-to-one mapping): - * - * Example: Before insertion, %journal file headers would look as follows: - *
-    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
-    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
-    * pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
-    * lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
-    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
-    * 
- * - * After insertion of 2 files after lid 2 (marked with *s): - *
-    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
-    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
-    * pfid --> | 0 | 1 | 2 |*6*|*7*| 3 | 4 | 5 |   pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*6*|*7*|
-    * lfid --> | 0 | 1 | 2 |*3*|*4*| 5 | 6 | 7 |   lfid --> | 0 | 1 | 2 | 5 | 6 | 7 |*3*|*4*|
-    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
-    * 
- * - * The insert() function updates the internal map immediately, but the physical files (which have both the pfid and - * lfid written into the file header) are only updated as they are overwritten in the normal course of enqueueing - * and dequeueing messages. If the %journal should fail after insertion but before the files following those inserted - * are overwritten, then duplicate lfids will be present (though no duplicate pfids are possible). The overwrite - * indicator (owi) flag and the pfid numbers may be used to resolve the ambiguity and determine the logically earlier - * lfid in this case. - * - * Example: Before insertion, the current active write file being lfid/pfid 2 as determined by the owi flag, %journal - * file headers would look as follows: - *
-    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
-    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
-    * pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
-    * lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |           lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |
-    *  owi --> | t | t | t | f | f | f |            owi --> | t | t | t | f | f | f |
-    *          +---+---+---+---+---+---+                    +---+---+---+---+---+---+
-    * 
- * - * After inserting 2 files after lfid 2 and then 3 (the newly inserted file) - marked with *s: - *
-    *          Logical view (sorted by lfid):               Physical view (sorted by pfid):
-    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
-    * pfid --> | 0 | 1 | 2 |*6*|*7*| 3 | 4 | 5 |   pfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*3*|*4*|
-    * lfid --> | 0 | 1 | 2 |*3*|*4*| 3 | 4 | 5 |   lfid --> | 0 | 1 | 2 | 3 | 4 | 5 |*3*|*4*|
-    *  owi --> | t | t | t | t | t | f | f | f |    owi --> | t | t | t | f | f | f | t | t |
-    *          +---+---+---+---+---+---+---+---+            +---+---+---+---+---+---+---+---+
-    * 
- * - * If a broker failure occurs at this point, then there are two independent tests that may be made to resolve - * duplicate lfids during recovery in such cases: - *
    - *
  1. The correct lfid has owi flag that matches that of pfid/lfid 0
  2. - *
  3. The most recently inserted (hence correct) lfid has pfids that are higher than the duplicate that was not - * overwritten
  4. - *
- * - * NOTE: NOT THREAD SAFE. Provide external thread protection if used in multi-threaded environments. - */ - class lpmgr - { - public: - /** - * \brief Function pointer to function that will create a new fcntl object and return its pointer. - * - * \param jcp Pointer to jcntl instance from which journal file details will be obtained. - * \param lfid Logical file ID for new fcntl instance. - * \param pfid Physical file ID for file associated with new fcntl instance. - * \param rdp Pointer to rcvdat instance which conatins recovery information for new fcntl instance when - * recovering an existing file, or null if a new file is to be created. - */ - typedef fcntl* (new_obj_fn_ptr)(jcntl* const jcp, - const u_int16_t lfid, - const u_int16_t pfid, - const rcvdat* const rdp); - - private: - bool _ae; ///< Auto-expand mode - u_int16_t _ae_max_jfiles; ///< Max file count for auto-expansion; 0 = no limit - std::vector _fcntl_arr; ///< Array of pointers to fcntl objects - - public: - lpmgr(); - virtual ~lpmgr(); - - /** - * \brief Initialize from scratch for a known number of %journal files. All lfid values are identical to pfid - * values (which is normal before any inserts have occurred). - * - * \param num_jfiles Number of files to be created, and consequently the number of fcntl objects in array - * _fcntl_arr. - * \param ae If true, allows auto-expansion; if false, disables auto-expansion. - * \param ae_max_jfiles The maximum number of files allowed for auto-expansion. Cannot be lower than the current - * number of files. However, a zero value disables the limit checks, and allows unlimited - * expansion. - * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that - * new files may be created. - * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence - * causes a new %journal file to be created). - */ - void initialize(const u_int16_t num_jfiles, - const bool ae, - const u_int16_t ae_max_jfiles, - jcntl* const jcp, - new_obj_fn_ptr fp); - - /** - * \brief Initialize from a known lfid-pfid map pfid_list (within rcvdat param rd), which is usually obtained - * from a recover. The index of pfid_list is the logical file id (lfid); the value contained in the vector is - * the physical file id (pfid). - * - * \param rd Ref to rcvdat struct which contains recovery data and the pfid_list. - * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that - * new files may be created. - * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence - * causes a new %journal file to be created). - */ - void recover(const rcvdat& rd, - jcntl* const jcp, - new_obj_fn_ptr fp); - - /** - * \brief Insert num_jfiles files after lfid index after_lfid. This causes all lfids after after_lfid to be - * increased by num_jfiles. - * - * Note that it is not possible to insert before lfid 0, and thus lfid 0 should always point to pfid 0. - * Inserting before lfid 0 is logically equivilent to inserting after the last lfid in a circular buffer. - * - * \param after_lfid Lid index after which to insert file(s). - * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that - * new files may be created. - * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence - * causes a new %journal file to be created). - * \param num_jfiles The number of files by which to increase. - */ - void insert(const u_int16_t after_lfid, - jcntl* const jcp, - new_obj_fn_ptr fp, - const u_int16_t num_jfiles = 1); - - /** - * \brief Clears _fcntl_arr and deletes all fcntl instances. - */ - void finalize(); - - /** - * \brief Returns true if initialized; false otherwise. After construction, will return false until initialize() - * is called; thereafter true until finalize() is called, whereupon it will return false again. - * - * \return True if initialized; false otherwise. - */ - inline bool is_init() const { return _fcntl_arr.size() > 0; } - - /** - * \brief Returns true if auto-expand mode is enabled; false if not. - * - * \return True if auto-expand mode is enabled; false if not. - */ - inline bool is_ae() const { return _ae; } - - /** - * \brief Sets the auto-expand mode to enabled if ae is true, to disabled otherwise. The value of _ae_max_jfiles - * must be valid to succeed (i.e. _ae_max_jfiles must be greater than the current number of files or be zero). - * - * \param ae If true will enable auto-expand mode; if false will disable it. - */ - void set_ae(const bool ae); - - /** - * \brief Returns the number of %journal files, including any that were appended or inserted since - * initialization. - * - * \return Number of %journal files if initialized; 0 otherwise. - */ - inline u_int16_t num_jfiles() const { return static_cast(_fcntl_arr.size()); } - - /** - * \brief Returns the maximum number of files allowed for auto-expansion. - * - * \return Maximum number of files allowed for auto-expansion. A zero value represents a disabled limit - * - i.e. unlimited expansion. - */ - inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; } - - /** - * \brief Sets the maximum number of files allowed for auto-expansion. A zero value disables the limit. - * - * \param ae_max_jfiles The maximum number of files allowed for auto-expansion. Cannot be lower than the current - * number of files. However, a zero value disables the limit checks, and allows unlimited - * expansion. - */ - void set_ae_max_jfiles(const u_int16_t ae_max_jfiles); - - /** - * \brief Calculates the number of future files available for auto-expansion. - * - * \return The number of future files available for auto-expansion. - */ - u_int16_t ae_jfiles_rem() const; - - /** - * \brief Get a pointer to fcntl instance for a given lfid. - * - * \return Pointer to fcntl object corresponding to logical file id lfid, or 0 if lfid is out of range - * (greater than number of files in use). - */ - inline fcntl* get_fcntlp(const u_int16_t lfid) const - { if (lfid >= _fcntl_arr.size()) return 0; return _fcntl_arr[lfid]; } - - // Testing functions - void get_pfid_list(std::vector& pfid_list) const; - void get_lfid_list(std::vector& lfid_list) const; - - protected: - - /** - * \brief Append num_jfiles files to the end of the logical and file id sequence. This is similar to extending - * the from-scratch initialization. - * - * \param jcp Pointer to jcntl instance. This is used to find the file path and base filename so that - * new files may be created. - * \param fp Pointer to function which creates and returns a pointer to a new fcntl object (and hence - * causes a new %journal file to be created). - * \param num_jfiles The number of files by which to increase. - */ - void append(jcntl* const jcp, - new_obj_fn_ptr fp, - const u_int16_t num_jfiles = 1); - - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_LPMGR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/pmgr.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/pmgr.cpp deleted file mode 100644 index 3dc61e2661..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/pmgr.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file pmgr.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::pmgr (page manager). See - * comments in file pmgr.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/pmgr.h" - -#include -#include -#include -#include "qpid/legacystore/jrnl/jcfg.h" -#include "qpid/legacystore/jrnl/jcntl.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include - - -namespace mrg -{ -namespace journal -{ - -pmgr::page_cb::page_cb(u_int16_t index): - _index(index), - _state(UNUSED), - _wdblks(0), - _rdblks(0), - _pdtokl(0), - _wfh(0), - _rfh(0), - _pbuff(0) -{} - -const char* -pmgr::page_cb::state_str() const -{ - switch(_state) - { - case UNUSED: - return "UNUSED"; - case IN_USE: - return "IN_USE"; - case AIO_PENDING: - return "AIO_PENDING"; - case AIO_COMPLETE: - return "AIO_COMPLETE"; - } - return ""; -} - -const u_int32_t pmgr::_sblksize = JRNL_SBLK_SIZE * JRNL_DBLK_SIZE; - -pmgr::pmgr(jcntl* jc, enq_map& emap, txn_map& tmap): - _cache_pgsize_sblks(0), - _cache_num_pages(0), - _jc(jc), - _emap(emap), - _tmap(tmap), - _page_base_ptr(0), - _page_ptr_arr(0), - _page_cb_arr(0), - _aio_cb_arr(0), - _aio_event_arr(0), - _ioctx(0), - _pg_index(0), - _pg_cntr(0), - _pg_offset_dblks(0), - _aio_evt_rem(0), - _cbp(0), - _enq_rec(), - _deq_rec(), - _txn_rec() -{} - -pmgr::~pmgr() -{ - pmgr::clean(); -} - -void -pmgr::initialize(aio_callback* const cbp, const u_int32_t cache_pgsize_sblks, const u_int16_t cache_num_pages) -{ - // As static use of this class keeps old values around, clean up first... - pmgr::clean(); - _pg_index = 0; - _pg_cntr = 0; - _pg_offset_dblks = 0; - _aio_evt_rem = 0; - _cache_pgsize_sblks = cache_pgsize_sblks; - _cache_num_pages = cache_num_pages; - _cbp = cbp; - - // 1. Allocate page memory (as a single block) - std::size_t cache_pgsize = _cache_num_pages * _cache_pgsize_sblks * _sblksize; - if (::posix_memalign(&_page_base_ptr, _sblksize, cache_pgsize)) - { - clean(); - std::ostringstream oss; - oss << "posix_memalign(): blksize=" << _sblksize << " size=" << cache_pgsize; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__MALLOC, oss.str(), "pmgr", "initialize"); - } - // 2. Allocate array of page pointers - _page_ptr_arr = (void**)std::malloc(_cache_num_pages * sizeof(void*)); - MALLOC_CHK(_page_ptr_arr, "_page_ptr_arr", "pmgr", "initialize"); - - // 3. Allocate and initilaize page control block (page_cb) array - _page_cb_arr = (page_cb*)std::malloc(_cache_num_pages * sizeof(page_cb)); - MALLOC_CHK(_page_cb_arr, "_page_cb_arr", "pmgr", "initialize"); - std::memset(_page_cb_arr, 0, _cache_num_pages * sizeof(page_cb)); - - // 5. Allocate IO control block (iocb) array - _aio_cb_arr = (aio_cb*)std::malloc(_cache_num_pages * sizeof(aio_cb)); - MALLOC_CHK(_aio_cb_arr, "_aio_cb_arr", "pmgr", "initialize"); - - // 6. Set page pointers in _page_ptr_arr, _page_cb_arr and iocbs to pages within page block - for (u_int16_t i=0; i<_cache_num_pages; i++) - { - _page_ptr_arr[i] = (void*)((char*)_page_base_ptr + _cache_pgsize_sblks * _sblksize * i); - _page_cb_arr[i]._index = i; - _page_cb_arr[i]._state = UNUSED; - _page_cb_arr[i]._pbuff = _page_ptr_arr[i]; - _page_cb_arr[i]._pdtokl = new std::deque; - _page_cb_arr[i]._pdtokl->clear(); - _aio_cb_arr[i].data = (void*)&_page_cb_arr[i]; - } - - // 7. Allocate io_event array, max one event per cache page plus one for each file - const u_int16_t max_aio_evts = _cache_num_pages + _jc->num_jfiles(); - _aio_event_arr = (aio_event*)std::malloc(max_aio_evts * sizeof(aio_event)); - MALLOC_CHK(_aio_event_arr, "_aio_event_arr", "pmgr", "initialize"); - - // 8. Initialize AIO context - if (int ret = aio::queue_init(max_aio_evts, &_ioctx)) - { - std::ostringstream oss; - oss << "io_queue_init() failed: " << FORMAT_SYSERR(-ret); - throw jexception(jerrno::JERR__AIO, oss.str(), "pmgr", "initialize"); - } -} - -void -pmgr::clean() -{ - // clean up allocated memory here - - if (_ioctx) - aio::queue_release(_ioctx); - - std::free(_page_base_ptr); - _page_base_ptr = 0; - - if (_page_cb_arr) - { - for (int i=0; i<_cache_num_pages; i++) - delete _page_cb_arr[i]._pdtokl; - std::free(_page_ptr_arr); - _page_ptr_arr = 0; - } - - std::free(_page_cb_arr); - _page_cb_arr = 0; - - std::free(_aio_cb_arr); - _aio_cb_arr = 0; - - std::free(_aio_event_arr); - _aio_event_arr = 0; -} - -const char* -pmgr::page_state_str(page_state ps) -{ - switch (ps) - { - case UNUSED: - return "UNUSED"; - case IN_USE: - return "IN_USE"; - case AIO_PENDING: - return "AIO_PENDING"; - case AIO_COMPLETE: - return "AIO_COMPLETE"; - } - return ""; -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/pmgr.h b/qpid/cpp/src/qpid/legacystore/jrnl/pmgr.h deleted file mode 100644 index 64115e225e..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/pmgr.h +++ /dev/null @@ -1,142 +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. - * - */ - -/** - * \file pmgr.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::pmgr (page manager). See - * class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_PMGR_H -#define QPID_LEGACYSTORE_JRNL_PMGR_H - -namespace mrg -{ -namespace journal -{ - class pmgr; - class jcntl; -} -} - -#include -#include "qpid/legacystore/jrnl/aio.h" -#include "qpid/legacystore/jrnl/aio_callback.h" -#include "qpid/legacystore/jrnl/data_tok.h" -#include "qpid/legacystore/jrnl/deq_rec.h" -#include "qpid/legacystore/jrnl/enq_map.h" -#include "qpid/legacystore/jrnl/enq_rec.h" -#include "qpid/legacystore/jrnl/fcntl.h" -#include "qpid/legacystore/jrnl/txn_map.h" -#include "qpid/legacystore/jrnl/txn_rec.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \brief Abstract class for managing either read or write page cache of arbitrary size and - * number of cache_num_pages. - */ - class pmgr - { - public: - /** - * \brief Enumeration of possible stats of a page within a page cache. - */ - enum page_state - { - UNUSED, ///< A page is uninitialized, contains no data. - IN_USE, ///< Page is in use. - AIO_PENDING, ///< An AIO request outstanding. - AIO_COMPLETE ///< An AIO request is complete. - }; - - protected: - /** - * \brief Page control block, carries control and state information for each page in the - * cache. - */ - struct page_cb - { - u_int16_t _index; ///< Index of this page - page_state _state; ///< Status of page - u_int64_t _frid; ///< First rid in page (used for fhdr init) - u_int32_t _wdblks; ///< Total number of dblks in page so far - u_int32_t _rdblks; ///< Total number of dblks in page - std::deque* _pdtokl; ///< Page message tokens list - fcntl* _wfh; ///< File handle for incrementing write compl counts - fcntl* _rfh; ///< File handle for incrementing read compl counts - void* _pbuff; ///< Page buffer - - page_cb(u_int16_t index); ///< Convenience constructor - const char* state_str() const; ///< Return state as string for this pcb - }; - - static const u_int32_t _sblksize; ///< Disk softblock size - u_int32_t _cache_pgsize_sblks; ///< Size of page cache cache_num_pages - u_int16_t _cache_num_pages; ///< Number of page cache cache_num_pages - jcntl* _jc; ///< Pointer to journal controller - enq_map& _emap; ///< Ref to enqueue map - txn_map& _tmap; ///< Ref to transaction map - void* _page_base_ptr; ///< Base pointer to page memory - void** _page_ptr_arr; ///< Array of pointers to cache_num_pages in page memory - page_cb* _page_cb_arr; ///< Array of page_cb structs - aio_cb* _aio_cb_arr; ///< Array of iocb structs - aio_event* _aio_event_arr; ///< Array of io_events - io_context_t _ioctx; ///< AIO context for read/write operations - u_int16_t _pg_index; ///< Index of current page being used - u_int32_t _pg_cntr; ///< Page counter; determines if file rotation req'd - u_int32_t _pg_offset_dblks; ///< Page offset (used so far) in data blocks - u_int32_t _aio_evt_rem; ///< Remaining AIO events - aio_callback* _cbp; ///< Pointer to callback object - - enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding - deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding - txn_rec _txn_rec; ///< Transaction record used for encoding/decoding - - public: - pmgr(jcntl* jc, enq_map& emap, txn_map& tmap); - virtual ~pmgr(); - - virtual int32_t get_events(page_state state, timespec* const timeout, bool flush = false) = 0; - inline u_int32_t get_aio_evt_rem() const { return _aio_evt_rem; } - static const char* page_state_str(page_state ps); - inline u_int32_t cache_pgsize_sblks() const { return _cache_pgsize_sblks; } - inline u_int16_t cache_num_pages() const { return _cache_num_pages; } - - protected: - virtual void initialize(aio_callback* const cbp, const u_int32_t cache_pgsize_sblks, - const u_int16_t cache_num_pages); - virtual void rotate_page() = 0; - virtual void clean(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_PMGR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rcvdat.h b/qpid/cpp/src/qpid/legacystore/jrnl/rcvdat.h deleted file mode 100644 index a7ef2341f0..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rcvdat.h +++ /dev/null @@ -1,181 +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. - * - */ - -/** - * \file rcvdat.h - * - * Qpid asynchronous store plugin library - * - * Contains structure for recovery status and offset data. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_RCVDAT_H -#define QPID_LEGACYSTORE_JRNL_RCVDAT_H - -#include -#include -#include -#include "qpid/legacystore/jrnl/jcfg.h" -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - - struct rcvdat - { - u_int16_t _njf; ///< Number of journal files - bool _ae; ///< Auto-expand mode - u_int16_t _aemjf; ///< Auto-expand mode max journal files - bool _owi; ///< Overwrite indicator - bool _frot; ///< First rotation flag - bool _jempty; ///< Journal data files empty - u_int16_t _ffid; ///< First file id - std::size_t _fro; ///< First record offset in ffid - u_int16_t _lfid; ///< Last file id - std::size_t _eo; ///< End offset (first byte past last record) - u_int64_t _h_rid; ///< Highest rid found - bool _lffull; ///< Last file is full - bool _jfull; ///< Journal is full - std::vector _fid_list; ///< Fid-lid mapping - list of fids in order of lid - std::vector _enq_cnt_list; ///< Number enqueued records found for each file - - rcvdat(): - _njf(0), - _ae(false), - _aemjf(0), - _owi(false), - _frot(false), - _jempty(true), - _ffid(0), - _fro(0), - _lfid(0), - _eo(0), - _h_rid(0), - _lffull(false), - _jfull(false), - _fid_list(), - _enq_cnt_list() - {} - - void reset(const u_int16_t num_jfiles, const bool auto_expand, const u_int16_t ae_max_jfiles) - { - _njf = num_jfiles; - _ae = auto_expand; - _aemjf = ae_max_jfiles; - _owi = false; - _frot = false; - _jempty = true; - _ffid = 0; - _fro = 0; - _lfid = 0; - _eo = 0; - _h_rid = 0; - _lffull = false; - _jfull = false; - _fid_list.clear(); - _enq_cnt_list.clear(); - _enq_cnt_list.resize(num_jfiles, 0); - } - - // Find first fid with enqueued records - u_int16_t ffid() - { - u_int16_t index = _ffid; - while (index != _lfid && _enq_cnt_list[index] == 0) - { - if (++index >= _njf) - index = 0; - } - return index; - } - - std::string to_string(const std::string& jid) - { - std::ostringstream oss; - oss << "Recover file analysis (jid=\"" << jid << "\"):" << std::endl; - oss << " Number of journal files (_njf) = " << _njf << std::endl; - oss << " Auto-expand mode (_ae) = " << (_ae ? "TRUE" : "FALSE") << std::endl; - if (_ae) oss << " Auto-expand mode max journal files (_aemjf) = " << _aemjf << std::endl; - oss << " Overwrite indicator (_owi) = " << (_owi ? "TRUE" : "FALSE") << std::endl; - oss << " First rotation (_frot) = " << (_frot ? "TRUE" : "FALSE") << std::endl; - oss << " Journal empty (_jempty) = " << (_jempty ? "TRUE" : "FALSE") << std::endl; - oss << " First (earliest) fid (_ffid) = " << _ffid << std::endl; - oss << " First record offset in first fid (_fro) = 0x" << std::hex << _fro << - std::dec << " (" << (_fro/JRNL_DBLK_SIZE) << " dblks)" << std::endl; - oss << " Last (most recent) fid (_lfid) = " << _lfid << std::endl; - oss << " End offset (_eo) = 0x" << std::hex << _eo << std::dec << " (" << - (_eo/JRNL_DBLK_SIZE) << " dblks)" << std::endl; - oss << " Highest rid (_h_rid) = 0x" << std::hex << _h_rid << std::dec << std::endl; - oss << " Last file full (_lffull) = " << (_lffull ? "TRUE" : "FALSE") << std::endl; - oss << " Journal full (_jfull) = " << (_jfull ? "TRUE" : "FALSE") << std::endl; - oss << " Normalized fid list (_fid_list) = ["; - for (std::vector::const_iterator i = _fid_list.begin(); i < _fid_list.end(); i++) - { - if (i != _fid_list.begin()) oss << ", "; - oss << *i; - } - oss << "]" << std::endl; - oss << " Enqueued records (txn & non-txn):" << std::endl; - for (unsigned i=0; i<_enq_cnt_list.size(); i++) - oss << " File " << std::setw(2) << i << ": " << _enq_cnt_list[i] << - std::endl; - return oss.str(); - } - - std::string to_log(const std::string& jid) - { - std::ostringstream oss; - oss << "Recover file analysis (jid=\"" << jid << "\"):"; - oss << " njf=" << _njf; - oss << " ae=" << (_owi ? "T" : "F"); - oss << " aemjf=" << _aemjf; - oss << " owi=" << (_ae ? "T" : "F"); - oss << " frot=" << (_frot ? "T" : "F"); - oss << " jempty=" << (_jempty ? "T" : "F"); - oss << " ffid=" << _ffid; - oss << " fro=0x" << std::hex << _fro << std::dec << " (" << - (_fro/JRNL_DBLK_SIZE) << " dblks)"; - oss << " lfid=" << _lfid; - oss << " eo=0x" << std::hex << _eo << std::dec << " (" << - (_eo/JRNL_DBLK_SIZE) << " dblks)"; - oss << " h_rid=0x" << std::hex << _h_rid << std::dec; - oss << " lffull=" << (_lffull ? "T" : "F"); - oss << " jfull=" << (_jfull ? "T" : "F"); - oss << " Enqueued records (txn & non-txn): [ "; - for (unsigned i=0; i<_enq_cnt_list.size(); i++) - { - if (i) oss << " "; - oss << "fid_" << std::setw(2) << std::setfill('0') << i << "=" << _enq_cnt_list[i]; - } - oss << " ]"; - return oss.str(); - } - }; -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_RCVDAT_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rec_hdr.h b/qpid/cpp/src/qpid/legacystore/jrnl/rec_hdr.h deleted file mode 100644 index ff6325a760..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rec_hdr.h +++ /dev/null @@ -1,143 +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. - * - */ - -/** - * \file rec_hdr.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rec_hdr (record header), - * which is a common initial header used for all journal record structures - * except the record tail (rec_tail). - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_REC_HDR_H -#define QPID_LEGACYSTORE_JRNL_REC_HDR_H - -#include -#include "qpid/legacystore/jrnl/jcfg.h" -#include - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for data common to the head of all journal files and records. - * This includes identification for the file type, the encoding version, endian - * indicator and a record ID. - * - * File header info in binary format (16 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+
-    * |     magic     | v | e | flags |
-    * +---+---+---+---+---+---+---+---+
-    * |              rid              |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct rec_hdr - { - u_int32_t _magic; ///< File type identifier (magic number) - u_int8_t _version; ///< File encoding version - u_int8_t _eflag; ///< Flag for determining endianness - u_int16_t _uflag; ///< User-defined flags - u_int64_t _rid; ///< Record ID (rotating 64-bit counter) - - // Global flags - static const u_int16_t HDR_OVERWRITE_INDICATOR_MASK = 0x1; - - // Convenience constructors and methods - /** - * \brief Default constructor, which sets all values to 0. - */ - inline rec_hdr(): _magic(0), _version(0), _eflag(0), _uflag(0), _rid(0) {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline rec_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const bool owi): _magic(magic), _version(version), -#if defined(JRNL_BIG_ENDIAN) - _eflag(RHM_BENDIAN_FLAG), -#else - _eflag(RHM_LENDIAN_FLAG), -#endif - _uflag(owi ? HDR_OVERWRITE_INDICATOR_MASK : 0), _rid(rid) {} - - /** - * \brief Convenience copy method. - */ - inline void hdr_copy(const rec_hdr& h) - { - _magic = h._magic; - _version = h._version; - _eflag = h._eflag; - _uflag = h._uflag; - _rid =h._rid; - } - - /** - * \brief Resets all fields to 0 - */ - inline void reset() - { - _magic = 0; - _version = 0; - _eflag = 0; - _uflag = 0; - _rid = 0; - } - - inline bool get_owi() const { return _uflag & HDR_OVERWRITE_INDICATOR_MASK; } - - inline void set_owi(const bool owi) - { - _uflag = owi ? _uflag | HDR_OVERWRITE_INDICATOR_MASK : - _uflag & (~HDR_OVERWRITE_INDICATOR_MASK); - } - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(rec_hdr); } - }; // struct rec_hdr - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_REC_HDR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rec_tail.h b/qpid/cpp/src/qpid/legacystore/jrnl/rec_tail.h deleted file mode 100644 index 0c36151927..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rec_tail.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file rec_tail.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rec_tail (record tail), used to - * finalize a persistent record. The presence of a valid tail at the expected - * position in the journal file indicates that the record write was completed. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_REC_TAIL_H -#define QPID_LEGACYSTORE_JRNL_REC_TAIL_H - -#include -#include "qpid/legacystore/jrnl/jcfg.h" - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for data common to the tail of all records. The magic number - * used here is the binary inverse (1's complement) of the magic used in the - * record header; this minimizes possible confusion with other headers that may - * be present during recovery. The tail is used with all records that have either - * XIDs or data - ie any size-variable content. Currently the only records that - * do NOT use the tail are non-transactional dequeues and filler records. - * - * Record header info in binary format (12 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+
-    * |   ~(magic)    |      rid      |
-    * +---+---+---+---+---+---+---+---+
-    * |  rid (con't)  |
-    * +---+---+---+---+
-    * 
- */ - struct rec_tail - { - u_int32_t _xmagic; ///< Binary inverse (1's complement) of hdr magic number - u_int64_t _rid; ///< ID (rotating 64-bit counter) - - - /** - * \brief Default constructor, which sets all values to 0. - */ - inline rec_tail(): _xmagic(0xffffffff), _rid(0) {} - - /** - * \brief Convenience constructor which initializes values during construction from - * existing enq_hdr instance. - */ - inline rec_tail(const rec_hdr& h): _xmagic(~h._magic), _rid(h._rid) {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - inline rec_tail(const u_int32_t xmagic, const u_int64_t rid): _xmagic(xmagic), _rid(rid) {} - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(rec_tail); } - }; - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_REC_TAIL_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rfc.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/rfc.cpp deleted file mode 100644 index 9b5ed95e81..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rfc.cpp +++ /dev/null @@ -1,82 +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. - * - */ - -/** - * \file rfc.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rfc (rotating - * file controller). See comments in file rfc.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/rfc.h" - -#include - -namespace mrg -{ -namespace journal -{ - -rfc::rfc(const lpmgr* lpmp): _lpmp(lpmp), _fc_index(0), _curr_fc(0) -{} - -rfc::~rfc() -{} - -void -rfc::finalize() -{ - unset_findex(); -} - -void -rfc::set_findex(const u_int16_t fc_index) -{ - _fc_index = fc_index; - _curr_fc = _lpmp->get_fcntlp(fc_index); - _curr_fc->rd_reset(); -} - -void -rfc::unset_findex() -{ - _fc_index = 0; - _curr_fc = 0; -} - -std::string -rfc::status_str() const -{ - if (!_lpmp->is_init()) - return "state: Uninitialized"; - if (_curr_fc == 0) - return "state: Inactive"; - std::ostringstream oss; - oss << "state: Active"; - return oss.str(); -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rfc.h b/qpid/cpp/src/qpid/legacystore/jrnl/rfc.h deleted file mode 100644 index faa5d566ba..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rfc.h +++ /dev/null @@ -1,193 +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. - * - */ - -/** - * \file rfc.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rfc (rotating - * file controller). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_RFC_H -#define QPID_LEGACYSTORE_JRNL_RFC_H - -namespace mrg -{ -namespace journal -{ -class rfc; -} -} - -#include "qpid/legacystore/jrnl/lpmgr.h" -#include "qpid/legacystore/jrnl/enums.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \class rfc - * \brief Rotating File Controller (rfc) - Class to handle the manangement of an array of file controllers (fcntl) - * objects for use in a circular disk buffer (journal). Each fcntl object corresponds to a file in the journal. - * - * The following states exist in this class: - * - *
-    *                                                                   is_init()  is_active()
-    *                  +===+                    _lpmp.is_init() == false
-    *      +---------->|   |     Uninitialized: _curr_fc == 0               F           F
-    *      |       +-->+===+ --+
-    *      |       |           |
-    *      |       |           |
-    *      |   finalize()   initialize()
-    *      |       |           |
-    *      |       |           |
-    *      |       +-- +===+<--+                _lpmp.is_init() == true
-    *  finalize()      |   |     Inactive:      _curr_fc == 0               T           F
-    *      |       +-->+===+ --+
-    *      |       |           |
-    *      |       |           |
-    *      | unset_findex() set_findex()
-    *      |       |           |
-    *      |       |           |
-    *      |       +-- +===+<--+                _lpmp.is_init() == true
-    *      +---------- |   |     Active:        _curr_fc != 0               T           T
-    *                  +===+
-    * 
- * - * The Uninitialized state is where the class starts after construction. Once the number of files is known and - * the array of file controllers allocated, then initialize() is called to set these, causing the state to move - * to Inactive. - * - * The Inactive state has the file controllers allocated and pointing to their respective journal files, but no - * current file controller has been selected. The pointer to the current file controller _curr_fc is null. Once the - * index of the active file is known, then calling set_findex() will set the index and internal pointer - * to the currently active file controller. This moves the state to Active. - * - * Note TODO: Comment on sync issues between change in num files in _lpmp and _fc_index/_curr_fc. - */ - class rfc - { - protected: - const lpmgr* _lpmp; ///< Pointer to jcntl's lpmgr instance containing lfid/pfid map and fcntl objects - u_int16_t _fc_index; ///< Index of current file controller - fcntl* _curr_fc; ///< Pointer to current file controller - - public: - rfc(const lpmgr* lpmp); - virtual ~rfc(); - - /** - * \brief Initialize the controller, moving from state Uninitialized to Inactive. The main function of - * initialize() is to set the number of files and the pointer to the fcntl array. - */ - virtual inline void initialize() {} - - /** - * \brief Reset the controller to Uninitialized state, usually called when the journal is stopped. Once called, - * initialize() must be called to reuse an instance. - */ - virtual void finalize(); - - /** - * \brief Check initialization state: true = Not Uninitialized, ie Initialized or Active; false = Uninitialized. - */ - virtual inline bool is_init() const { return _lpmp->is_init(); } - - /** - * \brief Check active state: true = Initialized and _curr_fc not null; false otherwise. - */ - virtual inline bool is_active() const { return _lpmp->is_init() && _curr_fc != 0; } - - /** - * \brief Sets the current file index and active fcntl object. Moves to state Active. - */ - virtual void set_findex(const u_int16_t fc_index); - - /** - * \brief Nulls the current file index and active fcntl pointer, moves to state Inactive. - */ - virtual void unset_findex(); - - /** - * \brief Rotate active file controller to next file in rotating file group. - * \exception jerrno::JERR__NINIT if called before calling initialize(). - */ - virtual iores rotate() = 0; - - /** - * \brief Returns the index of the currently active file within the rotating file group. - */ - inline u_int16_t index() const { return _fc_index; } - - /** - * \brief Returns the currently active journal file controller within the rotating file group. - */ - inline fcntl* file_controller() const { return _curr_fc; } - - /** - * \brief Returns the currently active physical file id (pfid) - */ - inline u_int16_t pfid() const { return _curr_fc->pfid(); } - - // Convenience access methods to current file controller - // Note: Do not call when not in active state - - inline u_int32_t enqcnt() const { return _curr_fc->enqcnt(); } - inline u_int32_t incr_enqcnt() { return _curr_fc->incr_enqcnt(); } - inline u_int32_t incr_enqcnt(const u_int16_t fid) { return _lpmp->get_fcntlp(fid)->incr_enqcnt(); } - inline u_int32_t add_enqcnt(const u_int32_t a) { return _curr_fc->add_enqcnt(a); } - inline u_int32_t add_enqcnt(const u_int16_t fid, const u_int32_t a) - { return _lpmp->get_fcntlp(fid)->add_enqcnt(a); } - inline u_int32_t decr_enqcnt(const u_int16_t fid) { return _lpmp->get_fcntlp(fid)->decr_enqcnt(); } - inline u_int32_t subtr_enqcnt(const u_int16_t fid, const u_int32_t s) - { return _lpmp->get_fcntlp(fid)->subtr_enqcnt(s); } - - virtual inline u_int32_t subm_cnt_dblks() const = 0; - virtual inline std::size_t subm_offs() const = 0; - virtual inline u_int32_t add_subm_cnt_dblks(u_int32_t a) = 0; - - virtual inline u_int32_t cmpl_cnt_dblks() const = 0; - virtual inline std::size_t cmpl_offs() const = 0; - virtual inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) = 0; - - virtual inline bool is_void() const = 0; - virtual inline bool is_empty() const = 0; - virtual inline u_int32_t remaining_dblks() const = 0; - virtual inline bool is_full() const = 0; - virtual inline bool is_compl() const = 0; - virtual inline u_int32_t aio_outstanding_dblks() const = 0; - virtual inline bool file_rotate() const = 0; - - // Debug aid - virtual std::string status_str() const; - }; // class rfc - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_RFC_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rmgr.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/rmgr.cpp deleted file mode 100644 index 204affd1d1..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rmgr.cpp +++ /dev/null @@ -1,698 +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. - * - */ - -/** - * \file rmgr.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rmgr (read manager). See - * comments in file rmgr.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/rmgr.h" - -#include -#include -#include -#include "qpid/legacystore/jrnl/jcntl.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include - -namespace mrg -{ -namespace journal -{ - -rmgr::rmgr(jcntl* jc, enq_map& emap, txn_map& tmap, rrfc& rrfc): - pmgr(jc, emap, tmap), - _rrfc(rrfc), - _hdr(), - _fhdr_buffer(0), - _fhdr_aio_cb_ptr(0), - _fhdr_rd_outstanding(false) -{} - -rmgr::~rmgr() -{ - rmgr::clean(); -} - -void -rmgr::initialize(aio_callback* const cbp) -{ - pmgr::initialize(cbp, JRNL_RMGR_PAGE_SIZE, JRNL_RMGR_PAGES); - clean(); - // Allocate memory for reading file header - if (::posix_memalign(&_fhdr_buffer, _sblksize, _sblksize)) - { - std::ostringstream oss; - oss << "posix_memalign(): blksize=" << _sblksize << " size=" << _sblksize; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__MALLOC, oss.str(), "rmgr", "initialize"); - } - _fhdr_aio_cb_ptr = new aio_cb; - std::memset(_fhdr_aio_cb_ptr, 0, sizeof(aio_cb)); -} - -void -rmgr::clean() -{ - std::free(_fhdr_buffer); - _fhdr_buffer = 0; - - if (_fhdr_aio_cb_ptr) - { - delete _fhdr_aio_cb_ptr; - _fhdr_aio_cb_ptr = 0; - } -} - -iores -rmgr::read(void** const datapp, std::size_t& dsize, void** const xidpp, std::size_t& xidsize, - bool& transient, bool& external, data_tok* dtokp, bool ignore_pending_txns) -{ - iores res = pre_read_check(dtokp); - if (res != RHM_IORES_SUCCESS) - { - set_params_null(datapp, dsize, xidpp, xidsize); - return res; - } - - if (dtokp->rstate() == data_tok::SKIP_PART) - { - if (_page_cb_arr[_pg_index]._state != AIO_COMPLETE) - { - aio_cycle(); // check if rd AIOs returned; initiate new reads if possible - return RHM_IORES_PAGE_AIOWAIT; - } - const iores res = skip(dtokp); - if (res != RHM_IORES_SUCCESS) - { - set_params_null(datapp, dsize, xidpp, xidsize); - return res; - } - } - if (dtokp->rstate() == data_tok::READ_PART) - { - assert(dtokp->rid() == _hdr._rid); - void* rptr = (void*)((char*)_page_ptr_arr[_pg_index] + (_pg_offset_dblks * JRNL_DBLK_SIZE)); - const iores res = read_enq(_hdr, rptr, dtokp); - dsize = _enq_rec.get_data(datapp); - xidsize = _enq_rec.get_xid(xidpp); - transient = _enq_rec.is_transient(); - external = _enq_rec.is_external(); - return res; - } - - set_params_null(datapp, dsize, xidpp, xidsize); - _hdr.reset(); - // Read header, determine next record type - while (true) - { - if(dblks_rem() == 0 && _rrfc.is_compl() && !_rrfc.is_wr_aio_outstanding()) - { - aio_cycle(); // check if rd AIOs returned; initiate new reads if possible - if(dblks_rem() == 0 && _rrfc.is_compl() && !_rrfc.is_wr_aio_outstanding()) - { - if (_jc->unflushed_dblks() > 0) - _jc->flush(); - else if (!_aio_evt_rem) - return RHM_IORES_EMPTY; - } - } - if (_page_cb_arr[_pg_index]._state != AIO_COMPLETE) - { - aio_cycle(); - return RHM_IORES_PAGE_AIOWAIT; - } - void* rptr = (void*)((char*)_page_ptr_arr[_pg_index] + (_pg_offset_dblks * JRNL_DBLK_SIZE)); - std::memcpy(&_hdr, rptr, sizeof(rec_hdr)); - switch (_hdr._magic) - { - case RHM_JDAT_ENQ_MAGIC: - { - _enq_rec.reset(); // sets enqueue rec size - // Check if RID of this rec is still enqueued, if so read it, else skip - bool is_enq = false; - int16_t fid = _emap.get_pfid(_hdr._rid); - if (fid < enq_map::EMAP_OK) - { - bool enforce_txns = !_jc->is_read_only() && !ignore_pending_txns; - // Block read for transactionally locked record (only when not recovering) - if (fid == enq_map::EMAP_LOCKED && enforce_txns) - return RHM_IORES_TXPENDING; - - // (Recover mode only) Ok, not in emap - now search tmap, if present then read - is_enq = _tmap.is_enq(_hdr._rid); - if (enforce_txns && is_enq) - return RHM_IORES_TXPENDING; - } - else - is_enq = true; - - if (is_enq) // ok, this record is enqueued, check it, then read it... - { - if (dtokp->rid()) - { - if (_hdr._rid != dtokp->rid()) - { - std::ostringstream oss; - oss << std::hex << "rid=0x" << _hdr._rid << "; dtok_rid=0x" << dtokp->rid() - << "; dtok_id=0x" << dtokp->id(); - throw jexception(jerrno::JERR_RMGR_RIDMISMATCH, oss.str(), "rmgr", "read"); - } - } - else - dtokp->set_rid(_hdr._rid); - -// TODO: Add member _fid to pmgr::page_cb which indicates the fid from which this page was -// populated. When this value is set in wmgr::flush() somewehere, then uncomment the following -// check: -// if (fid != _page_cb_arr[_pg_index]._fid) -// { -// std::ostringstream oss; -// oss << std::hex << std::setfill('0'); -// oss << "rid=0x" << std::setw(16) << _hdr._rid; -// oss << "; emap_fid=0x" << std::setw(4) << fid; -// oss << "; current_fid=" << _rrfc.fid(); -// throw jexception(jerrno::JERR_RMGR_FIDMISMATCH, oss.str(), "rmgr", -// "read"); -// } - - const iores res = read_enq(_hdr, rptr, dtokp); - dsize = _enq_rec.get_data(datapp); - xidsize = _enq_rec.get_xid(xidpp); - transient = _enq_rec.is_transient(); - external = _enq_rec.is_external(); - return res; - } - else // skip this record, it is already dequeued - consume_xid_rec(_hdr, rptr, dtokp); - break; - } - case RHM_JDAT_DEQ_MAGIC: - consume_xid_rec(_hdr, rptr, dtokp); - break; - case RHM_JDAT_TXA_MAGIC: - consume_xid_rec(_hdr, rptr, dtokp); - break; - case RHM_JDAT_TXC_MAGIC: - consume_xid_rec(_hdr, rptr, dtokp); - break; - case RHM_JDAT_EMPTY_MAGIC: - consume_filler(); - break; - default: - return RHM_IORES_EMPTY; - } - } -} - -int32_t -rmgr::get_events(page_state state, timespec* const timeout, bool flush) -{ - if (_aio_evt_rem == 0) // no events to get - return 0; - - int32_t ret; - if ((ret = aio::getevents(_ioctx, flush ? _aio_evt_rem : 1, _aio_evt_rem/*_cache_num_pages + _jc->num_jfiles()*/, _aio_event_arr, timeout)) < 0) - { - if (ret == -EINTR) // Interrupted by signal - return 0; - std::ostringstream oss; - oss << "io_getevents() failed: " << std::strerror(-ret) << " (" << ret << ")"; - throw jexception(jerrno::JERR__AIO, oss.str(), "rmgr", "get_events"); - } - if (ret == 0 && timeout) - return jerrno::AIO_TIMEOUT; - - std::vector pil; - pil.reserve(ret); - for (int i=0; idata); // This page control block (pcb) - long aioret = (long)_aio_event_arr[i].res; - if (aioret < 0) - { - std::ostringstream oss; - oss << "AIO read operation failed: " << std::strerror(-aioret) << " (" << aioret << ")"; - oss << " [pg=" << pcbp->_index << " buf=" << aiocbp->u.c.buf; - oss << " rsize=0x" << std::hex << aiocbp->u.c.nbytes; - oss << " offset=0x" << aiocbp->u.c.offset << std::dec; - oss << " fh=" << aiocbp->aio_fildes << "]"; - throw jexception(jerrno::JERR__AIO, oss.str(), "rmgr", "get_events"); - } - - if (pcbp) // Page reads have pcb - { - if (pcbp->_rfh->rd_subm_cnt_dblks() >= JRNL_SBLK_SIZE) // Detects if write reset of this fcntl obj has occurred. - { - // Increment the completed read offset - // NOTE: We cannot use _rrfc here, as it may have rotated since submitting count. - // Use stored pointer to fcntl in the pcb instead. - pcbp->_rdblks = aiocbp->u.c.nbytes / JRNL_DBLK_SIZE; - pcbp->_rfh->add_rd_cmpl_cnt_dblks(pcbp->_rdblks); - pcbp->_state = state; - pil[i] = pcbp->_index; - } - } - else // File header reads have no pcb - { - std::memcpy(&_fhdr, _fhdr_buffer, sizeof(file_hdr)); - _rrfc.add_cmpl_cnt_dblks(JRNL_SBLK_SIZE); - - u_int32_t fro_dblks = (_fhdr._fro / JRNL_DBLK_SIZE) - JRNL_SBLK_SIZE; - // Check fro_dblks does not exceed the write pointers which can happen in some corrupted journal recoveries - if (fro_dblks > _jc->wr_subm_cnt_dblks(_fhdr._pfid) - JRNL_SBLK_SIZE) - fro_dblks = _jc->wr_subm_cnt_dblks(_fhdr._pfid) - JRNL_SBLK_SIZE; - _pg_cntr = fro_dblks / (JRNL_RMGR_PAGE_SIZE * JRNL_SBLK_SIZE); - u_int32_t tot_pg_offs_dblks = _pg_cntr * JRNL_RMGR_PAGE_SIZE * JRNL_SBLK_SIZE; - _pg_index = _pg_cntr % JRNL_RMGR_PAGES; - _pg_offset_dblks = fro_dblks - tot_pg_offs_dblks; - _rrfc.add_subm_cnt_dblks(tot_pg_offs_dblks); - _rrfc.add_cmpl_cnt_dblks(tot_pg_offs_dblks); - - _fhdr_rd_outstanding = false; - _rrfc.set_valid(); - } - } - - // Perform AIO return callback - if (_cbp && ret) - _cbp->rd_aio_cb(pil); - return ret; -} - -void -rmgr::recover_complete() -{} - -void -rmgr::invalidate() -{ - if (_rrfc.is_valid()) - _rrfc.set_invalid(); -} - -void -rmgr::flush(timespec* timeout) -{ - // Wait for any outstanding AIO read operations to complete before synchronizing - while (_aio_evt_rem) - { - if (get_events(AIO_COMPLETE, timeout) == jerrno::AIO_TIMEOUT) // timed out, nothing returned - { - throw jexception(jerrno::JERR__TIMEOUT, - "Timed out waiting for outstanding read aio to return", "rmgr", "init_validation"); - } - } - - // Reset all read states and pointers - for (int i=0; i<_cache_num_pages; i++) - _page_cb_arr[i]._state = UNUSED; - _rrfc.unset_findex(); - _pg_index = 0; - _pg_offset_dblks = 0; -} - -bool -rmgr::wait_for_validity(timespec* timeout, const bool throw_on_timeout) -{ - bool timed_out = false; - while (!_rrfc.is_valid() && !timed_out) - { - timed_out = get_events(AIO_COMPLETE, timeout) == jerrno::AIO_TIMEOUT; - if (timed_out && throw_on_timeout) - throw jexception(jerrno::JERR__TIMEOUT, "Timed out waiting for read validity", "rmgr", "wait_for_validity"); - } - return _rrfc.is_valid(); -} - -iores -rmgr::pre_read_check(data_tok* dtokp) -{ - if (_aio_evt_rem) - get_events(AIO_COMPLETE, 0); - - if (!_rrfc.is_valid()) - return RHM_IORES_RCINVALID; - - // block reads until outstanding file header read completes as fro is needed to read - if (_fhdr_rd_outstanding) - return RHM_IORES_PAGE_AIOWAIT; - - if(dblks_rem() == 0 && _rrfc.is_compl() && !_rrfc.is_wr_aio_outstanding()) - { - aio_cycle(); // check if any AIOs have returned - if(dblks_rem() == 0 && _rrfc.is_compl() && !_rrfc.is_wr_aio_outstanding()) - { - if (_jc->unflushed_dblks() > 0) - _jc->flush(); - else if (!_aio_evt_rem) - return RHM_IORES_EMPTY; - } - } - - // Check write state of this token is ENQ - required for read - if (dtokp) - { - if (!dtokp->is_readable()) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "dtok_id=0x" << std::setw(8) << dtokp->id(); - oss << "; dtok_rid=0x" << std::setw(16) << dtokp->rid(); - oss << "; dtok_wstate=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_RMGR_ENQSTATE, oss.str(), "rmgr", "pre_read_check"); - } - } - - return RHM_IORES_SUCCESS; -} - -iores -rmgr::read_enq(rec_hdr& h, void* rptr, data_tok* dtokp) -{ - if (_page_cb_arr[_pg_index]._state != AIO_COMPLETE) - { - aio_cycle(); // check if any AIOs have returned - return RHM_IORES_PAGE_AIOWAIT; - } - - // Read data from this page, first block will have header and data size. - u_int32_t dblks_rd = _enq_rec.decode(h, rptr, dtokp->dblocks_read(), dblks_rem()); - dtokp->incr_dblocks_read(dblks_rd); - - _pg_offset_dblks += dblks_rd; - - // If data still incomplete, move to next page and decode again - while (dtokp->dblocks_read() < _enq_rec.rec_size_dblks()) - { - rotate_page(); - if (_page_cb_arr[_pg_index]._state != AIO_COMPLETE) - { - dtokp->set_rstate(data_tok::READ_PART); - dtokp->set_dsize(_enq_rec.data_size()); - return RHM_IORES_PAGE_AIOWAIT; - } - - rptr = (void*)((char*)_page_ptr_arr[_pg_index]); - dblks_rd = _enq_rec.decode(h, rptr, dtokp->dblocks_read(), dblks_rem()); - dtokp->incr_dblocks_read(dblks_rd); - _pg_offset_dblks += dblks_rd; - } - - // If we have finished with this page, rotate it - if (dblks_rem() == 0) - rotate_page(); - - // Set the record size in dtokp - dtokp->set_rstate(data_tok::READ); - dtokp->set_dsize(_enq_rec.data_size()); - return RHM_IORES_SUCCESS; -} - -void -rmgr::consume_xid_rec(rec_hdr& h, void* rptr, data_tok* dtokp) -{ - if (h._magic == RHM_JDAT_ENQ_MAGIC) - { - enq_hdr ehdr; - std::memcpy(&ehdr, rptr, sizeof(enq_hdr)); - if (ehdr.is_external()) - dtokp->set_dsize(ehdr._xidsize + sizeof(enq_hdr) + sizeof(rec_tail)); - else - dtokp->set_dsize(ehdr._xidsize + ehdr._dsize + sizeof(enq_hdr) + sizeof(rec_tail)); - } - else if (h._magic == RHM_JDAT_DEQ_MAGIC) - { - deq_hdr dhdr; - std::memcpy(&dhdr, rptr, sizeof(deq_hdr)); - if (dhdr._xidsize) - dtokp->set_dsize(dhdr._xidsize + sizeof(deq_hdr) + sizeof(rec_tail)); - else - dtokp->set_dsize(sizeof(deq_hdr)); - } - else if (h._magic == RHM_JDAT_TXA_MAGIC || h._magic == RHM_JDAT_TXC_MAGIC) - { - txn_hdr thdr; - std::memcpy(&thdr, rptr, sizeof(txn_hdr)); - dtokp->set_dsize(thdr._xidsize + sizeof(txn_hdr) + sizeof(rec_tail)); - } - else - { - std::ostringstream oss; - oss << "Record type found = \"" << (char*)&h._magic << "\""; - throw jexception(jerrno::JERR_RMGR_BADRECTYPE, oss.str(), "rmgr", "consume_xid_rec"); - } - dtokp->set_dblocks_read(0); - skip(dtokp); -} - -void -rmgr::consume_filler() -{ - // Filler (Magic "RHMx") is one dblk by definition - _pg_offset_dblks++; - if (dblks_rem() == 0) - rotate_page(); -} - -iores -rmgr::skip(data_tok* dtokp) -{ - u_int32_t dsize_dblks = jrec::size_dblks(dtokp->dsize()); - u_int32_t tot_dblk_cnt = dtokp->dblocks_read(); - while (true) - { - u_int32_t this_dblk_cnt = 0; - if (dsize_dblks - tot_dblk_cnt > dblks_rem()) - this_dblk_cnt = dblks_rem(); - else - this_dblk_cnt = dsize_dblks - tot_dblk_cnt; - if (this_dblk_cnt) - { - dtokp->incr_dblocks_read(this_dblk_cnt); - _pg_offset_dblks += this_dblk_cnt; - tot_dblk_cnt += this_dblk_cnt; - } - // If skip still incomplete, move to next page and decode again - if (tot_dblk_cnt < dsize_dblks) - { - if (dblks_rem() == 0) - rotate_page(); - if (_page_cb_arr[_pg_index]._state != AIO_COMPLETE) - { - dtokp->set_rstate(data_tok::SKIP_PART); - return RHM_IORES_PAGE_AIOWAIT; - } - } - else - { - // Skip complete, put state back to unread - dtokp->set_rstate(data_tok::UNREAD); - dtokp->set_dsize(0); - dtokp->set_dblocks_read(0); - - // If we have finished with this page, rotate it - if (dblks_rem() == 0) - rotate_page(); - return RHM_IORES_SUCCESS; - } - } -} - -iores -rmgr::aio_cycle() -{ - // Perform validity checks - if (_fhdr_rd_outstanding) // read of file header still outstanding in aio - return RHM_IORES_SUCCESS; - if (!_rrfc.is_valid()) - { - // Flush and reset all read states and pointers - flush(&jcntl::_aio_cmpl_timeout); - - _jc->get_earliest_fid(); // determine initial file to read; calls _rrfc.set_findex() to set value - // If this file has not yet been written to, return RHM_IORES_EMPTY - if (_rrfc.is_void() && !_rrfc.is_wr_aio_outstanding()) - return RHM_IORES_EMPTY; - init_file_header_read(); // send off AIO read request for file header - return RHM_IORES_SUCCESS; - } - - int16_t first_uninit = -1; - u_int16_t num_uninit = 0; - u_int16_t num_compl = 0; - bool outstanding = false; - // Index must start with current buffer and cycle around so that first - // uninitialized buffer is initialized first - for (u_int16_t i=_pg_index; i<_pg_index+_cache_num_pages; i++) - { - int16_t ci = i % _cache_num_pages; - switch (_page_cb_arr[ci]._state) - { - case UNUSED: - if (first_uninit < 0) - first_uninit = ci; - num_uninit++; - break; - case IN_USE: - break; - case AIO_PENDING: - outstanding = true; - break; - case AIO_COMPLETE: - num_compl++; - break; - default:; - } - } - iores res = RHM_IORES_SUCCESS; - if (num_uninit) - res = init_aio_reads(first_uninit, num_uninit); - else if (num_compl == _cache_num_pages) // This condition exists after invalidation - res = init_aio_reads(0, _cache_num_pages); - if (outstanding) - get_events(AIO_COMPLETE, 0); - return res; -} - -iores -rmgr::init_aio_reads(const int16_t first_uninit, const u_int16_t num_uninit) -{ - for (int16_t i=0; i pg_size_dblks ? pg_size_dblks : file_rem_dblks; - if (rd_size) - { - int16_t pi = (i + first_uninit) % _cache_num_pages; - // TODO: For perf, combine contiguous pages into single read - // 1 or 2 AIOs needed depending on whether read block folds - aio_cb* aiocbp = &_aio_cb_arr[pi]; - aio::prep_pread_2(aiocbp, _rrfc.fh(), _page_ptr_arr[pi], rd_size * JRNL_DBLK_SIZE, _rrfc.subm_offs()); - if (aio::submit(_ioctx, 1, &aiocbp) < 0) - throw jexception(jerrno::JERR__AIO, "rmgr", "init_aio_reads"); - _rrfc.add_subm_cnt_dblks(rd_size); - _aio_evt_rem++; - _page_cb_arr[pi]._state = AIO_PENDING; - _page_cb_arr[pi]._rfh = _rrfc.file_controller(); - } - else // If there is nothing to read for this page, neither will there be for the others... - break; - if (_rrfc.file_rotate()) - _rrfc.rotate(); - } - return RHM_IORES_SUCCESS; -} - -void -rmgr::rotate_page() -{ - _page_cb_arr[_pg_index]._rdblks = 0; - _page_cb_arr[_pg_index]._state = UNUSED; - if (_pg_offset_dblks >= JRNL_RMGR_PAGE_SIZE * JRNL_SBLK_SIZE) - { - _pg_offset_dblks = 0; - _pg_cntr++; - } - if (++_pg_index >= _cache_num_pages) - _pg_index = 0; - aio_cycle(); - _pg_offset_dblks = 0; - // This counter is for bookkeeping only, page rotates are handled directly in init_aio_reads() - // FIXME: _pg_cntr should be sync'd with aio ops, not use of page as it is now... - // Need to move reset into if (_rrfc.file_rotate()) above. - if (_pg_cntr >= (_jc->jfsize_sblks() / JRNL_RMGR_PAGE_SIZE)) - _pg_cntr = 0; -} - -u_int32_t -rmgr::dblks_rem() const -{ - return _page_cb_arr[_pg_index]._rdblks - _pg_offset_dblks; -} - -void -rmgr::set_params_null(void** const datapp, std::size_t& dsize, void** const xidpp, std::size_t& xidsize) -{ - *datapp = 0; - dsize = 0; - *xidpp = 0; - xidsize = 0; -} - -void -rmgr::init_file_header_read() -{ - _jc->fhdr_wr_sync(_rrfc.index()); // wait if the file header write is outstanding - int rfh = _rrfc.fh(); - aio::prep_pread_2(_fhdr_aio_cb_ptr, rfh, _fhdr_buffer, _sblksize, 0); - if (aio::submit(_ioctx, 1, &_fhdr_aio_cb_ptr) < 0) - throw jexception(jerrno::JERR__AIO, "rmgr", "init_file_header_read"); - _aio_evt_rem++; - _rrfc.add_subm_cnt_dblks(JRNL_SBLK_SIZE); - _fhdr_rd_outstanding = true; -} - -/* TODO (sometime in the future) -const iores -rmgr::get(const u_int64_t& rid, const std::size_t& dsize, const std::size_t& dsize_avail, - const void** const data, bool auto_discard) -{ - return RHM_IORES_SUCCESS; -} - -const iores -rmgr::discard(data_tok* dtokp) -{ - return RHM_IORES_SUCCESS; -} -*/ - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rmgr.h b/qpid/cpp/src/qpid/legacystore/jrnl/rmgr.h deleted file mode 100644 index 47a36ef35c..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rmgr.h +++ /dev/null @@ -1,114 +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. - * - */ - -/** - * \file rmgr.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rmgr (read manager). See - * class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_RMGR_H -#define QPID_LEGACYSTORE_JRNL_RMGR_H - -namespace mrg -{ -namespace journal -{ -class rmgr; -} -} - -#include -#include "qpid/legacystore/jrnl/enums.h" -#include "qpid/legacystore/jrnl/file_hdr.h" -#include "qpid/legacystore/jrnl/pmgr.h" -#include "qpid/legacystore/jrnl/rec_hdr.h" -#include "qpid/legacystore/jrnl/rrfc.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \brief Class for managing a read page cache of arbitrary size and number of pages. - * - * The read page cache works on the principle of filling as many pages as possilbe in advance of - * reading the data. This ensures that delays caused by AIO operations are minimized. - */ - class rmgr : public pmgr - { - private: - rrfc& _rrfc; ///< Ref to read rotating file controller - rec_hdr _hdr; ///< Header used to determind record type - - void* _fhdr_buffer; ///< Buffer used for fhdr reads - aio_cb* _fhdr_aio_cb_ptr; ///< iocb pointer for fhdr reads - file_hdr _fhdr; ///< file header instance for reading file headers - bool _fhdr_rd_outstanding; ///< true if a fhdr read is outstanding - - public: - rmgr(jcntl* jc, enq_map& emap, txn_map& tmap, rrfc& rrfc); - virtual ~rmgr(); - - using pmgr::initialize; - void initialize(aio_callback* const cbp); - iores read(void** const datapp, std::size_t& dsize, void** const xidpp, - std::size_t& xidsize, bool& transient, bool& external, data_tok* dtokp, - bool ignore_pending_txns); - int32_t get_events(page_state state, timespec* const timeout, bool flush = false); - void recover_complete(); - inline iores synchronize() { if (_rrfc.is_valid()) return RHM_IORES_SUCCESS; return aio_cycle(); } - void invalidate(); - bool wait_for_validity(timespec* const timeout, const bool throw_on_timeout = false); - - /* TODO (if required) - const iores get(const u_int64_t& rid, const std::size_t& dsize, const std::size_t& dsize_avail, - const void** const data, bool auto_discard); - const iores discard(data_tok* dtok); - */ - - private: - void clean(); - void flush(timespec* timeout); - iores pre_read_check(data_tok* dtokp); - iores read_enq(rec_hdr& h, void* rptr, data_tok* dtokp); - void consume_xid_rec(rec_hdr& h, void* rptr, data_tok* dtokp); - void consume_filler(); - iores skip(data_tok* dtokp); - iores aio_cycle(); - iores init_aio_reads(const int16_t first_uninit, const u_int16_t num_uninit); - void rotate_page(); - u_int32_t dblks_rem() const; - void set_params_null(void** const datapp, std::size_t& dsize, void** const xidpp, - std::size_t& xidsize); - void init_file_header_read(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_RMGR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rrfc.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/rrfc.cpp deleted file mode 100644 index fc6f5d427f..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rrfc.cpp +++ /dev/null @@ -1,125 +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. - * - */ - -/** - * \file rrfc.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rrfc (rotating - * file controller). See comments in file rrfc.h for details. - * - * \author Kim van der Riet - */ - - -#include "qpid/legacystore/jrnl/rrfc.h" - -#include -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" - -namespace mrg -{ -namespace journal -{ - -rrfc::rrfc(const lpmgr* lpmp): rfc(lpmp), _fh(-1), _valid(false) -{} - -rrfc::~rrfc() -{ - close_fh(); -} - -void -rrfc::finalize() -{ - unset_findex(); - rfc::finalize(); -} - -void -rrfc::set_findex(const u_int16_t fc_index) -{ - rfc::set_findex(fc_index); - open_fh(_curr_fc->fname()); -} - -void -rrfc::unset_findex() -{ - set_invalid(); - close_fh(); - rfc::unset_findex(); -} - -iores -rrfc::rotate() -{ - if (!_lpmp->num_jfiles()) - throw jexception(jerrno::JERR__NINIT, "rrfc", "rotate"); - u_int16_t next_fc_index = _fc_index + 1; - if (next_fc_index == _lpmp->num_jfiles()) - next_fc_index = 0; - set_findex(next_fc_index); - return RHM_IORES_SUCCESS; -} - -std::string -rrfc::status_str() const -{ - std::ostringstream oss; - oss << "rrfc: " << rfc::status_str(); - if (is_active()) - oss << " fcntl[" << _fc_index << "]: " << _curr_fc->status_str(); - return oss.str(); -} - -// === protected functions === - -void -rrfc::open_fh(const std::string& fn) -{ - close_fh(); - _fh = ::open(fn.c_str(), O_RDONLY | O_DIRECT); - if (_fh < 0) - { - std::ostringstream oss; - oss << "file=\"" << fn << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_RRFC_OPENRD, oss.str(), "rrfc", "open_fh"); - } -} - -void -rrfc::close_fh() -{ - if (_fh >= 0) - { - ::close(_fh); - _fh = -1; - } -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/rrfc.h b/qpid/cpp/src/qpid/legacystore/jrnl/rrfc.h deleted file mode 100644 index 5066d6048a..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/rrfc.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file rrfc.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::rrfc (rotating - * file controller). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_RRFC_H -#define QPID_LEGACYSTORE_JRNL_RRFC_H - -namespace mrg -{ -namespace journal -{ -class rrfc; -} -} - -#include "qpid/legacystore/jrnl/fcntl.h" -#include "qpid/legacystore/jrnl/rfc.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \class rrfc - * \brief Read Rotating File Controller (rrfc) - Subclassed from pure virtual class rfc. Used to control the read - * pipeline in a rotating file buffer or journal. See class rfc for further details. - * - * The states that exist in this class are identical to class rfc from which it inherits, but in addition, the value - * of the read file handle _fh is also considered. The calls to set_findex also opens the file handle _fh to the - * active file for reading. Similarly, unset_findex() closes this file handle. - * - *
-    *                                                                   is_init()  is_active()
-    *                  +===+                    _lpmp.is_init() == false
-    *      +---------->|   |     Uninitialized: _curr_fc == 0               F           F
-    *      |       +-->+===+ --+                _fh == -1
-    *      |       |           |
-    *      |       |           |
-    *      |   finalize()   initialize()
-    *      |       |           |
-    *      |       |           |
-    *      |       +-- +===+<--+                _lpmp.is_init() == true
-    *  finalize()      |   |     Inactive:      _curr_fc == 0               T           F
-    *      |       +-->+===+ --+                _fh == -1
-    *      |       |           |
-    *      |       |           |
-    *      | unset_findex() set_findex()
-    *      |       |           |
-    *      |       |           |
-    *      |       +-- +===+<--+                _lpmp.is_init() == true
-    *      +---------- |   |     Active:        _curr_fc != 0               T           T
-    *                  +===+                    _fh >= 0
-    * 
- * - * In adition to the states above, class rrfc contains a validity flag. This is operated indepenedently of the state - * machine. This flag (_valid) indicates when the read buffers are valid for reading. This is not strictly a state, - * but simply a flag used to keep track of the status, and is set/unset with calls to set_valid() and set_invalid() - * respectively. - */ - class rrfc : public rfc - { - protected: - int _fh; ///< Read file handle - bool _valid; ///< Flag is true when read pages contain vailid data - - public: - rrfc(const lpmgr* lpmp); - virtual ~rrfc(); - - /** - * \brief Initialize the controller, moving from state Uninitialized to Initialized. The main function of - * initialize() is to set the number of files and the pointer to the fcntl array. - */ - inline void initialize() { rfc::initialize(); _valid = false; } - - /** - * \brief Reset the controller to Uninitialized state, usually called when the journal is stopped. Once called, - * initialize() must be called to reuse an instance. - */ - void finalize(); - - /** - * \brief Opens the file handle for reading a particular fid. Moves to state open. - */ - void set_findex(const u_int16_t fc_index); - - /** - * \brief Closes the read file handle and nulls the active fcntl pointer. Moves to state closed. - */ - void unset_findex(); - - /** - * \brief Check the state: true = open; false = closed. - */ - inline bool is_active() const { return _curr_fc != 0 && _fh >= 0; } - - /** - * \brief Sets the validity flag which indicates that the read buffers contain valid data for reading. - */ - inline void set_invalid() { _valid = false; } - - /** - * \brief Resets the validity flag wich indicates that the read buffers are no longer synchronized and cannot - * be read whithout resynchronization. - */ - inline void set_valid() { _valid = true; } - - /** - * \brief Checks the read buffer validity status: true = valid, can be read; false = invalid, synchronization - * required. - */ - inline bool is_valid() const { return _valid; } - - /** - * \brief Rotate active file controller to next file in rotating file group. - * \exception jerrno::JERR__NINIT if called before calling initialize(). - */ - iores rotate(); - - inline int fh() const { return _fh; } - - inline u_int32_t subm_cnt_dblks() const { return _curr_fc->rd_subm_cnt_dblks(); } - inline std::size_t subm_offs() const { return _curr_fc->rd_subm_offs(); } - inline u_int32_t add_subm_cnt_dblks(u_int32_t a) { return _curr_fc->add_rd_subm_cnt_dblks(a); } - - inline u_int32_t cmpl_cnt_dblks() const { return _curr_fc->rd_cmpl_cnt_dblks(); } - inline std::size_t cmpl_offs() const { return _curr_fc->rd_cmpl_offs(); } - inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) { return _curr_fc->add_rd_cmpl_cnt_dblks(a); } - - inline bool is_void() const { return _curr_fc->rd_void(); } - inline bool is_empty() const { return _curr_fc->rd_empty(); } - inline u_int32_t remaining_dblks() const { return _curr_fc->rd_remaining_dblks(); } - inline bool is_full() const { return _curr_fc->is_rd_full(); } - inline bool is_compl() const { return _curr_fc->is_rd_compl(); } - inline u_int32_t aio_outstanding_dblks() const { return _curr_fc->rd_aio_outstanding_dblks(); } - inline bool file_rotate() const { return _curr_fc->rd_file_rotate(); } - inline bool is_wr_aio_outstanding() const { return _curr_fc->wr_aio_outstanding_dblks() > 0; } - - // Debug aid - std::string status_str() const; - - protected: - void open_fh(const std::string& fn); - void close_fh(); - }; // class rrfc - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_RRFC_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/slock.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/slock.cpp deleted file mode 100644 index 8f26d349ef..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/slock.cpp +++ /dev/null @@ -1,33 +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. - * - */ - -/** - * \file slock.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::slock (scoped lock). See - * comments in file slock.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/slock.h" diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/slock.h b/qpid/cpp/src/qpid/legacystore/jrnl/slock.h deleted file mode 100644 index c05b5cf336..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/slock.h +++ /dev/null @@ -1,85 +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. - * - */ - -/** - * \file slock.h - * - * Qpid asynchronous store plugin library - * - * Messaging journal scoped lock class mrg::journal::slock and scoped try-lock - * class mrg::journal::stlock. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_SLOCK_H -#define QPID_LEGACYSTORE_JRNL_SLOCK_H - -#include "qpid/legacystore/jrnl/jexception.h" -#include "qpid/legacystore/jrnl/smutex.h" -#include - -namespace mrg -{ -namespace journal -{ - - // Ultra-simple scoped lock class, auto-releases mutex when it goes out-of-scope - class slock - { - protected: - const smutex& _sm; - public: - inline slock(const smutex& sm) : _sm(sm) - { - PTHREAD_CHK(::pthread_mutex_lock(_sm.get()), "::pthread_mutex_lock", "slock", "slock"); - } - inline ~slock() - { - PTHREAD_CHK(::pthread_mutex_unlock(_sm.get()), "::pthread_mutex_unlock", "slock", "~slock"); - } - }; - - // Ultra-simple scoped try-lock class, auto-releases mutex when it goes out-of-scope - class stlock - { - protected: - const smutex& _sm; - bool _locked; - public: - inline stlock(const smutex& sm) : _sm(sm), _locked(false) - { - int ret = ::pthread_mutex_trylock(_sm.get()); - _locked = (ret == 0); // check if lock obtained - if (!_locked && ret != EBUSY) PTHREAD_CHK(ret, "::pthread_mutex_trylock", "stlock", "stlock"); - } - inline ~stlock() - { - if (_locked) - PTHREAD_CHK(::pthread_mutex_unlock(_sm.get()), "::pthread_mutex_unlock", "stlock", "~stlock"); - } - inline bool locked() const { return _locked; } - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_SLOCK_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/smutex.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/smutex.cpp deleted file mode 100644 index 6f8991ca5b..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/smutex.cpp +++ /dev/null @@ -1,33 +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. - * - */ - -/** - * \file smutex.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::smutex (scoped mutex). See - * comments in file smutex.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/smutex.h" diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/smutex.h b/qpid/cpp/src/qpid/legacystore/jrnl/smutex.h deleted file mode 100644 index def0fb70f6..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/smutex.h +++ /dev/null @@ -1,64 +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. - * - */ - -/** - * \file smutex.h - * - * Qpid asynchronous store plugin library - * - * Messaging journal scoped mutex class mrg::journal::smutex. - * - * \author Kim van der Riet - */ - - -#ifndef QPID_LEGACYSTORE_JRNL_SMUTEX_H -#define QPID_LEGACYSTORE_JRNL_SMUTEX_H - -#include "qpid/legacystore/jrnl/jexception.h" -#include - -namespace mrg -{ -namespace journal -{ - - // Ultra-simple scoped mutex class that allows a posix mutex to be initialized and destroyed with error checks - class smutex - { - protected: - mutable pthread_mutex_t _m; - public: - inline smutex() - { - PTHREAD_CHK(::pthread_mutex_init(&_m, 0), "::pthread_mutex_init", "smutex", "smutex"); - } - inline virtual ~smutex() - { - PTHREAD_CHK(::pthread_mutex_destroy(&_m), "::pthread_mutex_destroy", "smutex", "~smutex"); - } - inline pthread_mutex_t* get() const { return &_m; } - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_SMUTEX_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/time_ns.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/time_ns.cpp deleted file mode 100644 index 976068ef68..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/time_ns.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file time_ns.cpp - * - * Qpid asynchronous store plugin library - * - * Messaging journal time struct mrg::journal::time_ns, derived from - * the timespec struct and provided with helper functions. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/time_ns.h" - -#include - -namespace mrg -{ -namespace journal -{ - -const std::string -time_ns::str(int precision) const -{ - const double t = tv_sec + (tv_nsec/1e9); - std::ostringstream oss; - oss.setf(std::ios::fixed, std::ios::floatfield); - oss.precision(precision); - oss << t; - return oss.str(); -} - - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/time_ns.h b/qpid/cpp/src/qpid/legacystore/jrnl/time_ns.h deleted file mode 100644 index a9f69e2631..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/time_ns.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * \file time_ns.h - * - * Qpid asynchronous store plugin library - * - * Messaging journal time struct mrg::journal::time_ns, derived from - * the timespec struct and provided with helper functions. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_TIME_NS_H -#define QPID_LEGACYSTORE_JRNL_TIME_NS_H - -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - -struct time_ns : public timespec -{ - inline time_ns() { tv_sec = 0; tv_nsec = 0; } - inline time_ns(const std::time_t sec, const long nsec = 0) { tv_sec = sec; tv_nsec = nsec; } - inline time_ns(const time_ns& t) { tv_sec = t.tv_sec; tv_nsec = t.tv_nsec; } - - inline void set_zero() { tv_sec = 0; tv_nsec = 0; } - inline bool is_zero() const { return tv_sec == 0 && tv_nsec == 0; } - inline int now() { if(::clock_gettime(CLOCK_REALTIME, this)) return errno; return 0; } - const std::string str(int precision = 6) const; - - inline time_ns& operator=(const time_ns& rhs) - { tv_sec = rhs.tv_sec; tv_nsec = rhs.tv_nsec; return *this; } - inline time_ns& operator+=(const time_ns& rhs) - { - tv_nsec += rhs.tv_nsec; - if (tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } - tv_sec += rhs.tv_sec; - return *this; - } - inline time_ns& operator+=(const long ns) - { - tv_nsec += ns; - if (tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } - return *this; - } - inline time_ns& operator-=(const long ns) - { - tv_nsec -= ns; - if (tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000L; } - return *this; - } - inline time_ns& operator-=(const time_ns& rhs) - { - tv_nsec -= rhs.tv_nsec; - if (tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000L; } - tv_sec -= rhs.tv_sec; - return *this; - } - inline const time_ns operator+(const time_ns& rhs) - { time_ns t(*this); t += rhs; return t; } - inline const time_ns operator-(const time_ns& rhs) - { time_ns t(*this); t -= rhs; return t; } - inline bool operator==(const time_ns& rhs) - { return tv_sec == rhs.tv_sec && tv_nsec == rhs.tv_nsec; } - inline bool operator!=(const time_ns& rhs) - { return tv_sec != rhs.tv_sec || tv_nsec != rhs.tv_nsec; } - inline bool operator>(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec > rhs.tv_nsec; return tv_sec > rhs.tv_sec; } - inline bool operator>=(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec >= rhs.tv_nsec; return tv_sec >= rhs.tv_sec; } - inline bool operator<(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec < rhs.tv_nsec; return tv_sec < rhs.tv_sec; } - inline bool operator<=(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec <= rhs.tv_nsec; return tv_sec <= rhs.tv_sec; } -}; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_TIME_NS_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/txn_hdr.h b/qpid/cpp/src/qpid/legacystore/jrnl/txn_hdr.h deleted file mode 100644 index 94b812ccec..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/txn_hdr.h +++ /dev/null @@ -1,125 +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. - * - */ - -/** - * \file txn_hdr.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::txn_hdr (transaction - * record header), used to start a transaction (commit or abort) record. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_TXN_HDR_H -#define QPID_LEGACYSTORE_JRNL_TXN_HDR_H - -#include -#include "qpid/legacystore/jrnl/rec_hdr.h" - -namespace mrg -{ -namespace journal -{ - -#pragma pack(1) - - /** - * \brief Struct for transaction commit and abort records. - * - * Struct for DTX commit and abort records. Only the magic distinguishes between them. Since - * this record must be used in the context of a valid XID, the xidsize field must not be zero. - * Immediately following this record is the XID itself which is xidsize bytes long, followed by - * a rec_tail. - * - * Note that this record had its own rid distinct from the rids of the record(s) making up the - * transaction it is committing or aborting. - * - * Record header info in binary format (24 bytes): - *
-    *   0                           7
-    * +---+---+---+---+---+---+---+---+  -+
-    * |     magic     | v | e | flags |   |
-    * +---+---+---+---+---+---+---+---+   | struct hdr
-    * |              rid              |   |
-    * +---+---+---+---+---+---+---+---+  -+
-    * |            xidsize            |
-    * +---+---+---+---+---+---+---+---+
-    * v = file version (If the format or encoding of this file changes, then this
-    *     number should be incremented)
-    * e = endian flag, false (0x00) for little endian, true (0x01) for big endian
-    * 
- * - * Note that journal files should be transferable between 32- and 64-bit - * hardware of the same endianness, but not between hardware of opposite - * entianness without some sort of binary conversion utility. Thus buffering - * will be needed for types that change size between 32- and 64-bit compiles. - */ - struct txn_hdr : rec_hdr - { -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Big-endian filler for 32-bit size_t -#endif - std::size_t _xidsize; ///< XID size -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - u_int32_t _filler0; ///< Little-endian filler for 32-bit size_t -#endif - - /** - * \brief Default constructor, which sets all values to 0. - */ - txn_hdr(): rec_hdr(), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(0) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler0(0) -#endif - {} - - /** - * \brief Convenience constructor which initializes values during construction. - */ - txn_hdr(const u_int32_t magic, const u_int8_t version, const u_int64_t rid, - const std::size_t xidsize, const bool owi): rec_hdr(magic, version, rid, owi), -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - _filler0(0), -#endif - _xidsize(xidsize) -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - , _filler0(0) -#endif - {} - - /** - * \brief Returns the size of the header in bytes. - */ - inline static std::size_t size() { return sizeof(txn_hdr); } - }; - -#pragma pack() - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_TXN_HDR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/txn_map.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/txn_map.cpp deleted file mode 100644 index c514670601..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/txn_map.cpp +++ /dev/null @@ -1,256 +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. - * - */ - -/** - * \file txn_map.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::txn_map (transaction map). See - * comments in file txn_map.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/txn_map.h" - -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include "qpid/legacystore/jrnl/slock.h" -#include - -namespace mrg -{ -namespace journal -{ - -// return/error codes -int16_t txn_map::TMAP_RID_NOT_FOUND = -2; -int16_t txn_map::TMAP_XID_NOT_FOUND = -1; -int16_t txn_map::TMAP_OK = 0; -int16_t txn_map::TMAP_NOT_SYNCED = 0; -int16_t txn_map::TMAP_SYNCED = 1; - -txn_data_struct::txn_data_struct(const u_int64_t rid, const u_int64_t drid, const u_int16_t pfid, - const bool enq_flag, const bool commit_flag): - _rid(rid), - _drid(drid), - _pfid(pfid), - _enq_flag(enq_flag), - _commit_flag(commit_flag), - _aio_compl(false) -{} - -txn_map::txn_map(): - _map(), - _pfid_txn_cnt() -{} - -txn_map::~txn_map() {} - -void -txn_map::set_num_jfiles(const u_int16_t num_jfiles) -{ - _pfid_txn_cnt.resize(num_jfiles, 0); -} - -u_int32_t -txn_map::get_txn_pfid_cnt(const u_int16_t pfid) const -{ - return _pfid_txn_cnt.at(pfid); -} - -bool -txn_map::insert_txn_data(const std::string& xid, const txn_data& td) -{ - bool ok = true; - slock s(_mutex); - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // not found in map - { - txn_data_list list; - list.push_back(td); - std::pair ret = _map.insert(xmap_param(xid, list)); - if (!ret.second) // duplicate - ok = false; - } - else - itr->second.push_back(td); - _pfid_txn_cnt.at(td._pfid)++; - return ok; -} - -const txn_data_list -txn_map::get_tdata_list(const std::string& xid) -{ - slock s(_mutex); - return get_tdata_list_nolock(xid); -} - -const txn_data_list -txn_map::get_tdata_list_nolock(const std::string& xid) -{ - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // not found in map - return _empty_data_list; - return itr->second; -} - -const txn_data_list -txn_map::get_remove_tdata_list(const std::string& xid) -{ - slock s(_mutex); - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // not found in map - return _empty_data_list; - txn_data_list list = itr->second; - _map.erase(itr); - for (tdl_itr i=list.begin(); i!=list.end(); i++) - _pfid_txn_cnt.at(i->_pfid)--; - return list; -} - -bool -txn_map::in_map(const std::string& xid) -{ - slock s(_mutex); - xmap_itr itr= _map.find(xid); - return itr != _map.end(); -} - -u_int32_t -txn_map::enq_cnt() -{ - return cnt(true); -} - -u_int32_t -txn_map::deq_cnt() -{ - return cnt(true); -} - -u_int32_t -txn_map::cnt(const bool enq_flag) -{ - slock s(_mutex); - u_int32_t c = 0; - for (xmap_itr i = _map.begin(); i != _map.end(); i++) - { - for (tdl_itr j = i->second.begin(); j < i->second.end(); j++) - { - if (j->_enq_flag == enq_flag) - c++; - } - } - return c; -} - -int16_t -txn_map::is_txn_synced(const std::string& xid) -{ - slock s(_mutex); - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // not found in map - return TMAP_XID_NOT_FOUND; - bool is_synced = true; - for (tdl_itr litr = itr->second.begin(); litr < itr->second.end(); litr++) - { - if (!litr->_aio_compl) - { - is_synced = false; - break; - } - } - return is_synced ? TMAP_SYNCED : TMAP_NOT_SYNCED; -} - -int16_t -txn_map::set_aio_compl(const std::string& xid, const u_int64_t rid) -{ - slock s(_mutex); - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // xid not found in map - return TMAP_XID_NOT_FOUND; - for (tdl_itr litr = itr->second.begin(); litr < itr->second.end(); litr++) - { - if (litr->_rid == rid) - { - litr->_aio_compl = true; - return TMAP_OK; // rid found - } - } - // xid present, but rid not found - return TMAP_RID_NOT_FOUND; -} - -bool -txn_map::data_exists(const std::string& xid, const u_int64_t rid) -{ - bool found = false; - { - slock s(_mutex); - txn_data_list tdl = get_tdata_list_nolock(xid); - tdl_itr itr = tdl.begin(); - while (itr != tdl.end() && !found) - { - found = itr->_rid == rid; - itr++; - } - } - return found; -} - -bool -txn_map::is_enq(const u_int64_t rid) -{ - bool found = false; - { - slock s(_mutex); - for (xmap_itr i = _map.begin(); i != _map.end() && !found; i++) - { - txn_data_list list = i->second; - for (tdl_itr j = list.begin(); j < list.end() && !found; j++) - { - if (j->_enq_flag) - found = j->_rid == rid; - else - found = j->_drid == rid; - } - } - } - return found; -} - -void -txn_map::xid_list(std::vector& xv) -{ - xv.clear(); - { - slock s(_mutex); - for (xmap_itr itr = _map.begin(); itr != _map.end(); itr++) - xv.push_back(itr->first); - } -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/txn_map.h b/qpid/cpp/src/qpid/legacystore/jrnl/txn_map.h deleted file mode 100644 index 6b38564e53..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/txn_map.h +++ /dev/null @@ -1,159 +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. - * - */ - -/** - * \file txn_map.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::txn_map (transaction map). - * See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_TXN_MAP_H -#define QPID_LEGACYSTORE_JRNL_TXN_MAP_H - -namespace mrg -{ -namespace journal -{ - class txn_map; -} -} - -#include "qpid/legacystore/jrnl/smutex.h" -#include -#include -#include -#include -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \struct txn_data_struct - * \brief Struct encapsulating transaction data necessary for processing a transaction - * in the journal once it is closed with either a commit or abort. - */ - struct txn_data_struct - { - u_int64_t _rid; ///< Record id for this operation - u_int64_t _drid; ///< Dequeue record id for this operation - u_int16_t _pfid; ///< Physical file id, to be used when transferring to emap on commit - bool _enq_flag; ///< If true, enq op, otherwise deq op - bool _commit_flag; ///< (2PC transactions) Records 2PC complete c/a mode - bool _aio_compl; ///< Initially false, set to true when record AIO returns - txn_data_struct(const u_int64_t rid, const u_int64_t drid, const u_int16_t pfid, - const bool enq_flag, const bool commit_flag = false); - }; - typedef txn_data_struct txn_data; - typedef std::vector txn_data_list; - typedef txn_data_list::iterator tdl_itr; - - /** - * \class txn_map - * \brief Class for storing transaction data for each open (ie not committed or aborted) - * xid in the store. If aborted, records are discarded; if committed, they are - * transferred to the enqueue map. - * - * The data is encapsulated by struct txn_data_struct. A vector containing the information - * for each operation included as part of the same transaction is mapped against the - * xid. - * - * The aio_compl flag is set true as each AIO write operation for the enqueue or dequeue - * returns. Checking that all of these flags are true for a given xid is the mechanism - * used to determine if the transaction is syncronized (through method is_txn_synced()). - * - * On transaction commit, then each operation is handled as follows: - * - * If an enqueue (_enq_flag is true), then the rid and pfid are transferred to the enq_map. - * If a dequeue (_enq_flag is false), then the rid stored in the drid field is used to - * remove the corresponding record from the enq_map. - * - * On transaction abort, then each operation is handled as follows: - * - * If an enqueue (_enq_flag is true), then the data is simply discarded. - * If a dequeue (_enq_flag is false), then the lock for the corresponding enqueue in enq_map - * (if not a part of the same transaction) is removed, and the data discarded. - * - *
-    *   key      data
-    *
-    *   xid1 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   xid2 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   xid3 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   ...
-    * 
- */ - class txn_map - { - public: - // return/error codes - static int16_t TMAP_RID_NOT_FOUND; - static int16_t TMAP_XID_NOT_FOUND; - static int16_t TMAP_OK; - static int16_t TMAP_NOT_SYNCED; - static int16_t TMAP_SYNCED; - - private: - typedef std::pair xmap_param; - typedef std::map xmap; - typedef xmap::iterator xmap_itr; - - xmap _map; - smutex _mutex; - std::vector _pfid_txn_cnt; - const txn_data_list _empty_data_list; - - public: - txn_map(); - virtual ~txn_map(); - - void set_num_jfiles(const u_int16_t num_jfiles); - u_int32_t get_txn_pfid_cnt(const u_int16_t pfid) const; - bool insert_txn_data(const std::string& xid, const txn_data& td); - const txn_data_list get_tdata_list(const std::string& xid); - const txn_data_list get_remove_tdata_list(const std::string& xid); - bool in_map(const std::string& xid); - u_int32_t enq_cnt(); - u_int32_t deq_cnt(); - int16_t is_txn_synced(const std::string& xid); // -1=xid not found; 0=not synced; 1=synced - int16_t set_aio_compl(const std::string& xid, const u_int64_t rid); // -2=rid not found; -1=xid not found; 0=done - bool data_exists(const std::string& xid, const u_int64_t rid); - bool is_enq(const u_int64_t rid); - inline void clear() { _map.clear(); } - inline bool empty() const { return _map.empty(); } - inline size_t size() const { return _map.size(); } - void xid_list(std::vector& xv); - private: - u_int32_t cnt(const bool enq_flag); - const txn_data_list get_tdata_list_nolock(const std::string& xid); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_TXN_MAP_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.cpp deleted file mode 100644 index 1008e7700e..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.cpp +++ /dev/null @@ -1,448 +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. - * - */ - -/** - * \file txn_rec.cpp - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::txn_rec (journal dequeue - * record) class. See comments in file txn_rec.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/txn_rec.h" - -#include -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include - -namespace mrg -{ -namespace journal -{ - -txn_rec::txn_rec(): - _txn_hdr(), - _xidp(0), - _buff(0), - _txn_tail() -{ - _txn_hdr._version = RHM_JDAT_VERSION; -} - -txn_rec::txn_rec(const u_int32_t magic, const u_int64_t rid, const void* const xidp, - const std::size_t xidlen, const bool owi): - _txn_hdr(magic, RHM_JDAT_VERSION, rid, xidlen, owi), - _xidp(xidp), - _buff(0), - _txn_tail(_txn_hdr) -{} - -txn_rec::~txn_rec() -{ - clean(); -} - -void -txn_rec::reset(const u_int32_t magic) -{ - _txn_hdr._magic = magic; - _txn_hdr._rid = 0; - _txn_hdr._xidsize = 0; - _xidp = 0; - _buff = 0; - _txn_tail._xmagic = ~magic; - _txn_tail._rid = 0; -} - -void -txn_rec::reset(const u_int32_t magic, const u_int64_t rid, const void* const xidp, - const std::size_t xidlen, const bool owi) -{ - _txn_hdr._magic = magic; - _txn_hdr._rid = rid; - _txn_hdr.set_owi(owi); - _txn_hdr._xidsize = xidlen; - _xidp = xidp; - _buff = 0; - _txn_tail._xmagic = ~magic; - _txn_tail._rid = rid; -} - -u_int32_t -txn_rec::encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks) -{ - assert(wptr != 0); - assert(max_size_dblks > 0); - assert(_xidp != 0 && _txn_hdr._xidsize > 0); - - std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - std::size_t rem = max_size_dblks * JRNL_DBLK_SIZE; - std::size_t wr_cnt = 0; - if (rec_offs_dblks) // Continuation of split dequeue record (over 2 or more pages) - { - if (size_dblks(rec_size()) - rec_offs_dblks > max_size_dblks) // Further split required - { - rec_offs -= sizeof(_txn_hdr); - std::size_t wsize = _txn_hdr._xidsize > rec_offs ? _txn_hdr._xidsize - rec_offs : 0; - std::size_t wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= _txn_hdr._xidsize - wsize2; - if (rem) - { - wsize = sizeof(_txn_tail) > rec_offs ? sizeof(_txn_tail) - rec_offs : 0; - wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy((char*)wptr + wr_cnt, (char*)&_txn_tail + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= sizeof(_txn_tail) - wsize2; - } - assert(rem == 0); - assert(rec_offs == 0); - } - else // No further split required - { - rec_offs -= sizeof(_txn_hdr); - std::size_t wsize = _txn_hdr._xidsize > rec_offs ? _txn_hdr._xidsize - rec_offs : 0; - if (wsize) - { - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - } - rec_offs -= _txn_hdr._xidsize - wsize; - wsize = sizeof(_txn_tail) > rec_offs ? sizeof(_txn_tail) - rec_offs : 0; - if (wsize) - { - std::memcpy((char*)wptr + wr_cnt, (char*)&_txn_tail + rec_offs, wsize); - wr_cnt += wsize; -#ifdef RHM_CLEAN - std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - std::size_t dblk_rec_size = size_dblks(rec_size() - rec_offs) * JRNL_DBLK_SIZE; - std::memset((char*)wptr + wr_cnt, RHM_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - rec_offs -= sizeof(_txn_tail) - wsize; - assert(rec_offs == 0); - } - } - else // Start at beginning of data record - { - // Assumption: the header will always fit into the first dblk - std::memcpy(wptr, (void*)&_txn_hdr, sizeof(_txn_hdr)); - wr_cnt = sizeof(_txn_hdr); - if (size_dblks(rec_size()) > max_size_dblks) // Split required - { - std::size_t wsize; - rem -= sizeof(_txn_hdr); - if (rem) - { - wsize = rem >= _txn_hdr._xidsize ? _txn_hdr._xidsize : rem; - std::memcpy((char*)wptr + wr_cnt, _xidp, wsize); - wr_cnt += wsize; - rem -= wsize; - } - if (rem) - { - wsize = rem >= sizeof(_txn_tail) ? sizeof(_txn_tail) : rem; - std::memcpy((char*)wptr + wr_cnt, (void*)&_txn_tail, wsize); - wr_cnt += wsize; - rem -= wsize; - } - assert(rem == 0); - } - else // No split required - { - std::memcpy((char*)wptr + wr_cnt, _xidp, _txn_hdr._xidsize); - wr_cnt += _txn_hdr._xidsize; - std::memcpy((char*)wptr + wr_cnt, (void*)&_txn_tail, sizeof(_txn_tail)); - wr_cnt += sizeof(_txn_tail); -#ifdef RHM_CLEAN - std::size_t dblk_rec_size = size_dblks(rec_size()) * JRNL_DBLK_SIZE; - std::memset((char*)wptr + wr_cnt, RHM_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - } - return size_dblks(wr_cnt); -} - -u_int32_t -txn_rec::decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks) -{ - assert(rptr != 0); - assert(max_size_dblks > 0); - - std::size_t rd_cnt = 0; - if (rec_offs_dblks) // Continuation of record on new page - { - const u_int32_t hdr_xid_dblks = size_dblks(txn_hdr::size() + _txn_hdr._xidsize); - const u_int32_t hdr_xid_tail_dblks = size_dblks(txn_hdr::size() + _txn_hdr._xidsize + - rec_tail::size()); - const std::size_t rec_offs = rec_offs_dblks * JRNL_DBLK_SIZE; - - if (hdr_xid_tail_dblks - rec_offs_dblks <= max_size_dblks) - { - // Remainder of xid fits within this page - if (rec_offs - txn_hdr::size() < _txn_hdr._xidsize) - { - // Part of xid still outstanding, copy remainder of xid and tail - const std::size_t xid_offs = rec_offs - txn_hdr::size(); - const std::size_t xid_rem = _txn_hdr._xidsize - xid_offs; - std::memcpy((char*)_buff + xid_offs, rptr, xid_rem); - rd_cnt = xid_rem; - std::memcpy((void*)&_txn_tail, ((char*)rptr + rd_cnt), sizeof(_txn_tail)); - chk_tail(); - rd_cnt += sizeof(_txn_tail); - } - else - { - // Tail or part of tail only outstanding, complete tail - const std::size_t tail_offs = rec_offs - txn_hdr::size() - _txn_hdr._xidsize; - const std::size_t tail_rem = rec_tail::size() - tail_offs; - std::memcpy((char*)&_txn_tail + tail_offs, rptr, tail_rem); - chk_tail(); - rd_cnt = tail_rem; - } - } - else if (hdr_xid_dblks - rec_offs_dblks <= max_size_dblks) - { - // Remainder of xid fits within this page, tail split - const std::size_t xid_offs = rec_offs - txn_hdr::size(); - const std::size_t xid_rem = _txn_hdr._xidsize - xid_offs; - std::memcpy((char*)_buff + xid_offs, rptr, xid_rem); - rd_cnt += xid_rem; - const std::size_t tail_rem = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - if (tail_rem) - { - std::memcpy((void*)&_txn_tail, ((char*)rptr + xid_rem), tail_rem); - rd_cnt += tail_rem; - } - } - else - { - // Remainder of xid split - const std::size_t xid_cp_size = (max_size_dblks * JRNL_DBLK_SIZE); - std::memcpy((char*)_buff + rec_offs - txn_hdr::size(), rptr, xid_cp_size); - rd_cnt += xid_cp_size; - } - } - else // Start of record - { - // Get and check header - _txn_hdr.hdr_copy(h); - rd_cnt = sizeof(rec_hdr); -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - rd_cnt += sizeof(u_int32_t); // Filler 0 -#endif - //_txn_hdr._xidsize = *(std::size_t*)((char*)rptr + rd_cnt); - std::memcpy((void*)&_txn_hdr._xidsize, (char*)rptr + rd_cnt, sizeof(std::size_t)); - rd_cnt = _txn_hdr.size(); - chk_hdr(); - _buff = std::malloc(_txn_hdr._xidsize); - MALLOC_CHK(_buff, "_buff", "txn_rec", "decode"); - const u_int32_t hdr_xid_dblks = size_dblks(txn_hdr::size() + _txn_hdr._xidsize); - const u_int32_t hdr_xid_tail_dblks = size_dblks(txn_hdr::size() + _txn_hdr._xidsize + - rec_tail::size()); - - // Check if record (header + xid + tail) fits within this page, we can check the - // tail before the expense of copying data to memory - if (hdr_xid_tail_dblks <= max_size_dblks) - { - // Entire header, xid and tail fits within this page - std::memcpy(_buff, (char*)rptr + rd_cnt, _txn_hdr._xidsize); - rd_cnt += _txn_hdr._xidsize; - std::memcpy((void*)&_txn_tail, (char*)rptr + rd_cnt, sizeof(_txn_tail)); - rd_cnt += sizeof(_txn_tail); - chk_tail(); - } - else if (hdr_xid_dblks <= max_size_dblks) - { - // Entire header and xid fit within this page, tail split - std::memcpy(_buff, (char*)rptr + rd_cnt, _txn_hdr._xidsize); - rd_cnt += _txn_hdr._xidsize; - const std::size_t tail_rem = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - if (tail_rem) - { - std::memcpy((void*)&_txn_tail, (char*)rptr + rd_cnt, tail_rem); - rd_cnt += tail_rem; - } - } - else - { - // Header fits within this page, xid split - const std::size_t xid_cp_size = (max_size_dblks * JRNL_DBLK_SIZE) - rd_cnt; - std::memcpy(_buff, (char*)rptr + rd_cnt, xid_cp_size); - rd_cnt += xid_cp_size; - } - } - return size_dblks(rd_cnt); -} - -bool -txn_rec::rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs) -{ - if (rec_offs == 0) - { - // Read header, allocate for xid - _txn_hdr.hdr_copy(h); -#if defined(JRNL_BIG_ENDIAN) && defined(JRNL_32_BIT) - ifsp->ignore(sizeof(u_int32_t)); // _filler0 -#endif - ifsp->read((char*)&_txn_hdr._xidsize, sizeof(std::size_t)); -#if defined(JRNL_LITTLE_ENDIAN) && defined(JRNL_32_BIT) - ifsp->ignore(sizeof(u_int32_t)); // _filler0 -#endif - rec_offs = sizeof(_txn_hdr); - _buff = std::malloc(_txn_hdr._xidsize); - MALLOC_CHK(_buff, "_buff", "txn_rec", "rcv_decode"); - } - if (rec_offs < sizeof(_txn_hdr) + _txn_hdr._xidsize) - { - // Read xid (or continue reading xid) - std::size_t offs = rec_offs - sizeof(_txn_hdr); - ifsp->read((char*)_buff + offs, _txn_hdr._xidsize - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < _txn_hdr._xidsize - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - if (rec_offs < sizeof(_txn_hdr) + _txn_hdr._xidsize + sizeof(rec_tail)) - { - // Read tail (or continue reading tail) - std::size_t offs = rec_offs - sizeof(_txn_hdr) - _txn_hdr._xidsize; - ifsp->read((char*)&_txn_tail + offs, sizeof(rec_tail) - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < sizeof(rec_tail) - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - ifsp->ignore(rec_size_dblks() * JRNL_DBLK_SIZE - rec_size()); - chk_tail(); // Throws if tail invalid or record incomplete - assert(!ifsp->fail() && !ifsp->bad()); - return true; -} - -std::size_t -txn_rec::get_xid(void** const xidpp) -{ - if (!_buff) - { - *xidpp = 0; - return 0; - } - *xidpp = _buff; - return _txn_hdr._xidsize; -} - -std::string& -txn_rec::str(std::string& str) const -{ - std::ostringstream oss; - if (_txn_hdr._magic == RHM_JDAT_TXA_MAGIC) - oss << "dtxa_rec: m=" << _txn_hdr._magic; - else - oss << "dtxc_rec: m=" << _txn_hdr._magic; - oss << " v=" << (int)_txn_hdr._version; - oss << " rid=" << _txn_hdr._rid; - oss << " xid=\"" << _xidp << "\""; - str.append(oss.str()); - return str; -} - -std::size_t -txn_rec::xid_size() const -{ - return _txn_hdr._xidsize; -} - -std::size_t -txn_rec::rec_size() const -{ - return txn_hdr::size() + _txn_hdr._xidsize + rec_tail::size(); -} - -void -txn_rec::chk_hdr() const -{ - jrec::chk_hdr(_txn_hdr); - if (_txn_hdr._magic != RHM_JDAT_TXA_MAGIC && _txn_hdr._magic != RHM_JDAT_TXC_MAGIC) - { - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "dtx magic: rid=0x" << std::setw(16) << _txn_hdr._rid; - oss << ": expected=(0x" << std::setw(8) << RHM_JDAT_TXA_MAGIC; - oss << " or 0x" << RHM_JDAT_TXC_MAGIC; - oss << ") read=0x" << std::setw(2) << (int)_txn_hdr._magic; - throw jexception(jerrno::JERR_JREC_BADRECHDR, oss.str(), "txn_rec", "chk_hdr"); - } -} - -void -txn_rec::chk_hdr(u_int64_t rid) const -{ - chk_hdr(); - jrec::chk_rid(_txn_hdr, rid); -} - -void -txn_rec::chk_tail() const -{ - jrec::chk_tail(_txn_tail, _txn_hdr); -} - -void -txn_rec::clean() -{ - // clean up allocated memory here -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.h b/qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.h deleted file mode 100644 index 1a49df1c96..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/txn_rec.h +++ /dev/null @@ -1,101 +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. - * - */ - -/** - * \file txn_rec.h - * - * Qpid asynchronous store plugin library - * - * This file contains the code for the mrg::journal::txn_rec (journal data - * record) class. See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_TXN_REC_H -#define QPID_LEGACYSTORE_JRNL_TXN_REC_H - -namespace mrg -{ -namespace journal -{ -class txn_rec; -} -} - -#include -#include "qpid/legacystore/jrnl/jrec.h" -#include "qpid/legacystore/jrnl/txn_hdr.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \class txn_rec - * \brief Class to handle a single journal DTX commit or abort record. - */ - class txn_rec : public jrec - { - private: - txn_hdr _txn_hdr; ///< transaction header - const void* _xidp; ///< xid pointer for encoding (writing to disk) - void* _buff; ///< Pointer to buffer to receive data read from disk - rec_tail _txn_tail; ///< Record tail - - public: - // constructor used for read operations and xid must have memory allocated - txn_rec(); - // constructor used for write operations, where xid already exists - txn_rec(const u_int32_t magic, const u_int64_t rid, const void* const xidp, - const std::size_t xidlen, const bool owi); - virtual ~txn_rec(); - - // Prepare instance for use in reading data from journal - void reset(const u_int32_t magic); - // Prepare instance for use in writing data to journal - void reset(const u_int32_t magic, const u_int64_t rid, const void* const xidp, - const std::size_t xidlen, const bool owi); - u_int32_t encode(void* wptr, u_int32_t rec_offs_dblks, u_int32_t max_size_dblks); - u_int32_t decode(rec_hdr& h, void* rptr, u_int32_t rec_offs_dblks, - u_int32_t max_size_dblks); - // Decode used for recover - bool rcv_decode(rec_hdr h, std::ifstream* ifsp, std::size_t& rec_offs); - - std::size_t get_xid(void** const xidpp); - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return 0; } // This record never carries data - std::size_t xid_size() const; - std::size_t rec_size() const; - inline u_int64_t rid() const { return _txn_hdr._rid; } - - private: - void chk_hdr() const; - void chk_hdr(u_int64_t rid) const; - void chk_tail() const; - virtual void clean(); - }; // class txn_rec - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_TXN_REC_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/wmgr.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/wmgr.cpp deleted file mode 100644 index 4353fcfbca..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/wmgr.cpp +++ /dev/null @@ -1,1051 +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. - * - */ - -/** - * \file wmgr.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::wmgr (write manager). See - * comments in file wmgr.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/wmgr.h" - -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/file_hdr.h" -#include "qpid/legacystore/jrnl/jcntl.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include - -namespace mrg -{ -namespace journal -{ - -wmgr::wmgr(jcntl* jc, enq_map& emap, txn_map& tmap, wrfc& wrfc): - pmgr(jc, emap, tmap), - _wrfc(wrfc), - _max_dtokpp(0), - _max_io_wait_us(0), - _fhdr_base_ptr(0), - _fhdr_ptr_arr(0), - _fhdr_aio_cb_arr(0), - _cached_offset_dblks(0), - _jfsize_dblks(0), - _jfsize_pgs(0), - _num_jfiles(0), - _enq_busy(false), - _deq_busy(false), - _abort_busy(false), - _commit_busy(false), - _txn_pending_set() -{} - -wmgr::wmgr(jcntl* jc, enq_map& emap, txn_map& tmap, wrfc& wrfc, - const u_int32_t max_dtokpp, const u_int32_t max_iowait_us): - pmgr(jc, emap, tmap /* , dtoklp */), - _wrfc(wrfc), - _max_dtokpp(max_dtokpp), - _max_io_wait_us(max_iowait_us), - _fhdr_base_ptr(0), - _fhdr_ptr_arr(0), - _fhdr_aio_cb_arr(0), - _cached_offset_dblks(0), - _jfsize_dblks(0), - _jfsize_pgs(0), - _num_jfiles(0), - _enq_busy(false), - _deq_busy(false), - _abort_busy(false), - _commit_busy(false), - _txn_pending_set() -{} - -wmgr::~wmgr() -{ - wmgr::clean(); -} - -void -wmgr::initialize(aio_callback* const cbp, const u_int32_t wcache_pgsize_sblks, - const u_int16_t wcache_num_pages, const u_int32_t max_dtokpp, const u_int32_t max_iowait_us, - std::size_t eo) -{ - _enq_busy = false; - _deq_busy = false; - _abort_busy = false; - _commit_busy = false; - _max_dtokpp = max_dtokpp; - _max_io_wait_us = max_iowait_us; - - initialize(cbp, wcache_pgsize_sblks, wcache_num_pages); - - _jfsize_dblks = _jc->jfsize_sblks() * JRNL_SBLK_SIZE; - _jfsize_pgs = _jc->jfsize_sblks() / _cache_pgsize_sblks; - assert(_jc->jfsize_sblks() % JRNL_RMGR_PAGE_SIZE == 0); - - if (eo) - { - const u_int32_t wr_pg_size_dblks = _cache_pgsize_sblks * JRNL_SBLK_SIZE; - u_int32_t data_dblks = (eo / JRNL_DBLK_SIZE) - 4; // 4 dblks for file hdr - _pg_cntr = data_dblks / wr_pg_size_dblks; - _pg_offset_dblks = data_dblks - (_pg_cntr * wr_pg_size_dblks); - } -} - -iores -wmgr::enqueue(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const void* const xid_ptr, - const std::size_t xid_len, const bool transient, const bool external) -{ - if (xid_len) - assert(xid_ptr != 0); - - if (_deq_busy || _abort_busy || _commit_busy) - return RHM_IORES_BUSY; - - if (this_data_len != tot_data_len && !external) - return RHM_IORES_NOTIMPL; - - iores res = pre_write_check(WMGR_ENQUEUE, dtokp, xid_len, tot_data_len, external); - if (res != RHM_IORES_SUCCESS) - return res; - - bool cont = false; - if (_enq_busy) // If enqueue() exited last time with RHM_IORES_FULL or RHM_IORES_PAGE_AIOWAIT - { - if (dtokp->wstate() == data_tok::ENQ_PART) - cont = true; - else - { - std::ostringstream oss; - oss << "This data_tok: id=" << dtokp->id() << " state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_ENQDISCONT, oss.str(), "wmgr", "enqueue"); - } - } - - u_int64_t rid = (dtokp->external_rid() | cont) ? dtokp->rid() : _wrfc.get_incr_rid(); - _enq_rec.reset(rid, data_buff, tot_data_len, xid_ptr, xid_len, _wrfc.owi(), transient, - external); - if (!cont) - { - dtokp->set_rid(rid); - dtokp->set_dequeue_rid(0); - if (xid_len) - dtokp->set_xid(xid_ptr, xid_len); - else - dtokp->clear_xid(); - _enq_busy = true; - } - bool done = false; - while (!done) - { - assert(_pg_offset_dblks < _cache_pgsize_sblks * JRNL_SBLK_SIZE); - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * JRNL_DBLK_SIZE); - u_int32_t data_offs_dblks = dtokp->dblocks_written(); - u_int32_t ret = _enq_rec.encode(wptr, data_offs_dblks, - (_cache_pgsize_sblks * JRNL_SBLK_SIZE) - _pg_offset_dblks); - - // Remember fid which contains the record header in case record is split over several files - if (data_offs_dblks == 0) - dtokp->set_fid(_wrfc.index()); - _pg_offset_dblks += ret; - _cached_offset_dblks += ret; - dtokp->incr_dblocks_written(ret); - dtokp->incr_pg_cnt(); - _page_cb_arr[_pg_index]._pdtokl->push_back(dtokp); - - // Is the encoding of this record complete? - if (dtokp->dblocks_written() >= _enq_rec.rec_size_dblks()) - { - // TODO: Incorrect - must set state to ENQ_CACHED; ENQ_SUBM is set when AIO returns. - dtokp->set_wstate(data_tok::ENQ_SUBM); - dtokp->set_dsize(tot_data_len); - // Only add this data token to page token list when submit is complete, this way - // long multi-page messages have their token on the page containing the END of the - // message. AIO callbacks will then only process this token when entire message is - // enqueued. - _wrfc.incr_enqcnt(dtokp->fid()); - - if (xid_len) // If part of transaction, add to transaction map - { - std::string xid((const char*)xid_ptr, xid_len); - _tmap.insert_txn_data(xid, txn_data(rid, 0, dtokp->fid(), true)); - } - else - { - if (_emap.insert_pfid(rid, dtokp->fid()) < enq_map::EMAP_OK) // fail - { - // The only error code emap::insert_pfid() returns is enq_map::EMAP_DUP_RID. - std::ostringstream oss; - oss << std::hex << "rid=0x" << rid << " _pfid=0x" << dtokp->fid(); - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "wmgr", "enqueue"); - } - } - - done = true; - } - else - dtokp->set_wstate(data_tok::ENQ_PART); - - file_header_check(rid, cont, _enq_rec.rec_size_dblks() - data_offs_dblks); - flush_check(res, cont, done); - } - if (dtokp->wstate() >= data_tok::ENQ_SUBM) - _enq_busy = false; - return res; -} - -iores -wmgr::dequeue(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len, const bool txn_coml_commit) -{ - if (xid_len) - assert(xid_ptr != 0); - - if (_enq_busy || _abort_busy || _commit_busy) - return RHM_IORES_BUSY; - - iores res = pre_write_check(WMGR_DEQUEUE, dtokp); - if (res != RHM_IORES_SUCCESS) - return res; - - bool cont = false; - if (_deq_busy) // If dequeue() exited last time with RHM_IORES_FULL or RHM_IORES_PAGE_AIOWAIT - { - if (dtokp->wstate() == data_tok::DEQ_PART) - cont = true; - else - { - std::ostringstream oss; - oss << "This data_tok: id=" << dtokp->id() << " state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_DEQDISCONT, oss.str(), "wmgr", "dequeue"); - } - } - - const bool ext_rid = dtokp->external_rid(); - u_int64_t rid = (ext_rid | cont) ? dtokp->rid() : _wrfc.get_incr_rid(); - u_int64_t dequeue_rid = (ext_rid | cont) ? dtokp->dequeue_rid() : dtokp->rid(); - _deq_rec.reset(rid, dequeue_rid, xid_ptr, xid_len, _wrfc.owi(), txn_coml_commit); - if (!cont) - { - if (!ext_rid) - { - dtokp->set_rid(rid); - dtokp->set_dequeue_rid(dequeue_rid); - } - if (xid_len) - dtokp->set_xid(xid_ptr, xid_len); - else - dtokp->clear_xid(); - dequeue_check(dtokp->xid(), dequeue_rid); - dtokp->set_dblocks_written(0); // Reset dblks_written from previous op - _deq_busy = true; - } - bool done = false; - while (!done) - { - assert(_pg_offset_dblks < _cache_pgsize_sblks * JRNL_SBLK_SIZE); - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * JRNL_DBLK_SIZE); - u_int32_t data_offs_dblks = dtokp->dblocks_written(); - u_int32_t ret = _deq_rec.encode(wptr, data_offs_dblks, - (_cache_pgsize_sblks * JRNL_SBLK_SIZE) - _pg_offset_dblks); - - // Remember fid which contains the record header in case record is split over several files - if (data_offs_dblks == 0) - dtokp->set_fid(_wrfc.index()); - _pg_offset_dblks += ret; - _cached_offset_dblks += ret; - dtokp->incr_dblocks_written(ret); - dtokp->incr_pg_cnt(); - _page_cb_arr[_pg_index]._pdtokl->push_back(dtokp); - - // Is the encoding of this record complete? - if (dtokp->dblocks_written() >= _deq_rec.rec_size_dblks()) - { - // TODO: Incorrect - must set state to ENQ_CACHED; ENQ_SUBM is set when AIO returns. - dtokp->set_wstate(data_tok::DEQ_SUBM); - - if (xid_len) // If part of transaction, add to transaction map - { - // If the enqueue is part of a pending txn, it will not yet be in emap - _emap.lock(dequeue_rid); // ignore rid not found error - std::string xid((const char*)xid_ptr, xid_len); - _tmap.insert_txn_data(xid, txn_data(rid, dequeue_rid, dtokp->fid(), false)); - } - else - { - int16_t fid = _emap.get_remove_pfid(dtokp->dequeue_rid()); - if (fid < enq_map::EMAP_OK) // fail - { - if (fid == enq_map::EMAP_RID_NOT_FOUND) - { - std::ostringstream oss; - oss << std::hex << "rid=0x" << rid; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "dequeue"); - } - if (fid == enq_map::EMAP_LOCKED) - { - std::ostringstream oss; - oss << std::hex << "rid=0x" << rid; - throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "dequeue"); - } - } - _wrfc.decr_enqcnt(fid); - } - - done = true; - } - else - dtokp->set_wstate(data_tok::DEQ_PART); - - file_header_check(rid, cont, _deq_rec.rec_size_dblks() - data_offs_dblks); - flush_check(res, cont, done); - } - if (dtokp->wstate() >= data_tok::DEQ_SUBM) - _deq_busy = false; - return res; -} - -iores -wmgr::abort(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len) -{ - // commit and abort MUST have a valid xid - assert(xid_ptr != 0 && xid_len > 0); - - if (_enq_busy || _deq_busy || _commit_busy) - return RHM_IORES_BUSY; - - iores res = pre_write_check(WMGR_ABORT, dtokp); - if (res != RHM_IORES_SUCCESS) - return res; - - bool cont = false; - if (_abort_busy) // If abort() exited last time with RHM_IORES_FULL or RHM_IORES_PAGE_AIOWAIT - { - if (dtokp->wstate() == data_tok::ABORT_PART) - cont = true; - else - { - std::ostringstream oss; - oss << "This data_tok: id=" << dtokp->id() << " state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_DEQDISCONT, oss.str(), "wmgr", "abort"); - } - } - - u_int64_t rid = (dtokp->external_rid() | cont) ? dtokp->rid() : _wrfc.get_incr_rid(); - _txn_rec.reset(RHM_JDAT_TXA_MAGIC, rid, xid_ptr, xid_len, _wrfc.owi()); - if (!cont) - { - dtokp->set_rid(rid); - dtokp->set_dequeue_rid(0); - dtokp->set_xid(xid_ptr, xid_len); - dtokp->set_dblocks_written(0); // Reset dblks_written from previous op - _abort_busy = true; - } - bool done = false; - while (!done) - { - assert(_pg_offset_dblks < _cache_pgsize_sblks * JRNL_SBLK_SIZE); - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * JRNL_DBLK_SIZE); - u_int32_t data_offs_dblks = dtokp->dblocks_written(); - u_int32_t ret = _txn_rec.encode(wptr, data_offs_dblks, - (_cache_pgsize_sblks * JRNL_SBLK_SIZE) - _pg_offset_dblks); - - // Remember fid which contains the record header in case record is split over several files - if (data_offs_dblks == 0) - dtokp->set_fid(_wrfc.index()); - _pg_offset_dblks += ret; - _cached_offset_dblks += ret; - dtokp->incr_dblocks_written(ret); - dtokp->incr_pg_cnt(); - _page_cb_arr[_pg_index]._pdtokl->push_back(dtokp); - - // Is the encoding of this record complete? - if (dtokp->dblocks_written() >= _txn_rec.rec_size_dblks()) - { - dtokp->set_wstate(data_tok::ABORT_SUBM); - - // Delete this txn from tmap, unlock any locked records in emap - std::string xid((const char*)xid_ptr, xid_len); - txn_data_list tdl = _tmap.get_remove_tdata_list(xid); // tdl will be empty if xid not found - for (tdl_itr itr = tdl.begin(); itr != tdl.end(); itr++) - { - if (!itr->_enq_flag) - _emap.unlock(itr->_drid); // ignore rid not found error - if (itr->_enq_flag) - _wrfc.decr_enqcnt(itr->_pfid); - } - std::pair::iterator, bool> res = _txn_pending_set.insert(xid); - if (!res.second) - { - std::ostringstream oss; - oss << std::hex << "_txn_pending_set: xid=\"" << xid << "\""; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "wmgr", "abort"); - } - - done = true; - } - else - dtokp->set_wstate(data_tok::ABORT_PART); - - file_header_check(rid, cont, _txn_rec.rec_size_dblks() - data_offs_dblks); - flush_check(res, cont, done); - } - if (dtokp->wstate() >= data_tok::ABORT_SUBM) - _abort_busy = false; - return res; -} - -iores -wmgr::commit(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len) -{ - // commit and abort MUST have a valid xid - assert(xid_ptr != 0 && xid_len > 0); - - if (_enq_busy || _deq_busy || _abort_busy) - return RHM_IORES_BUSY; - - iores res = pre_write_check(WMGR_COMMIT, dtokp); - if (res != RHM_IORES_SUCCESS) - return res; - - bool cont = false; - if (_commit_busy) // If commit() exited last time with RHM_IORES_FULL or RHM_IORES_PAGE_AIOWAIT - { - if (dtokp->wstate() == data_tok::COMMIT_PART) - cont = true; - else - { - std::ostringstream oss; - oss << "This data_tok: id=" << dtokp->id() << " state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_DEQDISCONT, oss.str(), "wmgr", "commit"); - } - } - - u_int64_t rid = (dtokp->external_rid() | cont) ? dtokp->rid() : _wrfc.get_incr_rid(); - _txn_rec.reset(RHM_JDAT_TXC_MAGIC, rid, xid_ptr, xid_len, _wrfc.owi()); - if (!cont) - { - dtokp->set_rid(rid); - dtokp->set_dequeue_rid(0); - dtokp->set_xid(xid_ptr, xid_len); - dtokp->set_dblocks_written(0); // Reset dblks_written from previous op - _commit_busy = true; - } - bool done = false; - while (!done) - { - assert(_pg_offset_dblks < _cache_pgsize_sblks * JRNL_SBLK_SIZE); - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * JRNL_DBLK_SIZE); - u_int32_t data_offs_dblks = dtokp->dblocks_written(); - u_int32_t ret = _txn_rec.encode(wptr, data_offs_dblks, - (_cache_pgsize_sblks * JRNL_SBLK_SIZE) - _pg_offset_dblks); - - // Remember fid which contains the record header in case record is split over several files - if (data_offs_dblks == 0) - dtokp->set_fid(_wrfc.index()); - _pg_offset_dblks += ret; - _cached_offset_dblks += ret; - dtokp->incr_dblocks_written(ret); - dtokp->incr_pg_cnt(); - _page_cb_arr[_pg_index]._pdtokl->push_back(dtokp); - - // Is the encoding of this record complete? - if (dtokp->dblocks_written() >= _txn_rec.rec_size_dblks()) - { - dtokp->set_wstate(data_tok::COMMIT_SUBM); - - // Delete this txn from tmap, process records into emap - std::string xid((const char*)xid_ptr, xid_len); - txn_data_list tdl = _tmap.get_remove_tdata_list(xid); // tdl will be empty if xid not found - for (tdl_itr itr = tdl.begin(); itr != tdl.end(); itr++) - { - if (itr->_enq_flag) // txn enqueue - { - if (_emap.insert_pfid(itr->_rid, itr->_pfid) < enq_map::EMAP_OK) // fail - { - // The only error code emap::insert_pfid() returns is enq_map::EMAP_DUP_RID. - std::ostringstream oss; - oss << std::hex << "rid=0x" << itr->_rid << " _pfid=0x" << itr->_pfid; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "wmgr", "commit"); - } - } - else // txn dequeue - { - int16_t fid = _emap.get_remove_pfid(itr->_drid, true); - if (fid < enq_map::EMAP_OK) // fail - { - if (fid == enq_map::EMAP_RID_NOT_FOUND) - { - std::ostringstream oss; - oss << std::hex << "rid=0x" << rid; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "dequeue"); - } - if (fid == enq_map::EMAP_LOCKED) - { - std::ostringstream oss; - oss << std::hex << "rid=0x" << rid; - throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "dequeue"); - } - } - _wrfc.decr_enqcnt(fid); - } - } - std::pair::iterator, bool> res = _txn_pending_set.insert(xid); - if (!res.second) - { - std::ostringstream oss; - oss << std::hex << "_txn_pending_set: xid=\"" << xid << "\""; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "wmgr", "commit"); - } - - done = true; - } - else - dtokp->set_wstate(data_tok::COMMIT_PART); - - file_header_check(rid, cont, _txn_rec.rec_size_dblks() - data_offs_dblks); - flush_check(res, cont, done); - } - if (dtokp->wstate() >= data_tok::COMMIT_SUBM) - _commit_busy = false; - return res; -} - -void -wmgr::file_header_check(const u_int64_t rid, const bool cont, const u_int32_t rec_dblks_rem) -{ - // Has the file header been written (i.e. write pointers still at 0)? - if (_wrfc.is_void()) - { - bool file_fit = rec_dblks_rem <= _jfsize_dblks; - bool file_full = rec_dblks_rem == _jfsize_dblks; - std::size_t fro = 0; - if (cont) - { - if (file_fit && !file_full) - fro = (rec_dblks_rem + JRNL_SBLK_SIZE) * JRNL_DBLK_SIZE; - } - else - fro = JRNL_SBLK_SIZE * JRNL_DBLK_SIZE; - write_fhdr(rid, _wrfc.index(), _wrfc.index(), fro); - } -} - -void -wmgr::flush_check(iores& res, bool& cont, bool& done) -{ - // Is page is full, flush - if (_pg_offset_dblks >= _cache_pgsize_sblks * JRNL_SBLK_SIZE) - { - res = write_flush(); - assert(res == RHM_IORES_SUCCESS); - - if (_page_cb_arr[_pg_index]._state == AIO_PENDING && !done) - { - res = RHM_IORES_PAGE_AIOWAIT; - done = true; - } - - // If file is full, rotate to next file - if (_pg_cntr >= _jfsize_pgs) - { - iores rfres = rotate_file(); - if (rfres != RHM_IORES_SUCCESS) - res = rfres; - if (!done) - { - if (rfres == RHM_IORES_SUCCESS) - cont = true; - else - done = true; - } - } - } -} - -iores -wmgr::flush() -{ - iores res = write_flush(); - if (_pg_cntr >= _jfsize_pgs) - { - iores rfres = rotate_file(); - if (rfres != RHM_IORES_SUCCESS) - res = rfres; - } - return res; -} - -iores -wmgr::write_flush() -{ - iores res = RHM_IORES_SUCCESS; - // Don't bother flushing an empty page or one that is still in state AIO_PENDING - if (_cached_offset_dblks) - { - if (_page_cb_arr[_pg_index]._state == AIO_PENDING) - res = RHM_IORES_PAGE_AIOWAIT; - else - { - if (_page_cb_arr[_pg_index]._state != IN_USE) - { - std::ostringstream oss; - oss << "pg_index=" << _pg_index << " state=" << _page_cb_arr[_pg_index].state_str(); - throw jexception(jerrno::JERR_WMGR_BADPGSTATE, oss.str(), "wmgr", - "write_flush"); - } - - // Send current page using AIO - - // In manual flushes, dblks may not coincide with sblks, add filler records ("RHMx") - // if necessary. - dblk_roundup(); - - std::size_t pg_offs = (_pg_offset_dblks - _cached_offset_dblks) * JRNL_DBLK_SIZE; - aio_cb* aiocbp = &_aio_cb_arr[_pg_index]; - aio::prep_pwrite_2(aiocbp, _wrfc.fh(), - (char*)_page_ptr_arr[_pg_index] + pg_offs, _cached_offset_dblks * JRNL_DBLK_SIZE, - _wrfc.subm_offs()); - page_cb* pcbp = (page_cb*)(aiocbp->data); // This page control block (pcb) - pcbp->_wdblks = _cached_offset_dblks; - pcbp->_wfh = _wrfc.file_controller(); - if (aio::submit(_ioctx, 1, &aiocbp) < 0) - throw jexception(jerrno::JERR__AIO, "wmgr", "write_flush"); - _wrfc.add_subm_cnt_dblks(_cached_offset_dblks); - _wrfc.incr_aio_cnt(); - _aio_evt_rem++; - _cached_offset_dblks = 0; - _jc->instr_incr_outstanding_aio_cnt(); - - rotate_page(); // increments _pg_index, resets _pg_offset_dblks if req'd - if (_page_cb_arr[_pg_index]._state == UNUSED) - _page_cb_arr[_pg_index]._state = IN_USE; - } - } - get_events(UNUSED, 0); - if (_page_cb_arr[_pg_index]._state == UNUSED) - _page_cb_arr[_pg_index]._state = IN_USE; - return res; -} - -iores -wmgr::rotate_file() -{ - _pg_cntr = 0; - iores res = _wrfc.rotate(); - _jc->chk_wr_frot(); - return res; -} - -int32_t -wmgr::get_events(page_state state, timespec* const timeout, bool flush) -{ - if (_aio_evt_rem == 0) // no events to get - return 0; - - int ret = 0; - if ((ret = aio::getevents(_ioctx, flush ? _aio_evt_rem : 1, _aio_evt_rem/*_cache_num_pages + _jc->num_jfiles()*/, _aio_event_arr, timeout)) < 0) - { - if (ret == -EINTR) // Interrupted by signal - return 0; - std::ostringstream oss; - oss << "io_getevents() failed: " << std::strerror(-ret) << " (" << ret << ")"; - throw jexception(jerrno::JERR__AIO, oss.str(), "wmgr", "get_events"); - } - - if (ret == 0 && timeout) - return jerrno::AIO_TIMEOUT; - - int32_t tot_data_toks = 0; - for (int i=0; idata); // This page control block (pcb) - long aioret = (long)_aio_event_arr[i].res; - if (aioret < 0) - { - std::ostringstream oss; - oss << "AIO write operation failed: " << std::strerror(-aioret) << " (" << aioret << ") ["; - if (pcbp) - oss << "pg=" << pcbp->_index; - else - { - file_hdr* fhp = (file_hdr*)aiocbp->u.c.buf; - oss << "fid=" << fhp->_pfid; - } - oss << " size=" << aiocbp->u.c.nbytes; - oss << " offset=" << aiocbp->u.c.offset << " fh=" << aiocbp->aio_fildes << "]"; - throw jexception(jerrno::JERR__AIO, oss.str(), "wmgr", "get_events"); - } - if (pcbp) // Page writes have pcb - { - u_int32_t s = pcbp->_pdtokl->size(); - std::vector dtokl; - dtokl.reserve(s); - for (u_int32_t k=0; k_pdtokl->at(k); - if (dtokp->decr_pg_cnt() == 0) - { - std::set::iterator it; - switch (dtokp->wstate()) - { - case data_tok::ENQ_SUBM: - dtokl.push_back(dtokp); - tot_data_toks++; - dtokp->set_wstate(data_tok::ENQ); - if (dtokp->has_xid()) - // Ignoring return value here. A non-zero return can signify that the transaction - // has committed or aborted, and which was completed prior to the aio returning. - _tmap.set_aio_compl(dtokp->xid(), dtokp->rid()); - break; - case data_tok::DEQ_SUBM: - dtokl.push_back(dtokp); - tot_data_toks++; - dtokp->set_wstate(data_tok::DEQ); - if (dtokp->has_xid()) - // Ignoring return value - see note above. - _tmap.set_aio_compl(dtokp->xid(), dtokp->rid()); - break; - case data_tok::ABORT_SUBM: - dtokl.push_back(dtokp); - tot_data_toks++; - dtokp->set_wstate(data_tok::ABORTED); - it = _txn_pending_set.find(dtokp->xid()); - if (it == _txn_pending_set.end()) - { - std::ostringstream oss; - oss << std::hex << "_txn_pending_set: abort xid=\""; - oss << dtokp->xid() << "\""; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", - "get_events"); - } - _txn_pending_set.erase(it); - break; - case data_tok::COMMIT_SUBM: - dtokl.push_back(dtokp); - tot_data_toks++; - dtokp->set_wstate(data_tok::COMMITTED); - it = _txn_pending_set.find(dtokp->xid()); - if (it == _txn_pending_set.end()) - { - std::ostringstream oss; - oss << std::hex << "_txn_pending_set: commit xid=\""; - oss << dtokp->xid() << "\""; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", - "get_events"); - } - _txn_pending_set.erase(it); - break; - case data_tok::ENQ_PART: - case data_tok::DEQ_PART: - case data_tok::ABORT_PART: - case data_tok::COMMIT_PART: - // ignore these - break; - default: - // throw for anything else - std::ostringstream oss; - oss << "dtok_id=" << dtokp->id() << " dtok_state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_BADDTOKSTATE, oss.str(), "wmgr", - "get_events"); - } // switch - } // if - } // for - - // Increment the completed write offset - // NOTE: We cannot use _wrfc here, as it may have rotated since submitting count. - // Use stored pointer to fcntl in the pcb instead. - pcbp->_wfh->add_wr_cmpl_cnt_dblks(pcbp->_wdblks); - pcbp->_wfh->decr_aio_cnt(); - _jc->instr_decr_outstanding_aio_cnt(); - - // Clean up this pcb's data_tok list - pcbp->_pdtokl->clear(); - pcbp->_state = state; - - // Perform AIO return callback - if (_cbp && tot_data_toks) - _cbp->wr_aio_cb(dtokl); - } - else // File header writes have no pcb - { - // get lfid from original file header record, update info for that lfid - file_hdr* fhp = (file_hdr*)aiocbp->u.c.buf; - u_int32_t lfid = fhp->_lfid; - fcntl* fcntlp = _jc->get_fcntlp(lfid); - fcntlp->add_wr_cmpl_cnt_dblks(JRNL_SBLK_SIZE); - fcntlp->decr_aio_cnt(); - fcntlp->set_wr_fhdr_aio_outstanding(false); - } - } - - return tot_data_toks; -} - -bool -wmgr::is_txn_synced(const std::string& xid) -{ - // Ignore xid not found error here - if (_tmap.is_txn_synced(xid) == txn_map::TMAP_NOT_SYNCED) - return false; - // Check for outstanding commit/aborts - std::set::iterator it = _txn_pending_set.find(xid); - return it == _txn_pending_set.end(); -} - -void -wmgr::initialize(aio_callback* const cbp, const u_int32_t wcache_pgsize_sblks, const u_int16_t wcache_num_pages) -{ - pmgr::initialize(cbp, wcache_pgsize_sblks, wcache_num_pages); - wmgr::clean(); - _num_jfiles = _jc->num_jfiles(); - if (::posix_memalign(&_fhdr_base_ptr, _sblksize, _sblksize * _num_jfiles)) - { - wmgr::clean(); - std::ostringstream oss; - oss << "posix_memalign(): blksize=" << _sblksize << " size=" << _sblksize; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__MALLOC, oss.str(), "wmgr", "initialize"); - } - _fhdr_ptr_arr = (void**)std::malloc(_num_jfiles * sizeof(void*)); - MALLOC_CHK(_fhdr_ptr_arr, "_fhdr_ptr_arr", "wmgr", "initialize"); - _fhdr_aio_cb_arr = (aio_cb**)std::malloc(sizeof(aio_cb*) * _num_jfiles); - MALLOC_CHK(_fhdr_aio_cb_arr, "_fhdr_aio_cb_arr", "wmgr", "initialize"); - std::memset(_fhdr_aio_cb_arr, 0, sizeof(aio_cb*) * _num_jfiles); - for (u_int16_t i=0; i<_num_jfiles; i++) - { - _fhdr_ptr_arr[i] = (void*)((char*)_fhdr_base_ptr + _sblksize * i); - _fhdr_aio_cb_arr[i] = new aio_cb; - } - _page_cb_arr[0]._state = IN_USE; - _ddtokl.clear(); - _cached_offset_dblks = 0; - _enq_busy = false; -} - -iores -wmgr::pre_write_check(const _op_type op, const data_tok* const dtokp, - const std::size_t xidsize, const std::size_t dsize, const bool external - ) const -{ - // Check status of current file - if (!_wrfc.is_wr_reset()) - { - if (!_wrfc.wr_reset()) - return RHM_IORES_FULL; - } - - // Check status of current page is ok for writing - if (_page_cb_arr[_pg_index]._state != IN_USE) - { - if (_page_cb_arr[_pg_index]._state == UNUSED) - _page_cb_arr[_pg_index]._state = IN_USE; - else if (_page_cb_arr[_pg_index]._state == AIO_PENDING) - return RHM_IORES_PAGE_AIOWAIT; - else - { - std::ostringstream oss; - oss << "jrnl=" << _jc->id() << " op=" << _op_str[op]; - oss << " index=" << _pg_index << " pg_state=" << _page_cb_arr[_pg_index].state_str(); - throw jexception(jerrno::JERR_WMGR_BADPGSTATE, oss.str(), "wmgr", "pre_write_check"); - } - } - - // operation-specific checks - switch (op) - { - case WMGR_ENQUEUE: - { - // Check for enqueue reaching cutoff threshold - u_int32_t size_dblks = jrec::size_dblks(enq_rec::rec_size(xidsize, dsize, - external)); - if (!_enq_busy && _wrfc.enq_threshold(_cached_offset_dblks + size_dblks)) - return RHM_IORES_ENQCAPTHRESH; - if (!dtokp->is_writable()) - { - std::ostringstream oss; - oss << "jrnl=" << _jc->id() << " op=" << _op_str[op]; - oss << " dtok_id=" << dtokp->id() << " dtok_state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_BADDTOKSTATE, oss.str(), "wmgr", - "pre_write_check"); - } - } - break; - case WMGR_DEQUEUE: - if (!dtokp->is_dequeueable()) - { - std::ostringstream oss; - oss << "jrnl=" << _jc->id() << " op=" << _op_str[op]; - oss << " dtok_id=" << dtokp->id() << " dtok_state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_BADDTOKSTATE, oss.str(), "wmgr", - "pre_write_check"); - } - break; - case WMGR_ABORT: - break; - case WMGR_COMMIT: - break; - } - - return RHM_IORES_SUCCESS; -} - -void -wmgr::dequeue_check(const std::string& xid, const u_int64_t drid) -{ - // First check emap - bool found = false; - int16_t fid = _emap.get_pfid(drid); - if (fid < enq_map::EMAP_OK) // fail - { - if (fid == enq_map::EMAP_RID_NOT_FOUND) - { - if (xid.size()) - found = _tmap.data_exists(xid, drid); - } - else if (fid == enq_map::EMAP_LOCKED) - { - std::ostringstream oss; - oss << std::hex << "drid=0x" << drid; - throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "dequeue_check"); - } - } - else - found = true; - if (!found) - { - std::ostringstream oss; - oss << "jrnl=" << _jc->id() << " drid=0x" << std::hex << drid; - throw jexception(jerrno::JERR_WMGR_DEQRIDNOTENQ, oss.str(), "wmgr", "dequeue_check"); - } -} - -void -wmgr::dblk_roundup() -{ - const u_int32_t xmagic = RHM_JDAT_EMPTY_MAGIC; - u_int32_t wdblks = jrec::size_blks(_cached_offset_dblks, JRNL_SBLK_SIZE) * JRNL_SBLK_SIZE; - while (_cached_offset_dblks < wdblks) - { - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * JRNL_DBLK_SIZE); - std::memcpy(wptr, (const void*)&xmagic, sizeof(xmagic)); -#ifdef RHM_CLEAN - std::memset((char*)wptr + sizeof(xmagic), RHM_CLEAN_CHAR, JRNL_DBLK_SIZE - sizeof(xmagic)); -#endif - _pg_offset_dblks++; - _cached_offset_dblks++; - } -} - -void -wmgr::write_fhdr(u_int64_t rid, u_int16_t fid, u_int16_t lid, std::size_t fro) -{ - file_hdr fhdr(RHM_JDAT_FILE_MAGIC, RHM_JDAT_VERSION, rid, fid, lid, fro, _wrfc.owi(), true); - std::memcpy(_fhdr_ptr_arr[fid], &fhdr, sizeof(fhdr)); -#ifdef RHM_CLEAN - std::memset((char*)_fhdr_ptr_arr[fid] + sizeof(fhdr), RHM_CLEAN_CHAR, _sblksize - sizeof(fhdr)); -#endif - aio_cb* aiocbp = _fhdr_aio_cb_arr[fid]; - aio::prep_pwrite(aiocbp, _wrfc.fh(), _fhdr_ptr_arr[fid], _sblksize, 0); - if (aio::submit(_ioctx, 1, &aiocbp) < 0) - throw jexception(jerrno::JERR__AIO, "wmgr", "write_fhdr"); - _aio_evt_rem++; - _wrfc.add_subm_cnt_dblks(JRNL_SBLK_SIZE); - _wrfc.incr_aio_cnt(); - _wrfc.file_controller()->set_wr_fhdr_aio_outstanding(true); -} - -void -wmgr::rotate_page() -{ - _page_cb_arr[_pg_index]._state = AIO_PENDING; - if (_pg_offset_dblks >= _cache_pgsize_sblks * JRNL_SBLK_SIZE) - { - _pg_offset_dblks = 0; - _pg_cntr++; - } - if (++_pg_index >= _cache_num_pages) - _pg_index = 0; -} - -void -wmgr::clean() -{ - std::free(_fhdr_base_ptr); - _fhdr_base_ptr = 0; - - std::free(_fhdr_ptr_arr); - _fhdr_ptr_arr = 0; - - if (_fhdr_aio_cb_arr) - { - for (u_int32_t i=0; i<_num_jfiles; i++) - delete _fhdr_aio_cb_arr[i]; - std::free(_fhdr_aio_cb_arr); - _fhdr_aio_cb_arr = 0; - } -} - -const std::string -wmgr::status_str() const -{ - std::ostringstream oss; - oss << "wmgr: pi=" << _pg_index << " pc=" << _pg_cntr; - oss << " po=" << _pg_offset_dblks << " aer=" << _aio_evt_rem; - oss << " edac:" << (_enq_busy?"T":"F") << (_deq_busy?"T":"F"); - oss << (_abort_busy?"T":"F") << (_commit_busy?"T":"F"); - oss << " ps=["; - for (int i=0; i<_cache_num_pages; i++) - { - switch (_page_cb_arr[i]._state) - { - case UNUSED: oss << "-"; break; - case IN_USE: oss << "U"; break; - case AIO_PENDING: oss << "A"; break; - case AIO_COMPLETE: oss << "*"; break; - default: oss << _page_cb_arr[i]._state; - } - } - oss << "] " << _wrfc.status_str(); - return oss.str(); -} - -// static - -const char* wmgr::_op_str[] = {"enqueue", "dequeue", "abort", "commit"}; - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/wmgr.h b/qpid/cpp/src/qpid/legacystore/jrnl/wmgr.h deleted file mode 100644 index 8347221b1d..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/wmgr.h +++ /dev/null @@ -1,147 +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. - * - */ - -/** - * \file wmgr.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::wmgr (write manager). See - * class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_WMGR_H -#define QPID_LEGACYSTORE_JRNL_WMGR_H - -namespace mrg -{ -namespace journal -{ -class wmgr; -} -} - -#include -#include "qpid/legacystore/jrnl/enums.h" -#include "qpid/legacystore/jrnl/pmgr.h" -#include "qpid/legacystore/jrnl/wrfc.h" -#include - -namespace mrg -{ -namespace journal -{ - - /** - * \brief Class for managing a write page cache of arbitrary size and number of pages. - * - * The write page cache works on the principle of caching the write data within a page until - * that page is either full or flushed; this initiates a single AIO write operation to store - * the data on disk. - * - * The maximum disk throughput is achieved by keeping the write operations of uniform size. - * Waiting for a page cache to fill achieves this; and in high data volume/throughput situations - * achieves the optimal disk throughput. Calling flush() forces a write of the current page cache - * no matter how full it is, and disrupts the uniformity of the write operations. This should - * normally only be done if throughput drops and there is a danger of a page of unwritten data - * waiting around for excessive time. - * - * The usual tradeoff between data storage latency and throughput performance applies. - */ - class wmgr : public pmgr - { - private: - wrfc& _wrfc; ///< Ref to write rotating file controller - u_int32_t _max_dtokpp; ///< Max data writes per page - u_int32_t _max_io_wait_us; ///< Max wait in microseconds till submit - void* _fhdr_base_ptr; ///< Base pointer to file header memory - void** _fhdr_ptr_arr; ///< Array of pointers to file headers memory - aio_cb** _fhdr_aio_cb_arr; ///< Array of iocb pointers for file header writes - u_int32_t _cached_offset_dblks; ///< Amount of unwritten data in page (dblocks) - std::deque _ddtokl; ///< Deferred dequeue data_tok list - u_int32_t _jfsize_dblks; ///< Journal file size in dblks (NOT sblks!) - u_int32_t _jfsize_pgs; ///< Journal file size in cache pages - u_int16_t _num_jfiles; ///< Number of files used in iocb mallocs - - // TODO: Convert _enq_busy etc into a proper threadsafe lock - // TODO: Convert to enum? Are these encodes mutually exclusive? - bool _enq_busy; ///< Flag true if enqueue is in progress - bool _deq_busy; ///< Flag true if dequeue is in progress - bool _abort_busy; ///< Flag true if abort is in progress - bool _commit_busy; ///< Flag true if commit is in progress - - enum _op_type { WMGR_ENQUEUE = 0, WMGR_DEQUEUE, WMGR_ABORT, WMGR_COMMIT }; - static const char* _op_str[]; - - enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding - deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding - txn_rec _txn_rec; ///< Transaction record used for encoding/decoding - std::set _txn_pending_set; ///< Set containing xids of pending commits/aborts - - public: - wmgr(jcntl* jc, enq_map& emap, txn_map& tmap, wrfc& wrfc); - wmgr(jcntl* jc, enq_map& emap, txn_map& tmap, wrfc& wrfc, const u_int32_t max_dtokpp, - const u_int32_t max_iowait_us); - virtual ~wmgr(); - - void initialize(aio_callback* const cbp, const u_int32_t wcache_pgsize_sblks, - const u_int16_t wcache_num_pages, const u_int32_t max_dtokpp, - const u_int32_t max_iowait_us, std::size_t eo = 0); - iores enqueue(const void* const data_buff, const std::size_t tot_data_len, - const std::size_t this_data_len, data_tok* dtokp, const void* const xid_ptr, - const std::size_t xid_len, const bool transient, const bool external); - iores dequeue(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len, - const bool txn_coml_commit); - iores abort(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len); - iores commit(data_tok* dtokp, const void* const xid_ptr, const std::size_t xid_len); - iores flush(); - int32_t get_events(page_state state, timespec* const timeout, bool flush = false); - bool is_txn_synced(const std::string& xid); - inline bool curr_pg_blocked() const { return _page_cb_arr[_pg_index]._state != UNUSED; } - inline bool curr_file_blocked() const { return _wrfc.aio_cnt() > 0; } - inline u_int32_t unflushed_dblks() { return _cached_offset_dblks; } - - // Debug aid - const std::string status_str() const; - - private: - void initialize(aio_callback* const cbp, const u_int32_t wcache_pgsize_sblks, - const u_int16_t wcache_num_pages); - iores pre_write_check(const _op_type op, const data_tok* const dtokp, - const std::size_t xidsize = 0, const std::size_t dsize = 0, const bool external = false) - const; - void dequeue_check(const std::string& xid, const u_int64_t drid); - void file_header_check(const u_int64_t rid, const bool cont, const u_int32_t rec_dblks_rem); - void flush_check(iores& res, bool& cont, bool& done); - iores write_flush(); - iores rotate_file(); - void dblk_roundup(); - void write_fhdr(u_int64_t rid, u_int16_t fid, u_int16_t lid, std::size_t fro); - void rotate_page(); - void clean(); - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_WMGR_H diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/wrfc.cpp b/qpid/cpp/src/qpid/legacystore/jrnl/wrfc.cpp deleted file mode 100644 index 64ee65f1ac..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/wrfc.cpp +++ /dev/null @@ -1,164 +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. - * - */ - -/** - * \file wrfc.cpp - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::wrfc (rotating - * file controller). See comments in file wrfc.h for details. - * - * \author Kim van der Riet - */ - -#include "qpid/legacystore/jrnl/wrfc.h" - -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" - -namespace mrg -{ -namespace journal -{ - -wrfc::wrfc(const lpmgr* lpmp): - rfc(lpmp), - _fsize_sblks(0), - _fsize_dblks(0), - _enq_cap_offs_dblks(0), - _rid(0), - _reset_ok(false), - _owi(false), - _frot(true) -{} - -wrfc::~wrfc() -{} - -void -wrfc::initialize(const u_int32_t fsize_sblks, rcvdat* rdp) -{ - if (rdp) - { - _fc_index = rdp->_lfid; - _curr_fc = _lpmp->get_fcntlp(_fc_index); - _curr_fc->wr_reset(rdp); - _rid = rdp->_h_rid + 1; - _reset_ok = true; - _owi = rdp->_owi; - _frot = rdp->_frot; - if (rdp->_lffull) - rotate(); - } - else - { - rfc::initialize(); - rfc::set_findex(0); - _rid = 0ULL; - _reset_ok = false; - } - _fsize_sblks = fsize_sblks; - _fsize_dblks = fsize_sblks * JRNL_SBLK_SIZE; - _enq_cap_offs_dblks = (u_int32_t)std::ceil(_fsize_dblks * _lpmp->num_jfiles() * (100.0 - JRNL_ENQ_THRESHOLD) / 100); - // Check the offset is at least one file; if not, make it so - if (_enq_cap_offs_dblks < _fsize_dblks) - _enq_cap_offs_dblks = _fsize_dblks; -} - -iores wrfc::rotate() -{ - if (!_lpmp->num_jfiles()) - throw jexception(jerrno::JERR__NINIT, "wrfc", "rotate"); - _fc_index++; - if (_fc_index == _lpmp->num_jfiles()) - { - _fc_index = 0; - _owi = !_owi; - _frot = false; - } - _curr_fc = _lpmp->get_fcntlp(_fc_index); - if (_curr_fc->aio_cnt()) - return RHM_IORES_FILE_AIOWAIT; - if (!wr_reset()) //Checks if file is still in use (ie not fully dequeued yet) - return RHM_IORES_FULL; - return RHM_IORES_SUCCESS; -} - -u_int16_t wrfc::earliest_index() const -{ - if (_frot) - return 0; - u_int16_t next_index = _fc_index + 1; - if (next_index >= _lpmp->num_jfiles()) - next_index = 0; - return next_index; -} - -bool -wrfc::enq_threshold(const u_int32_t enq_dsize_dblks) const -{ - u_int32_t subm_dblks = subm_cnt_dblks(); // includes file hdr if > 0 - // This compensates for new files which don't have their file headers written yet, - // as file header space cannot be included in this calculation. - if (subm_dblks != 0) - subm_dblks -= 4; - u_int32_t fwd_dblks = subm_dblks + enq_dsize_dblks + _enq_cap_offs_dblks; - u_int16_t findex = _fc_index; - fcntl* fcp = _curr_fc; - bool in_use = false; // at least one file contains an enqueued record - bool overwrite = false; // reached the original journal file we started with - while (fwd_dblks && !(findex != _fc_index && fcp->enqcnt())) - { - fwd_dblks -= fwd_dblks > _fsize_dblks ? _fsize_dblks : fwd_dblks; - if (fwd_dblks) - { - if (++findex == _lpmp->num_jfiles()) - findex = 0; - overwrite |= findex == _fc_index; - fcp = _lpmp->get_fcntlp(findex); - } - in_use |= fcp->enqcnt() > 0; - } - // Return true if threshold exceeded - return (findex != _fc_index && in_use) || overwrite; -} - -bool wrfc::wr_reset() -{ - _reset_ok = _curr_fc->reset(); // returns false if full (ie file still contains enqueued recs) - return _reset_ok; -} - -// TODO: update this to reflect all status data -std::string -wrfc::status_str() const -{ - std::ostringstream oss; - oss << "wrfc: " << rfc::status_str(); - if (is_active()) - oss << " fcntl[" << _fc_index << "]: " << _curr_fc->status_str(); - return oss.str(); -} - -} // namespace journal -} // namespace mrg diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/wrfc.h b/qpid/cpp/src/qpid/legacystore/jrnl/wrfc.h deleted file mode 100644 index f0e4e73151..0000000000 --- a/qpid/cpp/src/qpid/legacystore/jrnl/wrfc.h +++ /dev/null @@ -1,154 +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. - * - */ - -/** - * \file wrfc.h - * - * Qpid asynchronous store plugin library - * - * File containing code for class mrg::journal::wrfc (write rotating - * file controller). See class documentation for details. - * - * \author Kim van der Riet - */ - -#ifndef QPID_LEGACYSTORE_JRNL_WRFC_H -#define QPID_LEGACYSTORE_JRNL_WRFC_H - -namespace mrg -{ -namespace journal -{ -class wrfc; -} -} - -#include -#include "qpid/legacystore/jrnl/enums.h" -#include "qpid/legacystore/jrnl/rrfc.h" - -namespace mrg -{ -namespace journal -{ - - /** - * \class wrfc - * \brief Class to handle write management of a journal rotating file controller. - */ - class wrfc : public rfc - { - private: - u_int32_t _fsize_sblks; ///< Size of journal files in sblks - u_int32_t _fsize_dblks; ///< Size of journal files in dblks - u_int32_t _enq_cap_offs_dblks; ///< Enqueue capacity offset - u_int64_t _rid; ///< Master counter for record ID (rid) - bool _reset_ok; ///< Flag set when reset succeeds - bool _owi; ///< Overwrite indicator - bool _frot; ///< Flag is true for first rotation, false otherwise - - public: - wrfc(const lpmgr* lpmp); - virtual ~wrfc(); - - /** - * \brief Initialize the controller. - * \param fsize_sblks Size of each journal file in sblks. - * \param rdp Struct carrying restore information. Optional for non-restore use, defaults to 0 (NULL). - */ - using rfc::initialize; - void initialize(const u_int32_t fsize_sblks, rcvdat* rdp = 0); - - /** - * \brief Rotate active file controller to next file in rotating file group. - * \exception jerrno::JERR__NINIT if called before calling initialize(). - */ - iores rotate(); - - /** - * \brief Returns the index of the earliest complete file within the rotating - * file group. Unwritten files are excluded. The currently active file is - * excluded unless it is the only written file. - */ - u_int16_t earliest_index() const; - - /** - * \brief Determines if a proposed write would cause the enqueue threshold to be exceeded. - * - * The following routine finds whether the next write will take the write pointer to beyond the - * enqueue limit threshold. The following illustrates how this is achieved. - *
-        * Current file index: 4                         +---+----------+
-        * X's mark still-enqueued records               |msg| 1-thresh |
-        * msg = current msg size + unwritten cache      +---+----------+
-        * thresh = JRNL_ENQ_THRESHOLD as a fraction     ^              V
-        *            +-------+-------+-------+-------+--+----+-------+-+-----+-------+
-        * file num ->|   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |
-        * enq recs ->| X  XX |XX XXX |XX XXXX|XXXXXXX|XX     |       |       |     X |
-        *            +-------+-------+-------+-------+--+----+-------+-+-----+-------+
-        *                                               ^        ^       ^
-        *                                  subm_dblks --+        |       |
-        *                                                      These files must be free of enqueues
-        *                                                      If not, return true.
-        * 
- * \param enq_dsize_dblks Proposed size of write in dblocks - */ - bool enq_threshold(const u_int32_t enq_dsize_dblks) const; - - inline u_int64_t rid() const { return _rid; } - inline u_int64_t get_incr_rid() { return _rid++; } - bool wr_reset(); - inline bool is_wr_reset() const { return _reset_ok; } - inline bool owi() const { return _owi; } - inline bool frot() const { return _frot; } - - // Convenience access methods to current file controller - - inline int fh() const { return _curr_fc->wr_fh(); } - - inline u_int32_t subm_cnt_dblks() const { return _curr_fc->wr_subm_cnt_dblks(); } - inline std::size_t subm_offs() const { return _curr_fc->wr_subm_offs(); } - inline u_int32_t add_subm_cnt_dblks(u_int32_t a) { return _curr_fc->add_wr_subm_cnt_dblks(a); } - - inline u_int32_t cmpl_cnt_dblks() const { return _curr_fc->wr_cmpl_cnt_dblks(); } - inline std::size_t cmpl_offs() const { return _curr_fc->wr_cmpl_offs(); } - inline u_int32_t add_cmpl_cnt_dblks(u_int32_t a) { return _curr_fc->add_wr_cmpl_cnt_dblks(a); } - - inline u_int16_t aio_cnt() const { return _curr_fc->aio_cnt(); } - inline u_int16_t incr_aio_cnt() { return _curr_fc->incr_aio_cnt(); } - inline u_int16_t decr_aio_cnt() { return _curr_fc->decr_aio_cnt(); } - - inline bool is_void() const { return _curr_fc->wr_void(); } - inline bool is_empty() const { return _curr_fc->wr_empty(); } - inline u_int32_t remaining_dblks() const { return _curr_fc->wr_remaining_dblks(); } - inline bool is_full() const { return _curr_fc->is_wr_full(); }; - inline bool is_compl() const { return _curr_fc->is_wr_compl(); }; - inline u_int32_t aio_outstanding_dblks() const { return _curr_fc->wr_aio_outstanding_dblks(); } - inline bool file_rotate() const { return _curr_fc->wr_file_rotate(); } - - // Debug aid - std::string status_str() const; - }; - -} // namespace journal -} // namespace mrg - -#endif // ifndef QPID_LEGACYSTORE_JRNL_WRFC_H diff --git a/qpid/cpp/src/qpid/legacystore/management-schema.xml b/qpid/cpp/src/qpid/legacystore/management-schema.xml deleted file mode 100644 index 71497cc0f9..0000000000 --- a/qpid/cpp/src/qpid/legacystore/management-schema.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qpid/cpp/src/qpid/linearstore/BindingDbt.cpp b/qpid/cpp/src/qpid/linearstore/BindingDbt.cpp deleted file mode 100644 index 47738cce39..0000000000 --- a/qpid/cpp/src/qpid/linearstore/BindingDbt.cpp +++ /dev/null @@ -1,50 +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/linearstore/BindingDbt.h" - -namespace qpid { -namespace linearstore { - -BindingDbt::BindingDbt(const qpid::broker::PersistableExchange& e, const qpid::broker::PersistableQueue& q, const std::string& k, const qpid::framing::FieldTable& a) - : data(new char[encodedSize(e, q, k, a)]), - buffer(data, encodedSize(e, q, k, a)) -{ - buffer.putLongLong(q.getPersistenceId()); - buffer.putShortString(q.getName()); - buffer.putShortString(k); - buffer.put(a); - - set_data(data); - set_size(encodedSize(e, q, k, a)); -} - -BindingDbt::~BindingDbt() -{ - delete [] data; -} - -uint32_t BindingDbt::encodedSize(const qpid::broker::PersistableExchange& /*not used*/, const qpid::broker::PersistableQueue& q, const std::string& k, const qpid::framing::FieldTable& a) -{ - return 8 /*queue id*/ + q.getName().size() + 1 + k.size() + 1 + a.encodedSize(); -} - -}} diff --git a/qpid/cpp/src/qpid/linearstore/BindingDbt.h b/qpid/cpp/src/qpid/linearstore/BindingDbt.h deleted file mode 100644 index e5d61de248..0000000000 --- a/qpid/cpp/src/qpid/linearstore/BindingDbt.h +++ /dev/null @@ -1,56 +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. - * - */ - -#ifndef QPID_LINEARSTORE_BINDINGDBT_H -#define QPID_LINEARSTORE_BINDINGDBT_H - -#include "db-inc.h" -#include "qpid/broker/PersistableExchange.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldTable.h" - -namespace qpid{ -namespace linearstore{ - -class BindingDbt : public Dbt -{ - char* data; - qpid::framing::Buffer buffer; - - static uint32_t encodedSize(const qpid::broker::PersistableExchange& e, - const qpid::broker::PersistableQueue& q, - const std::string& k, - const qpid::framing::FieldTable& a); - -public: - BindingDbt(const qpid::broker::PersistableExchange& e, - const qpid::broker::PersistableQueue& q, - const std::string& k, - const qpid::framing::FieldTable& a); - - virtual ~BindingDbt(); - -}; - -}} - -#endif // ifndef QPID_LINEARSTORE_BINDINGDBT_H diff --git a/qpid/cpp/src/qpid/linearstore/BufferValue.cpp b/qpid/cpp/src/qpid/linearstore/BufferValue.cpp deleted file mode 100644 index 5115055375..0000000000 --- a/qpid/cpp/src/qpid/linearstore/BufferValue.cpp +++ /dev/null @@ -1,56 +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/linearstore/BufferValue.h" - -namespace qpid { -namespace linearstore { - - - -BufferValue::BufferValue(uint32_t size, uint64_t offset) - : data(new char[size]), - buffer(data, size) -{ - set_data(data); - set_size(size); - set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); - set_doff(offset); - set_dlen(size); - set_ulen(size); -} - -BufferValue::BufferValue(const qpid::broker::Persistable& p) - : data(new char[p.encodedSize()]), - buffer(data, p.encodedSize()) -{ - p.encode(buffer); - - set_data(data); - set_size(p.encodedSize()); -} - -BufferValue::~BufferValue() -{ - delete [] data; -} - -}} diff --git a/qpid/cpp/src/qpid/linearstore/BufferValue.h b/qpid/cpp/src/qpid/linearstore/BufferValue.h deleted file mode 100644 index daeb81306a..0000000000 --- a/qpid/cpp/src/qpid/linearstore/BufferValue.h +++ /dev/null @@ -1,46 +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. - * - */ - -#ifndef QPID_LINEARSTORE_BUFFERVALUE_H -#define QPID_LINEARSTORE_BUFFERVALUE_H - -#include "db-inc.h" -#include "qpid/broker/Persistable.h" -#include "qpid/framing/Buffer.h" - -namespace qpid{ -namespace linearstore{ - -class BufferValue : public Dbt -{ - char* data; - -public: - qpid::framing::Buffer buffer; - - BufferValue(uint32_t size, uint64_t offset); - BufferValue(const qpid::broker::Persistable& p); - virtual ~BufferValue(); -}; - -}} - -#endif // ifndef QPID_LINEARSTORE_BUFFERVALUE_H diff --git a/qpid/cpp/src/qpid/linearstore/Cursor.h b/qpid/cpp/src/qpid/linearstore/Cursor.h deleted file mode 100644 index 0287803b21..0000000000 --- a/qpid/cpp/src/qpid/linearstore/Cursor.h +++ /dev/null @@ -1,50 +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. - * - */ - -#ifndef QPID_LINEARSTORE_CURSOR_H -#define QPID_LINEARSTORE_CURSOR_H - -#include -#include "db-inc.h" - -namespace qpid{ -namespace linearstore{ - -class Cursor -{ - Dbc* cursor; -public: - typedef boost::shared_ptr db_ptr; - - Cursor() : cursor(0) {} - virtual ~Cursor() { if(cursor) cursor->close(); } - - void open(db_ptr db, DbTxn* txn, uint32_t flags = 0) { db->cursor(txn, &cursor, flags); } - void close() { if(cursor) cursor->close(); cursor = 0; } - Dbc* get() { return cursor; } - Dbc* operator->() { return cursor; } - bool next(Dbt& key, Dbt& value) { return cursor->get(&key, &value, DB_NEXT) == 0; } - bool current(Dbt& key, Dbt& value) { return cursor->get(&key, &value, DB_CURRENT) == 0; } -}; - -}} - -#endif // ifndef QPID_LINEARSTORE_CURSOR_H diff --git a/qpid/cpp/src/qpid/linearstore/DataTokenImpl.cpp b/qpid/cpp/src/qpid/linearstore/DataTokenImpl.cpp deleted file mode 100644 index 0b1f3d7941..0000000000 --- a/qpid/cpp/src/qpid/linearstore/DataTokenImpl.cpp +++ /dev/null @@ -1,28 +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/linearstore/DataTokenImpl.h" - -using namespace qpid::linearstore; - -DataTokenImpl::DataTokenImpl():data_tok() {} - -DataTokenImpl::~DataTokenImpl() {} diff --git a/qpid/cpp/src/qpid/linearstore/DataTokenImpl.h b/qpid/cpp/src/qpid/linearstore/DataTokenImpl.h deleted file mode 100644 index 7152cef6a0..0000000000 --- a/qpid/cpp/src/qpid/linearstore/DataTokenImpl.h +++ /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. - * - */ - -#ifndef QPID_LINEARSTORE_DATATOKENIMPL_H -#define QPID_LINEARSTORE_DATATOKENIMPL_H - -#include "qpid/linearstore/journal/data_tok.h" -#include "qpid/broker/PersistableMessage.h" -#include - -namespace qpid{ -namespace linearstore{ - -class DataTokenImpl : public qpid::linearstore::journal::data_tok, public qpid::RefCounted -{ - private: - boost::intrusive_ptr sourceMsg; - public: - DataTokenImpl(); - virtual ~DataTokenImpl(); - - inline boost::intrusive_ptr& getSourceMessage() { return sourceMsg; } - inline void setSourceMessage(const boost::intrusive_ptr& msg) { sourceMsg = msg; } -}; - -} // namespace msgstore -} // namespace mrg - -#endif // ifndef QPID_LINEARSTORE_DATATOKENIMPL_H diff --git a/qpid/cpp/src/qpid/linearstore/ISSUES b/qpid/cpp/src/qpid/linearstore/ISSUES deleted file mode 100644 index 9294f929ac..0000000000 --- a/qpid/cpp/src/qpid/linearstore/ISSUES +++ /dev/null @@ -1,260 +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. -# - -Linear Store issues: - -Current/pending: -================ - Q-JIRA RHBZ Description / Comments - ------ ------- ---------------------- - 5359 - Linearstore: Implement new management schema and wire into store - 5360 - Linearstore: Evaluate and rework logging to produce a consistent log output -* 5361 1145359 Linearstore: No tests for linearstore functionality currently exist - svn r.1564893 2014-02-05: Added tx-test-soak.sh - svn r.1564935 2014-02-05: Added license text to tx-test-soak.sh - svn r.1625283 2014-09-16: Basic python tests from legacystore ported over to linearstore - * No existing tests for linearstore: - ** Basic broker-level tests for txn and non-txn recovery - ** Store-level tests which check write boundary conditions - ** EFP tests, including file recovery, error management - ** Unit tests - ** Basic performance tests - 5464 - [linearstore] Incompletely created journal files accumulate in EFP - - 1088944 [Linearstore] store does not return all files to EFP after purging big queue - - 1067480 [LinearStore] Provide a way to limit max count/size of empty files in EFP - - 1067429 [LinearStore] last file from deleted queue is not moved to EFP - - 1067482 [LinearStore] Provide a way to preallocate empty pages in EFP - 6303 1180660 [linearstore] Roll back auto-upgrade of store directory structure - svn r.1652486 2015-01-16 Fix, mutually exclusive dir structure introduced - 5880 867826 [RFE] Qpid memory usage is not consistent across restart - Tools install - - - - -Fixed/closed: -============= - Q-JIRA RHBZ Description / Comments - ------ ------- ---------------------- - 5357 1052518 Linearstore: Empty file recycling not functional - svn r.1545563 2013-11-26: Propsed fix. VERIFIED - 5358 1052727 Linearstore: Checksums not implemented in record tail - svn r.1547601 2013-12-03: Propsed fix. NEEDINFO on algorithm - 5387 1036071 Linearstore: Segmentation fault when deleting queue - svn r.1547641 2013-12-03: Propsed fix. VERIFIED - 5388 1035802 Linearstore: Segmentation fault when recovering empty queue - svn r.1547921 2013-12-04: Propsed fix. VERIFIED -NO-JIRA - Added missing Apache copyright/license text - svn r.1551304 2013-12-16: Propsed fix - 5425 1052445 Linearstore: Transaction Prepared List (TPL) fails with jexception 0x0402 AtomicCounter::addLimit() threw JERR_JNLF_FILEOFFSOVFL - svn r.1551361 2013-12-16: Proposed fix VERIFIED - 5442 1039949 Linearstore: Dtx recover test fails - svn r.1552772 2013-12-20: Proposed fix VERIFIED - 5444 1052775 Linearstore: Recovering from qpid-txtest fails with "Inconsistent TPL 2PC count" error message - svn r.1553148 2013-12-23: Proposed fix NEEDIFNO on reproduction and testing - - 1038599 [LinearStore] Abort when deleting used queue after restart - CLOSED-NOTABUG 2014-01-06 - 5460 1051097 [linearstore] Recovery of store which contains prepared but incomplete transactions results in message loss - svn r.1556892 2014-01-09: Proposed fix VERIFIED - 5473 1051924 [linearstore] Recovery of journal in which last logical file contains truncated record causes crash - svn r.1557620 2014-01-12: Proposed fix MODIFIED - 5483 - [linearstore] Recovery of journal with partly written record fails with "JERR_JREC_BADRECTAIL: Invalid data record tail" error message - svn r.1558589 2014-01-15: Proposed fix - * May be linked to RHBZ 1039522 - VERIFIED - * May be linked to RHBZ 1039525 - VERIFIED - - 1039522 Qpid crashes while recovering from linear store around apid::linearstore::journal::JournalFile::getFqFileName() including enq_rec::decode() threw JERR_JREC_BAD_RECTAIL - * Possible dup of 1039525 - * May be fixed by QPID-5483 - waiting for needinfo, recommend rebuilding with QPID-5483 fix and re-testing. VERIFIED. - - 1039525 Qpid crashes while recovering from linear store around apid::linearstore::journal::jexception::format including enq_rec::decode() threw JERR_JREC_BAD_REC_TAIL - * Possible dup of 1039522 - * May be fixed by QPID-5483 - waiting for needinfo, recommend rebuilding with QPID-5483 fix and re-testing. VERIFIED. - 5487 1054448 [linearstore] Replace use of /dev/urandom with c random generator calls - svn r.1558913 2014-01-16: Proposed fix VEFIFIED - 5484 1035843 Slow performance for producers - svn r.1558592 2014-01-15 fixes an issue with using /dev/random as a source of random numbers for Journal serial numbers. - svn r.1558913 2014-01-16 replaces use of /dev/urandom with several calls to rand() to construct a 64-bit random number. - * Recommend rebuilding and testing for performance again with these two fixes. VERIFIED. - 5479 1053701 [linearstore] Using recovered store results in "JERR_JNLF_FILEOFFSOVFL: Attempted to increase submitted offset past file size. (JournalFile::submittedDblkCount)" error message - * Probability: 2 of 600 (0.3%) using tx-test-soak.sh - * Fixed by checkin for QPID-5480, no longer able to reproduce. VERIFIED - 5480 1053749 [linearstore] Recovery of store failure with "JERR_MAP_NOTFOUND: Key not found in map." error message - svn r.1564877 2014-02-05: Proposed fix - * Probability: 6 of 600 (1.0%) using tx-test-soak.sh - * If broker is started a second time after failure, it starts correctly and test completes ok. - * Problem: File is being recycled to EFP with still-locked enqueues in it (ie dequeued transactionally). - * Problem: Record alignment check writes filler records to wrong file when decoding bad record moves across a file boundary - 5603 1063700 [linearstore] broker restart fails under stress test - svn r.1574513 2014-03-05: Proposed fix. POST - * jexception 0x0701 RecoveryManager::readNextRemainingRecord() threw JERR_JREC_BADRECTAIL - 5607 1064181 [linearstore] Qpidd closes transactional client session&connection with async_dequeue() failed - svn r.1575009 2014-03-06: Proposed fix. POST - * jexception 0x010b LinearFileController::getCurrentSerial() threw JERR_NULL - - 1064230 [linearstore] Qpidd linearstore recovery sometimes fail to recover messages with recoverMessages() failed - * jexception 0x0701 RecoveryManager::readNextRemainingRecord() threw JERR_JREC_BADRECTAIL - * possible dup of 1063700 - - 1036026 [LinearStore] Qpid linear store unable to create durable queue - framing-error: Queue : create() failed: jexception 0x0000 - * UNABLE TO REPRODUCE - but Frantizek has additional info - * Retested after checkin 1575009, problem solved. VERIFIED - 5651 - [C++ broker] segfault in qpid::linearstore::journal::jdir::clear_dir when declaring durable queue - svn r.1582730 2014-03-28: Proposed fix by Pavel Moravec - * Bug introduced by r.1578899. - 5661 - [linearstore] Set default cmake build to exclude linearstore - svn r.1584379 2014-04-03: Proposed solution. - * Run ccmake, select BUILD_LINEARSTORE to change its value to ON to build. - 5750 1078142 [linearstore] qpidd closes connection with (distributed) transactional client while checking previous transaction, broker signals error (closed by error: Queue Ve0-2: async_dequeue() failed: exception 0x0103 wmgr::get_events() threw JERR__AIO: AIO error) - svn r.1594215 2014-05-13: Proposed solution. - * jexception 0x0103 wmgr::get_events() threw JERR__AIO: AIO error. (AIO write operation failed: Invalid argument (-22) [pg=0 size=8192 offset=4096 fh=22]) - 5655 1078937 [linearstore] Installation and tests for new store analysis tool qpid-qls-analyze - svn r.1596633 2014-05-21: Modified to run from installed location - 5767 1098118 [linearstore] broker segfaults when recovering journal file with damaged header - svn r.1596509 2014-05-21: Proposed solution (committed by pmoravec) - svn r.1599243 2014-06-02: Solution to additional case of file header corruption - 5924 1124906 [linearstore] Qpidd Will Not Start with Large Number of Queues - svn r.1614665 2014-07-30: Proposed solution - 5948 1121660 [AMQP 1.0] Broker restart failure with durable topic using non-durable exchange - svn r.1616287 2014-08-06: Proposed solution checked in by gsim - This turned out to be an AMQP error, fix does not affect store code. - 6043 1089652 [RFE]: Configuration option for linear store to delete or overwrite the used journal files. - svn r.1620426 2014-08-25: Proposed solution - 6147 1152012 [C++ broker linearstore] missing journal id in "trace Mgmt create journal." log - svn r.1631360 2014-10-13: Proposed solution - 6157 1150397 linearstore: segfault when 2 journals request new journal file from empty EFP - svn r.1632504 2014-10-17: Proposed solution by pmoravec - 6230 1165200 [linearstore] qpid-qls-analyze fails when analyzing empty journal - svn r.1643053 2014-11-18: Proposed fix - 6232 1163650 [C++ broker] Linearstore segfaults when ulimit prevents creating new file in EFP - svn r.1640357 2014-11-14: Proposed fix by pmoravec - 6248 1167911 [linearstore] Symlink creation fails if store dir path is not absolute - svn r.1641689 2014-11-25: Proposed solution - 5671 1160367 [linearstore] Add ability to use disk partitions and select per-queue EFPs - svn r.1636598 2014-11-04: WIP: New EFP and journal dir structure using symlinks - svn r.1637985 2014-11-10: WIP: Auto-upgrade from old dir structure to new - svn r.1649081 2015-01-02: WIP: Specify new queue using qpid-config --durable together with --efp-partition-num and/or --efp-pool-file-size. Needs testing. - - 1148807 [linearstore] Restarting broker with empty journal raises confusing warning - Fixed by svn r.1649081 of bug 5671 / 1160367 above - 6303 1180660 [linearstore] Roll back auto-upgrade of store directory structure - svn r.1652486 2015-01-16: Fix, mutually exclusive dir structure introduced - 5362 1145363 Linearstore: No store tools exist for examining the journals - svn r.1556888 2014-01-09: WIP checkin for linearstore version of qpid_qls_analyze. Needs testing and tidy-up. - svn r.1560530 2014-01-22: Bugfixes for qpid_qls_analyze - svn r.1561848 2014-01-27: Bugfixes and enhancements for qpid_qls_analyze - svn r.1564808 2014-02-05: Bugfixes and enhancements for qpid_qls_analyze - svn r.1578899 2014-03-18: Bugfixes and enhancements for qpid_qls_analyze - svn r.1583778 2014-04-01: Bugfix for qpid_qls_analyze - svn r.1652490 2015-01-16: Update for new partition capability and resulting dir structure change - * Store analysis and status - * Recovery/reading of message content - * Empty file pool status and management - - 1066256 [LinearStore] changing efp size after using store broke the new durable nodes creation - Believed to be fixed by 5671 / 1160367 - 6355 1188748 [linearstore] Installation error - svn r.1656771 2015-02-03: Proposed fix. - 6394 - [linearstore] Make linearstore the default store for linux builds - svn r.1660430 2015-02-17: Proposed fix. - svn r.1660702 2015-02-18: Corrected incorrect status messages. - 6399 - Windows run_test.ps1 script needs revamp to match run_test - svn r.1671128 2015-04-03: Proposed fix for store tests - 6551 1223789 [C++ broker]: linearstore raising JERR_LFCR_SEQNUMNOTFOUND after sending many DTX transactions - 1223795 svn r.1680861 2015-05-21: Proposed fix. - 1224300 - 6730 1261180 Make the journal flush timeout configurable in the C++ broker - svn r.1702130 2015-09-09: Proposed fix by Andrew Stitcher (astitcher) -NO-JIRA - Improve iostreams error reporting by printing out the value of errno - svn r.1702258 2015-09-10: Proposed fix - - -Ordered checkin list: -===================== -In order to port the linearstore changes from trunk to a branch, the following svn checkins need to be ported in order: - -no. svn r Q-JIRA RHBZ Date Alt Committer ---- ------- ------- -------- ---------- ------------- - 1. 1545563 5357 1052518 2013-11-26 0.22-mrg - 2. 1547601 5358 1052727 2013-12-03 0.22-mrg - 3. 1547641 5387 1036071 2013-12-03 0.22-mrg - 4. 1547921 5388 1035802 2013-12-04 0.22-mrg - 5. 1551304 NO-JIRA - 2013-12-16 0.22-mrg (aconway) - 6. 1551361 5425 1052445 2013-12-16 0.22-mrg - 7. 1552772 5442 1039949 2013-12-20 0.22-mrg - 8. 1553148 5444 1052775 2013-12-23 0.22-mrg - 9. 1556888 5362 - 2014-01-09 -10. 1556892 5460 1051097 2014-01-09 0.22-mrg -11. 1557620 5473 1051924 2014-01-12 0.22-mrg -12. 1558589 5483 - 2014-01-15 0.22-mrg -13. 1558592 5484 1035843 2014-01-15 0.22-mrg -14. 1558913 5487 1054448 2014-01-16 0.22-mrg -15. 1560530 5362 - 2014-01-22 -16. 1561848 5362 - 2014-01-27 -17. 1564808 5362 - 2014-02-05 -18. 1564877 5480 1053749 2014-02-05 0.22-mrg -19. 1564893 5361 - 2014-02-05 -20. 1564935 5361 - 2014-02-05 -21. 1574513 5603 1063700 2014-03-05 0.22-mrg -22. 1575009 5607 1064181 2014-03-06 0.22-mrg -23. 1578899 5362 - 2014-03-18 parts in 0.22-mrg -24. 1582730 5651 - 2014-03-28 0.22-mrg (pmoravec) -25. 1583778 5362 - 2014-04-01 -26. 1584379 5661 - 2014-04-03 -27. 1594215 5750 1078142 2014-05-13 0.22-mrg -28. 1596509 5767 1098118 2014-05-21 0.22-mrg (pmoravec) -29. 1596633 NO-JIRA 1078937 2014-05-21 (includes tools install update) -30. 1599243 5767 1098118 2014-06-02 0.22-mrg -31. 1599243 5767 1098118 2014-06-02 -32. 1614665 5924 1124906 2014-07-30 -33. 1620426 6043 1089652 2014-08-25 -34. 1631360 6147 1152012 2014-10-13 (pmoravec) -35. 1632504 6157 1150397 2014-10-17 (pmoravec) -36. 1636598 5671 1160367 2014-11-04 -37. 1637985 5671 1160367 2014-11-10 -38. 1643053 6230 1165200 2014-11-18 -39. 1640357 6232 1163650 2014-11-18 (pmoravec) -40. 1641689 6248 1167911 2014-11-25 -41. 1642731 NO_JIRA - 2014-12-01 -42. 1649081 5671 1160367 2015-01-02 -43. 1649082 NO-JIRA - 2015-01-02 -44. 1652486 6303 1180660 2015-01-16 -45. 1656771 6355 1188748 2015-02-03 -46. 1660430 6394 - 2015-02-17 -47. 1660702 6394 - 2015-02-18 -48. 1671128 6399 - 2015-04-03 (aconway) -49. 1680861 6551 1223789 2015-05-21 (pmoravec) - 1223795 - 1224300 -50. 1702130 6730 1261180 2015-09-09 (astitcher) -51. 1702258 NO-JIRA - 2015-09-10 -52. NO-JIRA - 2015-09-10 - -See above sections for details on these checkins. - -Future work: -============ -* One journal file lost when queue deleted. All files except for one are recycled back to the EFP. -* Complete exceptions - several exceptions thrown using jexception have no exception numbers -* Investigate ability of store to detect missing journal files, especially from logical end of a journal -* Investigate ability of store to handle file muddle-ups (ie journal files from EFP which are not zeroed or other journals) -* Look at improving the efficiency of recovery - right now the entire store is read once, and then each recovered record xid and data is read again - -Code tidy-up ------------- -* Remove old comments -* Use c++ cast templates instead of (xxx)y -* Member names: xxx_ -* Rename classes, functions and variables to camel-case -* Add Doxygen docs to classes -* Make fid's consistent in name (fid, file_id, pfid) and format (hex vs decimal) diff --git a/qpid/cpp/src/qpid/linearstore/IdDbt.cpp b/qpid/cpp/src/qpid/linearstore/IdDbt.cpp deleted file mode 100644 index d427085bbe..0000000000 --- a/qpid/cpp/src/qpid/linearstore/IdDbt.cpp +++ /dev/null @@ -1,42 +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/linearstore/IdDbt.h" - -using namespace qpid::linearstore; - -IdDbt::IdDbt() : id(0) -{ - init(); -} - -IdDbt::IdDbt(uint64_t _id) : id(_id) -{ - init(); -} - -void IdDbt::init() -{ - set_data(&id); - set_size(sizeof(uint64_t)); - set_ulen(sizeof(uint64_t)); - set_flags(DB_DBT_USERMEM); -} diff --git a/qpid/cpp/src/qpid/linearstore/IdDbt.h b/qpid/cpp/src/qpid/linearstore/IdDbt.h deleted file mode 100644 index c7264491ab..0000000000 --- a/qpid/cpp/src/qpid/linearstore/IdDbt.h +++ /dev/null @@ -1,42 +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. - * - */ - -#ifndef QPID_LINEARSTORE_IDDBT_H -#define QPID_LINEARSTORE_IDDBT_H - -#include "db-inc.h" - -namespace qpid{ -namespace linearstore{ - -class IdDbt : public Dbt -{ - void init(); -public: - uint64_t id; - - IdDbt(uint64_t id); - IdDbt(); -}; - -}} - -#endif // ifndef QPID_LINEARSTORE_IDDBT_H diff --git a/qpid/cpp/src/qpid/linearstore/IdSequence.cpp b/qpid/cpp/src/qpid/linearstore/IdSequence.cpp deleted file mode 100644 index 4d3172ffe9..0000000000 --- a/qpid/cpp/src/qpid/linearstore/IdSequence.cpp +++ /dev/null @@ -1,40 +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/linearstore/IdSequence.h" - -using namespace qpid::linearstore; -using qpid::sys::Mutex; - -IdSequence::IdSequence() : id(1) {} - -uint64_t IdSequence::next() -{ - Mutex::ScopedLock guard(lock); - if (!id) id++; // avoid 0 when folding around - return id++; -} - -void IdSequence::reset(uint64_t value) -{ - //deliberately not threadsafe, used only on recovery - id = value; -} diff --git a/qpid/cpp/src/qpid/linearstore/IdSequence.h b/qpid/cpp/src/qpid/linearstore/IdSequence.h deleted file mode 100644 index 17996eec52..0000000000 --- a/qpid/cpp/src/qpid/linearstore/IdSequence.h +++ /dev/null @@ -1,43 +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. - * - */ - -#ifndef QPID_LINEARSTORE_IDSEQUENCE_H -#define QPID_LINEARSTORE_IDSEQUENCE_H - -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Mutex.h" - -namespace qpid{ -namespace linearstore{ - -class IdSequence -{ - qpid::sys::Mutex lock; - uint64_t id; -public: - IdSequence(); - uint64_t next(); - void reset(uint64_t value); -}; - -}} - -#endif // ifndef QPID_LINEARSTORE_IDSEQUENCE_H diff --git a/qpid/cpp/src/qpid/linearstore/JournalImpl.cpp b/qpid/cpp/src/qpid/linearstore/JournalImpl.cpp deleted file mode 100644 index b2d41275a0..0000000000 --- a/qpid/cpp/src/qpid/linearstore/JournalImpl.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/linearstore/JournalImpl.h" - -#include "qpid/linearstore/DataTokenImpl.h" -#include "qpid/linearstore/JournalLogImpl.h" -#include "qpid/linearstore/journal/jexception.h" -#include "qpid/linearstore/StoreException.h" -#include "qpid/management/ManagementAgent.h" - -namespace qpid { -namespace linearstore { - -InactivityFireEvent::InactivityFireEvent(JournalImpl* p, - const ::qpid::sys::Duration timeout): - ::qpid::sys::TimerTask(timeout, "JournalInactive:"+p->id()), _parent(p) {} - -void InactivityFireEvent::fire() { - ::qpid::sys::Mutex::ScopedLock sl(_ife_lock); - if (_parent) { - _parent->flushFire(); - } -} - -GetEventsFireEvent::GetEventsFireEvent(JournalImpl* p, - const ::qpid::sys::Duration timeout): - ::qpid::sys::TimerTask(timeout, "JournalGetEvents:"+p->id()), _parent(p) -{} - -void GetEventsFireEvent::fire() { - ::qpid::sys::Mutex::ScopedLock sl(_gefe_lock); - if (_parent) { - _parent->getEventsFire(); - } -} - -JournalImpl::JournalImpl(::qpid::sys::Timer& timer_, - const std::string& journalId, - const std::string& journalDirectory, - JournalLogImpl& journalLogRef, - const ::qpid::sys::Duration getEventsTimeout, - const ::qpid::sys::Duration flushTimeout, - ::qpid::management::ManagementAgent* a, - DeleteCallback onDelete): - jcntl(journalId, journalDirectory, journalLogRef), - timer(timer_), - _journalLogRef(journalLogRef), - getEventsTimerSetFlag(false), - writeActivityFlag(false), - flushTriggeredFlag(true), - deleteCallback(onDelete) -{ - getEventsFireEventsPtr = new GetEventsFireEvent(this, getEventsTimeout); - inactivityFireEventPtr = new InactivityFireEvent(this, flushTimeout); - { - timer.start(); - timer.add(inactivityFireEventPtr); - } - - initManagement(a); - - QLS_LOG2(info, _jid, "Created"); - std::ostringstream oss; - oss << "Journal directory = \"" << journalDirectory << "\""; - QLS_LOG2(debug, _jid, oss.str()); -} - -JournalImpl::~JournalImpl() -{ - if (deleteCallback) deleteCallback(*this); - if (_init_flag && !_stop_flag){ - try { stop(true); } // NOTE: This will *block* until all outstanding disk aio calls are complete! - catch (const ::qpid::linearstore::journal::jexception& e) { QLS_LOG2(error, _jid, e.what()); } - } - getEventsFireEventsPtr->cancel(); - inactivityFireEventPtr->cancel(); - - if (_mgmtObject.get() != 0) { - _mgmtObject->resourceDestroy(); - _mgmtObject.reset(); - } - - QLS_LOG2(info, _jid, "Destroyed"); -} - -void -JournalImpl::initManagement(::qpid::management::ManagementAgent* a) -{ - _agent = a; - if (_agent != 0) - { - _mgmtObject = ::qmf::org::apache::qpid::linearstore::Journal::shared_ptr ( - new ::qmf::org::apache::qpid::linearstore::Journal(_agent, this, _jid)); - - _mgmtObject->set_directory(_jdir.dirname()); -// _mgmtObject->set_baseFileName(_base_filename); -// _mgmtObject->set_readPageSize(JRNL_RMGR_PAGE_SIZE * JRNL_SBLK_SIZE); -// _mgmtObject->set_readPages(JRNL_RMGR_PAGES); - - // The following will be set on initialize(), but being properties, these must be set to 0 in the meantime - //_mgmtObject->set_initialFileCount(0); - //_mgmtObject->set_dataFileSize(0); - //_mgmtObject->set_currentFileCount(0); - _mgmtObject->set_writePageSize(0); - _mgmtObject->set_writePages(0); - - _agent->addObject(_mgmtObject, 0, true); - } -} - - -void -JournalImpl::initialize(::qpid::linearstore::journal::EmptyFilePool* efpp_, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - ::qpid::linearstore::journal::aio_callback* const cbp) -{ -// efpp->createJournal(_jdir); -// QLS_LOG2(info, _jid, "Initialized"); -// std::ostringstream oss; -//// oss << "Initialize; num_jfiles=" << num_jfiles << " jfsize_sblks=" << jfsize_sblks; -// oss << "Initialize; efpPartitionNumber=" << efpp_->getPartitionNumber(); -// oss << " efpFileSizeKb=" << efpp_->fileSizeKib(); -// oss << " wcache_pgsize_sblks=" << wcache_pgsize_sblks; -// oss << " wcache_num_pages=" << wcache_num_pages; -// QLS_LOG2(debug, _jid, oss.str()); - jcntl::initialize(efpp_, wcache_num_pages, wcache_pgsize_sblks, cbp); -// QLS_LOG2(debug, _jid, "Initialization complete"); - // TODO: replace for linearstore: _lpmgr -/* - if (_mgmtObject.get() != 0) - { - _mgmtObject->set_initialFileCount(_lpmgr.num_jfiles()); - _mgmtObject->set_autoExpand(_lpmgr.is_ae()); - _mgmtObject->set_currentFileCount(_lpmgr.num_jfiles()); - _mgmtObject->set_maxFileCount(_lpmgr.ae_max_jfiles()); - _mgmtObject->set_dataFileSize(_jfsize_sblks * JRNL_SBLK_SIZE); - _mgmtObject->set_writePageSize(wcache_pgsize_sblks * JRNL_SBLK_SIZE); - _mgmtObject->set_writePages(wcache_num_pages); - } - if (_agent != 0) - _agent->raiseEvent::(qmf::org::apache::qpid::linearstore::EventCreated(_jid, _jfsize_sblks * JRNL_SBLK_SIZE, _lpmgr.num_jfiles()), - qpid::management::ManagementAgent::SEV_NOTE); -*/ -} - -void -JournalImpl::recover(boost::shared_ptr< ::qpid::linearstore::journal::EmptyFilePoolManager> efpm, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - ::qpid::linearstore::journal::aio_callback* const cbp, - boost::ptr_list* prep_tx_list_ptr, - uint64_t& highest_rid, - uint64_t queue_id) -{ - std::ostringstream oss1; - oss1 << "Recover;"; - oss1 << " queue_id = 0x" << std::hex << queue_id << std::dec; - oss1 << " wcache_pgsize_sblks=" << wcache_pgsize_sblks; - oss1 << " wcache_num_pages=" << wcache_num_pages; - QLS_LOG2(debug, _jid, oss1.str()); - // TODO: replace for linearstore: _lpmgr -/* - if (_mgmtObject.get() != 0) - { - _mgmtObject->set_initialFileCount(_lpmgr.num_jfiles()); - _mgmtObject->set_autoExpand(_lpmgr.is_ae()); - _mgmtObject->set_currentFileCount(_lpmgr.num_jfiles()); - _mgmtObject->set_maxFileCount(_lpmgr.ae_max_jfiles()); - _mgmtObject->set_dataFileSize(_jfsize_sblks * JRNL_SBLK_SIZE); - _mgmtObject->set_writePageSize(wcache_pgsize_sblks * JRNL_SBLK_SIZE); - _mgmtObject->set_writePages(wcache_num_pages); - } -*/ - - // TODO: This is ugly, find a way for RecoveryManager to use boost::ptr_list* directly - if (prep_tx_list_ptr) { - // Create list of prepared xids - std::vector prep_xid_list; - for (PreparedTransaction::list::iterator i = prep_tx_list_ptr->begin(); i != prep_tx_list_ptr->end(); i++) { - prep_xid_list.push_back(i->xid); - } - - jcntl::recover(efpm.get(), wcache_num_pages, wcache_pgsize_sblks, cbp, &prep_xid_list, highest_rid); - } else { - jcntl::recover(efpm.get(), wcache_num_pages, wcache_pgsize_sblks, cbp, 0, highest_rid); - } - - // Populate PreparedTransaction lists from _tmap - if (prep_tx_list_ptr) - { - for (PreparedTransaction::list::iterator i = prep_tx_list_ptr->begin(); i != prep_tx_list_ptr->end(); i++) { - ::qpid::linearstore::journal::txn_data_list_t tdl = _tmap.get_tdata_list(i->xid); // tdl will be empty if xid not found - for (::qpid::linearstore::journal::tdl_itr_t tdl_itr = tdl.begin(); tdl_itr < tdl.end(); tdl_itr++) { - if (tdl_itr->enq_flag_) { // enqueue op - i->enqueues->add(queue_id, tdl_itr->rid_); - } else { // dequeue op - i->dequeues->add(queue_id, tdl_itr->drid_); - } - } - } - } - std::ostringstream oss2; - oss2 << "Recover phase 1 complete; highest rid found = 0x" << std::hex << highest_rid; - oss2 << std::dec << "; emap.size=" << _emap.size() << "; tmap.size=" << _tmap.size(); - oss2 << "; journal now read-only."; - QLS_LOG2(debug, _jid, oss2.str()); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->inc_recordDepth(_emap.size()); - _mgmtObject->inc_enqueues(_emap.size()); - _mgmtObject->inc_txn(_tmap.size()); - _mgmtObject->inc_txnEnqueues(_tmap.enq_cnt()); - _mgmtObject->inc_txnDequeues(_tmap.deq_cnt()); - } -} - -void -JournalImpl::recover_complete() -{ - jcntl::recover_complete(); - QLS_LOG2(debug, _jid, "Recover phase 2 complete; journal now writable."); - // TODO: replace for linearstore: _lpmgr -/* - if (_agent != 0) - _agent->raiseEvent(qmf::org::apache::qpid::linearstore::EventRecovered(_jid, _jfsize_sblks * JRNL_SBLK_SIZE, _lpmgr.num_jfiles(), - _emap.size(), _tmap.size(), _tmap.enq_cnt(), _tmap.deq_cnt()), qpid::management::ManagementAgent::SEV_NOTE); -*/ -} - - -void -JournalImpl::enqueue_data_record(const void* const data_buff, - const size_t tot_data_len, - const size_t this_data_len, - ::qpid::linearstore::journal::data_tok* dtokp, - const bool transient) -{ - handleIoResult(jcntl::enqueue_data_record(data_buff, tot_data_len, this_data_len, dtokp, transient)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->inc_enqueues(); - _mgmtObject->inc_recordDepth(); - } -} - -void -JournalImpl::enqueue_extern_data_record(const size_t tot_data_len, - ::qpid::linearstore::journal::data_tok* dtokp, - const bool transient) -{ - handleIoResult(jcntl::enqueue_extern_data_record(tot_data_len, dtokp, transient)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->inc_enqueues(); - _mgmtObject->inc_recordDepth(); - } -} - -void -JournalImpl::enqueue_txn_data_record(const void* const data_buff, - const size_t tot_data_len, - const size_t this_data_len, - ::qpid::linearstore::journal::data_tok* dtokp, - const std::string& xid, - const bool tpc_flag, - const bool transient) -{ - bool txn_incr = _mgmtObject.get() != 0 ? _tmap.in_map(xid) : false; - - handleIoResult(jcntl::enqueue_txn_data_record(data_buff, tot_data_len, this_data_len, dtokp, xid, tpc_flag, transient)); - - if (_mgmtObject.get() != 0) - { - if (!txn_incr) // If this xid was not in _tmap, it will be now... - _mgmtObject->inc_txn(); - _mgmtObject->inc_enqueues(); - _mgmtObject->inc_txnEnqueues(); - _mgmtObject->inc_recordDepth(); - } -} - -void -JournalImpl::enqueue_extern_txn_data_record(const size_t tot_data_len, - ::qpid::linearstore::journal::data_tok* dtokp, - const std::string& xid, - const bool tpc_flag, - const bool transient) -{ - bool txn_incr = _mgmtObject.get() != 0 ? _tmap.in_map(xid) : false; - - handleIoResult(jcntl::enqueue_extern_txn_data_record(tot_data_len, dtokp, xid, tpc_flag, transient)); - - if (_mgmtObject.get() != 0) - { - if (!txn_incr) // If this xid was not in _tmap, it will be now... - _mgmtObject->inc_txn(); - _mgmtObject->inc_enqueues(); - _mgmtObject->inc_txnEnqueues(); - _mgmtObject->inc_recordDepth(); - } -} - -void -JournalImpl::dequeue_data_record(::qpid::linearstore::journal::data_tok* const dtokp, - const bool txn_coml_commit) -{ - handleIoResult(jcntl::dequeue_data_record(dtokp, txn_coml_commit)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->inc_dequeues(); - _mgmtObject->inc_txnDequeues(); - _mgmtObject->dec_recordDepth(); - } -} - -void -JournalImpl::dequeue_txn_data_record(::qpid::linearstore::journal::data_tok* const dtokp, - const std::string& xid, - const bool tpc_flag, - const bool txn_coml_commit) -{ - bool txn_incr = _mgmtObject.get() != 0 ? _tmap.in_map(xid) : false; - - handleIoResult(jcntl::dequeue_txn_data_record(dtokp, xid, tpc_flag, txn_coml_commit)); - - if (_mgmtObject.get() != 0) - { - if (!txn_incr) // If this xid was not in _tmap, it will be now... - _mgmtObject->inc_txn(); - _mgmtObject->inc_dequeues(); - _mgmtObject->inc_txnDequeues(); - _mgmtObject->dec_recordDepth(); - } -} - -void -JournalImpl::txn_abort(::qpid::linearstore::journal::data_tok* const dtokp, - const std::string& xid) -{ - handleIoResult(jcntl::txn_abort(dtokp, xid)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->dec_txn(); - _mgmtObject->inc_txnAborts(); - } -} - -void -JournalImpl::txn_commit(::qpid::linearstore::journal::data_tok* const dtokp, - const std::string& xid) -{ - handleIoResult(jcntl::txn_commit(dtokp, xid)); - - if (_mgmtObject.get() != 0) - { - _mgmtObject->dec_txn(); - _mgmtObject->inc_txnCommits(); - } -} - -void -JournalImpl::stop(bool block_till_aio_cmpl) -{ - InactivityFireEvent* ifep = dynamic_cast(inactivityFireEventPtr.get()); - assert(ifep); // dynamic_cast can return null if the cast fails - ifep->cancel(); - jcntl::stop(block_till_aio_cmpl); - - if (_mgmtObject.get() != 0) { - _mgmtObject->resourceDestroy(); - _mgmtObject.reset(); - } -} - -::qpid::linearstore::journal::iores -JournalImpl::flush(const bool block_till_aio_cmpl) -{ - const ::qpid::linearstore::journal::iores res = jcntl::flush(block_till_aio_cmpl); - { - ::qpid::sys::Mutex::ScopedLock sl(_getf_lock); - if (_wmgr.get_aio_evt_rem() && !getEventsTimerSetFlag) { setGetEventTimer(); } - } - return res; -} - -void -JournalImpl::getEventsFire() -{ - ::qpid::sys::Mutex::ScopedLock sl(_getf_lock); - getEventsTimerSetFlag = false; - if (_wmgr.get_aio_evt_rem()) { jcntl::get_wr_events(0); } - if (_wmgr.get_aio_evt_rem()) { setGetEventTimer(); } -} - -void -JournalImpl::flushFire() -{ - if (writeActivityFlag) { - writeActivityFlag = false; - flushTriggeredFlag = false; - } else { - if (!flushTriggeredFlag) { - flush(false); - flushTriggeredFlag = true; - } - } - inactivityFireEventPtr->setupNextFire(); - { - timer.add(inactivityFireEventPtr); - } -} - -void -JournalImpl::wr_aio_cb(std::vector< ::qpid::linearstore::journal::data_tok*>& dtokl) -{ - for (std::vector< ::qpid::linearstore::journal::data_tok*>::const_iterator i=dtokl.begin(); i!=dtokl.end(); i++) - { - DataTokenImpl* dtokp = static_cast(*i); - if (/*!is_stopped() &&*/ dtokp->getSourceMessage()) - { - switch (dtokp->wstate()) - { - case ::qpid::linearstore::journal::data_tok::ENQ: -//std::cout << "<<<>>> JournalImpl::wr_aio_cb() ENQ dtokp rid=0x" << std::hex << dtokp->rid() << std::dec << std::endl << std::flush; // DEBUG - dtokp->getSourceMessage()->enqueueComplete(); - break; - case ::qpid::linearstore::journal::data_tok::DEQ: -//std::cout << "<<<>>> JournalImpl::wr_aio_cb() DEQ dtokp rid=0x" << std::hex << dtokp->rid() << std::dec << std::endl << std::flush; // DEBUG -/* Don't need to signal until we have a way to ack completion of dequeue in AMQP - dtokp->getSourceMessage()->dequeueComplete(); - if ( dtokp->getSourceMessage()->isDequeueComplete() ) // clear id after last dequeue - dtokp->getSourceMessage()->setPersistenceId(0); -*/ - break; - default: ; - } - } - dtokp->release(); - } -} - -void -JournalImpl::rd_aio_cb(std::vector& /*pil*/) -{} - -void -JournalImpl::createStore() { - -} - -void -JournalImpl::handleIoResult(const ::qpid::linearstore::journal::iores r) -{ - writeActivityFlag = true; - switch (r) - { - case ::qpid::linearstore::journal::RHM_IORES_SUCCESS: - return; - default: - { - std::ostringstream oss; - oss << "Unexpected I/O response (" << ::qpid::linearstore::journal::iores_str(r) << ")."; - QLS_LOG2(error, _jid, oss.str()); - THROW_STORE_FULL_EXCEPTION(oss.str()); - } - } -} - -::qpid::management::Manageable::status_t JournalImpl::ManagementMethod (uint32_t /*methodId*/, - ::qpid::management::Args& /*args*/, - std::string& /*text*/) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - -/* - switch (methodId) - { - case _qmf::Journal::METHOD_EXPAND : - //_qmf::ArgsJournalExpand& eArgs = (_qmf::ArgsJournalExpand&) args; - - // Implement "expand" using eArgs.i_by (expand-by argument) - - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } -*/ - - return status; -} - -}} diff --git a/qpid/cpp/src/qpid/linearstore/JournalImpl.h b/qpid/cpp/src/qpid/linearstore/JournalImpl.h deleted file mode 100644 index 667579253e..0000000000 --- a/qpid/cpp/src/qpid/linearstore/JournalImpl.h +++ /dev/null @@ -1,252 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNALIMPL_H -#define QPID_LINEARSTORE_JOURNALIMPL_H - -#include -#include "qpid/broker/PersistableQueue.h" -#include "qpid/linearstore/journal/aio_callback.h" -#include "qpid/linearstore/journal/jcntl.h" -#include "qpid/linearstore/PreparedTransaction.h" -#include "qpid/sys/Timer.h" - -#include "qmf/org/apache/qpid/linearstore/Journal.h" - -namespace qpid{ - -namespace sys { -//class Timer; -} - -namespace linearstore{ -namespace journal { -// class EmptyFilePool; -} -class JournalImpl; -class JournalLogImpl; - -class InactivityFireEvent : public ::qpid::sys::TimerTask -{ - JournalImpl* _parent; - ::qpid::sys::Mutex _ife_lock; - - public: - InactivityFireEvent(JournalImpl* p, - const ::qpid::sys::Duration timeout); - virtual ~InactivityFireEvent() {} - void fire(); - inline void cancel() { ::qpid::sys::Mutex::ScopedLock sl(_ife_lock); _parent = 0; } -}; - -class GetEventsFireEvent : public ::qpid::sys::TimerTask -{ - JournalImpl* _parent; - ::qpid::sys::Mutex _gefe_lock; - - public: - GetEventsFireEvent(JournalImpl* p, - const ::qpid::sys::Duration timeout); - virtual ~GetEventsFireEvent() {} - void fire(); - inline void cancel() { ::qpid::sys::Mutex::ScopedLock sl(_gefe_lock); _parent = 0; } -}; - -class JournalImpl : public ::qpid::broker::ExternalQueueStore, - public ::qpid::linearstore::journal::jcntl, - public ::qpid::linearstore::journal::aio_callback -{ - public: - typedef boost::function DeleteCallback; - - protected: - ::qpid::sys::Timer& timer; - JournalLogImpl& _journalLogRef; - bool getEventsTimerSetFlag; - boost::intrusive_ptr< ::qpid::sys::TimerTask> getEventsFireEventsPtr; - ::qpid::sys::Mutex _getf_lock; - ::qpid::sys::Mutex _read_lock; - - bool writeActivityFlag; - bool flushTriggeredFlag; - boost::intrusive_ptr< ::qpid::sys::TimerTask> inactivityFireEventPtr; - - ::qpid::management::ManagementAgent* _agent; - ::qmf::org::apache::qpid::linearstore::Journal::shared_ptr _mgmtObject; - DeleteCallback deleteCallback; - - public: - - JournalImpl(::qpid::sys::Timer& timer, - const std::string& journalId, - const std::string& journalDirectory, - JournalLogImpl& journalLogRef, - const ::qpid::sys::Duration getEventsTimeout, - const ::qpid::sys::Duration flushTimeout, - ::qpid::management::ManagementAgent* agent, - DeleteCallback deleteCallback=DeleteCallback() ); - - virtual ~JournalImpl(); - - void initManagement(::qpid::management::ManagementAgent* agent); - - void initialize(::qpid::linearstore::journal::EmptyFilePool* efp, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - ::qpid::linearstore::journal::aio_callback* const cbp); - - inline void initialize(::qpid::linearstore::journal::EmptyFilePool* efpp, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks) { - initialize(efpp, wcache_num_pages, wcache_pgsize_sblks, this); - } - - void recover(boost::shared_ptr< ::qpid::linearstore::journal::EmptyFilePoolManager> efpm, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - ::qpid::linearstore::journal::aio_callback* const cbp, - boost::ptr_list* prep_tx_list_ptr, - uint64_t& highest_rid, - uint64_t queue_id); - - inline void recover(boost::shared_ptr< ::qpid::linearstore::journal::EmptyFilePoolManager> efpm, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - boost::ptr_list* prep_tx_list_ptr, - uint64_t& highest_rid, - uint64_t queue_id) { - recover(efpm, wcache_num_pages, wcache_pgsize_sblks, this, prep_tx_list_ptr, highest_rid, queue_id); - } - - void recover_complete(); - - // Overrides for write inactivity timer - void enqueue_data_record(const void* const data_buff, - const size_t tot_data_len, - const size_t this_data_len, - ::qpid::linearstore::journal::data_tok* dtokp, - const bool transient); - - void enqueue_extern_data_record(const size_t tot_data_len, - ::qpid::linearstore::journal::data_tok* dtokp, - const bool transient); - - void enqueue_txn_data_record(const void* const data_buff, - const size_t tot_data_len, - const size_t this_data_len, - ::qpid::linearstore::journal::data_tok* dtokp, - const std::string& xid, - const bool tpc_flag, - const bool transient); - - void enqueue_extern_txn_data_record(const size_t tot_data_len, - ::qpid::linearstore::journal::data_tok* dtokp, - const std::string& xid, - const bool tpc_flag, - const bool transient); - - void dequeue_data_record(::qpid::linearstore::journal::data_tok* - const dtokp, - const bool txn_coml_commit); - - void dequeue_txn_data_record(::qpid::linearstore::journal::data_tok* const dtokp, - const std::string& xid, - const bool tpc_flag, - const bool txn_coml_commit); - - void txn_abort(::qpid::linearstore::journal::data_tok* const dtokp, const std::string& xid); - - void txn_commit(::qpid::linearstore::journal::data_tok* const dtokp, const std::string& xid); - - void stop(bool block_till_aio_cmpl = false); - - // Overrides for get_events timer - ::qpid::linearstore::journal::iores flush(const bool block_till_aio_cmpl); - - // TimerTask callback - void getEventsFire(); - void flushFire(); - - // AIO callbacks - virtual void wr_aio_cb(std::vector< ::qpid::linearstore::journal::data_tok*>& dtokl); - virtual void rd_aio_cb(std::vector& pil); - - ::qpid::management::ManagementObject::shared_ptr GetManagementObject (void) const - { return _mgmtObject; } - - ::qpid::management::Manageable::status_t ManagementMethod(uint32_t, - ::qpid::management::Args&, - std::string&); - - void resetDeleteCallback() { deleteCallback = DeleteCallback(); } - - protected: - void createStore(); - - inline void setGetEventTimer() - { - getEventsFireEventsPtr->setupNextFire(); - timer.add(getEventsFireEventsPtr); - getEventsTimerSetFlag = true; - } - void handleIoResult(const ::qpid::linearstore::journal::iores r); - - // Management instrumentation callbacks overridden from jcntl - inline void instr_incr_outstanding_aio_cnt() { - if (_mgmtObject.get() != 0) _mgmtObject->inc_outstandingAIOs(); - } - inline void instr_decr_outstanding_aio_cnt() { - if (_mgmtObject.get() != 0) _mgmtObject->dec_outstandingAIOs(); - } - -}; // class JournalImpl - -class TplJournalImpl : public JournalImpl -{ - public: - TplJournalImpl(::qpid::sys::Timer& timer, - const std::string& journalId, - const std::string& journalDirectory, - JournalLogImpl& journalLogRef, - const ::qpid::sys::Duration getEventsTimeout, - const ::qpid::sys::Duration flushTimeout, - ::qpid::management::ManagementAgent* agent) : - JournalImpl(timer, journalId, journalDirectory, journalLogRef, getEventsTimeout, flushTimeout, agent) - {} - - virtual ~TplJournalImpl() {} - - // Special version of read_data_record that ignores transactions - needed when reading the TPL - inline ::qpid::linearstore::journal::iores read_data_record(void** const datapp, - std::size_t& dsize, - void** const xidpp, - std::size_t& xidsize, - bool& transient, - bool& external, - ::qpid::linearstore::journal::data_tok* const dtokp) { - return JournalImpl::read_data_record(datapp, dsize, xidpp, xidsize, transient, external, dtokp, false); - } -}; // class TplJournalImpl - -} // namespace msgstore -} // namespace mrg - -#endif // ifndef QPID_LINEARSTORE_JOURNALIMPL_H diff --git a/qpid/cpp/src/qpid/linearstore/JournalLogImpl.cpp b/qpid/cpp/src/qpid/linearstore/JournalLogImpl.cpp deleted file mode 100644 index c3e631a6ca..0000000000 --- a/qpid/cpp/src/qpid/linearstore/JournalLogImpl.cpp +++ /dev/null @@ -1,61 +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/linearstore/JournalLogImpl.h" - -#include "qpid/log/Statement.h" - -namespace qpid { -namespace linearstore { - -JournalLogImpl::JournalLogImpl(const qpid::linearstore::journal::JournalLog::log_level_t logLevelThreshold) : qpid::linearstore::journal::JournalLog(logLevelThreshold) {} -JournalLogImpl::~JournalLogImpl() {} - -void -JournalLogImpl::log(const qpid::linearstore::journal::JournalLog::log_level_t level, - const std::string& log_stmt) const { - switch (level) { - case LOG_CRITICAL: QPID_LOG(critical, "Linear Store: " << log_stmt); break; - case LOG_ERROR: QPID_LOG(error, "Linear Store: " << log_stmt); break; - case LOG_WARN: QPID_LOG(warning, "Linear Store: " << log_stmt); break; - case LOG_NOTICE: QPID_LOG(notice, "Linear Store: " << log_stmt); break; - case LOG_INFO: QPID_LOG(info, "Linear Store: " << log_stmt); break; - case LOG_DEBUG: QPID_LOG(debug, "Linear Store: " << log_stmt); break; - default: QPID_LOG(trace, "Linear Store: " << log_stmt); - } -} - -void -JournalLogImpl::log(const qpid::linearstore::journal::JournalLog::log_level_t level, - const std::string& jid, - const std::string& log_stmt) const { - switch (level) { - case LOG_CRITICAL: QPID_LOG(critical, "Linear Store: Journal \"" << jid << "\": " << log_stmt); break; - case LOG_ERROR: QPID_LOG(error, "Linear Store: Journal \"" << jid << "\": " << log_stmt); break; - case LOG_WARN: QPID_LOG(warning, "Linear Store: Journal \"" << jid << "\": " << log_stmt); break; - case LOG_NOTICE: QPID_LOG(notice, "Linear Store: Journal \"" << jid << "\": " << log_stmt); break; - case LOG_INFO: QPID_LOG(info, "Linear Store: Journal \"" << jid << "\": " << log_stmt); break; - case LOG_DEBUG: QPID_LOG(debug, "Linear Store: Journal \"" << jid << "\": " << log_stmt); break; - default: QPID_LOG(trace, "Linear Store: Journal \"" << jid << "\": " << log_stmt); - } -} - -}} // namespace qpid::linearstore diff --git a/qpid/cpp/src/qpid/linearstore/JournalLogImpl.h b/qpid/cpp/src/qpid/linearstore/JournalLogImpl.h deleted file mode 100644 index 846eaac124..0000000000 --- a/qpid/cpp/src/qpid/linearstore/JournalLogImpl.h +++ /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. - * - */ - -#ifndef QPID_LINEARSTORE_LOG_H -#define QPID_LINEARSTORE_LOG_H - -#include "qpid/linearstore/journal/JournalLog.h" - -#define QLS_LOG(level, msg) QPID_LOG(level, "Linear Store: " << msg) -#define QLS_LOG2(level, queue, msg) QPID_LOG(level, "Linear Store: Journal \"" << queue << "\":" << msg) - -namespace qpid { -namespace linearstore { - -class JournalLogImpl : public qpid::linearstore::journal::JournalLog -{ -public: - JournalLogImpl(const qpid::linearstore::journal::JournalLog::log_level_t logLevelThreshold); - virtual ~JournalLogImpl(); - virtual void log(const qpid::linearstore::journal::JournalLog::log_level_t logLevel, - const std::string& logStatement) const; - virtual void log(const qpid::linearstore::journal::JournalLog::log_level_t logLevel, - const std::string& journalId, - const std::string& logStatement) const; -}; - -}} // namespace qpid::linearstore - -#endif // QPID_LINEARSTORE_LOG_H diff --git a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp b/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp deleted file mode 100644 index 68c49e4d90..0000000000 --- a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp +++ /dev/null @@ -1,1562 +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/linearstore/MessageStoreImpl.h" - -#include "qpid/broker/Broker.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/linearstore/BindingDbt.h" -#include "qpid/linearstore/BufferValue.h" -#include "qpid/linearstore/Cursor.h" -#include "qpid/linearstore/DataTokenImpl.h" -#include "qpid/linearstore/IdDbt.h" -#include "qpid/linearstore/JournalImpl.h" -#include "qpid/linearstore/journal/EmptyFilePoolManager.h" -#include "qpid/linearstore/StoreException.h" -#include "qpid/linearstore/TxnCtxt.h" -#include "qpid/log/Statement.h" - -#include "qmf/org/apache/qpid/linearstore/Package.h" - -#define MAX_AIO_SLEEPS 100000 // tot: ~1 sec -#define AIO_SLEEP_TIME_US 10 // 0.01 ms - -//namespace _qmf = qmf::org::apache::qpid::linearstore; - -namespace qpid{ -namespace linearstore{ - -const std::string MessageStoreImpl::storeTopLevelDir("qls"); // Sets the top-level store dir name - -qpid::sys::Mutex TxnCtxt::globalSerialiser; - -MessageStoreImpl::MessageStoreImpl(qpid::broker::Broker* broker_, const char* envpath_) : - defaultEfpPartitionNumber(0), - defaultEfpFileSize_kib(0), - overwriteBeforeReturnFlag(false), - wCachePgSizeSblks(0), - wCacheNumPages(0), - tplWCachePgSizeSblks(0), - tplWCacheNumPages(0), - highestRid(0), - journalFlushTimeout(defJournalFlushTimeoutNs), - isInit(false), - envPath(envpath_), - broker(broker_), - jrnlLog(qpid::linearstore::journal::JournalLog::LOG_NOTICE), - mgmtObject(), - agent(0) -{ - // Test of values for QLS_RAND_SHIFT1, QLS_RAND_SHIFT2 and QLS_RAND_MASK - if((((uint64_t)RAND_MAX << QLS_RAND_SHIFT1) ^ ((uint64_t)RAND_MAX << QLS_RAND_SHIFT2) ^ (RAND_MAX & QLS_RAND_MASK)) != 0xffffffffffffffffULL) { - THROW_STORE_EXCEPTION("[linearstore] 64-bit random number generation alignment error"); - } - ::srand(::time(NULL)); -} - -uint32_t MessageStoreImpl::chkJrnlWrPageCacheSize(const uint32_t param_, const std::string& paramName_) -{ - uint32_t p = param_; - - if (p == 0) { - // For zero value, use default - p = QLS_WMGR_DEF_PAGE_SIZE_KIB; - QLS_LOG(warning, "parameter " << paramName_ << " (" << param_ << ") must be a power of 2 between 1 and 128; changing this parameter to default value (" << p << ")"); - } else if ( p > 128 || (p & (p-1)) ) { - // For any positive value that is not a power of 2, use closest value - if (p < 6) p = 4; - else if (p < 12) p = 8; - else if (p < 24) p = 16; - else if (p < 48) p = 32; - else if (p < 96) p = 64; - else p = 128; - QLS_LOG(warning, "parameter " << paramName_ << " (" << param_ << ") must be a power of 2 between 1 and 128; changing this parameter to closest allowable value (" << p << ")"); - } - return p; -} - -uint16_t MessageStoreImpl::getJrnlWrNumPages(const uint32_t wrPageSizeKib_) -{ - uint32_t wrPageSizeSblks = wrPageSizeKib_ / QLS_SBLK_SIZE_KIB; // convert from KiB to number sblks - uint32_t defTotWCacheSizeSblks = QLS_WMGR_DEF_PAGE_SIZE_SBLKS * QLS_WMGR_DEF_PAGES; - switch (wrPageSizeKib_) - { - case 1: - case 2: - case 4: - // 256 KiB total cache - return defTotWCacheSizeSblks / wrPageSizeSblks / 4; - case 8: - case 16: - // 512 KiB total cache - return defTotWCacheSizeSblks / wrPageSizeSblks / 2; - default: // 32, 64, 128 - // 1 MiB total cache - return defTotWCacheSizeSblks / wrPageSizeSblks; - } -} - -qpid::linearstore::journal::efpPartitionNumber_t MessageStoreImpl::chkEfpPartition(const qpid::linearstore::journal::efpPartitionNumber_t partition_, - const std::string& /*paramName_*/) { - // TODO: check against list of existing partitions, throw if not found - return partition_; -} - -qpid::linearstore::journal::efpDataSize_kib_t MessageStoreImpl::chkEfpFileSizeKiB(const qpid::linearstore::journal::efpDataSize_kib_t efpFileSizeKib_, - const std::string& paramName_) { - uint8_t rem = efpFileSizeKib_ % uint64_t(QLS_SBLK_SIZE_KIB); - if (rem != 0) { - uint64_t newVal = efpFileSizeKib_ - rem; - if (rem >= (QLS_SBLK_SIZE_KIB / 2)) - newVal += QLS_SBLK_SIZE_KIB; - QLS_LOG(warning, "Parameter " << paramName_ << " (" << efpFileSizeKib_ << ") must be a multiple of " << - QLS_SBLK_SIZE_KIB << "; changing this parameter to the closest allowable value (" << - newVal << ")"); - return newVal; - } - return efpFileSizeKib_; - - // TODO: check against list of existing pools in the given partition -} - -void MessageStoreImpl::initManagement () -{ - if (broker != 0) { - agent = broker->getManagementAgent(); - if (agent != 0) { - qmf::org::apache::qpid::linearstore::Package packageInitializer(agent); - mgmtObject = qmf::org::apache::qpid::linearstore::Store::shared_ptr ( - new qmf::org::apache::qpid::linearstore::Store(agent, this, broker)); - - mgmtObject->set_storeDir(storeDir); - mgmtObject->set_tplIsInitialized(false); - mgmtObject->set_tplDirectory(getTplBaseDir()); - mgmtObject->set_tplWritePageSize(tplWCachePgSizeSblks * QLS_SBLK_SIZE_BYTES); - mgmtObject->set_tplWritePages(tplWCacheNumPages); - - agent->addObject(mgmtObject, 0, true); - - // Initialize all existing queues (ie those recovered before management was initialized) - for (JournalListMapItr i=journalList.begin(); i!=journalList.end(); i++) { - i->second->initManagement(agent); - } - } - } -} - -bool MessageStoreImpl::init(const qpid::Options* options_) -{ - // Extract and check options - const StoreOptions* opts = static_cast(options_); - qpid::linearstore::journal::efpPartitionNumber_t efpPartition = chkEfpPartition(opts->efpPartition, "efp-partition"); - qpid::linearstore::journal::efpDataSize_kib_t efpFilePoolSize_kib = chkEfpFileSizeKiB(opts->efpFileSizeKib, "efp-file-size"); - uint32_t jrnlWrCachePageSizeKib = chkJrnlWrPageCacheSize(opts->wCachePageSizeKib, "wcache-page-size"); - uint32_t tplJrnlWrCachePageSizeKib = chkJrnlWrPageCacheSize(opts->tplWCachePageSizeKib, "tpl-wcache-page-size"); - journalFlushTimeout = opts->journalFlushTimeout; - - // Pass option values to init() - return init(opts->storeDir, efpPartition, efpFilePoolSize_kib, opts->truncateFlag, jrnlWrCachePageSizeKib, - tplJrnlWrCachePageSizeKib, opts->overwriteBeforeReturnFlag); -} - -// These params, taken from options, are assumed to be correct and verified -bool MessageStoreImpl::init(const std::string& storeDir_, - qpid::linearstore::journal::efpPartitionNumber_t efpPartition_, - qpid::linearstore::journal::efpDataSize_kib_t efpFileSize_kib_, - const bool truncateFlag_, - uint32_t wCachePageSizeKib_, - uint32_t tplWCachePageSizeKib_, - const bool overwriteBeforeReturnFlag_) -{ - if (isInit) return true; - - // Set geometry members (converting to correct units where req'd) - overwriteBeforeReturnFlag = overwriteBeforeReturnFlag_; - defaultEfpPartitionNumber = efpPartition_; - defaultEfpFileSize_kib = efpFileSize_kib_; - wCachePgSizeSblks = wCachePageSizeKib_ / QLS_SBLK_SIZE_KIB; // convert from KiB to number sblks - wCacheNumPages = getJrnlWrNumPages(wCachePageSizeKib_); - tplWCachePgSizeSblks = tplWCachePageSizeKib_ / QLS_SBLK_SIZE_KIB; // convert from KiB to number sblks - tplWCacheNumPages = getJrnlWrNumPages(tplWCachePageSizeKib_); - if (storeDir_.size()>0) storeDir = storeDir_; - - if (truncateFlag_) - truncateInit(); - init(truncateFlag_); - - QLS_LOG(notice, "Store module initialized; store-dir=" << storeDir_); - QLS_LOG(info, "> Default EFP partition: " << defaultEfpPartitionNumber); - QLS_LOG(info, "> Default EFP file size: " << defaultEfpFileSize_kib << " (KiB)"); - QLS_LOG(info, "> Default write cache page size: " << wCachePageSizeKib_ << " (KiB)"); - QLS_LOG(info, "> Default number of write cache pages: " << wCacheNumPages); - QLS_LOG(info, "> TPL write cache page size: " << tplWCachePageSizeKib_ << " (KiB)"); - QLS_LOG(info, "> TPL number of write cache pages: " << tplWCacheNumPages); - QLS_LOG(info, "> EFP partition: " << defaultEfpPartitionNumber); - QLS_LOG(info, "> EFP file size pool: " << defaultEfpFileSize_kib << " (KiB)"); - QLS_LOG(info, "> Overwrite before return to EFP: " << (overwriteBeforeReturnFlag?"True":"False")); - QLS_LOG(info, "> Maximum journal flush time: " << journalFlushTimeout); - - return isInit; -} - -void MessageStoreImpl::init(const bool truncateFlag) -{ - const int retryMax = 3; - int bdbRetryCnt = 0; - do { - if (bdbRetryCnt++ > 0) - { - closeDbs(); - ::usleep(1000000); // 1 sec delay - QLS_LOG(error, "Previoius BDB store initialization failed, retrying (" << bdbRetryCnt << " of " << retryMax << ")..."); - } - - try { - qpid::linearstore::journal::jdir::create_dir(getBdbBaseDir()); - - dbenv.reset(new DbEnv(0)); - dbenv->set_errpfx("linearstore"); - dbenv->set_lg_regionmax(256000); // default = 65000 - dbenv->open(getBdbBaseDir().c_str(), DB_THREAD | DB_CREATE | DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_USE_ENVIRON | DB_RECOVER, 0); - - // Databases are constructed here instead of the constructor so that the DB_RECOVER flag can be used - // against the database environment. Recover can only be performed if no databases have been created - // against the environment at the time of recovery, as recovery invalidates the environment. - queueDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(queueDb); - configDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(configDb); - exchangeDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(exchangeDb); - mappingDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(mappingDb); - bindingDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(bindingDb); - generalDb.reset(new Db(dbenv.get(), 0)); - dbs.push_back(generalDb); - - TxnCtxt txn; - txn.begin(dbenv.get(), false); - try { - open(queueDb, txn.get(), "queues.db", false); - open(configDb, txn.get(), "config.db", false); - open(exchangeDb, txn.get(), "exchanges.db", false); - open(mappingDb, txn.get(), "mappings.db", true); - open(bindingDb, txn.get(), "bindings.db", true); - open(generalDb, txn.get(), "general.db", false); - txn.commit(); - } catch (...) { txn.abort(); throw; } - // NOTE: during normal initialization, agent == 0 because the store is initialized before the management infrastructure. - // However during a truncated initialization in a cluster, agent != 0. We always pass 0 as the agent for the - // TplStore to keep things consistent in a cluster. See https://bugzilla.redhat.com/show_bug.cgi?id=681026 - tplStorePtr.reset(new TplJournalImpl(broker->getTimer(), "TplStore", getTplBaseDir(), jrnlLog, defJournalGetEventsTimeoutNs, journalFlushTimeout, 0)); - isInit = true; - } catch (const DbException& e) { - if (e.get_errno() == DB_VERSION_MISMATCH) - { - QLS_LOG(error, "Database environment mismatch: This version of db4 does not match that which created the store database.: " << e.what()); - THROW_STORE_EXCEPTION_2("Database environment mismatch: This version of db4 does not match that which created the store database. " - "(If recovery is not important, delete the contents of the store directory. Otherwise, try upgrading the database using " - "db_upgrade or using db_recover - but the db4-utils package must also be installed to use these utilities.)", e); - } - QLS_LOG(error, "BDB exception occurred while initializing store: " << e.what()); - if (bdbRetryCnt >= retryMax) - THROW_STORE_EXCEPTION_2("BDB exception occurred while initializing store", e); - } catch (const StoreException&) { - throw; - } catch (const qpid::linearstore::journal::jexception& e) { - QLS_LOG(error, "Journal Exception occurred while initializing store: " << e); - THROW_STORE_EXCEPTION_2("Journal Exception occurred while initializing store", e.what()); - } catch (...) { - QLS_LOG(error, "Unknown exception occurred while initializing store."); - throw; - } - } while (!isInit); - - efpMgr.reset(new qpid::linearstore::journal::EmptyFilePoolManager(getStoreTopLevelDir(), - defaultEfpPartitionNumber, - defaultEfpFileSize_kib, - overwriteBeforeReturnFlag, - truncateFlag, - jrnlLog)); - efpMgr->findEfpPartitions(); -} - -void MessageStoreImpl::finalize() -{ - if (tplStorePtr.get() && tplStorePtr->is_ready()) tplStorePtr->stop(true); - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - for (JournalListMapItr i = journalList.begin(); i != journalList.end(); i++) - { - JournalImpl* jQueue = i->second; - jQueue->resetDeleteCallback(); - if (jQueue->is_ready()) jQueue->stop(true); - } - } - - if (mgmtObject.get() != 0) { - mgmtObject->resourceDestroy(); - mgmtObject.reset(); - } -} - -void MessageStoreImpl::truncateInit() -{ - if (isInit) { - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - if (journalList.size()) { // check no queues exist - std::ostringstream oss; - oss << "truncateInit() called with " << journalList.size() << " queues still in existence"; - THROW_STORE_EXCEPTION(oss.str()); - } - } - closeDbs(); - dbs.clear(); - if (tplStorePtr->is_ready()) tplStorePtr->stop(true); - dbenv->close(0); - isInit = false; - } - - qpid::linearstore::journal::jdir::delete_dir(getBdbBaseDir()); - - // TODO: Linearstore: harvest all discarded journal files into the empty file pool(s). - qpid::linearstore::journal::jdir::delete_dir(getJrnlBaseDir()); - qpid::linearstore::journal::jdir::delete_dir(getTplBaseDir()); - QLS_LOG(info, "Store directory " << getStoreTopLevelDir() << " was truncated."); -} - -void MessageStoreImpl::chkTplStoreInit() -{ - // Prevent multiple threads from late-initializing the TPL - qpid::sys::Mutex::ScopedLock sl(tplInitLock); - if (!tplStorePtr->is_ready()) { - qpid::linearstore::journal::jdir::create_dir(getTplBaseDir()); - tplStorePtr->initialize(getEmptyFilePool(defaultEfpPartitionNumber, defaultEfpFileSize_kib), tplWCacheNumPages, tplWCachePgSizeSblks); - if (mgmtObject.get() != 0) mgmtObject->set_tplIsInitialized(true); - } -} - -void MessageStoreImpl::open(db_ptr db_, - DbTxn* txn_, - const char* file_, - bool dupKey_) -{ - if(dupKey_) db_->set_flags(DB_DUPSORT); - db_->open(txn_, file_, 0, DB_BTREE, DB_CREATE | DB_THREAD, 0); -} - -void MessageStoreImpl::closeDbs() -{ - for (std::list::iterator i = dbs.begin(); i != dbs.end(); i++) { - (*i)->close(0); - } - dbs.clear(); -} - -MessageStoreImpl::~MessageStoreImpl() -{ - finalize(); - try { - closeDbs(); - } catch (const DbException& e) { - QLS_LOG(error, "Error closing BDB databases: " << e.what()); - } catch (const qpid::linearstore::journal::jexception& e) { - QLS_LOG(error, "Error: " << e.what()); - } catch (const std::exception& e) { - QLS_LOG(error, "Error: " << e.what()); - } catch (...) { - QLS_LOG(error, "Unknown error in MessageStoreImpl::~MessageStoreImpl()"); - } - - if (mgmtObject.get() != 0) { - mgmtObject->resourceDestroy(); - mgmtObject.reset(); - } -} - -void MessageStoreImpl::create(qpid::broker::PersistableQueue& queue_, - const qpid::framing::FieldTable& args_) -{ - QLS_LOG(info, "*** MessageStoreImpl::create() queue=\"" << queue_.getName() << "\""); // DEBUG - checkInit(); - if (queue_.getPersistenceId()) { - THROW_STORE_EXCEPTION("Queue already created: " + queue_.getName()); - } - JournalImpl* jQueue = 0; - - if (queue_.getName().size() == 0) - { - QLS_LOG(error, "Cannot create store for empty (null) queue name - queue create ignored."); - return; - } - - jQueue = new JournalImpl(broker->getTimer(), queue_.getName(), getJrnlDir(queue_.getName()), jrnlLog, - defJournalGetEventsTimeoutNs, journalFlushTimeout, agent, - boost::bind(&MessageStoreImpl::journalDeleted, this, _1)); - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - journalList[queue_.getName()]=jQueue; - } - - queue_.setExternalQueueStore(dynamic_cast(jQueue)); - try { - jQueue->initialize(getEmptyFilePool(args_), wCacheNumPages, wCachePgSizeSblks); - } catch (const qpid::linearstore::journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queue_.getName() + ": create() failed: " + e.what()); - } - try { - if (!create(queueDb, queueIdSequence, queue_)) { - THROW_STORE_EXCEPTION("Queue already exists: " + queue_.getName()); - } - } catch (const DbException& e) { - THROW_STORE_EXCEPTION_2("Error creating queue named " + queue_.getName(), e); - } -} - -qpid::linearstore::journal::EmptyFilePool* -MessageStoreImpl::getEmptyFilePool(const qpid::linearstore::journal::efpPartitionNumber_t efpPartitionNumber_, - const qpid::linearstore::journal::efpDataSize_kib_t efpFileSizeKib_) { - qpid::linearstore::journal::EmptyFilePool* efpp = efpMgr->getEmptyFilePool(efpPartitionNumber_, efpFileSizeKib_); - if (efpp == 0) { - std::ostringstream oss; - oss << "Partition=" << efpPartitionNumber_ << "; EfpFileSize=" << efpFileSizeKib_ << " KiB"; - throw qpid::linearstore::journal::jexception(qpid::linearstore::journal::jerrno::JERR_EFP_NOEFP, oss.str(), "MessageStoreImpl", "getEmptyFilePool"); - } - return efpp; -} - -qpid::linearstore::journal::EmptyFilePool* -MessageStoreImpl::getEmptyFilePool(const qpid::framing::FieldTable& args_) { - qpid::framing::FieldTable::ValuePtr value; - qpid::linearstore::journal::efpPartitionNumber_t localEfpPartition = defaultEfpPartitionNumber; - value = args_.get("qpid.efp_partition_num"); - if (value.get() != 0 && !value->empty() && value->convertsTo()) { - localEfpPartition = chkEfpPartition((uint32_t)value->get(), "qpid.efp_partition_num"); - } - - qpid::linearstore::journal::efpDataSize_kib_t localEfpFileSizeKib = defaultEfpFileSize_kib; - value = args_.get("qpid.efp_pool_file_size"); - if (value.get() != 0 && !value->empty() && value->convertsTo()) { - localEfpFileSizeKib = chkEfpFileSizeKiB((uint32_t)value->get(), "qpid.efp_pool_file_size"); - } - return getEmptyFilePool(localEfpPartition, localEfpFileSizeKib); -} - -void MessageStoreImpl::destroy(qpid::broker::PersistableQueue& queue_) -{ - QLS_LOG(info, "*** MessageStoreImpl::destroy() queue=\"" << queue_.getName() << "\""); - checkInit(); - destroy(queueDb, queue_); - deleteBindingsForQueue(queue_); - qpid::broker::ExternalQueueStore* eqs = queue_.getExternalQueueStore(); - if (eqs) { - JournalImpl* jQueue = static_cast(eqs); - jQueue->delete_jrnl_files(); - queue_.setExternalQueueStore(0); // will delete the journal if exists - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - journalList.erase(queue_.getName()); - } - } -} - -void MessageStoreImpl::create(const qpid::broker::PersistableExchange& exchange_, - const qpid::framing::FieldTable& /*args_*/) -{ - checkInit(); - if (exchange_.getPersistenceId()) { - THROW_STORE_EXCEPTION("Exchange already created: " + exchange_.getName()); - } - try { - if (!create(exchangeDb, exchangeIdSequence, exchange_)) { - THROW_STORE_EXCEPTION("Exchange already exists: " + exchange_.getName()); - } - } catch (const DbException& e) { - THROW_STORE_EXCEPTION_2("Error creating exchange named " + exchange_.getName(), e); - } -} - -void MessageStoreImpl::destroy(const qpid::broker::PersistableExchange& exchange) -{ - checkInit(); - destroy(exchangeDb, exchange); - //need to also delete bindings - IdDbt key(exchange.getPersistenceId()); - bindingDb->del(0, &key, DB_AUTO_COMMIT); -} - -void MessageStoreImpl::create(const qpid::broker::PersistableConfig& general_) -{ - checkInit(); - if (general_.getPersistenceId()) { - THROW_STORE_EXCEPTION("General configuration item already created"); - } - try { - if (!create(generalDb, generalIdSequence, general_)) { - THROW_STORE_EXCEPTION("General configuration already exists"); - } - } catch (const DbException& e) { - THROW_STORE_EXCEPTION_2("Error creating general configuration", e); - } -} - -void MessageStoreImpl::destroy(const qpid::broker::PersistableConfig& general_) -{ - checkInit(); - destroy(generalDb, general_); -} - -bool MessageStoreImpl::create(db_ptr db_, - IdSequence& seq_, - const qpid::broker::Persistable& p_) -{ - uint64_t id (seq_.next()); - Dbt key(&id, sizeof(id)); - BufferValue value (p_); - - int status; - TxnCtxt txn; - txn.begin(dbenv.get(), true); - try { - status = db_->put(txn.get(), &key, &value, DB_NOOVERWRITE); - txn.commit(); - } catch (...) { - txn.abort(); - throw; - } - if (status == DB_KEYEXIST) { - return false; - } else { - p_.setPersistenceId(id); - return true; - } -} - -void MessageStoreImpl::destroy(db_ptr db, const qpid::broker::Persistable& p_) -{ - qpid::sys::Mutex::ScopedLock sl(bdbLock); - IdDbt key(p_.getPersistenceId()); - db->del(0, &key, DB_AUTO_COMMIT); -} - - -void MessageStoreImpl::bind(const qpid::broker::PersistableExchange& e_, - const qpid::broker::PersistableQueue& q_, - const std::string& k_, - const qpid::framing::FieldTable& a_) -{ - checkInit(); - IdDbt key(e_.getPersistenceId()); - BindingDbt value(e_, q_, k_, a_); - TxnCtxt txn; - txn.begin(dbenv.get(), true); - try { - put(bindingDb, txn.get(), key, value); - txn.commit(); - } catch (...) { - txn.abort(); - throw; - } -} - -void MessageStoreImpl::unbind(const qpid::broker::PersistableExchange& e_, - const qpid::broker::PersistableQueue& q_, - const std::string& k_, - const qpid::framing::FieldTable& /*a_*/) -{ - checkInit(); - deleteBinding(e_, q_, k_); -} - -void MessageStoreImpl::recover(qpid::broker::RecoveryManager& registry_) -{ - checkInit(); - txn_list prepared; - recoverLockedMappings(prepared); - - std::ostringstream oss; - oss << "Recovered transaction prepared list:"; - for (txn_list::iterator i = prepared.begin(); i != prepared.end(); i++) { - oss << std::endl << " " << qpid::linearstore::journal::jcntl::str2hexnum(i->xid); - } - QLS_LOG(debug, oss.str()); - - queue_index queues;//id->queue - exchange_index exchanges;//id->exchange - message_index messages;//id->message - - TxnCtxt txn; - txn.begin(dbenv.get(), false); - try { - //read all queues, calls recoversMessages for each queue - recoverQueues(txn, registry_, queues, prepared, messages); - - //recover exchange & bindings: - recoverExchanges(txn, registry_, exchanges); - recoverBindings(txn, exchanges, queues); - - //recover general-purpose configuration - recoverGeneral(txn, registry_); - - txn.commit(); - } catch (const DbException& e) { - txn.abort(); - THROW_STORE_EXCEPTION_2("Error on recovery", e); - } catch (...) { - txn.abort(); - throw; - } - - //recover transactions: - qpid::linearstore::journal::txn_map& txn_map_ref = tplStorePtr->get_txn_map(); - for (txn_list::iterator i = prepared.begin(); i != prepared.end(); i++) { - const PreparedTransaction pt = *i; - if (mgmtObject.get() != 0) { - mgmtObject->inc_tplTransactionDepth(); - mgmtObject->inc_tplTxnPrepares(); - } - - std::string xid = pt.xid; - qpid::linearstore::journal::txn_data_list_t tdl = txn_map_ref.get_tdata_list(xid); - if (tdl.size() == 0) THROW_STORE_EXCEPTION("XID not found in txn_map"); - qpid::linearstore::journal::txn_op_stats_t txn_op_stats(tdl); - bool commitFlag = txn_op_stats.abortCnt == 0; - - // If a record is found that is dequeued but not committed/aborted from tplStore, then a complete() call - // was interrupted part way through committing/aborting the impacted queues. Complete this process. - bool incomplTplTxnFlag = txn_op_stats.deqCnt > 0; - - if (txn_op_stats.tpcCnt > 0) { - // Dtx (2PC) transaction - TPCTxnCtxt* tpcc = new TPCTxnCtxt(xid, &messageIdSequence); - std::auto_ptr txn(tpcc); - tpcc->recoverDtok(txn_op_stats.rid, xid); - tpcc->prepare(tplStorePtr.get()); - - qpid::broker::RecoverableTransaction::shared_ptr dtx; - if (!incomplTplTxnFlag) dtx = registry_.recoverTransaction(xid, txn); - if (pt.enqueues.get()) { - for (LockedMappings::iterator j = pt.enqueues->begin(); j != pt.enqueues->end(); j++) { - tpcc->addXidRecord(queues[j->first]->getExternalQueueStore()); - if (!incomplTplTxnFlag) dtx->enqueue(queues[j->first], messages[j->second]); - } - } - if (pt.dequeues.get()) { - for (LockedMappings::iterator j = pt.dequeues->begin(); j != pt.dequeues->end(); j++) { - tpcc->addXidRecord(queues[j->first]->getExternalQueueStore()); - if (!incomplTplTxnFlag) dtx->dequeue(queues[j->first], messages[j->second]); - } - } - - if (incomplTplTxnFlag) { - tpcc->complete(commitFlag); - } - } else { - // Local (1PC) transaction - boost::shared_ptr opcc(new TxnCtxt(xid, &messageIdSequence)); - opcc->recoverDtok(txn_op_stats.rid, xid); - opcc->prepare(tplStorePtr.get()); - - if (pt.enqueues.get()) { - for (LockedMappings::iterator j = pt.enqueues->begin(); j != pt.enqueues->end(); j++) { - opcc->addXidRecord(queues[j->first]->getExternalQueueStore()); - } - } - if (pt.dequeues.get()) { - for (LockedMappings::iterator j = pt.dequeues->begin(); j != pt.dequeues->end(); j++) { - opcc->addXidRecord(queues[j->first]->getExternalQueueStore()); - } - } - if (incomplTplTxnFlag) { - opcc->complete(commitFlag); - } else { - completed(*opcc.get(), commitFlag); - } - } - - } - registry_.recoveryComplete(); -} - -void MessageStoreImpl::recoverQueues(TxnCtxt& txn, - qpid::broker::RecoveryManager& registry, - queue_index& queue_index, - txn_list& prepared, - message_index& messages) -{ - Cursor queues; - queues.open(queueDb, txn.get()); - - uint64_t maxQueueId(1); - - IdDbt key; - Dbt value; - //read all queues - while (queues.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - //create a Queue instance - qpid::broker::RecoverableQueue::shared_ptr queue = registry.recoverQueue(buffer); - //set the persistenceId and update max as required - queue->setPersistenceId(key.id); - - const std::string queueName = queue->getName().c_str(); - JournalImpl* jQueue = 0; - if (queueName.size() == 0) - { - QLS_LOG(error, "Cannot recover empty (null) queue name - ignoring and attempting to continue."); - break; - } - jQueue = new JournalImpl(broker->getTimer(), queueName, getJrnlDir(queueName),jrnlLog, - defJournalGetEventsTimeoutNs, journalFlushTimeout, agent, - boost::bind(&MessageStoreImpl::journalDeleted, this, _1)); - { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - journalList[queueName] = jQueue; - } - queue->setExternalQueueStore(dynamic_cast(jQueue)); - - try - { - long rcnt = 0L; // recovered msg count - long idcnt = 0L; // in-doubt msg count - uint64_t thisHighestRid = 0ULL; - jQueue->recover(boost::dynamic_pointer_cast(efpMgr), wCacheNumPages, wCachePgSizeSblks, &prepared, thisHighestRid, key.id); - - // Check for changes to queue store settings qpid.file_count and qpid.file_size resulting - // from recovery of a store that has had its size changed externally by the resize utility. - // If so, update the queue store settings so that QMF queries will reflect the new values. - // TODO: Update this for new settings, as qpid.file_count and qpid.file_size no longer apply -/* - const qpid::framing::FieldTable& storeargs = queue->getSettings().storeSettings; - qpid::framing::FieldTable::ValuePtr value; - value = storeargs.get("qpid.file_count"); - if (value.get() != 0 && !value->empty() && value->convertsTo() && (uint16_t)value->get() != jQueue->num_jfiles()) { - queue->addArgument("qpid.file_count", jQueue->num_jfiles()); - } - value = storeargs.get("qpid.file_size"); - if (value.get() != 0 && !value->empty() && value->convertsTo() && (uint32_t)value->get() != jQueue->jfsize_sblks()/JRNL_RMGR_PAGE_SIZE) { - queue->addArgument("qpid.file_size", jQueue->jfsize_sblks()/JRNL_RMGR_PAGE_SIZE); - } -*/ - - if (highestRid == 0ULL) - highestRid = thisHighestRid; - else if (thisHighestRid - highestRid < 0x8000000000000000ULL) // RFC 1982 comparison for unsigned 64-bit - highestRid = thisHighestRid; - recoverMessages(txn, registry, queue, prepared, messages, rcnt, idcnt); - QLS_LOG(info, "Recovered queue \"" << queueName << "\": " << rcnt << " messages recovered; " << idcnt << " messages in-doubt."); - jQueue->recover_complete(); // start journal. - } catch (const qpid::linearstore::journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queueName + ": recoverQueues() failed: " + e.what()); - } - //read all messages: done on a per queue basis if using Journal - - queue_index[key.id] = queue; - maxQueueId = std::max(key.id, maxQueueId); - } - - // NOTE: highestRid is set by both recoverQueues() and recoverTplStore() as - // the messageIdSequence is used for both queue journals and the tpl journal. - messageIdSequence.reset(highestRid + 1); - QLS_LOG(info, "Most recent persistence id found: 0x" << std::hex << highestRid << std::dec); - - queueIdSequence.reset(maxQueueId + 1); -} - - -void MessageStoreImpl::recoverExchanges(TxnCtxt& txn_, - qpid::broker::RecoveryManager& registry_, - exchange_index& index_) -{ - //TODO: this is a copy&paste from recoverQueues - refactor! - Cursor exchanges; - exchanges.open(exchangeDb, txn_.get()); - - uint64_t maxExchangeId(1); - IdDbt key; - Dbt value; - //read all exchanges - while (exchanges.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - //create a Exchange instance - qpid::broker::RecoverableExchange::shared_ptr exchange = registry_.recoverExchange(buffer); - if (exchange) { - //set the persistenceId and update max as required - exchange->setPersistenceId(key.id); - index_[key.id] = exchange; - QLS_LOG(info, "Recovered exchange \"" << exchange->getName() << '"'); - } - maxExchangeId = std::max(key.id, maxExchangeId); - } - exchangeIdSequence.reset(maxExchangeId + 1); -} - -void MessageStoreImpl::recoverBindings(TxnCtxt& txn_, - exchange_index& exchanges_, - queue_index& queues_) -{ - Cursor bindings; - bindings.open(bindingDb, txn_.get()); - - IdDbt key; - Dbt value; - while (bindings.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - if (buffer.available() < 8) { - QLS_LOG(error, "Not enough data for binding: " << buffer.available()); - THROW_STORE_EXCEPTION("Not enough data for binding"); - } - uint64_t queueId = buffer.getLongLong(); - std::string queueName; - std::string routingkey; - qpid::framing::FieldTable args; - buffer.getShortString(queueName); - buffer.getShortString(routingkey); - buffer.get(args); - exchange_index::iterator exchange = exchanges_.find(key.id); - queue_index::iterator queue = queues_.find(queueId); - if (exchange != exchanges_.end() && queue != queues_.end()) { - //could use the recoverable queue here rather than the name... - exchange->second->bind(queueName, routingkey, args); - QLS_LOG(info, "Recovered binding exchange=" << exchange->second->getName() - << " key=" << routingkey - << " queue=" << queueName); - } else { - //stale binding, delete it - QLS_LOG(warning, "Deleting stale binding"); - bindings->del(0); - } - } -} - -void MessageStoreImpl::recoverGeneral(TxnCtxt& txn_, - qpid::broker::RecoveryManager& registry_) -{ - Cursor items; - items.open(generalDb, txn_.get()); - - uint64_t maxGeneralId(1); - IdDbt key; - Dbt value; - //read all items - while (items.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - //create instance - qpid::broker::RecoverableConfig::shared_ptr config = registry_.recoverConfig(buffer); - //set the persistenceId and update max as required - config->setPersistenceId(key.id); - maxGeneralId = std::max(key.id, maxGeneralId); - } - generalIdSequence.reset(maxGeneralId + 1); -} - -void MessageStoreImpl::recoverMessages(TxnCtxt& /*txn*/, - qpid::broker::RecoveryManager& recovery, - qpid::broker::RecoverableQueue::shared_ptr& queue, - txn_list& prepared, - message_index& messages, - long& rcnt, - long& idcnt) -{ - size_t preambleLength = sizeof(uint32_t)/*header size*/; - - JournalImpl* jc = static_cast(queue->getExternalQueueStore()); - unsigned msg_count = 0; - - // TODO: This optimization to skip reading if there are no enqueued messages to read - // breaks the python system test in phase 6 with "Exception: Cannot write lock file" - // Figure out what is breaking. - //bool read = jc->get_enq_cnt() > 0; - bool read = true; - - void* dbuff = NULL; - size_t dbuffSize = 0; - void* xidbuff = NULL; - size_t xidbuffSize = 0; - bool transientFlag = false; - bool externalFlag = false; - DataTokenImpl dtok; - dtok.set_wstate(DataTokenImpl::NONE); - qpid::linearstore::journal::txn_map& txn_map_ref = tplStorePtr->get_txn_map(); - - // Read the message from the Journal. - try { - unsigned aio_sleep_cnt = 0; - while (read) { - qpid::linearstore::journal::iores res = jc->read_data_record(&dbuff, dbuffSize, &xidbuff, xidbuffSize, transientFlag, externalFlag, &dtok, false); - - switch (res) - { - case qpid::linearstore::journal::RHM_IORES_SUCCESS: { - msg_count++; - qpid::broker::RecoverableMessage::shared_ptr msg; - char* data = (char*)dbuff; - - unsigned headerSize; - if (externalFlag) { - msg = getExternMessage(recovery, dtok.rid(), headerSize); // large message external to jrnl - } else { - headerSize = qpid::framing::Buffer(data, preambleLength).getLong(); - qpid::framing::Buffer headerBuff(data+ preambleLength, headerSize); - msg = recovery.recoverMessage(headerBuff); - } - msg->setPersistenceId(dtok.rid()); - // At some future point if delivery attempts are stored, then this call would - // become optional depending on that information. - msg->setRedelivered(); - // Reset the TTL for the recovered message - msg->computeExpiration(); - - uint32_t contentOffset = headerSize + preambleLength; - uint64_t contentSize = dbuffSize - contentOffset; - if (msg->loadContent(contentSize) && !externalFlag) { - //now read the content - qpid::framing::Buffer contentBuff(data + contentOffset, contentSize); - msg->decodeContent(contentBuff); - } - - PreparedTransaction::list::iterator i = PreparedTransaction::getLockedPreparedTransaction(prepared, queue->getPersistenceId(), dtok.rid()); - if (i == prepared.end()) { // not in prepared list - rcnt++; - queue->recover(msg); - } else { - uint64_t rid = dtok.rid(); - std::string xid(i->xid); - qpid::linearstore::journal::txn_data_list_t tdl = txn_map_ref.get_tdata_list(xid); - if (tdl.size() == 0) THROW_STORE_EXCEPTION("XID not found in txn_map"); - qpid::linearstore::journal::txn_op_stats_t txn_op_stats(tdl); - if (txn_op_stats.deqCnt > 0 || txn_op_stats.tpcCnt == 0) { - if (jc->is_enqueued(rid, true)) { - // Enqueue is non-tx, dequeue tx - assert(jc->is_locked(rid)); // This record MUST be locked by a txn dequeue - if (txn_op_stats.abortCnt > 0) { - rcnt++; - queue->recover(msg); // recover message in abort case only - } - } else { - // Enqueue and/or dequeue tx - qpid::linearstore::journal::txn_map& tmap = jc->get_txn_map(); - qpid::linearstore::journal::txn_data_list_t txnList = tmap.get_tdata_list(xid); // txnList will be empty if xid not found - bool enq = false; - bool deq = false; - for (qpid::linearstore::journal::tdl_itr_t j = txnList.begin(); jenq_flag_ && j->rid_ == rid) - enq = true; - else if (!j->enq_flag_ && j->drid_ == rid) - deq = true; - } - if (enq && !deq && txn_op_stats.abortCnt == 0) { - rcnt++; - queue->recover(msg); // recover txn message in commit case only - } - } - } else { - idcnt++; - messages[rid] = msg; - } - } - - dtok.reset(); - dtok.set_wstate(DataTokenImpl::NONE); - - if (xidbuff) { - ::free(xidbuff); - xidbuff = NULL; - } - if (dbuff) { - ::free(dbuff); - dbuff = NULL; - } - aio_sleep_cnt = 0; - break; - } - case qpid::linearstore::journal::RHM_IORES_PAGE_AIOWAIT: - if (++aio_sleep_cnt > MAX_AIO_SLEEPS) - THROW_STORE_EXCEPTION("Timeout waiting for AIO in MessageStoreImpl::recoverMessages()"); - ::usleep(AIO_SLEEP_TIME_US); - break; - case qpid::linearstore::journal::RHM_IORES_EMPTY: - read = false; - break; // done with all messages. (add call in jrnl to test that _emap is empty.) - default: - std::ostringstream oss; - oss << "recoverMessages(): Queue: " << queue->getName() << ": Unexpected return from journal read: " << qpid::linearstore::journal::iores_str(res); - THROW_STORE_EXCEPTION(oss.str()); - } // switch - } // while - } catch (const qpid::linearstore::journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queue->getName() + ": recoverMessages() failed: " + e.what()); - } -} - -qpid::broker::RecoverableMessage::shared_ptr MessageStoreImpl::getExternMessage(qpid::broker::RecoveryManager& /*recovery*/, - uint64_t /*messageId*/, - unsigned& /*headerSize*/) -{ - throw qpid::linearstore::journal::jexception(qpid::linearstore::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "getExternMessage"); -} - -int MessageStoreImpl::enqueueMessage(TxnCtxt& txn_, - IdDbt& msgId_, - qpid::broker::RecoverableMessage::shared_ptr& msg_, - queue_index& index_, - txn_list& prepared_, - message_index& messages_) -{ - Cursor mappings; - mappings.open(mappingDb, txn_.get()); - - IdDbt value; - - int count(0); - for (int status = mappings->get(&msgId_, &value, DB_SET); status == 0; status = mappings->get(&msgId_, &value, DB_NEXT_DUP)) { - if (index_.find(value.id) == index_.end()) { - QLS_LOG(warning, "Recovered message for queue that no longer exists"); - mappings->del(0); - } else { - qpid::broker::RecoverableQueue::shared_ptr queue = index_[value.id]; - if (PreparedTransaction::isLocked(prepared_, value.id, msgId_.id)) { - messages_[msgId_.id] = msg_; - } else { - queue->recover(msg_); - } - count++; - } - } - mappings.close(); - return count; -} - - -void MessageStoreImpl::recoverTplStore() -{ - if (qpid::linearstore::journal::jdir::exists(tplStorePtr->jrnl_dir())) { - uint64_t thisHighestRid = 0ULL; - tplStorePtr->recover(boost::dynamic_pointer_cast(efpMgr), tplWCacheNumPages, tplWCachePgSizeSblks, 0, thisHighestRid, 0); - if (highestRid == 0ULL) - highestRid = thisHighestRid; - else if (thisHighestRid - highestRid < 0x8000000000000000ULL) // RFC 1982 comparison for unsigned 64-bit - highestRid = thisHighestRid; - tplStorePtr->recover_complete(); // start TPL - } -} - -void MessageStoreImpl::recoverLockedMappings(txn_list& txns) -{ - if (!tplStorePtr->is_ready()) - recoverTplStore(); - std::vector xidList; - tplStorePtr->get_txn_map().xid_list(xidList); - for (std::vector::const_iterator i=xidList.begin(); i!=xidList.end(); ++i) { - LockedMappings::shared_ptr enq_ptr; - enq_ptr.reset(new LockedMappings); - LockedMappings::shared_ptr deq_ptr; - deq_ptr.reset(new LockedMappings); - txns.push_back(new PreparedTransaction(*i, enq_ptr, deq_ptr)); - } -} - -void MessageStoreImpl::collectPreparedXids(std::set& xids) -{ - if (!tplStorePtr->is_ready()) { - recoverTplStore(); - } - std::vector xidList; - tplStorePtr->get_txn_map().xid_list(xidList); - for (std::vector::const_iterator i=xidList.begin(); i!=xidList.end(); ++i) { - qpid::linearstore::journal::txn_data_list_t tdl = tplStorePtr->get_txn_map().get_tdata_list(*i); - qpid::linearstore::journal::txn_op_stats_t txn_op_stats(tdl); - if (txn_op_stats.tpcCnt > 0) { - if (txn_op_stats.enqCnt - txn_op_stats.deqCnt > 0) { - xids.insert(*i); - } - } - } -} - -void MessageStoreImpl::stage(const boost::intrusive_ptr& /*msg*/) -{ - throw qpid::linearstore::journal::jexception(qpid::linearstore::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "stage"); -} - -void MessageStoreImpl::destroy(qpid::broker::PersistableMessage& /*msg*/) -{ - throw qpid::linearstore::journal::jexception(qpid::linearstore::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "destroy"); -} - -void MessageStoreImpl::appendContent(const boost::intrusive_ptr& /*msg*/, - const std::string& /*data*/) -{ - throw qpid::linearstore::journal::jexception(qpid::linearstore::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "appendContent"); -} - -void MessageStoreImpl::loadContent(const qpid::broker::PersistableQueue& /*queue*/, - const boost::intrusive_ptr& /*msg*/, - std::string& /*data*/, - uint64_t /*offset*/, - uint32_t /*length*/) -{ - throw qpid::linearstore::journal::jexception(qpid::linearstore::journal::jerrno::JERR__NOTIMPL, "MessageStoreImpl", "loadContent"); -} - -void MessageStoreImpl::flush(const qpid::broker::PersistableQueue& queue_) -{ -// QLS_LOG(info, "*** MessageStoreImpl::flush() queue=\"" << queue_.getName() << "\""); - if (queue_.getExternalQueueStore() == 0) return; - checkInit(); - std::string qn = queue_.getName(); - try { - JournalImpl* jc = static_cast(queue_.getExternalQueueStore()); - if (jc) { - // TODO: check if this result should be used... - /*mrg::journal::iores res =*/ jc->flush(false); - } - } catch (const qpid::linearstore::journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + qn + ": flush() failed: " + e.what() ); - } -} - -void MessageStoreImpl::enqueue(qpid::broker::TransactionContext* ctxt_, - const boost::intrusive_ptr& msg_, - const qpid::broker::PersistableQueue& queue_) -{ - //QLS_LOG(info, "*** MessageStoreImpl::enqueue() queue=\"" << queue_.getName() << "\""); - checkInit(); - uint64_t queueId (queue_.getPersistenceId()); - if (queueId == 0) { - THROW_STORE_EXCEPTION("Queue not created: " + queue_.getName()); - } - - TxnCtxt implicit; - TxnCtxt* txn = 0; - if (ctxt_) { - txn = check(ctxt_); - } else { - txn = &implicit; - } - - if (msg_->getPersistenceId() == 0) { - msg_->setPersistenceId(messageIdSequence.next()); - } - store(&queue_, txn, msg_); - - // add queue* to the txn map.. - if (ctxt_) txn->addXidRecord(queue_.getExternalQueueStore()); -} - -uint64_t MessageStoreImpl::msgEncode(std::vector& buff_, - const boost::intrusive_ptr& message_) -{ - uint32_t headerSize = message_->encodedHeaderSize(); - uint64_t size = message_->encodedSize() + sizeof(uint32_t); - try { buff_ = std::vector(size); } // long + headers + content - catch (const std::exception& e) { - std::ostringstream oss; - oss << "Unable to allocate memory for encoding message; requested size: " << size << "; error: " << e.what(); - THROW_STORE_EXCEPTION(oss.str()); - } - qpid::framing::Buffer buffer(&buff_[0],size); - buffer.putLong(headerSize); - message_->encode(buffer); - return size; -} - -void MessageStoreImpl::store(const qpid::broker::PersistableQueue* queue_, - TxnCtxt* txn_, - const boost::intrusive_ptr& message_) -{ - //QLS_LOG(info, "*** MessageStoreImpl::store() queue=\"" << queue_->getName() << "\""); - std::vector buff; - uint64_t size = msgEncode(buff, message_); - - try { - if (queue_) { - boost::intrusive_ptr dtokp(new DataTokenImpl); - dtokp->addRef(); - dtokp->setSourceMessage(message_); - dtokp->set_external_rid(true); - dtokp->set_rid(message_->getPersistenceId()); // set the messageID into the Journal header (record-id) - - JournalImpl* jc = static_cast(queue_->getExternalQueueStore()); - if (txn_->getXid().empty()) { - jc->enqueue_data_record(&buff[0], size, size, dtokp.get(), !message_->isPersistent()); - } else { - jc->enqueue_txn_data_record(&buff[0], size, size, dtokp.get(), txn_->getXid(), txn_->isTPC(), !message_->isPersistent()); - } - } else { - THROW_STORE_EXCEPTION(std::string("MessageStoreImpl::store() failed: queue NULL.")); - } - } catch (const qpid::linearstore::journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Queue ") + queue_->getName() + ": MessageStoreImpl::store() failed: " + - e.what()); - } -} - -void MessageStoreImpl::dequeue(qpid::broker::TransactionContext* ctxt_, - const boost::intrusive_ptr& msg_, - const qpid::broker::PersistableQueue& queue_) -{ - //QLS_LOG(info, "*** MessageStoreImpl::dequeue() queue=\"" << queue_.getName() << "\""); - checkInit(); - uint64_t queueId (queue_.getPersistenceId()); - uint64_t messageId (msg_->getPersistenceId()); - if (queueId == 0) { - THROW_STORE_EXCEPTION("Queue \"" + queue_.getName() + "\" has null queue Id (has not been created)"); - } - if (messageId == 0) { - THROW_STORE_EXCEPTION("Queue \"" + queue_.getName() + "\": Dequeuing message with null persistence Id."); - } - - TxnCtxt implicit; - TxnCtxt* txn = 0; - if (ctxt_) { - txn = check(ctxt_); - } else { - txn = &implicit; - } - - // add queue* to the txn map.. - if (ctxt_) txn->addXidRecord(queue_.getExternalQueueStore()); - async_dequeue(ctxt_, msg_, queue_); - msg_->dequeueComplete(); -} - -void MessageStoreImpl::async_dequeue(qpid::broker::TransactionContext* ctxt_, - const boost::intrusive_ptr& msg_, - const qpid::broker::PersistableQueue& queue_) -{ - //QLS_LOG(info, "*** MessageStoreImpl::async_dequeue() queue=\"" << queue_.getName() << "\""); - boost::intrusive_ptr ddtokp(new DataTokenImpl); - ddtokp->setSourceMessage(msg_); - ddtokp->set_external_rid(true); - ddtokp->set_rid(messageIdSequence.next()); - ddtokp->set_dequeue_rid(msg_->getPersistenceId()); - ddtokp->set_wstate(DataTokenImpl::ENQ); - TxnCtxt* txn = 0; - std::string tid; - if (ctxt_) { - txn = check(ctxt_); - tid = txn->getXid(); - } - // Manually increase the ref count, as raw pointers are used beyond this point - ddtokp->addRef(); - try { - JournalImpl* jc = static_cast(queue_.getExternalQueueStore()); - if (tid.empty()) { - jc->dequeue_data_record(ddtokp.get(), false); - } else { - jc->dequeue_txn_data_record(ddtokp.get(), tid, txn?txn->isTPC():false, false); - } - } catch (const qpid::linearstore::journal::jexception& e) { - ddtokp->release(); - THROW_STORE_EXCEPTION(std::string("Queue ") + queue_.getName() + ": async_dequeue() failed: " + e.what()); - } -} - -void MessageStoreImpl::completed(TxnCtxt& txn_, - bool commit_) -{ - try { - chkTplStoreInit(); // Late initialize (if needed) - - // Nothing to do if not prepared - if (txn_.getDtok()->is_enqueued()) { - txn_.incrDtokRef(); - DataTokenImpl* dtokp = txn_.getDtok(); - dtokp->set_dequeue_rid(dtokp->rid()); - dtokp->set_rid(messageIdSequence.next()); - tplStorePtr->dequeue_txn_data_record(txn_.getDtok(), txn_.getXid(), txn_.isTPC(), commit_); - } - txn_.complete(commit_); - if (mgmtObject.get() != 0) { - mgmtObject->dec_tplTransactionDepth(); - if (commit_) - mgmtObject->inc_tplTxnCommits(); - else - mgmtObject->inc_tplTxnAborts(); - } - } catch (const std::exception& e) { - QLS_LOG(error, "Error completing xid " << qpid::linearstore::journal::jcntl::str2hexnum(txn_.getXid()) << ": " << e.what()); - throw; - } -} - -std::auto_ptr MessageStoreImpl::begin() -{ - checkInit(); - // pass sequence number for c/a - return std::auto_ptr(new TxnCtxt(&messageIdSequence)); -} - -std::auto_ptr MessageStoreImpl::begin(const std::string& xid_) -{ - checkInit(); - IdSequence* jtx = &messageIdSequence; - // pass sequence number for c/a - return std::auto_ptr(new TPCTxnCtxt(xid_, jtx)); -} - -void MessageStoreImpl::prepare(qpid::broker::TPCTransactionContext& ctxt_) -{ - checkInit(); - TxnCtxt* txn = dynamic_cast(&ctxt_); -//std::string xid=txn->getXid(); std::cout << "*** MessageStoreImpl::prepare() xid=" << std::hex; -//for (unsigned i=0; igetXid(); std::cout << "*** MessageStoreImpl::localPrepare() xid=" << std::hex; -//for (unsigned i=0; isync(); - - ctxt_->incrDtokRef(); - DataTokenImpl* dtokp = ctxt_->getDtok(); - dtokp->set_external_rid(true); - dtokp->set_rid(messageIdSequence.next()); - char tpcFlag = static_cast(ctxt_->isTPC()); - tplStorePtr->enqueue_txn_data_record(&tpcFlag, sizeof(char), sizeof(char), dtokp, ctxt_->getXid(), tpcFlag != 0, false); - ctxt_->prepare(tplStorePtr.get()); - // make sure all the data is written to disk before returning - ctxt_->sync(); - if (mgmtObject.get() != 0) { - mgmtObject->inc_tplTransactionDepth(); - mgmtObject->inc_tplTxnPrepares(); - } - } catch (const std::exception& e) { - QLS_LOG(error, "Error preparing xid " << ctxt_->getXid() << ": " << e.what()); - throw; - } -} - -void MessageStoreImpl::commit(qpid::broker::TransactionContext& ctxt_) -{ - checkInit(); - TxnCtxt* txn(check(&ctxt_)); - if (!txn->isTPC()) { - if (txn->impactedQueuesEmpty()) return; - localPrepare(dynamic_cast(txn)); - } - completed(*dynamic_cast(txn), true); -} - -void MessageStoreImpl::abort(qpid::broker::TransactionContext& ctxt_) -{ - checkInit(); - TxnCtxt* txn(check(&ctxt_)); - if (!txn->isTPC()) { - if (txn->impactedQueuesEmpty()) return; - localPrepare(dynamic_cast(txn)); - } - completed(*dynamic_cast(txn), false); -} - -TxnCtxt* MessageStoreImpl::check(qpid::broker::TransactionContext* ctxt_) -{ - TxnCtxt* txn = dynamic_cast(ctxt_); - if(!txn) throw qpid::broker::InvalidTransactionContextException(); - return txn; -} - -void MessageStoreImpl::put(db_ptr db_, - DbTxn* txn_, - Dbt& key_, - Dbt& value_) -{ - try { - int status = db_->put(txn_, &key_, &value_, DB_NODUPDATA); - if (status == DB_KEYEXIST) { - THROW_STORE_EXCEPTION("duplicate data"); - } else if (status) { - THROW_STORE_EXCEPTION(DbEnv::strerror(status)); - } - } catch (const DbException& e) { - THROW_STORE_EXCEPTION(e.what()); - } -} - -void MessageStoreImpl::deleteBindingsForQueue(const qpid::broker::PersistableQueue& queue_) -{ - TxnCtxt txn; - txn.begin(dbenv.get(), true); - try { - { - Cursor bindings; - bindings.open(bindingDb, txn.get()); - - IdDbt key; - Dbt value; - while (bindings.next(key, value)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - if (buffer.available() < 8) { - THROW_STORE_EXCEPTION("Not enough data for binding"); - } - uint64_t queueId = buffer.getLongLong(); - if (queue_.getPersistenceId() == queueId) { - bindings->del(0); - QLS_LOG(debug, "Deleting binding for " << queue_.getName() << " " << key.id << "->" << queueId); - } - } - } - txn.commit(); - } catch (const std::exception& e) { - txn.abort(); - THROW_STORE_EXCEPTION_2("Error deleting bindings", e.what()); - } catch (...) { - txn.abort(); - throw; - } - QLS_LOG(debug, "Deleted all bindings for " << queue_.getName() << ":" << queue_.getPersistenceId()); -} - -void MessageStoreImpl::deleteBinding(const qpid::broker::PersistableExchange& exchange_, - const qpid::broker::PersistableQueue& queue_, - const std::string& bkey_) -{ - TxnCtxt txn; - txn.begin(dbenv.get(), true); - try { - { - Cursor bindings; - bindings.open(bindingDb, txn.get()); - - IdDbt key(exchange_.getPersistenceId()); - Dbt value; - - for (int status = bindings->get(&key, &value, DB_SET); status == 0; status = bindings->get(&key, &value, DB_NEXT_DUP)) { - qpid::framing::Buffer buffer(reinterpret_cast(value.get_data()), value.get_size()); - if (buffer.available() < 8) { - THROW_STORE_EXCEPTION("Not enough data for binding"); - } - uint64_t queueId = buffer.getLongLong(); - if (queue_.getPersistenceId() == queueId) { - std::string q; - std::string k; - buffer.getShortString(q); - buffer.getShortString(k); - if (bkey_ == k) { - bindings->del(0); - QLS_LOG(debug, "Deleting binding for " << queue_.getName() << " " << key.id << "->" << queueId); - } - } - } - } - txn.commit(); - } catch (const std::exception& e) { - txn.abort(); - THROW_STORE_EXCEPTION_2("Error deleting bindings", e.what()); - } catch (...) { - txn.abort(); - throw; - } -} - -std::string MessageStoreImpl::getStoreTopLevelDir() { - std::ostringstream dir; - dir << storeDir << "/" << storeTopLevelDir; - return dir.str(); -} - - -std::string MessageStoreImpl::getJrnlBaseDir() -{ - std::ostringstream dir; - dir << storeDir << "/" << storeTopLevelDir << "/jrnl2/" ; - return dir.str(); -} - -std::string MessageStoreImpl::getBdbBaseDir() -{ - std::ostringstream dir; - dir << storeDir << "/" << storeTopLevelDir << "/dat2/" ; - return dir.str(); -} - -std::string MessageStoreImpl::getTplBaseDir() -{ - std::ostringstream dir; - dir << storeDir << "/" << storeTopLevelDir << "/tpl2/" ; - return dir.str(); -} - -std::string MessageStoreImpl::getJrnlDir(const std::string& queueName_) -{ - std::ostringstream oss; - oss << getJrnlBaseDir() << queueName_; - return oss.str(); -} - -std::string MessageStoreImpl::getStoreDir() const { return storeDir; } - -void MessageStoreImpl::journalDeleted(JournalImpl& j_) { - qpid::sys::Mutex::ScopedLock sl(journalListLock); - journalList.erase(j_.id()); -} - -MessageStoreImpl::StoreOptions::StoreOptions(const std::string& name_) : - qpid::Options(name_), - truncateFlag(defTruncateFlag), - wCachePageSizeKib(defWCachePageSizeKib), - tplWCachePageSizeKib(defTplWCachePageSizeKib), - efpPartition(defEfpPartition), - efpFileSizeKib(defEfpFileSizeKib), - overwriteBeforeReturnFlag(defOverwriteBeforeReturnFlag), - journalFlushTimeout(defJournalFlushTimeoutNs) -{ - addOptions() - ("store-dir", qpid::optValue(storeDir, "DIR"), - "Store directory location for persistence (instead of using --data-dir value). " - "Required if --no-data-dir is also used.") - ("truncate", qpid::optValue(truncateFlag, "yes|no"), - "If yes|true|1, will truncate the store (discard any existing records). If no|false|0, will preserve " - "the existing store files for recovery.") - ("wcache-page-size", qpid::optValue(wCachePageSizeKib, "N"), - "Size of the pages in the write page cache in KiB. " - "Allowable values - powers of 2: 1, 2, 4, ... , 128. " - "Lower values decrease latency at the expense of throughput.") - ("tpl-wcache-page-size", qpid::optValue(tplWCachePageSizeKib, "N"), - "Size of the pages in the transaction prepared list write page cache in KiB. " - "Allowable values - powers of 2: 1, 2, 4, ... , 128. " - "Lower values decrease latency at the expense of throughput.") - ("efp-partition", qpid::optValue(efpPartition, "N"), - "Empty File Pool partition to use for finding empty journal files") - ("efp-file-size", qpid::optValue(efpFileSizeKib, "N"), - "Empty File Pool file size in KiB to use for journal files. Must be a multiple of 4 KiB.") - ("overwrite-before-return", qpid::optValue(overwriteBeforeReturnFlag, "yes|no"), - "If yes|true|1, will overwrite each store file with zeros before returning " - "it to the Empty File Pool. When not in use (the default), then old message data remains " - "in the file, but is overwritten on next use. This option should only be used where security " - "considerations justify it as it makes the store somewhat slower.") - ("journal-flush-timeout", qpid::optValue(journalFlushTimeout, "SECONDS"), - "Maximum time to wait to flush journal") - ; -} - -}} diff --git a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h b/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h deleted file mode 100644 index 8b11e115b6..0000000000 --- a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h +++ /dev/null @@ -1,355 +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. - * - */ - -#ifndef QPID_LINEARSTORE_MESSAGESTOREIMPL_H -#define QPID_LINEARSTORE_MESSAGESTOREIMPL_H - -#include "qpid/broker/MessageStore.h" - -#include "qpid/Options.h" -#include "qpid/linearstore/IdSequence.h" -#include "qpid/linearstore/JournalLogImpl.h" -#include "qpid/linearstore/journal/jcfg.h" -#include "qpid/linearstore/journal/EmptyFilePoolTypes.h" -#include "qpid/linearstore/PreparedTransaction.h" -#include "qpid/sys/Time.h" - -#include "qmf/org/apache/qpid/linearstore/Store.h" - -#include - -// Assume DB_VERSION_MAJOR == 4 -#if (DB_VERSION_MINOR == 2) -#include -#define DB_BUFFER_SMALL ENOMEM -#endif - -class Db; -class DbEnv; -class Dbt; -class DbTxn; - -namespace qpid { -namespace broker { - class Broker; -} -namespace sys { - class Timer; -} -namespace linearstore{ -namespace journal { - class EmptyFilePool; - class EmptyFilePoolManager; -} - -class IdDbt; -class JournalImpl; -class TplJournalImpl; -class TxnCtxt; - -/** - * An implementation of the MessageStore interface based on Berkeley DB - */ -class MessageStoreImpl : public qpid::broker::MessageStore, public qpid::management::Manageable -{ - public: - typedef boost::shared_ptr db_ptr; - typedef boost::shared_ptr dbEnv_ptr; - - struct StoreOptions : public qpid::Options { - StoreOptions(const std::string& name="Linear Store Options"); - std::string clusterName; - std::string storeDir; - bool truncateFlag; - uint32_t wCachePageSizeKib; - uint32_t tplWCachePageSizeKib; - uint16_t efpPartition; - uint64_t efpFileSizeKib; - bool overwriteBeforeReturnFlag; - qpid::sys::Duration journalFlushTimeout; - }; - - private: - typedef std::map queue_index; - typedef std::map exchange_index; - typedef std::map message_index; - - typedef LockedMappings::map txn_lock_map; - typedef boost::ptr_list txn_list; - - typedef std::map JournalListMap; - typedef JournalListMap::iterator JournalListMapItr; - - // Default store settings - static const bool defTruncateFlag = false; - static const uint32_t defWCachePageSizeKib = QLS_WMGR_DEF_PAGE_SIZE_KIB; - static const uint32_t defTplWCachePageSizeKib = defWCachePageSizeKib / 8; - static const uint16_t defEfpPartition = 1; - static const uint64_t defEfpFileSizeKib = 512 * QLS_SBLK_SIZE_KIB; - static const bool defOverwriteBeforeReturnFlag = false; - static const std::string storeTopLevelDir; - - // FIXME aconway 2010-03-09: was 10ms - static const uint64_t defJournalGetEventsTimeoutNs = 1 * 1000000; // 1ms - static const uint64_t defJournalFlushTimeoutNs = 500 * 1000000; // 500ms - - std::list dbs; - dbEnv_ptr dbenv; - db_ptr queueDb; - db_ptr configDb; - db_ptr exchangeDb; - db_ptr mappingDb; - db_ptr bindingDb; - db_ptr generalDb; - - // Pointer to Transaction Prepared List (TPL) journal instance - boost::shared_ptr tplStorePtr; - qpid::sys::Mutex tplInitLock; - JournalListMap journalList; - qpid::sys::Mutex journalListLock; - qpid::sys::Mutex bdbLock; - - IdSequence queueIdSequence; - IdSequence exchangeIdSequence; - IdSequence generalIdSequence; - IdSequence messageIdSequence; - std::string storeDir; - qpid::linearstore::journal::efpPartitionNumber_t defaultEfpPartitionNumber; - qpid::linearstore::journal::efpDataSize_kib_t defaultEfpFileSize_kib; - bool overwriteBeforeReturnFlag; - uint32_t wCachePgSizeSblks; - uint16_t wCacheNumPages; - uint32_t tplWCachePgSizeSblks; - uint16_t tplWCacheNumPages; - uint64_t highestRid; - qpid::sys::Duration journalFlushTimeout; - bool isInit; - const char* envPath; - qpid::broker::Broker* broker; - JournalLogImpl jrnlLog; - boost::shared_ptr efpMgr; - - qmf::org::apache::qpid::linearstore::Store::shared_ptr mgmtObject; - qpid::management::ManagementAgent* agent; - - - // Parameter validation and calculation - static uint32_t chkJrnlWrPageCacheSize(const uint32_t param, - const std::string& paramName/*, - const uint16_t jrnlFsizePgs*/); - static uint16_t getJrnlWrNumPages(const uint32_t wrPageSizeKiB); - static qpid::linearstore::journal::efpPartitionNumber_t chkEfpPartition(const qpid::linearstore::journal::efpPartitionNumber_t partition, - const std::string& paramName); - static qpid::linearstore::journal::efpDataSize_kib_t chkEfpFileSizeKiB(const qpid::linearstore::journal::efpDataSize_kib_t efpFileSizeKiB, - const std::string& paramName); - - void init(const bool truncateFlag); - - void recoverQueues(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery, - queue_index& index, - txn_list& locked, - message_index& messages); - void recoverMessages(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery, - queue_index& index, - txn_list& locked, - message_index& prepared); - void recoverMessages(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery, - qpid::broker::RecoverableQueue::shared_ptr& queue, - txn_list& locked, - message_index& prepared, - long& rcnt, - long& idcnt); - qpid::broker::RecoverableMessage::shared_ptr getExternMessage(qpid::broker::RecoveryManager& recovery, - uint64_t mId, - unsigned& headerSize); - void recoverExchanges(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery, - exchange_index& index); - void recoverBindings(TxnCtxt& txn, - exchange_index& exchanges, - queue_index& queues); - void recoverGeneral(TxnCtxt& txn, - qpid::broker::RecoveryManager& recovery); - int enqueueMessage(TxnCtxt& txn, - IdDbt& msgId, - qpid::broker::RecoverableMessage::shared_ptr& msg, - queue_index& index, - txn_list& locked, - message_index& prepared); - void recoverTplStore(); - void recoverLockedMappings(txn_list& txns); - TxnCtxt* check(qpid::broker::TransactionContext* ctxt); - uint64_t msgEncode(std::vector& buff, const boost::intrusive_ptr& message); - void store(const qpid::broker::PersistableQueue* queue, - TxnCtxt* txn, - const boost::intrusive_ptr& message); - void async_dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue); - void destroy(db_ptr db, - const qpid::broker::Persistable& p); - bool create(db_ptr db, - IdSequence& seq, - const qpid::broker::Persistable& p); - void completed(TxnCtxt& txn, - bool commit); - void deleteBindingsForQueue(const qpid::broker::PersistableQueue& queue); - void deleteBinding(const qpid::broker::PersistableExchange& exchange, - const qpid::broker::PersistableQueue& queue, - const std::string& key); - - void put(db_ptr db, - DbTxn* txn, - Dbt& key, - Dbt& value); - void open(db_ptr db, - DbTxn* txn, - const char* file, - bool dupKey); - void closeDbs(); - - // journal functions - void createJrnlQueue(const qpid::broker::PersistableQueue& queue); - std::string getJrnlDir(const std::string& queueName); - qpid::linearstore::journal::EmptyFilePool* getEmptyFilePool(const qpid::linearstore::journal::efpPartitionNumber_t p, const qpid::linearstore::journal::efpDataSize_kib_t s); - qpid::linearstore::journal::EmptyFilePool* getEmptyFilePool(const qpid::framing::FieldTable& args); - std::string getStoreTopLevelDir(); - std::string getJrnlBaseDir(); - std::string getBdbBaseDir(); - std::string getTplBaseDir(); - inline void checkInit() { - // TODO: change the default dir to ~/.qpidd - if (!isInit) { init("/tmp"); isInit = true; } - } - void chkTplStoreInit(); - - public: - typedef boost::shared_ptr shared_ptr; - - MessageStoreImpl(qpid::broker::Broker* broker, const char* envpath = 0); - - virtual ~MessageStoreImpl(); - - bool init(const qpid::Options* options); - - bool init(const std::string& dir, - qpid::linearstore::journal::efpPartitionNumber_t efpPartition = defEfpPartition, - qpid::linearstore::journal::efpDataSize_kib_t efpFileSizeKib = defEfpFileSizeKib, - const bool truncateFlag = false, - uint32_t wCachePageSize = defWCachePageSizeKib, - uint32_t tplWCachePageSize = defTplWCachePageSizeKib, - const bool overwriteBeforeReturnFlag_ = false); - - void truncateInit(); - - void initManagement (); - - void finalize(); - - // --- Implementation of qpid::broker::MessageStore --- - - void create(qpid::broker::PersistableQueue& queue, - const qpid::framing::FieldTable& args); - - void destroy(qpid::broker::PersistableQueue& queue); - - void create(const qpid::broker::PersistableExchange& queue, - const qpid::framing::FieldTable& args); - - void destroy(const qpid::broker::PersistableExchange& queue); - - void bind(const qpid::broker::PersistableExchange& exchange, - const qpid::broker::PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - void unbind(const qpid::broker::PersistableExchange& exchange, - const qpid::broker::PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - void create(const qpid::broker::PersistableConfig& config); - - void destroy(const qpid::broker::PersistableConfig& config); - - void recover(qpid::broker::RecoveryManager& queues); - - void stage(const boost::intrusive_ptr& msg); - - void destroy(qpid::broker::PersistableMessage& msg); - - void appendContent(const boost::intrusive_ptr& msg, - const std::string& data); - - void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - void enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue); - - void dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const qpid::broker::PersistableQueue& queue); - - void flush(const qpid::broker::PersistableQueue& queue); - - inline uint32_t outstandingQueueAIO(const qpid::broker::PersistableQueue& /*queue*/) { return 0; }; // TODO: Deprecate this call - - void collectPreparedXids(std::set& xids); - - std::auto_ptr begin(); - - std::auto_ptr begin(const std::string& xid); - - void prepare(qpid::broker::TPCTransactionContext& ctxt); - - void localPrepare(TxnCtxt* ctxt); - - void commit(qpid::broker::TransactionContext& ctxt); - - void abort(qpid::broker::TransactionContext& ctxt); - - // --- Implementation of qpid::management::Managable --- - - qpid::management::ManagementObject::shared_ptr GetManagementObject (void) const - { return mgmtObject; } - - inline qpid::management::Manageable::status_t ManagementMethod (uint32_t, qpid::management::Args&, std::string&) - { return qpid::management::Manageable::STATUS_OK; } - - std::string getStoreDir() const; - - private: - void journalDeleted(JournalImpl&); - -}; // class MessageStoreImpl - -} // namespace msgstore -} // namespace mrg - -#endif // ifndef QPID_LINEARSTORE_MESSAGESTOREIMPL_H diff --git a/qpid/cpp/src/qpid/linearstore/PreparedTransaction.cpp b/qpid/cpp/src/qpid/linearstore/PreparedTransaction.cpp deleted file mode 100644 index 1b92ca8c23..0000000000 --- a/qpid/cpp/src/qpid/linearstore/PreparedTransaction.cpp +++ /dev/null @@ -1,81 +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/linearstore/PreparedTransaction.h" - -namespace qpid { -namespace linearstore { - -void LockedMappings::add(queue_id queue, message_id message) -{ - locked.push_back(std::make_pair(queue, message)); -} - -bool LockedMappings::isLocked(queue_id queue, message_id message) -{ - idpair op( std::make_pair(queue, message) ); - return find(locked.begin(), locked.end(), op) != locked.end(); -} - -void LockedMappings::add(LockedMappings::map& map, std::string& key, queue_id queue, message_id message) -{ - LockedMappings::map::iterator i = map.find(key); - if (i == map.end()) { - LockedMappings::shared_ptr ptr(new LockedMappings()); - i = map.insert(std::make_pair(key, ptr)).first; - } - i->second->add(queue, message); -} - -bool PreparedTransaction::isLocked(queue_id queue, message_id message) -{ - return (enqueues.get() && enqueues->isLocked(queue, message)) - || (dequeues.get() && dequeues->isLocked(queue, message)); -} - - -bool PreparedTransaction::isLocked(PreparedTransaction::list& txns, queue_id queue, message_id message) -{ - for (PreparedTransaction::list::iterator i = txns.begin(); i != txns.end(); i++) { - if (i->isLocked(queue, message)) { - return true; - } - } - return false; -} - -PreparedTransaction::list::iterator PreparedTransaction::getLockedPreparedTransaction(PreparedTransaction::list& txns, queue_id queue, message_id message) -{ - for (PreparedTransaction::list::iterator i = txns.begin(); i != txns.end(); i++) { - if (i->isLocked(queue, message)) { - return i; - } - } - return txns.end(); -} - -PreparedTransaction::PreparedTransaction(const std::string& _xid, - LockedMappings::shared_ptr _enqueues, - LockedMappings::shared_ptr _dequeues) - - : xid(_xid), enqueues(_enqueues), dequeues(_dequeues) {} - -}} diff --git a/qpid/cpp/src/qpid/linearstore/PreparedTransaction.h b/qpid/cpp/src/qpid/linearstore/PreparedTransaction.h deleted file mode 100644 index 7b381ba3b9..0000000000 --- a/qpid/cpp/src/qpid/linearstore/PreparedTransaction.h +++ /dev/null @@ -1,73 +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. - * - */ - -#ifndef QPID_LINEARSTORE_PREPAREDTRANSACTION_H -#define QPID_LINEARSTORE_PREPAREDTRANSACTION_H - -#include -#include -#include -#include -#include - -namespace qpid{ -namespace linearstore{ - -typedef uint64_t queue_id; -typedef uint64_t message_id; - -class LockedMappings -{ -public: - typedef boost::shared_ptr shared_ptr; - typedef std::map map; - typedef std::pair idpair; - typedef std::list::iterator iterator; - - void add(queue_id queue, message_id message); - bool isLocked(queue_id queue, message_id message); - std::size_t size() { return locked.size(); } - iterator begin() { return locked.begin(); } - iterator end() { return locked.end(); } - - static void add(LockedMappings::map& map, std::string& key, queue_id queue, message_id message); - -private: - std::list locked; -}; - -struct PreparedTransaction -{ - typedef boost::ptr_list list; - - const std::string xid; - const LockedMappings::shared_ptr enqueues; - const LockedMappings::shared_ptr dequeues; - - PreparedTransaction(const std::string& xid, LockedMappings::shared_ptr enqueues, LockedMappings::shared_ptr dequeues); - bool isLocked(queue_id queue, message_id message); - static bool isLocked(PreparedTransaction::list& txns, queue_id queue, message_id message); - static PreparedTransaction::list::iterator getLockedPreparedTransaction(PreparedTransaction::list& txns, queue_id queue, message_id message); -}; - -}} - -#endif // ifndef QPID_LINEARSTORE_PREPAREDTRANSACTION_H diff --git a/qpid/cpp/src/qpid/linearstore/StoreException.h b/qpid/cpp/src/qpid/linearstore/StoreException.h deleted file mode 100644 index 7a598a524f..0000000000 --- a/qpid/cpp/src/qpid/linearstore/StoreException.h +++ /dev/null @@ -1,56 +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. - * - */ - -#ifndef QPID_LINEARSTORE_STOREEXCEPTION_H -#define QPID_LINEARSTORE_STOREEXCEPTION_H - -#include -#include "db-inc.h" - -namespace qpid{ -namespace linearstore{ - -class StoreException : public std::exception -{ - std::string text; -public: - StoreException(const std::string& _text) : text(_text) {} - StoreException(const std::string& _text, const DbException& cause) : text(_text + ": " + cause.what()) {} - virtual ~StoreException() throw() {} - virtual const char* what() const throw() { return text.c_str(); } -}; - -class StoreFullException : public StoreException -{ -public: - StoreFullException(const std::string& _text) : StoreException(_text) {} - StoreFullException(const std::string& _text, const DbException& cause) : StoreException(_text, cause) {} - virtual ~StoreFullException() throw() {} - -}; - -#define THROW_STORE_EXCEPTION(MESSAGE) throw StoreException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__)) -#define THROW_STORE_EXCEPTION_2(MESSAGE, EXCEPTION) throw StoreException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__), EXCEPTION) -#define THROW_STORE_FULL_EXCEPTION(MESSAGE) throw StoreFullException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__)) - -}} - -#endif // ifndef QPID_LINEARSTORE_STOREEXCEPTION_H diff --git a/qpid/cpp/src/qpid/linearstore/StorePlugin.cpp b/qpid/cpp/src/qpid/linearstore/StorePlugin.cpp deleted file mode 100644 index cd8c7ed8a3..0000000000 --- a/qpid/cpp/src/qpid/linearstore/StorePlugin.cpp +++ /dev/null @@ -1,97 +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/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/DataDir.h" -#include "qpid/linearstore/JournalLogImpl.h" -#include "qpid/linearstore/MessageStoreImpl.h" -#include "qpid/log/Statement.h" - -using qpid::linearstore::MessageStoreImpl; - -namespace qpid { -namespace broker { - -using namespace std; - -struct StorePlugin : public Plugin { - - MessageStoreImpl::StoreOptions options; - boost::shared_ptr store; - - Options* getOptions() { return &options; } - - void earlyInitialize (Plugin::Target& target) - { - Broker* broker = dynamic_cast(&target); - if (!broker) return; - store.reset(new MessageStoreImpl(broker)); - const DataDir& dataDir = broker->getDataDir (); - if (options.storeDir.empty ()) - { - if (!dataDir.isEnabled ()) - throw Exception ("linearstore: If broker option --data-dir is blank or --no-data-dir is specified, linearstore option --store-dir must be present."); - - options.storeDir = dataDir.getPath (); - } else { - // Check if store dir is absolute. If not, make it absolute using qpidd executable dir as base - if (options.storeDir.at(0) != '/') { - char buf[1024]; - if (::getcwd(buf, sizeof(buf)-1) == 0) { - std::ostringstream oss; - oss << "linearstore: getcwd() unable to read current directory: errno=" << errno << " (" << strerror(errno) << ")"; - throw Exception(oss.str()); - } - std::string newStoreDir = std::string(buf) + "/" + options.storeDir; - std::ostringstream oss; - oss << "store-dir option \"" << options.storeDir << "\" is not absolute, changed to \"" << newStoreDir << "\""; - QLS_LOG(warning, oss.str()); - options.storeDir = newStoreDir; - } - } - store->init(&options); - boost::shared_ptr brokerStore(store); - broker->setStore(brokerStore); - target.addFinalizer(boost::bind(&StorePlugin::finalize, this)); - } - - void initialize(Plugin::Target& target) - { - Broker* broker = dynamic_cast(&target); - if (!broker) return; - if (!store) return; - QLS_LOG(info, "Enabling management instrumentation."); - store->initManagement(); - } - - void finalize() - { - store.reset(); - } - - const char* id() {return "StorePlugin";} -}; - -static StorePlugin instance; // Static initialization. - -}} // namespace qpid::broker diff --git a/qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp b/qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp deleted file mode 100644 index e26f0b8b6f..0000000000 --- a/qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp +++ /dev/null @@ -1,185 +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/linearstore/TxnCtxt.h" - -#include "qpid/linearstore/DataTokenImpl.h" -#include "qpid/linearstore/JournalImpl.h" -#include "qpid/linearstore/StoreException.h" - -namespace qpid{ -namespace linearstore{ - -void TxnCtxt::completeTxn(bool commit) { - sync(); - for (ipqItr i = impactedQueues.begin(); i != impactedQueues.end(); i++) { - commitTxn(static_cast(*i), commit); - } - impactedQueues.clear(); - if (preparedXidStorePtr) - commitTxn(preparedXidStorePtr, commit); -} - -void TxnCtxt::commitTxn(JournalImpl* jc, bool commit) { - if (jc && loggedtx) { /* if using journal */ - boost::intrusive_ptr dtokp(new DataTokenImpl); - dtokp->addRef(); - dtokp->set_external_rid(true); - dtokp->set_rid(loggedtx->next()); - try { - if (commit) { - jc->txn_commit(dtokp.get(), getXid()); - sync(); - } else { - jc->txn_abort(dtokp.get(), getXid()); - } - } catch (const qpid::linearstore::journal::jexception& e) { - std::ostringstream oss; - oss << "Error during " << (commit ? "commit" : "abort") << ": " << e.what(); - THROW_STORE_EXCEPTION(oss.str()); - } - } -} - -// static -sys::uuid_t TxnCtxt::uuid; - -// static -IdSequence TxnCtxt::uuidSeq; - -// static -bool TxnCtxt::staticInit = TxnCtxt::setUuid(); - -// static -bool TxnCtxt::setUuid() { - qpid::sys::uuid_generate(uuid); - return true; -} - -TxnCtxt::TxnCtxt(IdSequence* _loggedtx) : loggedtx(_loggedtx), dtokp(new DataTokenImpl), preparedXidStorePtr(0), txn(0) { - if (loggedtx) { -// // Human-readable tid: 53 bytes -// // uuit_t is a char[16] -// tid.reserve(53); -// uint64_t* u1 = (uint64_t*)uuid; -// uint64_t* u2 = (uint64_t*)(uuid + sizeof(uint64_t)); -// std::stringstream s; -// s << "tid:" << std::hex << std::setfill('0') << std::setw(16) << uuidSeq.next() << ":" << std::setw(16) << *u1 << std::setw(16) << *u2; -// tid.assign(s.str()); - - // Binary tid: 24 bytes - tid.reserve(24); - uint64_t c = uuidSeq.next(); - tid.append((char*)&c, sizeof(c)); - tid.append((char*)&uuid, sizeof(uuid)); - } -} - -TxnCtxt::TxnCtxt(std::string _tid, IdSequence* _loggedtx) : loggedtx(_loggedtx), dtokp(new DataTokenImpl), preparedXidStorePtr(0), tid(_tid), txn(0) {} - -TxnCtxt::~TxnCtxt() { abort(); } - -void TxnCtxt::sync() { - if (loggedtx) { - try { - for (ipqItr i = impactedQueues.begin(); i != impactedQueues.end(); i++) - jrnl_flush(static_cast(*i)); - if (preparedXidStorePtr) - jrnl_flush(preparedXidStorePtr); - for (ipqItr i = impactedQueues.begin(); i != impactedQueues.end(); i++) - jrnl_sync(static_cast(*i), &qpid::linearstore::journal::jcntl::_aio_cmpl_timeout); - if (preparedXidStorePtr) - jrnl_sync(preparedXidStorePtr, &qpid::linearstore::journal::jcntl::_aio_cmpl_timeout); - } catch (const qpid::linearstore::journal::jexception& e) { - THROW_STORE_EXCEPTION(std::string("Error during txn sync: ") + e.what()); - } - } -} - -void TxnCtxt::jrnl_flush(JournalImpl* jc) { - if (jc && !(jc->is_txn_synced(getXid()))) - jc->flush(false); -} - -void TxnCtxt::jrnl_sync(JournalImpl* jc, timespec* timeout) { - if (!jc || jc->is_txn_synced(getXid())) - return; - while (jc->get_wr_aio_evt_rem()) { - if (jc->get_wr_events(timeout) == qpid::linearstore::journal::jerrno::AIO_TIMEOUT && timeout) - THROW_STORE_EXCEPTION(std::string("Error: timeout waiting for TxnCtxt::jrnl_sync()")); - } -} - -void TxnCtxt::begin(DbEnv* env, bool sync) { - int err; - try { err = env->txn_begin(0, &txn, 0); } - catch (const DbException&) { txn = 0; throw; } - if (err != 0) { - std::ostringstream oss; - oss << "Error: Env::txn_begin() returned error code: " << err; - THROW_STORE_EXCEPTION(oss.str()); - } - if (sync) - globalHolder = AutoScopedLock(new qpid::sys::Mutex::ScopedLock(globalSerialiser)); -} - -void TxnCtxt::commit() { - if (txn) { - txn->commit(0); - txn = 0; - globalHolder.reset(); - } -} - -void TxnCtxt::abort(){ - if (txn) { - txn->abort(); - txn = 0; - globalHolder.reset(); - } -} - -DbTxn* TxnCtxt::get() { return txn; } - -bool TxnCtxt::isTPC() { return false; } - -const std::string& TxnCtxt::getXid() { return tid; } - -void TxnCtxt::addXidRecord(qpid::broker::ExternalQueueStore* queue) { impactedQueues.insert(queue); } - -void TxnCtxt::complete(bool commit) { completeTxn(commit); } - -bool TxnCtxt::impactedQueuesEmpty() { return impactedQueues.empty(); } - -DataTokenImpl* TxnCtxt::getDtok() { return dtokp.get(); } - -void TxnCtxt::incrDtokRef() { dtokp->addRef(); } - -void TxnCtxt::recoverDtok(const uint64_t rid, const std::string xid) { - dtokp->set_rid(rid); - dtokp->set_wstate(DataTokenImpl::ENQ); - dtokp->set_xid(xid); - dtokp->set_external_rid(true); -} - -TPCTxnCtxt::TPCTxnCtxt(const std::string& _xid, IdSequence* _loggedtx) : TxnCtxt(_loggedtx), xid(_xid) {} - -}} diff --git a/qpid/cpp/src/qpid/linearstore/TxnCtxt.h b/qpid/cpp/src/qpid/linearstore/TxnCtxt.h deleted file mode 100644 index 764063a615..0000000000 --- a/qpid/cpp/src/qpid/linearstore/TxnCtxt.h +++ /dev/null @@ -1,115 +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. - * - */ - -#ifndef QPID_LINEARSTORE_TXNCTXT_H -#define QPID_LINEARSTORE_TXNCTXT_H - -#include -#include "qpid/broker/TransactionalStore.h" -#include "qpid/linearstore/IdSequence.h" -#include "qpid/sys/uuid.h" - -class DbEnv; -class DbTxn; - -namespace qpid { -namespace broker { - class ExternalQueueStore; -} -namespace linearstore{ - class DataTokenImpl; - class JournalImpl; - -class TxnCtxt : public qpid::broker::TransactionContext -{ - protected: - static qpid::sys::Mutex globalSerialiser; - - static sys::uuid_t uuid; - static IdSequence uuidSeq; - static bool staticInit; - static bool setUuid(); - - typedef std::set ipqdef; - typedef ipqdef::iterator ipqItr; - typedef std::auto_ptr AutoScopedLock; - - ipqdef impactedQueues; // list of Queues used in the txn - IdSequence* loggedtx; - boost::intrusive_ptr dtokp; - AutoScopedLock globalHolder; - JournalImpl* preparedXidStorePtr; - - /** - * local txn id, if non XA. - */ - std::string tid; - DbTxn* txn; - - virtual void completeTxn(bool commit); - void commitTxn(JournalImpl* jc, bool commit); - void jrnl_flush(JournalImpl* jc); - void jrnl_sync(JournalImpl* jc, timespec* timeout); - - public: - TxnCtxt(IdSequence* _loggedtx=NULL); - TxnCtxt(std::string _tid, IdSequence* _loggedtx); - virtual ~TxnCtxt(); - - /** - * Call to make sure all the data for this txn is written to safe store - * - *@return if the data successfully synced. - */ - void sync(); - void begin(DbEnv* env, bool sync = false); - void commit(); - void abort(); - DbTxn* get(); - virtual bool isTPC(); - virtual const std::string& getXid(); - - void addXidRecord(qpid::broker::ExternalQueueStore* queue); - inline void prepare(JournalImpl* _preparedXidStorePtr) { preparedXidStorePtr = _preparedXidStorePtr; } - void complete(bool commit); - bool impactedQueuesEmpty(); - DataTokenImpl* getDtok(); - void incrDtokRef(); - void recoverDtok(const uint64_t rid, const std::string xid); -}; - - -class TPCTxnCtxt : public TxnCtxt, public qpid::broker::TPCTransactionContext -{ - protected: - const std::string xid; - - public: - TPCTxnCtxt(const std::string& _xid, IdSequence* _loggedtx); - inline virtual bool isTPC() { return true; } - inline virtual const std::string& getXid() { return xid; } -}; - -}} - -#endif // ifndef QPID_LINEARSTORE_TXNCTXT_H - - diff --git a/qpid/cpp/src/qpid/linearstore/journal/AtomicCounter.h b/qpid/cpp/src/qpid/linearstore/journal/AtomicCounter.h deleted file mode 100644 index 73e5fecf93..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/AtomicCounter.h +++ /dev/null @@ -1,133 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_ATOMICCOUNTER_H_ -#define QPID_LINEARSTORE_JOURNAL_ATOMICCOUNTER_H_ - -#include "qpid/linearstore/journal/slock.h" -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -template -class AtomicCounter -{ -private: - std::string id_; - T count_; - mutable smutex countMutex; - -public: - AtomicCounter(const std::string& id, const T& initValue) : id_(id), count_(initValue) {} - - virtual ~AtomicCounter() {} - - T get() const { - slock l(countMutex); - return count_; - } - - void set(const T v) { - slock l(countMutex); - count_ = v; - } - - T increment() { - slock l(countMutex); - return ++count_; - } - - T add(const T& a) { - slock l(countMutex); - count_ += a; - return count_; - } - - T addLimit(const T& a, const T& limit, const uint32_t jerr) { - slock l(countMutex); - if (count_ + a > limit) throw jexception(jerr, id_, "AtomicCounter", "addLimit"); - count_ += a; - return count_; - } - - T decrement() { - slock l(countMutex); - return --count_; - } - - T decrementLimit(const T& limit = T(0), const uint32_t jerr = jerrno::JERR__UNDERFLOW) { - slock l(countMutex); - if (count_ < limit + 1) { - throw jexception(jerr, id_, "AtomicCounter", "decrementLimit"); - } - return --count_; - } - - T subtract(const T& s) { - slock l(countMutex); - count_ -= s; - return count_; - } - - T subtractLimit(const T& s, const T& limit = T(0), const uint32_t jerr = jerrno::JERR__UNDERFLOW) { - slock l(countMutex); - if (count_ < limit + s) throw jexception(jerr, id_, "AtomicCounter", "subtractLimit"); - count_ -= s; - return count_; - } - - bool operator==(const T& o) const { - slock l(countMutex); - return count_ == o; - } - - bool operator<(const T& o) const { - slock l(countMutex); - return count_ < o; - } - - bool operator<=(const T& o) const { - slock l(countMutex); - return count_ <= o; - } - - friend T operator-(const T& a, const AtomicCounter& b) { - slock l(b.countMutex); - return a - b.count_; - } - - friend T operator-(const AtomicCounter& a, const T& b) { - slock l(a.countMutex); - return a.count_ - b; - } - - friend T operator-(const AtomicCounter&a, const AtomicCounter& b) { - slock l1(a.countMutex); - slock l2(b.countMutex); - return a.count_ - b.count_; - } -}; - -}}} // namespace qpid::qls_jrnl - -#endif // QPID_LINEARSTORE_JOURNAL_ATOMICCOUNTER_H_ diff --git a/qpid/cpp/src/qpid/linearstore/journal/Checksum.cpp b/qpid/cpp/src/qpid/linearstore/journal/Checksum.cpp deleted file mode 100644 index eaede12d8e..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/Checksum.cpp +++ /dev/null @@ -1,45 +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/linearstore/journal/Checksum.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -Checksum::Checksum() : a(1UL), b(0UL), MOD_ADLER(65521UL) {} - -Checksum::~Checksum() {} - -void Checksum::addData(const unsigned char* data, const std::size_t len) { - if (data) { - for (uint32_t i = 0; i < len; i++) { - a = (a + data[i]) % MOD_ADLER; - b = (a + b) % MOD_ADLER; - } - } -} - -uint32_t Checksum::getChecksum() { - return (b << 16) | a; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/Checksum.h b/qpid/cpp/src/qpid/linearstore/journal/Checksum.h deleted file mode 100644 index d96aac2991..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/Checksum.h +++ /dev/null @@ -1,54 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_CHECKSUM_H_ -#define QPID_LINEARSTORE_JOURNAL_CHECKSUM_H_ - -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -/* - * This checksum routine uses the Adler-32 algorithm as described in - * http://en.wikipedia.org/wiki/Adler-32. It is structured so that the - * data for which the checksum must be calculated can be added in several - * stages through the addData() function, and when complete, the checksum - * is obtained through a call to getChecksum(). - */ -class Checksum -{ -private: - uint32_t a; - uint32_t b; - const uint32_t MOD_ADLER; -public: - Checksum(); - virtual ~Checksum(); - void addData(const unsigned char* data, const std::size_t len); - uint32_t getChecksum(); -}; - -}}} - -#endif // QPID_LINEARSTORE_JOURNAL_CHECKSUM_H_ diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.cpp b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.cpp deleted file mode 100644 index 681ced3fd7..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.cpp +++ /dev/null @@ -1,479 +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 "EmptyFilePool.h" - -#include -#include "qpid/linearstore/journal/EmptyFilePoolPartition.h" -#include "qpid/linearstore/journal/jcfg.h" -#include "qpid/linearstore/journal/jdir.h" -#include "qpid/linearstore/journal/JournalLog.h" -#include "qpid/linearstore/journal/slock.h" -#include "qpid/linearstore/journal/utils/file_hdr.h" -#include "qpid/types/Uuid.h" -#include -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -// static -std::string EmptyFilePool::s_inuseFileDirectory_ = "in_use"; - -// static -std::string EmptyFilePool::s_returnedFileDirectory_ = "returned"; - -EmptyFilePool::EmptyFilePool(const std::string& efpDirectory, - const EmptyFilePoolPartition* partitionPtr, - const bool overwriteBeforeReturnFlag, - const bool truncateFlag, - JournalLog& journalLogRef) : - efpDirectory_(efpDirectory), - efpDataSize_kib_(dataSizeFromDirName_kib(efpDirectory, partitionPtr->getPartitionNumber())), - partitionPtr_(partitionPtr), - overwriteBeforeReturnFlag_(overwriteBeforeReturnFlag), - truncateFlag_(truncateFlag), - journalLogRef_(journalLogRef) -{} - -EmptyFilePool::~EmptyFilePool() {} - -void EmptyFilePool::initialize() { - if (::mkdir(efpDirectory_.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) { // Create EFP dir if it does not yet exist - if (errno != EEXIST) { - std::ostringstream oss; - oss << "directory=" << efpDirectory_ << " " << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_EFP_MKDIR, oss.str(), "EmptyFilePool", "initialize"); - } - } - - // Process empty files in main dir - std::vector dirList; - jdir::read_dir(efpDirectory_, dirList, false, true, false, false); - for (std::vector::iterator i = dirList.begin(); i != dirList.end(); ++i) { - size_t dotPos = i->rfind("."); - if (dotPos != std::string::npos) { - if (i->substr(dotPos).compare(".jrnl") == 0 && i->length() == 41) { - std::string emptyFileName(efpDirectory_ + "/" + (*i)); - if (validateEmptyFile(emptyFileName)) { - pushEmptyFile(emptyFileName); - } - } - } - } - - // Create 'in_use' and 'returned' subdirs if they don't already exist - // Return files to EFP in 'in_use' and 'returned' subdirs if they do exist - initializeSubDirectory(efpDirectory_ + "/" + s_inuseFileDirectory_); - initializeSubDirectory(efpDirectory_ + "/" + s_returnedFileDirectory_); -} - -efpDataSize_kib_t EmptyFilePool::dataSize_kib() const { - return efpDataSize_kib_; -} - -efpFileSize_kib_t EmptyFilePool::fileSize_kib() const { - return efpDataSize_kib_ + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB); -} - -efpDataSize_sblks_t EmptyFilePool::dataSize_sblks() const { - return efpDataSize_kib_ / QLS_SBLK_SIZE_KIB; -} - -efpFileSize_sblks_t EmptyFilePool::fileSize_sblks() const { - return (efpDataSize_kib_ / QLS_SBLK_SIZE_KIB) + QLS_JRNL_FHDR_RES_SIZE_SBLKS; -} - -efpFileCount_t EmptyFilePool::numEmptyFiles() const { - slock l(emptyFileListMutex_); - return efpFileCount_t(emptyFileList_.size()); -} - -efpDataSize_kib_t EmptyFilePool::cumFileSize_kib() const { - slock l(emptyFileListMutex_); - return efpDataSize_kib_t(emptyFileList_.size()) * efpDataSize_kib_; -} - -efpPartitionNumber_t EmptyFilePool::getPartitionNumber() const { - return partitionPtr_->getPartitionNumber(); -} - -const EmptyFilePoolPartition* EmptyFilePool::getPartition() const { - return partitionPtr_; -} - -const efpIdentity_t EmptyFilePool::getIdentity() const { - return efpIdentity_t(partitionPtr_->getPartitionNumber(), efpDataSize_kib_); -} - -std::string EmptyFilePool::takeEmptyFile(const std::string& destDirectory) { - std::string emptyFileName = popEmptyFile(); - std::string newFileName = efpDirectory_ + "/" + s_inuseFileDirectory_ + emptyFileName.substr(emptyFileName.rfind('/')); // NOTE: substr() includes leading '/' - std::string symlinkName = destDirectory + emptyFileName.substr(emptyFileName.rfind('/')); // NOTE: substr() includes leading '/' - if (!moveFile(emptyFileName, newFileName)) { - // Try again with new UUID for file name - newFileName = efpDirectory_ + "/" + s_inuseFileDirectory_ + "/" + getEfpFileName(); - if (!moveFile(emptyFileName, newFileName)) { -//std::cerr << "*** DEBUG: pushEmptyFile " << emptyFileName << "from EmptyFilePool::takeEmptyFile()" << std::endl; // DEBUG - pushEmptyFile(emptyFileName); // Return empty file to pool - std::ostringstream oss; - oss << "file=\"" << emptyFileName << "\" dest=\"" << newFileName << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "EmptyFilePool", "takeEmptyFile"); - } - } - if (createSymLink(newFileName, symlinkName)) { - std::ostringstream oss; - oss << "file=\"" << emptyFileName << "\" dest=\"" << newFileName << "\" symlink=\"" << symlinkName << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__SYMLINK, oss.str(), "EmptyFilePool", "takeEmptyFile"); - } - return symlinkName; -} - -void EmptyFilePool::returnEmptyFileSymlink(const std::string& emptyFileSymlink) { - if (isFile(emptyFileSymlink)) { - returnEmptyFile(emptyFileSymlink); - } else if(isSymlink(emptyFileSymlink)) { - returnEmptyFile(deleteSymlink(emptyFileSymlink)); - } else { - std::ostringstream oss; - oss << "File \"" << emptyFileSymlink << "\" is neither a file nor a symlink"; - throw jexception(jerrno::JERR_EFP_BADFILETYPE, oss.str(), "EmptyFilePool", "returnEmptyFileSymlink"); - } -} - -//static -std::string EmptyFilePool::dirNameFromDataSize(const efpDataSize_kib_t efpDataSize_kib) { - std::ostringstream oss; - oss << efpDataSize_kib << "k"; - return oss.str(); -} - - -// static -efpDataSize_kib_t EmptyFilePool::dataSizeFromDirName_kib(const std::string& dirName, - const efpPartitionNumber_t partitionNumber) { - // Check for dirName format 'NNNk', where NNN is a number, convert NNN into an integer. NNN cannot be 0. - std::string n(dirName.substr(dirName.rfind('/')+1)); - bool valid = true; - for (uint16_t charNum = 0; charNum < n.length(); ++charNum) { - if (charNum < n.length()-1) { - if (!::isdigit((int)n[charNum])) { - valid = false; - break; - } - } else { - valid = n[charNum] == 'k'; - } - } - efpDataSize_kib_t s = ::atol(n.c_str()); - if (!valid || s == 0 || s % QLS_SBLK_SIZE_KIB != 0) { - std::ostringstream oss; - oss << "Partition: " << partitionNumber << "; EFP directory: \'" << n << "\'"; - throw jexception(jerrno::JERR_EFP_BADEFPDIRNAME, oss.str(), "EmptyFilePool", "fileSizeKbFromDirName"); - } - return s; -} - -// --- protected functions --- -void EmptyFilePool::checkIosState(const int io_errno, - std::ofstream& ofs, - const uint32_t jerrno, - const std::string& fqFileName, - const std::string& operation, - const std::string& errorMessage, - const std::string& className, - const std::string& fnName) { - if (!ofs.good()) { - if (ofs.is_open()) { - ofs.close(); - } - std::ostringstream oss; - oss << "IO failure: eofbit=" << (ofs.eof()?"T":"F") << " failbit=" << (ofs.fail()?"T":"F") << " badbit=" - << (ofs.bad()?"T":"F") << " file=" << fqFileName << FORMAT_SYSERR(io_errno) << ") operation=" - << operation << ": " << errorMessage; - throw jexception(jerrno, oss.str(), className, fnName); - } -} - -std::string EmptyFilePool::createEmptyFile() { - std::string efpfn = getEfpFileName(); - overwriteFileContents(efpfn); - return efpfn; -} - -std::string EmptyFilePool::getEfpFileName() { - qpid::types::Uuid uuid(true); - std::ostringstream oss; - oss << efpDirectory_ << "/" << uuid << QLS_JRNL_FILE_EXTENSION; - return oss.str(); -} - -void EmptyFilePool::initializeSubDirectory(const std::string& fqDirName) { - std::vector dirList; - if (jdir::exists(fqDirName)) { - if (truncateFlag_) { - jdir::read_dir(fqDirName, dirList, false, true, false, false); - for (std::vector::iterator i = dirList.begin(); i != dirList.end(); ++i) { - size_t dotPos = i->rfind("."); - if (i->substr(dotPos).compare(".jrnl") == 0 && i->length() == 41) { - returnEmptyFile(fqDirName + "/" + (*i)); - } else { - std::ostringstream oss; - oss << "File \'" << *i << "\' was not a journal file and was not returned to EFP."; - journalLogRef_.log(JournalLog::LOG_WARN, oss.str()); - } - } - } - } else { - jdir::create_dir(fqDirName); - } -} - -void EmptyFilePool::overwriteFileContents(const std::string& fqFileName) { - ::file_hdr_t fh; - ::file_hdr_create(&fh, QLS_FILE_MAGIC, QLS_JRNL_VERSION, QLS_JRNL_FHDR_RES_SIZE_SBLKS, partitionPtr_->getPartitionNumber(), efpDataSize_kib_); - std::ofstream ofs(fqFileName.c_str(), std::ofstream::out | std::ofstream::binary); - checkIosState(errno, ofs, jerrno::JERR_EFP_FOPEN, fqFileName, "constructor", "Failed to create file", "EmptyFilePool", "overwriteFileContents"); - ofs.write((char*)&fh, sizeof(::file_hdr_t)); - checkIosState(errno, ofs, jerrno::JERR_EFP_FWRITE, fqFileName, "write()", "Failed to write header", "EmptyFilePool", "overwriteFileContents"); - uint64_t rem = ((efpDataSize_kib_ + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB)) * 1024) - sizeof(::file_hdr_t); - while (rem--) { - ofs.put('\0'); - checkIosState(errno, ofs, jerrno::JERR_EFP_FWRITE, fqFileName, "put()", "Failed to put \0", "EmptyFilePool", "overwriteFileContents"); - } - ofs.close(); -//std::cout << "*** WARNING: EFP " << efpDirectory_ << " is empty - created new journal file " << fqFileName.substr(fqFileName.rfind('/') + 1) << " on the fly" << std::endl; // DEBUG -} - -std::string EmptyFilePool::popEmptyFile() { - std::string emptyFileName; - bool listEmptyFlag; - { - slock l(emptyFileListMutex_); - listEmptyFlag = emptyFileList_.empty(); - if (!listEmptyFlag) { - emptyFileName = emptyFileList_.front(); - emptyFileList_.pop_front(); - } - } - // If the list is empty, create a new file and return the file name. - if (listEmptyFlag) { - emptyFileName = createEmptyFile(); - } - return emptyFileName; -} - -void EmptyFilePool::pushEmptyFile(const std::string fqFileName) { - slock l(emptyFileListMutex_); - emptyFileList_.push_back(fqFileName); -} - -void EmptyFilePool::returnEmptyFile(const std::string& emptyFileName) { - std::string returnedFileName = efpDirectory_ + "/" + s_returnedFileDirectory_ + emptyFileName.substr(emptyFileName.rfind('/')); // NOTE: substr() includes leading '/' - if (!moveFile(emptyFileName, returnedFileName)) { - ::unlink(emptyFileName.c_str()); -//std::cerr << "*** WARNING: Unable to move file " << emptyFileName << " to " << returnedFileName << "; deleted." << std::endl; // DEBUG - } - - // TODO: On a separate thread, process returned files by overwriting headers and, optionally, their contents and - // returning them to the EFP directory - resetEmptyFileHeader(returnedFileName); - if (overwriteBeforeReturnFlag_) { - overwriteFileContents(returnedFileName); - } - std::string sanitizedEmptyFileName = efpDirectory_ + returnedFileName.substr(returnedFileName.rfind('/')); // NOTE: substr() includes leading '/' - if (!moveFile(returnedFileName, sanitizedEmptyFileName)) { - ::unlink(returnedFileName.c_str()); -//std::cerr << "*** WARNING: Unable to move file " << returnedFileName << " to " << sanitizedEmptyFileName << "; deleted." << std::endl; // DEBUG - } else { - pushEmptyFile(sanitizedEmptyFileName); - } -} - -void EmptyFilePool::resetEmptyFileHeader(const std::string& fqFileName) { - std::fstream fs(fqFileName.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary); - if (fs.good()) { - const std::streamsize buffsize = QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES; - char buff[buffsize]; - fs.read((char*)buff, buffsize); - std::streampos bytesRead = fs.tellg(); - if (std::streamoff(bytesRead) == buffsize) { - ::file_hdr_reset((::file_hdr_t*)buff); - // set rest of buffer to 0 - ::memset(buff + sizeof(::file_hdr_t), 0, MAX_FILE_HDR_LEN - sizeof(::file_hdr_t)); - fs.seekp(0, std::fstream::beg); - fs.write(buff, buffsize); - std::streampos bytesWritten = fs.tellp(); - if (std::streamoff(bytesWritten) != buffsize) { -//std::cerr << "*** ERROR: Unable to write file header of file \"" << fqFileName << "\": tried to write " << buffsize << " bytes; wrote " << bytesWritten << " bytes." << std::endl; // DEBUG - } - } else { -//std::cerr << "*** ERROR: Unable to read file header of file \"" << fqFileName << "\": tried to read " << sizeof(::file_hdr_t) << " bytes; read " << bytesRead << " bytes." << std::endl; // DEBUG - } - fs.close(); - } else { -//std::cerr << "*** ERROR: Unable to open file \"" << fqFileName << "\" for reading" << std::endl; // DEBUG - } -} - -bool EmptyFilePool::validateEmptyFile(const std::string& emptyFileName) const { - std::ostringstream oss; - struct stat s; - if (::stat(emptyFileName.c_str(), &s)) - { - oss << "stat: file=\"" << emptyFileName << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_STAT, oss.str(), "EmptyFilePool", "validateEmptyFile"); - } - - // Size matches pool - efpDataSize_kib_t expectedSize = (QLS_SBLK_SIZE_KIB + efpDataSize_kib_) * 1024; - if ((efpDataSize_kib_t)s.st_size != expectedSize) { - oss << "ERROR: File " << emptyFileName << ": Incorrect size: Expected=" << expectedSize - << "; actual=" << s.st_size; - journalLogRef_.log(JournalLog::LOG_ERROR, oss.str()); - return false; - } - - // Open file and read header - std::fstream fs(emptyFileName.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary); - if (!fs) { - oss << "ERROR: File " << emptyFileName << ": Unable to open for reading"; - journalLogRef_.log(JournalLog::LOG_ERROR, oss.str()); - return false; - } - const std::streamsize buffsize = QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES; - char buff[buffsize]; - fs.read((char*)buff, buffsize); - std::streampos bytesRead = fs.tellg(); - if (std::streamoff(bytesRead) != buffsize) { - oss << "ERROR: Unable to read file header of file \"" << emptyFileName << "\": tried to read " - << buffsize << " bytes; read " << bytesRead << " bytes"; - journalLogRef_.log(JournalLog::LOG_ERROR, oss.str()); - fs.close(); - return false; - } - - // Check file header - ::file_hdr_t* fhp = (::file_hdr_t*)buff; - const bool jrnlMagicError = fhp->_rhdr._magic != QLS_FILE_MAGIC; - const bool jrnlVersionError = fhp->_rhdr._version != QLS_JRNL_VERSION; - const bool jrnlPartitionError = fhp->_efp_partition != partitionPtr_->getPartitionNumber(); - const bool jrnlFileSizeError = fhp->_data_size_kib != efpDataSize_kib_; - if (jrnlMagicError || jrnlVersionError || jrnlPartitionError || jrnlFileSizeError) - { - oss << "ERROR: File " << emptyFileName << ": Invalid file header - mismatched header fields: " << - (jrnlMagicError ? "magic " : "") << - (jrnlVersionError ? "version " : "") << - (jrnlPartitionError ? "partition" : "") << - (jrnlFileSizeError ? "file-size" : ""); - journalLogRef_.log(JournalLog::LOG_ERROR, oss.str()); - fs.close(); - return false; - } - - // Check file header is reset - if (!::is_file_hdr_reset(fhp)) { - ::file_hdr_reset(fhp); - ::memset(buff + sizeof(::file_hdr_t), 0, MAX_FILE_HDR_LEN - sizeof(::file_hdr_t)); // set rest of buffer to 0 - fs.seekp(0, std::fstream::beg); - fs.write(buff, buffsize); - std::streampos bytesWritten = fs.tellp(); - if (std::streamoff(bytesWritten) != buffsize) { - oss << "ERROR: Unable to write file header of file \"" << emptyFileName << "\": tried to write " - << buffsize << " bytes; wrote " << bytesWritten << " bytes"; - journalLogRef_.log(JournalLog::LOG_ERROR, oss.str()); - fs.close(); - return false; - } - oss << "WARNING: File " << emptyFileName << ": File header not reset"; - journalLogRef_.log(JournalLog::LOG_WARN, oss.str()); - } - - // Close file - fs.close(); - return true; -} - -//static -int EmptyFilePool::createSymLink(const std::string& fqFileName, - const std::string& fqLinkName) { - if(::symlink(fqFileName.c_str(), fqLinkName.c_str())) { - if (errno == EEXIST) return errno; // File name exists - std::ostringstream oss; - oss << "file=\"" << fqFileName << "\" symlink=\"" << fqLinkName << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__SYMLINK, oss.str(), "EmptyFilePool", "createSymLink"); - } - return 0; -} - -//static -std::string EmptyFilePool::deleteSymlink(const std::string& fqLinkName) { - char buff[1024]; - ssize_t len = ::readlink(fqLinkName.c_str(), buff, 1024); - if (len < 0) { - std::ostringstream oss; - oss << "symlink=\"" << fqLinkName << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__SYMLINK, oss.str(), "EmptyFilePool", "deleteSymlink"); - } - ::unlink(fqLinkName.c_str()); - return std::string(buff, len); -} - -//static -bool EmptyFilePool::isFile(const std::string& fqName) { - struct stat buff; - if (::lstat(fqName.c_str(), &buff)) { - std::ostringstream oss; - oss << "lstat file=\"" << fqName << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_EFP_LSTAT, oss.str(), "EmptyFilePool", "isFile"); - } - return S_ISREG(buff.st_mode); -} - -//static -bool EmptyFilePool::isSymlink(const std::string& fqName) { - struct stat buff; - if (::lstat(fqName.c_str(), &buff)) { - std::ostringstream oss; - oss << "lstat file=\"" << fqName << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_EFP_LSTAT, oss.str(), "EmptyFilePool", "isSymlink"); - } - return S_ISLNK(buff.st_mode); - -} - -// static -bool EmptyFilePool::moveFile(const std::string& from, - const std::string& to) { - if (::rename(from.c_str(), to.c_str())) { - if (errno == EEXIST) { - return false; // File name exists - } - std::ostringstream oss; - oss << "file=\"" << from << "\" dest=\"" << to << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "EmptyFilePool", "returnEmptyFile"); - } - return true; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.h b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.h deleted file mode 100644 index 935057fe2b..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePool.h +++ /dev/null @@ -1,119 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOL_H_ -#define QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOL_H_ - -namespace qpid { -namespace linearstore { -namespace journal { - class EmptyFilePool; -}}} - -#include -#include "qpid/linearstore/journal/EmptyFilePoolTypes.h" -#include "qpid/linearstore/journal/smutex.h" - -namespace qpid { -namespace linearstore { -namespace journal { -class EmptyFilePoolPartition; -class jdir; -class JournalFile; -class JournalLog; - -class EmptyFilePool -{ -protected: - typedef std::deque emptyFileList_t; - typedef emptyFileList_t::const_iterator emptyFileListConstItr_t; - - static std::string s_inuseFileDirectory_; - static std::string s_returnedFileDirectory_; - - const std::string efpDirectory_; - const efpDataSize_kib_t efpDataSize_kib_; - const EmptyFilePoolPartition* partitionPtr_; - const bool overwriteBeforeReturnFlag_; - const bool truncateFlag_; - JournalLog& journalLogRef_; - -private: - emptyFileList_t emptyFileList_; - smutex emptyFileListMutex_; - -public: - EmptyFilePool(const std::string& efpDirectory, - const EmptyFilePoolPartition* partitionPtr, - const bool overwriteBeforeReturnFlag, - const bool truncateFlag, - JournalLog& journalLogRef); - virtual ~EmptyFilePool(); - - void initialize(); - efpDataSize_kib_t dataSize_kib() const; - efpFileSize_kib_t fileSize_kib() const; - efpDataSize_sblks_t dataSize_sblks() const; - efpFileSize_sblks_t fileSize_sblks() const; - efpFileCount_t numEmptyFiles() const; - efpDataSize_kib_t cumFileSize_kib() const; - efpPartitionNumber_t getPartitionNumber() const; - const EmptyFilePoolPartition* getPartition() const; - const efpIdentity_t getIdentity() const; - - std::string takeEmptyFile(const std::string& destDirectory); - void returnEmptyFileSymlink(const std::string& emptyFileSymlink); - - static std::string dirNameFromDataSize(const efpDataSize_kib_t efpDataSize_kib); - static efpDataSize_kib_t dataSizeFromDirName_kib(const std::string& dirName, - const efpPartitionNumber_t partitionNumber); - -protected: - void checkIosState(const int io_errno, - std::ofstream& ofs, - const uint32_t jerrno, - const std::string& fqFileName, - const std::string& operation, - const std::string& errorMessage, - const std::string& className, - const std::string& fnName); - std::string createEmptyFile(); - std::string getEfpFileName(); - void initializeSubDirectory(const std::string& fqDirName); - void overwriteFileContents(const std::string& fqFileName); - std::string popEmptyFile(); - void pushEmptyFile(const std::string fqFileName); - void returnEmptyFile(const std::string& emptyFileName); - void resetEmptyFileHeader(const std::string& fqFileName); - bool validateEmptyFile(const std::string& emptyFileName) const; - - static int createSymLink(const std::string& fqFileName, - const std::string& fqLinkName); - static std::string deleteSymlink(const std::string& fqLinkName); - static bool isFile(const std::string& fqName); - static bool isSymlink(const std::string& fqName); - static bool moveFile(const std::string& fromFqPath, - const std::string& toFqPath); -}; - -}}} - -#endif /* QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOL_H_ */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.cpp b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.cpp deleted file mode 100644 index a02679736e..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.cpp +++ /dev/null @@ -1,211 +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 "EmptyFilePoolManager.h" - -#include "qpid/linearstore/journal/EmptyFilePool.h" -#include "qpid/linearstore/journal/EmptyFilePoolPartition.h" -#include "qpid/linearstore/journal/jdir.h" -#include "qpid/linearstore/journal/JournalLog.h" -#include "qpid/linearstore/journal/slock.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -EmptyFilePoolManager::EmptyFilePoolManager(const std::string& qlsStorePath, - const efpPartitionNumber_t defaultPartitionNumber, - const efpDataSize_kib_t defaultEfpDataSize_kib, - const bool overwriteBeforeReturnFlag, - const bool truncateFlag, - JournalLog& journalLogRef) : - qlsStorePath_(qlsStorePath), - defaultPartitionNumber_(defaultPartitionNumber), - defaultEfpDataSize_kib_(defaultEfpDataSize_kib), - overwriteBeforeReturnFlag_(overwriteBeforeReturnFlag), - truncateFlag_(truncateFlag), - journalLogRef_(journalLogRef) -{} - -EmptyFilePoolManager::~EmptyFilePoolManager() { - slock l(partitionMapMutex_); - for (partitionMapItr_t i = partitionMap_.begin(); i != partitionMap_.end(); ++i) { - delete i->second; - } - partitionMap_.clear(); -} - -void EmptyFilePoolManager::findEfpPartitions() { -//std::cout << "*** Reading " << qlsStorePath_ << std::endl; // DEBUG - bool foundPartition = false; - std::vector dirList; - while (!foundPartition) { - jdir::read_dir(qlsStorePath_, dirList, true, false, true, false); - for (std::vector::iterator i = dirList.begin(); i != dirList.end(); ++i) { - efpPartitionNumber_t pn = EmptyFilePoolPartition::getPartitionNumber(*i); - if (pn > 0) { // valid partition name found - std::string fullDirPath(qlsStorePath_ + "/" + (*i)); - EmptyFilePoolPartition* efppp = insertPartition(pn, fullDirPath); - if (efppp != 0) - efppp->findEmptyFilePools(); - foundPartition = true; - } - } - - // If no partition was found, create an empty default partition. - if (!foundPartition) { - std::ostringstream oss1; - oss1 << qlsStorePath_ << "/" << EmptyFilePoolPartition::getPartionDirectoryName(defaultPartitionNumber_) - << "/" << EmptyFilePoolPartition::s_efpTopLevelDir_ - << "/" << EmptyFilePool::dirNameFromDataSize(defaultEfpDataSize_kib_); - jdir::create_dir(oss1.str()); - insertPartition(defaultPartitionNumber_, oss1.str()); - std::ostringstream oss2; - oss2 << "No EFP partition found, creating an empty partition at " << oss1.str(); - journalLogRef_.log(JournalLog::LOG_INFO, oss2.str()); - } - } - - journalLogRef_.log(JournalLog::LOG_INFO, "EFP Manager initialization complete"); - std::vector partitionList; - getEfpPartitions(partitionList); - if (partitionList.size() == 0) { - journalLogRef_.log(JournalLog::LOG_WARN, "NO EFP PARTITIONS FOUND! No queue creation is possible."); - } else { - std::stringstream oss; - oss << "EFP Partitions found: " << partitionList.size(); - journalLogRef_.log(JournalLog::LOG_INFO, oss.str()); - for (std::vector::const_iterator i=partitionList.begin(); i!= partitionList.end(); ++i) { - journalLogRef_.log(JournalLog::LOG_INFO, (*i)->toString(5U)); - } - } -} - -void EmptyFilePoolManager::getEfpFileSizes(std::vector& efpFileSizeList, - const efpPartitionNumber_t efpPartitionNumber) const { - if (efpPartitionNumber == 0) { - for (partitionMapConstItr_t i=partitionMap_.begin(); i!=partitionMap_.end(); ++i) { - i->second->getEmptyFilePoolSizes_kib(efpFileSizeList); - } - } else { - partitionMapConstItr_t i = partitionMap_.find(efpPartitionNumber); - if (i != partitionMap_.end()) { - i->second->getEmptyFilePoolSizes_kib(efpFileSizeList); - } - } -} - -EmptyFilePoolPartition* EmptyFilePoolManager::getEfpPartition(const efpPartitionNumber_t partitionNumber) { - partitionMapItr_t i = partitionMap_.find(partitionNumber); - if (i == partitionMap_.end()) - return 0; - else - return i->second; -} - -void EmptyFilePoolManager::getEfpPartitionNumbers(std::vector& partitionNumberList, - const efpDataSize_kib_t efpDataSize_kib) const { - slock l(partitionMapMutex_); - for (partitionMapConstItr_t i=partitionMap_.begin(); i!=partitionMap_.end(); ++i) { - if (efpDataSize_kib == 0) { - partitionNumberList.push_back(i->first); - } else { - std::vector efpFileSizeList; - i->second->getEmptyFilePoolSizes_kib(efpFileSizeList); - for (std::vector::iterator j=efpFileSizeList.begin(); j!=efpFileSizeList.end(); ++j) { - if (*j == efpDataSize_kib) { - partitionNumberList.push_back(i->first); - break; - } - } - } - } -} - -void EmptyFilePoolManager::getEfpPartitions(std::vector& partitionList, - const efpDataSize_kib_t efpDataSize_kib) { - slock l(partitionMapMutex_); - for (partitionMapConstItr_t i=partitionMap_.begin(); i!=partitionMap_.end(); ++i) { - if (efpDataSize_kib == 0) { - partitionList.push_back(i->second); - } else { - std::vector efpFileSizeList; - i->second->getEmptyFilePoolSizes_kib(efpFileSizeList); - for (std::vector::iterator j=efpFileSizeList.begin(); j!=efpFileSizeList.end(); ++j) { - if (*j == efpDataSize_kib) { - partitionList.push_back(i->second); - break; - } - } - } - } -} - -EmptyFilePool* EmptyFilePoolManager::getEmptyFilePool(const efpIdentity_t efpIdentity) { - return getEmptyFilePool(efpIdentity.pn_, efpIdentity.ds_); -} - -EmptyFilePool* EmptyFilePoolManager::getEmptyFilePool(const efpPartitionNumber_t partitionNumber, - const efpDataSize_kib_t efpDataSize_kib) { - EmptyFilePoolPartition* efppp = getEfpPartition(partitionNumber > 0 ? partitionNumber : defaultPartitionNumber_); - if (efppp == 0) { - return 0; - } - return efppp->getEmptyFilePool(efpDataSize_kib > 0 ? efpDataSize_kib : defaultEfpDataSize_kib_, true); -} - -void EmptyFilePoolManager::getEmptyFilePools(std::vector& emptyFilePoolList, - const efpPartitionNumber_t efpPartitionNumber) { - if (efpPartitionNumber == 0) { - for (partitionMapConstItr_t i=partitionMap_.begin(); i!=partitionMap_.end(); ++i) { - i->second->getEmptyFilePools(emptyFilePoolList); - } - } else { - partitionMapConstItr_t i = partitionMap_.find(efpPartitionNumber); - if (i != partitionMap_.end()) { - i->second->getEmptyFilePools(emptyFilePoolList); - } - } -} - -uint16_t EmptyFilePoolManager::getNumEfpPartitions() const { - return partitionMap_.size(); -} - -EmptyFilePoolPartition* EmptyFilePoolManager::insertPartition(const efpPartitionNumber_t pn, const std::string& fullPartitionPath) { - EmptyFilePoolPartition* efppp = 0; - try { - efppp = new EmptyFilePoolPartition(pn, fullPartitionPath, overwriteBeforeReturnFlag_, truncateFlag_, journalLogRef_); - { - slock l(partitionMapMutex_); - partitionMap_[pn] = efppp; - } - } catch (const std::exception& e) { - if (efppp != 0) { - delete efppp; - efppp = 0; - } -//std::cerr << "*** Unable to initialize partition " << pn << " (\'" << fullPartitionPath << "\'): " << e.what() << std::endl; // DEBUG - } - return efppp; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.h b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.h deleted file mode 100644 index d0aa7fa7d6..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolManager.h +++ /dev/null @@ -1,83 +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. - * - */ - -#ifndef QPID_QLS_JRNL_EMPTYFILEPOOLMANAGER_H_ -#define QPID_QLS_JRNL_EMPTYFILEPOOLMANAGER_H_ - -#include -#include "qpid/linearstore/journal/EmptyFilePoolTypes.h" -#include "qpid/linearstore/journal/smutex.h" -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -class EmptyFilePool; -class EmptyFilePoolPartition; -class JournalLog; - -class EmptyFilePoolManager -{ -protected: - typedef std::map partitionMap_t; - typedef partitionMap_t::iterator partitionMapItr_t; - typedef partitionMap_t::const_iterator partitionMapConstItr_t; - - const std::string qlsStorePath_; - const efpPartitionNumber_t defaultPartitionNumber_; - const efpDataSize_kib_t defaultEfpDataSize_kib_; - const bool overwriteBeforeReturnFlag_; - const bool truncateFlag_; - JournalLog& journalLogRef_; - partitionMap_t partitionMap_; - smutex partitionMapMutex_; - -public: - EmptyFilePoolManager(const std::string& qlsStorePath_, - const efpPartitionNumber_t defaultPartitionNumber, - const efpDataSize_kib_t defaultEfpDataSize_kib, - const bool overwriteBeforeReturnFlag, - const bool truncateFlag, - JournalLog& journalLogRef_); - virtual ~EmptyFilePoolManager(); - - void findEfpPartitions(); - void getEfpFileSizes(std::vector& efpFileSizeList, - const efpPartitionNumber_t efpPartitionNumber = 0) const; - EmptyFilePoolPartition* getEfpPartition(const efpPartitionNumber_t partitionNumber); - void getEfpPartitionNumbers(std::vector& partitionNumberList, - const efpDataSize_kib_t efpDataSize_kib = 0) const; - void getEfpPartitions(std::vector& partitionList, - const efpDataSize_kib_t efpDataSize_kib = 0); - EmptyFilePool* getEmptyFilePool(const efpIdentity_t efpIdentity); - EmptyFilePool* getEmptyFilePool(const efpPartitionNumber_t partitionNumber, - const efpDataSize_kib_t efpDataSize_kib); - void getEmptyFilePools(std::vector& emptyFilePoolList, - const efpPartitionNumber_t efpPartitionNumber = 0); - uint16_t getNumEfpPartitions() const; -protected: - EmptyFilePoolPartition* insertPartition(const efpPartitionNumber_t pn, const std::string& fullPartitionPath); -}; - -}}} - -#endif /* QPID_QLS_JRNL_EMPTYFILEPOOLMANAGER_H_ */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.cpp b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.cpp deleted file mode 100644 index 12d2db74b8..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.cpp +++ /dev/null @@ -1,199 +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/linearstore/journal/EmptyFilePoolPartition.h" - -#include -#include "qpid/linearstore/journal/EmptyFilePool.h" -#include "qpid/linearstore/journal/jdir.h" -#include "qpid/linearstore/journal/JournalLog.h" -#include "qpid/linearstore/journal/slock.h" -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -// static -const std::string EmptyFilePoolPartition::s_efpTopLevelDir_("efp"); // Sets the top-level efp dir within a partition - -EmptyFilePoolPartition::EmptyFilePoolPartition(const efpPartitionNumber_t partitionNum, - const std::string& partitionDir, - const bool overwriteBeforeReturnFlag, - const bool truncateFlag, - JournalLog& journalLogRef) : - partitionNum_(partitionNum), - partitionDir_(partitionDir), - overwriteBeforeReturnFlag_(overwriteBeforeReturnFlag), - truncateFlag_(truncateFlag), - journalLogRef_(journalLogRef) -{ - validatePartitionDir(); -} - -EmptyFilePoolPartition::~EmptyFilePoolPartition() { - slock l(efpMapMutex_); - for (efpMapItr_t i = efpMap_.begin(); i != efpMap_.end(); ++i) { - delete i->second; - } - efpMap_.clear(); -} - -void -EmptyFilePoolPartition::findEmptyFilePools() { -//std::cout << "*** EmptyFilePoolPartition::findEmptyFilePools(): Reading " << partitionDir_ << std::endl; // DEBUG - std::string efpDir(partitionDir_ + "/" + s_efpTopLevelDir_); - if (jdir::is_dir(efpDir)) { - std::vector dirList; - jdir::read_dir(efpDir, dirList, true, false, false, true); - for (std::vector::iterator i = dirList.begin(); i != dirList.end(); ++i) { - createEmptyFilePool(*i); - } - } else { - std::ostringstream oss; - oss << "Partition \"" << partitionDir_ << "\" does not contain top level EFP dir \"" << s_efpTopLevelDir_ << "\""; - journalLogRef_.log(JournalLog::LOG_WARN, oss.str()); - } -} - -EmptyFilePool* EmptyFilePoolPartition::getEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib, const bool createIfNonExistent) { - { - slock l(efpMapMutex_); - efpMapItr_t i = efpMap_.find(efpDataSize_kib); - if (i != efpMap_.end()) - return i->second; - } - if (createIfNonExistent) { - return createEmptyFilePool(efpDataSize_kib); - } - return 0; -} - -void EmptyFilePoolPartition::getEmptyFilePools(std::vector& efpList) { - slock l(efpMapMutex_); - for (efpMapItr_t i=efpMap_.begin(); i!=efpMap_.end(); ++i) { - efpList.push_back(i->second); - } -} - -void EmptyFilePoolPartition::getEmptyFilePoolSizes_kib(std::vector& efpDataSizesList_kib) const { - slock l(efpMapMutex_); - for (efpMapConstItr_t i=efpMap_.begin(); i!=efpMap_.end(); ++i) { - efpDataSizesList_kib.push_back(i->first); - } -} - -std::string EmptyFilePoolPartition::getPartitionDirectory() const { - return partitionDir_; -} - -efpPartitionNumber_t EmptyFilePoolPartition::getPartitionNumber() const { - return partitionNum_; -} - -std::string EmptyFilePoolPartition::toString(const uint16_t indent) const { - std::string indentStr(indent, ' '); - std::stringstream oss; - oss << "EFP Partition " << partitionNum_ << ":" << std::endl; - oss << indentStr << "EFP Partition Analysis (partition " << partitionNum_ << " at \"" << partitionDir_ << "\"):" << std::endl; - if (efpMap_.empty()) { - oss << indentStr << "" << std::endl; - } else { - oss << indentStr << std::setw(12) << "efp_size_kib" - << std::setw(12) << "num_files" - << std::setw(18) << "tot_capacity_kib" << std::endl; - oss << indentStr << std::setw(12) << "------------" - << std::setw(12) << "----------" - << std::setw(18) << "----------------" << std::endl; - { - slock l(efpMapMutex_); - for (efpMapConstItr_t i=efpMap_.begin(); i!= efpMap_.end(); ++i) { - oss << indentStr << std::setw(12) << i->first - << std::setw(12) << i->second->numEmptyFiles() - << std::setw(18) << i->second->cumFileSize_kib() << std::endl; - } - } - } - return oss.str(); -} - -// static -std::string EmptyFilePoolPartition::getPartionDirectoryName(const efpPartitionNumber_t partitionNumber) { - std::ostringstream oss; - oss << "p" << std::setfill('0') << std::setw(3) << partitionNumber; - return oss.str(); -} - -//static -efpPartitionNumber_t EmptyFilePoolPartition::getPartitionNumber(const std::string& name) { - if (name.length() == 4 && name[0] == 'p' && ::isdigit(name[1]) && ::isdigit(name[2]) && ::isdigit(name[3])) { - long pn = ::strtol(name.c_str() + 1, 0, 10); - if (pn == 0 && errno) { - return 0; - } else { - return (efpPartitionNumber_t)pn; - } - } - return 0; -} - -// --- protected functions --- - -EmptyFilePool* EmptyFilePoolPartition::createEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib) { - std::string fqEfpDirectoryName(partitionDir_ + "/" + EmptyFilePoolPartition::s_efpTopLevelDir_ + "/" + EmptyFilePool::dirNameFromDataSize(efpDataSize_kib)); - return createEmptyFilePool(fqEfpDirectoryName); -} - -EmptyFilePool* EmptyFilePoolPartition::createEmptyFilePool(const std::string fqEfpDirectoryName) { - EmptyFilePool* efpp = 0; - try { - efpp = new EmptyFilePool(fqEfpDirectoryName, this, overwriteBeforeReturnFlag_, truncateFlag_, journalLogRef_); - { - slock l(efpMapMutex_); - efpMap_[efpp->dataSize_kib()] = efpp; - } - } - catch (const std::exception& e) { - if (efpp != 0) { - delete efpp; - efpp = 0; - } - std::ostringstream oss; - oss << "EmptyFilePool create failed: " << e.what(); - journalLogRef_.log(JournalLog::LOG_WARN, oss.str()); - } - if (efpp != 0) { - efpp->initialize(); - } - return efpp; -} - -void EmptyFilePoolPartition::validatePartitionDir() { - std::ostringstream ss; - if (!jdir::is_dir(partitionDir_)) { - ss << "Invalid partition directory: \'" << partitionDir_ << "\' is not a directory"; - throw jexception(jerrno::JERR_EFP_BADPARTITIONDIR, ss.str(), "EmptyFilePoolPartition", "validatePartitionDir"); - } - - // TODO: other validity checks here -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.h b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.h deleted file mode 100644 index 570e2b073f..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolPartition.h +++ /dev/null @@ -1,82 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOLPARTITION_H_ -#define QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOLPARTITION_H_ - -#include -#include "qpid/linearstore/journal/EmptyFilePoolTypes.h" -#include "qpid/linearstore/journal/smutex.h" -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -class EmptyFilePool; -class JournalLog; - -class EmptyFilePoolPartition -{ -public: - static const std::string s_efpTopLevelDir_; -protected: - typedef std::map efpMap_t; - typedef efpMap_t::iterator efpMapItr_t; - typedef efpMap_t::const_iterator efpMapConstItr_t; - - const efpPartitionNumber_t partitionNum_; - const std::string partitionDir_; - const bool overwriteBeforeReturnFlag_; - const bool truncateFlag_; - JournalLog& journalLogRef_; - efpMap_t efpMap_; - smutex efpMapMutex_; - -public: - EmptyFilePoolPartition(const efpPartitionNumber_t partitionNum, - const std::string& partitionDir, - const bool overwriteBeforeReturnFlag, - const bool truncateFlag, - JournalLog& journalLogRef); - virtual ~EmptyFilePoolPartition(); - - void findEmptyFilePools(); - EmptyFilePool* getEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib, const bool createIfNonExistent); - void getEmptyFilePools(std::vector& efpList); - void getEmptyFilePoolSizes_kib(std::vector& efpDataSizesList) const; - std::string getPartitionDirectory() const; - efpPartitionNumber_t getPartitionNumber() const; - std::string toString(const uint16_t indent) const; - - static std::string getPartionDirectoryName(const efpPartitionNumber_t partitionNumber); - static efpPartitionNumber_t getPartitionNumber(const std::string& name); - -protected: - EmptyFilePool* createEmptyFilePool(const efpDataSize_kib_t efpDataSize_kib); - EmptyFilePool* createEmptyFilePool(const std::string fqEfpDirectoryName); - void validatePartitionDir(); -}; - -}}} - -#endif /* QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOLPARTITION_H_ */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolTypes.h b/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolTypes.h deleted file mode 100644 index 4cae4e6538..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/EmptyFilePoolTypes.h +++ /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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOLTYPES_H_ -#define QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOLTYPES_H_ - -#include -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -typedef uint64_t efpDataSize_kib_t; ///< Size of data part of file (excluding file header) in kib -typedef uint64_t efpFileSize_kib_t; ///< Size of file (header + data) in kib -typedef uint32_t efpDataSize_sblks_t; ///< Size of data part of file (excluding file header) in sblks -typedef uint32_t efpFileSize_sblks_t; ///< Size of file (header + data) in sblks -typedef uint32_t efpFileCount_t; ///< Number of files in a partition or pool -typedef uint16_t efpPartitionNumber_t; ///< Number assigned to a partition - -typedef struct efpIdentity_t { - efpPartitionNumber_t pn_; - efpDataSize_kib_t ds_; - efpIdentity_t() : pn_(0), ds_(0) {} - efpIdentity_t(efpPartitionNumber_t pn, efpDataSize_kib_t ds) : pn_(pn), ds_(ds) {} - efpIdentity_t(const efpIdentity_t& ei) : pn_(ei.pn_), ds_(ei.ds_) {} - friend std::ostream& operator<<(std::ostream& os, const efpIdentity_t& id) { - // This two-stage write allows this << operator to be used with std::setw() for formatted writes - std::ostringstream oss; - oss << id.pn_ << "," << id.ds_; - os << oss.str(); - return os; - } -} efpIdentity_t; - -}}} - -#endif /* QPID_LINEARSTORE_JOURNAL_EMPTYFILEPOOLTYPES_H_ */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp b/qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp deleted file mode 100644 index ed03a8413f..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp +++ /dev/null @@ -1,349 +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/linearstore/journal/JournalFile.h" - -#include -#include "qpid/linearstore/journal/jcfg.h" -#include "qpid/linearstore/journal/pmgr.h" -#include "qpid/linearstore/journal/utils/file_hdr.h" -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -JournalFile::JournalFile(const std::string& fqFileName, - const efpIdentity_t& efpIdentity, - const uint64_t fileSeqNum, - const std::string queueName) : - efpIdentity_(efpIdentity), - fqFileName_(fqFileName), - fileSeqNum_(fileSeqNum), - queueName_(queueName), - serial_(getRandom64()), - firstRecordOffset_(0ULL), - fileHandle_(-1), - fileCloseFlag_(false), - fileHeaderBasePtr_ (0), - fileHeaderPtr_(0), - aioControlBlockPtr_(0), - fileSize_dblks_(((efpIdentity.ds_ * 1024) + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES)) / QLS_DBLK_SIZE_BYTES), - initializedFlag_(false), - enqueuedRecordCount_("JournalFile::enqueuedRecordCount", 0), - submittedDblkCount_("JournalFile::submittedDblkCount", 0), - completedDblkCount_("JournalFile::completedDblkCount", 0), - outstandingAioOpsCount_("JournalFile::outstandingAioOpsCount", 0) -{} - -JournalFile::JournalFile(const std::string& fqFileName, - const ::file_hdr_t& fileHeader, - const std::string queueName) : - efpIdentity_(fileHeader._efp_partition, fileHeader._data_size_kib), - fqFileName_(fqFileName), - fileSeqNum_(fileHeader._file_number), - queueName_(queueName), - serial_(fileHeader._rhdr._serial), - firstRecordOffset_(fileHeader._fro), - fileHandle_(-1), - fileCloseFlag_(false), - fileHeaderBasePtr_ (0), - fileHeaderPtr_(0), - aioControlBlockPtr_(0), - fileSize_dblks_(((fileHeader._data_size_kib * 1024) + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES)) / QLS_DBLK_SIZE_BYTES), - initializedFlag_(false), - enqueuedRecordCount_("JournalFile::enqueuedRecordCount", 0), - submittedDblkCount_("JournalFile::submittedDblkCount", 0), - completedDblkCount_("JournalFile::completedDblkCount", 0), - outstandingAioOpsCount_("JournalFile::outstandingAioOpsCount", 0) -{} - -JournalFile::~JournalFile() { - finalize(); -} - -void -JournalFile::initialize(const uint32_t completedDblkCount) { - if (!initializedFlag_) { - if (::posix_memalign(&fileHeaderBasePtr_, QLS_AIO_ALIGN_BOUNDARY_BYTES, QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024)) - { - std::ostringstream oss; - oss << "posix_memalign(): blksize=" << QLS_AIO_ALIGN_BOUNDARY_BYTES << " size=" << (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024); - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__MALLOC, oss.str(), "JournalFile", "initialize"); - } - fileHeaderPtr_ = (::file_hdr_t*)fileHeaderBasePtr_; - aioControlBlockPtr_ = new aio_cb; - initializedFlag_ = true; - } - if (completedDblkCount > 0UL) { - submittedDblkCount_.set(completedDblkCount); - completedDblkCount_.set(completedDblkCount); - } -} - -void -JournalFile::finalize() { - if (fileHeaderBasePtr_ != 0) { - std::free(fileHeaderBasePtr_); - fileHeaderBasePtr_ = 0; - fileHeaderPtr_ = 0; - } - if (aioControlBlockPtr_ != 0) { - delete(aioControlBlockPtr_); - aioControlBlockPtr_ = 0; - } -} - -const std::string JournalFile::getFqFileName() const { - return fqFileName_; -} - -uint64_t JournalFile::getFileSeqNum() const { - return fileSeqNum_; -} - -uint64_t JournalFile::getSerial() const { - return serial_; -} - -int JournalFile::open() { - fileHandle_ = ::open(fqFileName_.c_str(), O_WRONLY | O_DIRECT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // 0644 -rw-r--r-- - if (fileHandle_ < 0) { - std::ostringstream oss; - oss << "file=\"" << fqFileName_ << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JNLF_OPEN, oss.str(), "JournalFile", "open"); - } - return fileHandle_; -} - -void JournalFile::close() { - if (fileHandle_ >= 0) { - if (getOutstandingAioDblks()) { - fileCloseFlag_ = true; // Close later when all outstanding AIOs have returned - } else { - int res = ::close(fileHandle_); - fileHandle_ = -1; - if (res != 0) { - std::ostringstream oss; - oss << "file=\"" << fqFileName_ << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JNLF_CLOSE, oss.str(), "JournalFile", "open"); - } - } - } -} - -void JournalFile::asyncFileHeaderWrite(io_context_t ioContextPtr, - const efpPartitionNumber_t efpPartitionNumber, - const efpDataSize_kib_t efpDataSize_kib, - const uint16_t userFlags, - const uint64_t recordId, - const uint64_t firstRecordOffset) { - firstRecordOffset_ = firstRecordOffset; - ::file_hdr_create(fileHeaderPtr_, QLS_FILE_MAGIC, QLS_JRNL_VERSION, QLS_JRNL_FHDR_RES_SIZE_SBLKS, efpPartitionNumber, efpDataSize_kib); - ::file_hdr_init(fileHeaderBasePtr_, - QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024, - userFlags, - serial_, - recordId, - firstRecordOffset, - fileSeqNum_, - queueName_.size(), - queueName_.data()); - const std::size_t wr_size = QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024; - if (!isOpen()) open(); - aio::prep_pwrite(aioControlBlockPtr_, fileHandle_, (void*)fileHeaderBasePtr_, wr_size, 0UL); - if (!aio::is_aligned(aioControlBlockPtr_->u.c.buf, QLS_AIO_ALIGN_BOUNDARY_BYTES)) { - std::ostringstream oss; - oss << "AIO operation on misaligned buffer: iocb->u.c.buf=" << aioControlBlockPtr_->u.c.buf << std::endl; - throw jexception(jerrno::JERR__AIO, oss.str(), "JournalFile", "asyncFileHeaderWrite"); - } - if (aio::submit(ioContextPtr, 1, &aioControlBlockPtr_) < 0) { - std::ostringstream oss; - oss << "queue=\"" << queueName_ << "\" fid=0x" << std::hex << fileSeqNum_ << " wr_size=0x" << wr_size << " foffs=0x0"; - throw jexception(jerrno::JERR__AIO, oss.str(), "JournalFile", "asyncFileHeaderWrite"); - } - addSubmittedDblkCount(QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_DBLKS); - incrOutstandingAioOperationCount(); -} - -void JournalFile::asyncPageWrite(io_context_t ioContextPtr, - aio_cb* aioControlBlockPtr, - void* data, - uint32_t dataSize_dblks) { - const std::size_t wr_size = dataSize_dblks * QLS_DBLK_SIZE_BYTES; - const uint64_t foffs = submittedDblkCount_.get() * QLS_DBLK_SIZE_BYTES; - if (!isOpen()) open(); - aio::prep_pwrite_2(aioControlBlockPtr, fileHandle_, data, wr_size, foffs); - if (!aio::is_aligned(aioControlBlockPtr->u.c.buf, QLS_AIO_ALIGN_BOUNDARY_BYTES)) { - std::ostringstream oss; - oss << "AIO operation on misaligned buffer: iocb->u.c.buf=" << aioControlBlockPtr->u.c.buf << std::endl; - throw jexception(jerrno::JERR__AIO, oss.str(), "JournalFile", "asyncPageWrite"); - } - pmgr::page_cb* pcbp = (pmgr::page_cb*)(aioControlBlockPtr->data); // This page's control block (pcb) - pcbp->_wdblks = dataSize_dblks; - pcbp->_jfp = this; - if (aio::submit(ioContextPtr, 1, &aioControlBlockPtr) < 0) { - std::ostringstream oss; - oss << "queue=\"" << queueName_ << "\" fid=0x" << std::hex << fileSeqNum_ << " wr_size=0x" << wr_size << " foffs=0x" << foffs; - throw jexception(jerrno::JERR__AIO, oss.str(), "JournalFile", "asyncPageWrite"); - } - addSubmittedDblkCount(dataSize_dblks); - incrOutstandingAioOperationCount(); -} - -uint32_t JournalFile::getEnqueuedRecordCount() const { - return enqueuedRecordCount_.get(); -} - -uint32_t JournalFile::incrEnqueuedRecordCount() { - return enqueuedRecordCount_.increment(); -} - -uint32_t JournalFile::decrEnqueuedRecordCount() { - return enqueuedRecordCount_.decrementLimit(); -} - -uint32_t JournalFile::addCompletedDblkCount(const uint32_t a) { - return completedDblkCount_.addLimit(a, submittedDblkCount_.get(), jerrno::JERR_JNLF_CMPLOFFSOVFL); -} - -uint16_t JournalFile::getOutstandingAioOperationCount() const { - return outstandingAioOpsCount_.get(); -} - -uint16_t JournalFile::decrOutstandingAioOperationCount() { - uint16_t r = outstandingAioOpsCount_.decrementLimit(); - if (fileCloseFlag_ && outstandingAioOpsCount_ == 0) { // Delayed close - close(); - } - return r; -} - -efpIdentity_t JournalFile::getEfpIdentity() const { - return efpIdentity_; -} - -uint64_t JournalFile::getFirstRecordOffset() const { - return firstRecordOffset_; -} - -void JournalFile::setFirstRecordOffset(const uint64_t firstRecordOffset) { - firstRecordOffset_ = firstRecordOffset; -} - -// --- Status helper functions --- - -bool JournalFile::isEmpty() const { - return submittedDblkCount_ == 0; -} - -bool JournalFile::isNoEnqueuedRecordsRemaining() const { - return /*!enqueueStarted_ &&*/ // Not part-way through encoding an enqueue - isFullAndComplete() && // Full with all AIO returned - enqueuedRecordCount_ == 0; // No remaining enqueued records -} - -// debug aid -const std::string JournalFile::status_str(const uint8_t indentDepth) const { - std::string indent((size_t)indentDepth, '.'); - std::ostringstream oss; - oss << indent << "JournalFile: fileName=" << getFileName() << std::endl; - oss << indent << " directory=" << getDirectory() << std::endl; - oss << indent << " fileSizeDblks=" << fileSize_dblks_ << std::endl; - oss << indent << " open=" << (isOpen() ? "T" : "F") << std::endl; - oss << indent << " fileHandle=" << fileHandle_ << std::endl; - oss << indent << " enqueuedRecordCount=" << getEnqueuedRecordCount() << std::endl; - oss << indent << " submittedDblkCount=" << getSubmittedDblkCount() << std::endl; - oss << indent << " completedDblkCount=" << getCompletedDblkCount() << std::endl; - oss << indent << " outstandingAioOpsCount=" << getOutstandingAioOperationCount() << std::endl; - oss << indent << " isEmpty()=" << (isEmpty() ? "T" : "F") << std::endl; - oss << indent << " isDataEmpty()=" << (isDataEmpty() ? "T" : "F") << std::endl; - oss << indent << " dblksRemaining()=" << dblksRemaining() << std::endl; - oss << indent << " isFull()=" << (isFull() ? "T" : "F") << std::endl; - oss << indent << " isFullAndComplete()=" << (isFullAndComplete() ? "T" : "F") << std::endl; - oss << indent << " getOutstandingAioDblks()=" << getOutstandingAioDblks() << std::endl; - oss << indent << " getNextFile()=" << (getNextFile() ? "T" : "F") << std::endl; - return oss.str(); -} - -// --- protected functions --- - -const std::string JournalFile::getDirectory() const { - return fqFileName_.substr(0, fqFileName_.rfind('/')); -} - -const std::string JournalFile::getFileName() const { - return fqFileName_.substr(fqFileName_.rfind('/')+1); -} - -//static -uint64_t JournalFile::getRandom64() { - // TODO: ::rand() is not thread safe, either lock or use rand_r(seed) with a thread-local seed. - return ((uint64_t)::rand() << QLS_RAND_SHIFT1) | ((uint64_t)::rand() << QLS_RAND_SHIFT2) | (::rand() & QLS_RAND_MASK); -} - -bool JournalFile::isOpen() const { - return fileHandle_ >= 0; -} - -uint32_t JournalFile::getSubmittedDblkCount() const { - return submittedDblkCount_.get(); -} - -uint32_t JournalFile::addSubmittedDblkCount(const uint32_t a) { - return submittedDblkCount_.addLimit(a, fileSize_dblks_, jerrno::JERR_JNLF_FILEOFFSOVFL); -} - -uint32_t JournalFile::getCompletedDblkCount() const { - return completedDblkCount_.get(); -} - -uint16_t JournalFile::incrOutstandingAioOperationCount() { - return outstandingAioOpsCount_.increment(); -} - -u_int32_t JournalFile::dblksRemaining() const { - return fileSize_dblks_ - submittedDblkCount_; -} - -bool JournalFile::getNextFile() const { - return isFull(); -} - -u_int32_t JournalFile::getOutstandingAioDblks() const { - return submittedDblkCount_ - completedDblkCount_; -} - -bool JournalFile::isDataEmpty() const { - return submittedDblkCount_ <= QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_DBLKS; -} - -bool JournalFile::isFull() const { - return submittedDblkCount_ == fileSize_dblks_; -} - -bool JournalFile::isFullAndComplete() const { - return completedDblkCount_ == fileSize_dblks_; -} - - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/JournalFile.h b/qpid/cpp/src/qpid/linearstore/journal/JournalFile.h deleted file mode 100644 index e33830ef7f..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/JournalFile.h +++ /dev/null @@ -1,132 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_JOURNALFILE_H_ -#define QPID_LINEARSTORE_JOURNAL_JOURNALFILE_H_ - -#include "qpid/linearstore/journal/aio.h" -#include "qpid/linearstore/journal/AtomicCounter.h" -#include "qpid/linearstore/journal/EmptyFilePoolTypes.h" - -class file_hdr_t; - -namespace qpid { -namespace linearstore { -namespace journal { - -class JournalFile -{ -protected: - const efpIdentity_t efpIdentity_; - const std::string fqFileName_; - const uint64_t fileSeqNum_; - const std::string queueName_; - const uint64_t serial_; - uint64_t firstRecordOffset_; - int fileHandle_; - bool fileCloseFlag_; - void* fileHeaderBasePtr_; - ::file_hdr_t* fileHeaderPtr_; - aio_cb* aioControlBlockPtr_; - uint32_t fileSize_dblks_; ///< File size in data blocks, including file header - bool initializedFlag_; - - AtomicCounter enqueuedRecordCount_; ///< Count of enqueued records - AtomicCounter submittedDblkCount_; ///< Write file count (data blocks) for submitted AIO - AtomicCounter completedDblkCount_; ///< Write file count (data blocks) for completed AIO - AtomicCounter outstandingAioOpsCount_; ///< Outstanding AIO operations on this file - -public: - // Constructor for creating new file with known fileSeqNum and random serial - JournalFile(const std::string& fqFileName, - const efpIdentity_t& efpIdentity, - const uint64_t fileSeqNum, - const std::string queueName); - // Constructor for recovery in which fileSeqNum and serial are recovered from fileHeader param - JournalFile(const std::string& fqFileName, - const ::file_hdr_t& fileHeader, - const std::string queueName); - virtual ~JournalFile(); - - void initialize(const uint32_t completedDblkCount); - void finalize(); - - const std::string getFqFileName() const; - uint64_t getFileSeqNum() const; - uint64_t getSerial() const; - - int open(); - void close(); - void asyncFileHeaderWrite(io_context_t ioContextPtr, - const efpPartitionNumber_t efpPartitionNumber, - const efpDataSize_kib_t efpDataSize_kib, - const uint16_t userFlags, - const uint64_t recordId, - const uint64_t firstRecordOffset); - void asyncPageWrite(io_context_t ioContextPtr, - aio_cb* aioControlBlockPtr, - void* data, - uint32_t dataSize_dblks); - - uint32_t getSubmittedDblkCount() const; - uint32_t getEnqueuedRecordCount() const; - uint32_t incrEnqueuedRecordCount(); - uint32_t decrEnqueuedRecordCount(); - - uint32_t addCompletedDblkCount(const uint32_t a); - - uint16_t getOutstandingAioOperationCount() const; - uint16_t decrOutstandingAioOperationCount(); - - efpIdentity_t getEfpIdentity() const; - uint64_t getFirstRecordOffset() const; - void setFirstRecordOffset(const uint64_t firstRecordOffset); - - // Status helper functions - bool isEmpty() const; ///< True if no writes of any kind have occurred - bool isNoEnqueuedRecordsRemaining() const; ///< True when all enqueued records (or parts) have been dequeued - - // debug aid - const std::string status_str(const uint8_t indentDepth) const; - -protected: - const std::string getDirectory() const; - const std::string getFileName() const; - static uint64_t getRandom64(); - bool isOpen() const; - - uint32_t addSubmittedDblkCount(const uint32_t a); - - uint32_t getCompletedDblkCount() const; - - uint16_t incrOutstandingAioOperationCount(); - - u_int32_t dblksRemaining() const; ///< Dblks remaining until full - bool getNextFile() const; ///< True when next file is needed - u_int32_t getOutstandingAioDblks() const; ///< Dblks still to be written - bool isDataEmpty() const; ///< True if only file header written, data is still empty - bool isFull() const; ///< True if all possible dblks have been submitted (but may not yet have returned from AIO) - bool isFullAndComplete() const; ///< True if all submitted dblks have returned from AIO -}; - -}}} - -#endif // QPID_LINEARSTORE_JOURNAL_JOURNALFILE_H_ diff --git a/qpid/cpp/src/qpid/linearstore/journal/JournalLog.cpp b/qpid/cpp/src/qpid/linearstore/journal/JournalLog.cpp deleted file mode 100644 index c35ec97e91..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/JournalLog.cpp +++ /dev/null @@ -1,63 +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/linearstore/journal/JournalLog.h" - -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -JournalLog::JournalLog(log_level_t logLevelThreshold) : logLevelThreshold_(logLevelThreshold) {} - -JournalLog::~JournalLog() {} - -void JournalLog::log(const log_level_t logLevel, - const std::string& logStatement) const { - if (logLevel >= logLevelThreshold_) { - std::cerr << log_level_str(logLevel) << ": " << logStatement << std::endl; - } -} - -void JournalLog::log(log_level_t logLevel, - const std::string& journalId, - const std::string& logStatement) const { - if (logLevel >= logLevelThreshold_) { - std::cerr << log_level_str(logLevel) << ": Journal \"" << journalId << "\": " << logStatement << std::endl; - } -} - -const char* JournalLog::log_level_str(log_level_t logLevel) { - switch (logLevel) - { - case LOG_TRACE: return "TRACE"; - case LOG_DEBUG: return "DEBUG"; - case LOG_INFO: return "INFO"; - case LOG_NOTICE: return "NOTICE"; - case LOG_WARN: return "WARN"; - case LOG_ERROR: return "ERROR"; - case LOG_CRITICAL: return "CRITICAL"; - } - return ""; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/JournalLog.h b/qpid/cpp/src/qpid/linearstore/journal/JournalLog.h deleted file mode 100644 index cf503cb9d2..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/JournalLog.h +++ /dev/null @@ -1,60 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_JOURNALLOG_H_ -#define QPID_LINEARSTORE_JOURNAL_JOURNALLOG_H_ - -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -class JournalLog -{ -public: - typedef enum _log_level { - LOG_TRACE = 0, - LOG_DEBUG, - LOG_INFO, - LOG_NOTICE, - LOG_WARN, - LOG_ERROR, - LOG_CRITICAL - } log_level_t; - -protected: - const log_level_t logLevelThreshold_; - -public: - JournalLog(log_level_t logLevelThreshold); - virtual ~JournalLog(); - virtual void log(const log_level_t logLevel, - const std::string& logStatement) const; - virtual void log(const log_level_t logLevel, - const std::string& journalId, - const std::string& logStatement) const; - static const char* log_level_str(const log_level_t logLevel); -}; - -}}} - -#endif // QPID_LINEARSTORE_JOURNAL_JOURNALLOG_H_ diff --git a/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp b/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp deleted file mode 100644 index 08d565ca2e..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp +++ /dev/null @@ -1,243 +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/linearstore/journal/LinearFileController.h" - -#include "qpid/linearstore/journal/EmptyFilePool.h" -#include "qpid/linearstore/journal/jcntl.h" -#include "qpid/linearstore/journal/JournalFile.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -LinearFileController::LinearFileController(jcntl& jcntlRef) : - jcntlRef_(jcntlRef), - emptyFilePoolPtr_(0), - fileSeqCounter_("LinearFileController::fileSeqCounter", 0), - recordIdCounter_("LinearFileController::recordIdCounter", 0), - decrCounter_("LinearFileController::decrCounter", 0), - currentJournalFilePtr_(0) -{} - -LinearFileController::~LinearFileController() {} - -void LinearFileController::initialize(const std::string& journalDirectory, - EmptyFilePool* emptyFilePoolPtr, - uint64_t initialFileNumberVal) { - journalDirectory_.assign(journalDirectory); - emptyFilePoolPtr_ = emptyFilePoolPtr; - fileSeqCounter_.set(initialFileNumberVal); -} - -void LinearFileController::finalize() { - if (currentJournalFilePtr_) { - currentJournalFilePtr_->close(); - currentJournalFilePtr_ = 0; - } - while (!journalFileList_.empty()) { - delete journalFileList_.front(); - journalFileList_.pop_front(); - } -} - -void LinearFileController::addJournalFile(JournalFile* journalFilePtr, - const uint32_t completedDblkCount, - const bool makeCurrentFlag) { - if (makeCurrentFlag && currentJournalFilePtr_) { - currentJournalFilePtr_->close(); - currentJournalFilePtr_ = 0; - } - journalFilePtr->initialize(completedDblkCount); - { - slock l(journalFileListMutex_); - journalFileList_.push_back(journalFilePtr); - } - if (makeCurrentFlag) { - currentJournalFilePtr_ = journalFilePtr; - } -} - -efpDataSize_sblks_t LinearFileController::dataSize_sblks() const { - return emptyFilePoolPtr_->dataSize_sblks(); -} - -efpFileSize_sblks_t LinearFileController::fileSize_sblks() const { - return emptyFilePoolPtr_->fileSize_sblks(); -} - -void LinearFileController::getNextJournalFile() { - if (currentJournalFilePtr_) - currentJournalFilePtr_->close(); - pullEmptyFileFromEfp(); -} - -uint64_t LinearFileController::getNextRecordId() { - return recordIdCounter_.increment(); -} - -void LinearFileController::removeFileToEfp(const std::string& fileName) { - if (emptyFilePoolPtr_) { - emptyFilePoolPtr_->returnEmptyFileSymlink(fileName); - } -} - -void LinearFileController::restoreEmptyFile(const std::string& fileName) { - // TODO: Add checks that this file is of a valid size; if not, delete this and get one from the EFP - addJournalFile(fileName, emptyFilePoolPtr_->getIdentity(), getNextFileSeqNum(), 0); -} - -void LinearFileController::purgeEmptyFilesToEfp() { - slock l(journalFileListMutex_); - while (journalFileList_.front()->isNoEnqueuedRecordsRemaining() && journalFileList_.size() > 1) { // Can't purge last file, even if it has no enqueued records - emptyFilePoolPtr_->returnEmptyFileSymlink(journalFileList_.front()->getFqFileName()); - delete journalFileList_.front(); - journalFileList_.pop_front(); - } -} - -uint32_t LinearFileController::getEnqueuedRecordCount(const uint64_t fileSeqNumber) { - return find(fileSeqNumber)->getEnqueuedRecordCount(); -} - -uint32_t LinearFileController::incrEnqueuedRecordCount(const uint64_t fileSeqNumber) { - return find(fileSeqNumber)->incrEnqueuedRecordCount(); -} - -uint32_t LinearFileController::decrEnqueuedRecordCount(const uint64_t fileSeqNumber) { - uint32_t r = find(fileSeqNumber)->decrEnqueuedRecordCount(); - - // TODO: Re-evaluate after testing and profiling - // This is the first go at implementing auto-purge, which checks for all trailing empty files and recycles - // them back to the EFP. This version checks every 100 decrements using decrCounter_ (an action which releases - // records). We need to check this rather simple scheme works for outlying scenarios (large and tiny data - // records) without impacting performance or performing badly (leaving excessive empty files in the journals). - if (decrCounter_.increment() % 100ULL == 0ULL) { - purgeEmptyFilesToEfp(); - } - return r; -} - -uint32_t LinearFileController::addWriteCompletedDblkCount(const uint64_t fileSeqNumber, const uint32_t a) { - return find(fileSeqNumber)->addCompletedDblkCount(a); -} - -uint16_t LinearFileController::decrOutstandingAioOperationCount(const uint64_t fileSeqNumber) { - return find(fileSeqNumber)->decrOutstandingAioOperationCount(); -} - -void LinearFileController::asyncFileHeaderWrite(io_context_t ioContextPtr, - const uint16_t userFlags, - const uint64_t recordId, - const uint64_t firstRecordOffset) { - currentJournalFilePtr_->asyncFileHeaderWrite(ioContextPtr, - emptyFilePoolPtr_->getPartitionNumber(), - emptyFilePoolPtr_->dataSize_kib(), - userFlags, - recordId, - firstRecordOffset); -} - -void LinearFileController::asyncPageWrite(io_context_t ioContextPtr, - aio_cb* aioControlBlockPtr, - void* data, - uint32_t dataSize_dblks) { - assertCurrentJournalFileValid("asyncPageWrite"); - currentJournalFilePtr_->asyncPageWrite(ioContextPtr, aioControlBlockPtr, data, dataSize_dblks); -} - -uint64_t LinearFileController::getCurrentFileSeqNum() const { - assertCurrentJournalFileValid("getCurrentFileSeqNum"); - return currentJournalFilePtr_->getFileSeqNum(); -} - -uint64_t LinearFileController::getCurrentSerial() const { - assertCurrentJournalFileValid("getCurrentSerial"); - return currentJournalFilePtr_->getSerial(); -} - -bool LinearFileController::isEmpty() const { - assertCurrentJournalFileValid("isEmpty"); - return currentJournalFilePtr_->isEmpty(); -} - -const std::string LinearFileController::status(const uint8_t indentDepth) const { - std::string indent((size_t)indentDepth, '.'); - std::ostringstream oss; - oss << indent << "LinearFileController: queue=" << jcntlRef_.id() << std::endl; - oss << indent << " journalDirectory=" << journalDirectory_ << std::endl; - oss << indent << " fileSeqCounter=" << fileSeqCounter_.get() << std::endl; - oss << indent << " recordIdCounter=" << recordIdCounter_.get() << std::endl; - oss << indent << " journalFileList.size=" << journalFileList_.size() << std::endl; - if (checkCurrentJournalFileValid()) { - oss << currentJournalFilePtr_->status_str(indentDepth+2); - } else { - oss << indent << " " << std::endl; - } - return oss.str(); -} - -// --- protected functions --- - -void LinearFileController::addJournalFile(const std::string& fileName, - const efpIdentity_t& efpIdentity, - const uint64_t fileSeqNumber, - const uint32_t completedDblkCount) { - JournalFile* jfp = new JournalFile(fileName, efpIdentity, fileSeqNumber, jcntlRef_.id()); - addJournalFile(jfp, completedDblkCount, true); -} - -void LinearFileController::assertCurrentJournalFileValid(const char* const functionName) const { - if (!checkCurrentJournalFileValid()) { - throw jexception(jerrno::JERR__NULL, "LinearFileController", functionName); - } -} - -bool LinearFileController::checkCurrentJournalFileValid() const { - return currentJournalFilePtr_ != 0; -} - -JournalFile* LinearFileController::find(const uint64_t fileSeqNumber) { - if (currentJournalFilePtr_ && currentJournalFilePtr_->getFileSeqNum() == fileSeqNumber) - return currentJournalFilePtr_; - - slock l(journalFileListMutex_); - for (JournalFileListItr_t i=journalFileList_.begin(); i!=journalFileList_.end(); ++i) { - if ((*i)->getFileSeqNum() == fileSeqNumber) { - return *i; - } - } - - std::ostringstream oss; - oss << "fileSeqNumber=" << fileSeqNumber; - throw jexception(jerrno::JERR_LFCR_SEQNUMNOTFOUND, oss.str(), "LinearFileController", "find"); -} - -uint64_t LinearFileController::getNextFileSeqNum() { - return fileSeqCounter_.increment(); -} - -void LinearFileController::pullEmptyFileFromEfp() { - std::string efn = emptyFilePoolPtr_->takeEmptyFile(journalDirectory_); // Moves file from EFP only (ie no file init), returns new file name - addJournalFile(efn, emptyFilePoolPtr_->getIdentity(), getNextFileSeqNum(), 0); -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h b/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h deleted file mode 100644 index 3cdfb72a37..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h +++ /dev/null @@ -1,119 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_LINEARFILECONTROLLER_H_ -#define QPID_LINEARSTORE_JOURNAL_LINEARFILECONTROLLER_H_ - -#include -#include "qpid/linearstore/journal/aio.h" -#include "qpid/linearstore/journal/AtomicCounter.h" -#include "qpid/linearstore/journal/EmptyFilePoolTypes.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -class EmptyFilePool; -class jcntl; -class JournalFile; - -class LinearFileController -{ -protected: - typedef std::deque JournalFileList_t; - typedef JournalFileList_t::iterator JournalFileListItr_t; - - jcntl& jcntlRef_; - std::string journalDirectory_; - EmptyFilePool* emptyFilePoolPtr_; - AtomicCounter fileSeqCounter_; - AtomicCounter recordIdCounter_; - AtomicCounter decrCounter_; - - JournalFileList_t journalFileList_; - JournalFile* currentJournalFilePtr_; - smutex journalFileListMutex_; - -public: - LinearFileController(jcntl& jcntlRef); - virtual ~LinearFileController(); - - void initialize(const std::string& journalDirectory, - EmptyFilePool* emptyFilePoolPtr, - uint64_t initialFileNumberVal); - void finalize(); - - void addJournalFile(JournalFile* journalFilePtr, - const uint32_t completedDblkCount, - const bool makeCurrentFlag); - - efpDataSize_sblks_t dataSize_sblks() const; - efpFileSize_sblks_t fileSize_sblks() const; - void getNextJournalFile(); - uint64_t getNextRecordId(); - void removeFileToEfp(const std::string& fileName); - void restoreEmptyFile(const std::string& fileName); - void purgeEmptyFilesToEfp(); - - // Functions for manipulating counts of non-current JournalFile instances in journalFileList_ - uint32_t getEnqueuedRecordCount(const uint64_t fileSeqNumber); - uint32_t incrEnqueuedRecordCount(const uint64_t fileSeqNumber); - uint32_t decrEnqueuedRecordCount(const uint64_t fileSeqNumber); - uint32_t addWriteCompletedDblkCount(const uint64_t fileSeqNumber, - const uint32_t a); - uint16_t decrOutstandingAioOperationCount(const uint64_t fileSeqNumber); - - // Pass-through functions for current JournalFile class - void asyncFileHeaderWrite(io_context_t ioContextPtr, - const uint16_t userFlags, - const uint64_t recordId, - const uint64_t firstRecordOffset); - void asyncPageWrite(io_context_t ioContextPtr, - aio_cb* aioControlBlockPtr, - void* data, - uint32_t dataSize_dblks); - - uint64_t getCurrentFileSeqNum() const; - uint64_t getCurrentSerial() const; - bool isEmpty() const; - - // Debug aid - const std::string status(const uint8_t indentDepth) const; - -protected: - void addJournalFile(const std::string& fileName, - const efpIdentity_t& efpIdentity, - const uint64_t fileSeqNumber, - const uint32_t completedDblkCount); - void assertCurrentJournalFileValid(const char* const functionName) const; - bool checkCurrentJournalFileValid() const; - JournalFile* find(const uint64_t fileSeqNumber); - uint64_t getNextFileSeqNum(); - void pullEmptyFileFromEfp(); -}; - -typedef void (LinearFileController::*lfcAddJournalFileFn)(JournalFile* journalFilePtr, - const uint32_t completedDblkCount, - const bool makeCurrentFlag); - -}}} - -#endif // QPID_LINEARSTORE_JOURNAL_LINEARFILECONTROLLER_H_ diff --git a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp b/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp deleted file mode 100644 index 254566e824..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp +++ /dev/null @@ -1,949 +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/linearstore/journal/RecoveryManager.h" - -#include -#include -#include -#include "qpid/linearstore/journal/Checksum.h" -#include "qpid/linearstore/journal/data_tok.h" -#include "qpid/linearstore/journal/deq_rec.h" -#include "qpid/linearstore/journal/EmptyFilePool.h" -#include "qpid/linearstore/journal/EmptyFilePoolManager.h" -#include "qpid/linearstore/journal/enq_map.h" -#include "qpid/linearstore/journal/enq_rec.h" -#include "qpid/linearstore/journal/jcfg.h" -#include "qpid/linearstore/journal/jdir.h" -#include "qpid/linearstore/journal/JournalFile.h" -#include "qpid/linearstore/journal/JournalLog.h" -#include "qpid/linearstore/journal/jrec.h" -#include "qpid/linearstore/journal/LinearFileController.h" -#include "qpid/linearstore/journal/txn_map.h" -#include "qpid/linearstore/journal/txn_rec.h" -#include "qpid/linearstore/journal/utils/enq_hdr.h" -#include "qpid/linearstore/journal/utils/file_hdr.h" -#include -#include -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -RecoveredRecordData_t::RecoveredRecordData_t(const uint64_t rid, const uint64_t fid, const std::streampos foffs, bool ptxn) : - recordId_(rid), - fileId_(fid), - fileOffset_(foffs), - pendingTransaction_(ptxn) -{} - -bool recordIdListCompare(RecoveredRecordData_t a, RecoveredRecordData_t b) { - return a.recordId_ < b.recordId_; -} - -RecoveredFileData_t::RecoveredFileData_t(JournalFile* journalFilePtr, const uint32_t completedDblkCount) : - journalFilePtr_(journalFilePtr), - completedDblkCount_(completedDblkCount) -{} - -RecoveryManager::RecoveryManager(const std::string& journalDirectory, - const std::string& queuename, - enq_map& enqueueMapRef, - txn_map& transactionMapRef, - JournalLog& journalLogRef) : - journalDirectory_(journalDirectory), - queueName_(queuename), - enqueueMapRef_(enqueueMapRef), - transactionMapRef_(transactionMapRef), - journalLogRef_(journalLogRef), - journalEmptyFlag_(false), - firstRecordOffset_(0), - endOffset_(0), - highestRecordId_(0ULL), - highestFileNumber_(0ULL), - lastFileFullFlag_(false), - initial_fid_(0), - currentSerial_(0), - efpFileSize_kib_(0) -{} - -RecoveryManager::~RecoveryManager() { - for (fileNumberMapItr_t i = fileNumberMap_.begin(); i != fileNumberMap_.end(); ++i) { - delete i->second; - } - fileNumberMap_.clear(); -} - -void RecoveryManager::analyzeJournals(const std::vector* preparedTransactionListPtr, - EmptyFilePoolManager* emptyFilePoolManager, - EmptyFilePool** emptyFilePoolPtrPtr) { - // Analyze file headers of existing journal files - efpIdentity_t efpIdentity; - analyzeJournalFileHeaders(efpIdentity); - - if (journalEmptyFlag_) { - if (uninitFileList_.empty()) { - *emptyFilePoolPtrPtr = emptyFilePoolManager->getEmptyFilePool(0, 0); // Use default EFP - } else { - *emptyFilePoolPtrPtr = emptyFilePoolManager->getEmptyFilePool(efpIdentity); - } - } else { - *emptyFilePoolPtrPtr = emptyFilePoolManager->getEmptyFilePool(efpIdentity); - if (! *emptyFilePoolPtrPtr) { - // TODO: At a later time, this could be used to establish a new pool size provided the partition exists. - // If the partition does not exist, this is always an error. For now, throw an exception, as this should - // not occur in any practical application. Once multiple partitions and mixed EFPs are supported, this - // needs to be resolved. Note that EFP size is always a multiple of QLS_SBLK_SIZE_BYTES (currently 4096 - // bytes, any other value cannot be used and should be rejected as an error. - std::ostringstream oss; - oss << "Invalid EFP identity: Partition=" << efpIdentity.pn_ << " Size=" << efpIdentity.ds_ << "k"; - throw jexception(jerrno::JERR_RCVM_INVALIDEFPID, oss.str(), "RecoveryManager", "analyzeJournals"); - } - efpFileSize_kib_ = (*emptyFilePoolPtrPtr)->fileSize_kib(); - - // Read all records, establish remaining enqueued records - if (inFileStream_.is_open()) { - inFileStream_.close(); - } - while (getNextRecordHeader()) {} - if (inFileStream_.is_open()) { - inFileStream_.close(); - } - - // Check for file full condition - lastFileFullFlag_ = endOffset_ == (std::streamoff)(*emptyFilePoolPtrPtr)->fileSize_kib() * 1024; - - // Remove leading files which have no enqueued records - removeEmptyFiles(*emptyFilePoolPtrPtr); - - // Remove all txns from tmap that are not in the prepared list - if (preparedTransactionListPtr) { - std::vector xidList; - transactionMapRef_.xid_list(xidList); - for (std::vector::iterator itr = xidList.begin(); itr != xidList.end(); itr++) { - std::vector::const_iterator pitr = - std::find(preparedTransactionListPtr->begin(), preparedTransactionListPtr->end(), *itr); - if (pitr == preparedTransactionListPtr->end()) { // not found in prepared list - txn_data_list_t tdl = transactionMapRef_.get_remove_tdata_list(*itr); // tdl will be empty if xid not found - // Unlock any affected enqueues in emap - for (tdl_itr_t i=tdl.begin(); ienq_flag_) { // enq op - decrement enqueue count - fileNumberMap_[i->fid_]->journalFilePtr_->decrEnqueuedRecordCount(); - } else if (enqueueMapRef_.is_enqueued(i->drid_, true)) { // deq op - unlock enq record - if (enqueueMapRef_.unlock(i->drid_) < enq_map::EMAP_OK) { // fail - // enq_map::unlock()'s only error is enq_map::EMAP_RID_NOT_FOUND - std::ostringstream oss; - oss << std::hex << "_emap.unlock(): drid=0x\"" << i->drid_; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "RecoveryManager", "analyzeJournals"); - } - } - } - } - } - } - prepareRecordList(); - } -} - -std::streamoff RecoveryManager::getEndOffset() const { - return endOffset_; -} - -uint64_t RecoveryManager::getHighestFileNumber() const { - return highestFileNumber_; -} - -uint64_t RecoveryManager::getHighestRecordId() const { - return highestRecordId_; -} - -bool RecoveryManager::isLastFileFull() const { - return lastFileFullFlag_; -} - -bool RecoveryManager::readNextRemainingRecord(void** const dataPtrPtr, - std::size_t& dataSize, - void** const xidPtrPtr, - std::size_t& xidSize, - bool& transient, - bool& external, - data_tok* const dtokp, - bool ignore_pending_txns) { - bool foundRecord = false; - do { - if (recordIdListConstItr_ == recordIdList_.end()) { - return false; - } - if (recordIdListConstItr_->pendingTransaction_ && ignore_pending_txns) { // Pending transaction - ++recordIdListConstItr_; // ignore, go to next record - } else { - foundRecord = true; - } - } while (!foundRecord); - - if (!inFileStream_.is_open() || currentJournalFileItr_->first != recordIdListConstItr_->fileId_) { - if (!getFile(recordIdListConstItr_->fileId_, false)) { - std::ostringstream oss; - oss << "Failed to open file with file-id=" << recordIdListConstItr_->fileId_; - throw jexception(jerrno::JERR__FILEIO, oss.str(), "RecoveryManager", "readNextRemainingRecord"); - } - } - inFileStream_.seekg(recordIdListConstItr_->fileOffset_, std::ifstream::beg); - if (!inFileStream_.good()) { - std::ostringstream oss; - oss << "Could not find offset 0x" << std::hex << recordIdListConstItr_->fileOffset_ << " in file " << getCurrentFileName(); - throw jexception(jerrno::JERR__FILEIO, oss.str(), "RecoveryManager", "readNextRemainingRecord"); - } - - ::enq_hdr_t enqueueHeader; - inFileStream_.read((char*)&enqueueHeader, sizeof(::enq_hdr_t)); - if (inFileStream_.gcount() != sizeof(::enq_hdr_t)) { - std::ostringstream oss; - oss << "Could not read enqueue header from file " << getCurrentFileName() << " at offset 0x" << std::hex << recordIdListConstItr_->fileOffset_; - throw jexception(jerrno::JERR__FILEIO, oss.str(), "RecoveryManager", "readNextRemainingRecord"); - } - // check flags - transient = ::is_enq_transient(&enqueueHeader); - external = ::is_enq_external(&enqueueHeader); - - // read xid - xidSize = enqueueHeader._xidsize; - *xidPtrPtr = ::malloc(xidSize); - if (*xidPtrPtr == 0) { - std::ostringstream oss; - oss << "xidPtr, size=0x" << std::hex << xidSize; - throw jexception(jerrno::JERR__MALLOC, oss.str(), "RecoveryManager", "readNextRemainingRecord"); - } - readJournalData((char*)*xidPtrPtr, xidSize); - - // read data - dataSize = enqueueHeader._dsize; - *dataPtrPtr = ::malloc(dataSize); - if (*xidPtrPtr == 0) { - std::ostringstream oss; - oss << "dataPtr, size=0x" << std::hex << dataSize; - throw jexception(jerrno::JERR__MALLOC, oss.str(), "RecoveryManager", "readNextRemainingRecord"); - } - readJournalData((char*)*dataPtrPtr, dataSize); - - // Check enqueue record checksum - Checksum checksum; - checksum.addData((const unsigned char*)&enqueueHeader, sizeof(::enq_hdr_t)); - if (xidSize > 0) { - checksum.addData((const unsigned char*)*xidPtrPtr, xidSize); - } - if (dataSize > 0) { - checksum.addData((const unsigned char*)*dataPtrPtr, dataSize); - } - ::rec_tail_t enqueueTail; - readJournalData((char*)&enqueueTail, sizeof(::rec_tail_t)); - uint32_t cs = checksum.getChecksum(); - uint16_t res = ::rec_tail_check(&enqueueTail, &enqueueHeader._rhdr, cs); - if (res != 0) { - std::stringstream oss; - oss << "Bad record tail:" << std::hex; - if (res & ::REC_TAIL_MAGIC_ERR_MASK) { - oss << std::endl << " Magic: expected 0x" << ~enqueueHeader._rhdr._magic << "; found 0x" << enqueueTail._xmagic; - } - if (res & ::REC_TAIL_SERIAL_ERR_MASK) { - oss << std::endl << " Serial: expected 0x" << enqueueHeader._rhdr._serial << "; found 0x" << enqueueTail._serial; - } - if (res & ::REC_TAIL_RID_ERR_MASK) { - oss << std::endl << " Record Id: expected 0x" << enqueueHeader._rhdr._rid << "; found 0x" << enqueueTail._rid; - } - if (res & ::REC_TAIL_CHECKSUM_ERR_MASK) { - oss << std::endl << " Checksum: expected 0x" << cs << "; found 0x" << enqueueTail._checksum; - } - throw jexception(jerrno::JERR_JREC_BADRECTAIL, oss.str(), "RecoveryManager", "readNextRemainingRecord"); // TODO: Don't throw exception, log info - } - - // Set data token - dtokp->set_wstate(data_tok::ENQ); - dtokp->set_rid(enqueueHeader._rhdr._rid); - dtokp->set_dsize(dataSize); - if (xidSize) { - dtokp->set_xid(*xidPtrPtr, xidSize); - } - - ++recordIdListConstItr_; - return true; -} - -void RecoveryManager::recoveryComplete() { - if(inFileStream_.is_open()) { - inFileStream_.close(); - } -} - -void RecoveryManager::setLinearFileControllerJournals(lfcAddJournalFileFn fnPtr, - LinearFileController* lfcPtr) { - if (journalEmptyFlag_) { - if (uninitFileList_.size() > 0) { - // TODO: Handle case if uninitFileList_.size() > 1, but this should not happen in normal operation. Here we assume only one item in the list. - std::string uninitFile = uninitFileList_.back(); - uninitFileList_.pop_back(); - lfcPtr->restoreEmptyFile(uninitFile); - } - } else { - if (initial_fid_ == 0) { - throw jexception(jerrno::JERR_RCVM_NULLFID, "RecoveryManager", "setLinearFileControllerJournals"); - } - for (fileNumberMapConstItr_t i = fileNumberMap_.begin(); i != fileNumberMap_.end(); ++i) { - (lfcPtr->*fnPtr)(i->second->journalFilePtr_, i->second->completedDblkCount_, i->first == initial_fid_); - } - } - - std::ostringstream oss; - bool logFlag = !notNeededFilesList_.empty(); - if (logFlag) { - oss << "Files removed from head of journal: prior truncation during recovery:"; - } - while (!notNeededFilesList_.empty()) { - lfcPtr->removeFileToEfp(notNeededFilesList_.back()); - oss << std::endl << " * " << notNeededFilesList_.back(); - notNeededFilesList_.pop_back(); - } - if (logFlag) { - journalLogRef_.log(JournalLog::LOG_NOTICE, queueName_, oss.str()); - } -} - -std::string RecoveryManager::toString(const std::string& jid, const uint16_t indent) const { - std::string indentStr(indent, ' '); - std::ostringstream oss; - oss << std::endl << indentStr << "Journal recovery analysis (jid=\"" << jid << "\"):" << std::endl; - if (journalEmptyFlag_) { - oss << indentStr << "" << std::endl; - } else { - oss << indentStr << std::setw(7) << "file_id" - << std::setw(43) << "file_name" - << std::setw(12) << "record_cnt" - << std::setw(16) << "fro" - << std::setw(12) << "efp_id" - << std::endl; - oss << indentStr << std::setw(7) << "-------" - << std::setw(43) << "-----------------------------------------" - << std::setw(12) << "----------" - << std::setw(16) << "--------------" - << std::setw(12) << "----------" - << std::endl; - uint32_t totalRecordCount(0UL); - for (fileNumberMapConstItr_t k=fileNumberMap_.begin(); k!=fileNumberMap_.end(); ++k) { - std::string fqFileName = k->second->journalFilePtr_->getFqFileName(); - std::ostringstream fid; - fid << std::hex << "0x" << k->first; - std::ostringstream fro; - fro << std::hex << "0x" << k->second->journalFilePtr_->getFirstRecordOffset(); - oss << indentStr << std::setw(7) << fid.str() - << std::setw(43) << fqFileName.substr(fqFileName.rfind('/')+1) - << std::setw(12) << k->second->journalFilePtr_->getEnqueuedRecordCount() - << std::setw(16) << fro.str() - << std::setw(12) << k->second->journalFilePtr_->getEfpIdentity() - << std::endl; - totalRecordCount += k->second->journalFilePtr_->getEnqueuedRecordCount(); - } - oss << indentStr << std::setw(62) << "----------" << std::endl; - oss << indentStr << std::setw(62) << totalRecordCount << std::endl; - oss << indentStr << "First record offset in first file = 0x" << std::hex << firstRecordOffset_ << - std::dec << " (" << (firstRecordOffset_/QLS_DBLK_SIZE_BYTES) << " dblks)" << std::endl; - oss << indentStr << "End offset in last file = 0x" << std::hex << endOffset_ << std::dec << " (" << - (endOffset_/QLS_DBLK_SIZE_BYTES) << " dblks)" << std::endl; - oss << indentStr << "Highest rid found = 0x" << std::hex << highestRecordId_ << std::dec << std::endl; - oss << indentStr << "Last file full = " << (lastFileFullFlag_ ? "TRUE" : "FALSE") << std::endl; - } - return oss.str(); -} - -// --- protected functions --- - -void RecoveryManager::analyzeJournalFileHeaders(efpIdentity_t& efpIdentity) { - std::string headerQueueName; - ::file_hdr_t fileHeader; - stringList_t directoryList; - jdir::read_dir(journalDirectory_, directoryList, false, true, false, true); - for (stringListConstItr_t i = directoryList.begin(); i != directoryList.end(); ++i) { - bool hdrOk = readJournalFileHeader(*i, fileHeader, headerQueueName); - bool hdrEmpty = ::is_file_hdr_reset(&fileHeader); - if (!hdrOk) { - std::ostringstream oss; - oss << "Journal file " << (*i) << " is corrupted or invalid"; - journalLogRef_.log(JournalLog::LOG_WARN, queueName_, oss.str()); - } else if (hdrEmpty) { - // Read symlink, find efp directory name which is efp size in KiB - // TODO: place this bit into a common function as it is also used in EmptyFilePool.cpp::deleteSymlink() - char buff[1024]; - ssize_t len = ::readlink((*i).c_str(), buff, 1024); - if (len < 0) { - std::ostringstream oss; - oss << "symlink=\"" << (*i) << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__SYMLINK, oss.str(), "RecoveryManager", "analyzeJournalFileHeaders"); - } - // Find second and third '/' from back of string, which contains the EFP directory name - *(::strrchr(buff, '/')) = '\0'; - *(::strrchr(buff, '/')) = '\0'; - int efpDataSize_kib = atoi(::strrchr(buff, '/') + 1); - uninitFileList_.push_back(*i); - efpIdentity.pn_ = fileHeader._efp_partition; - efpIdentity.ds_ = efpDataSize_kib; - } else if (headerQueueName.compare(queueName_) != 0) { - std::ostringstream oss; - oss << "Journal file " << (*i) << " belongs to queue \"" << headerQueueName << "\": ignoring"; - journalLogRef_.log(JournalLog::LOG_WARN, queueName_, oss.str()); - } else { - JournalFile* jfp = new JournalFile(*i, fileHeader, queueName_); - std::pair res = fileNumberMap_.insert( - std::pair(fileHeader._file_number, new RecoveredFileData_t(jfp, 0))); - if (!res.second) { - std::ostringstream oss; - oss << "Journal file " << (*i) << " has fid=0x" << std::hex << jfp->getFileSeqNum() << " which already exists for this journal."; - throw jexception(oss.str()); // TODO: complete this exception - } - if (fileHeader._file_number > highestFileNumber_) { - highestFileNumber_ = fileHeader._file_number; - } - // TODO: Logic weak here for detecting error conditions in journal, specifically when no - // valid files exist, or files from mixed EFPs. Currently last read file header determines - // efpIdentity. - efpIdentity.pn_ = fileHeader._efp_partition; - efpIdentity.ds_ = fileHeader._data_size_kib; - } - } - -//std::cerr << "*** RecoveryManager::analyzeJournalFileHeaders() fileNumberMap_.size()=" << fileNumberMap_.size() << std::endl; // DEBUG - if (fileNumberMap_.empty()) { - journalEmptyFlag_ = true; - } else { - currentJournalFileItr_ = fileNumberMap_.begin(); - } -} - -void RecoveryManager::checkFileStreamOk(bool checkEof) { - if (inFileStream_.fail() || inFileStream_.bad() || checkEof ? inFileStream_.eof() : false) { - std::ostringstream oss; - oss << "Stream status: fail=" << (inFileStream_.fail()?"T":"F") << " bad=" << (inFileStream_.bad()?"T":"F"); - if (checkEof) { - oss << " eof=" << (inFileStream_.eof()?"T":"F"); - } - throw jexception(jerrno::JERR_RCVM_STREAMBAD, oss.str(), "RecoveryManager", "checkFileStreamOk"); - } -} - -void RecoveryManager::checkJournalAlignment(const uint64_t start_fid, const std::streampos recordPosition) { - if (recordPosition % QLS_DBLK_SIZE_BYTES != 0) { - std::ostringstream oss; - oss << "Current read pointer not dblk aligned: recordPosition=0x" << std::hex << recordPosition; - oss << " (dblk alignment offset = 0x" << (recordPosition % QLS_DBLK_SIZE_BYTES); - throw jexception(jerrno::JERR_RCVM_NOTDBLKALIGNED, oss.str(), "RecoveryManager", "checkJournalAlignment"); - } - std::streampos currentPosn = recordPosition; - unsigned sblkOffset = currentPosn % QLS_SBLK_SIZE_BYTES; - if (sblkOffset) - { - std::ostringstream oss1; - oss1 << std::hex << "Bad record alignment found at fid=0x" << start_fid; - oss1 << " offs=0x" << currentPosn << " (likely journal overwrite boundary); " << std::dec; - oss1 << (QLS_SBLK_SIZE_DBLKS - (sblkOffset/QLS_DBLK_SIZE_BYTES)) << " filler record(s) required."; - journalLogRef_.log(JournalLog::LOG_WARN, queueName_, oss1.str()); - - fileNumberMapConstItr_t fnmItr = fileNumberMap_.find(start_fid); - std::ofstream outFileStream(fnmItr->second->journalFilePtr_->getFqFileName().c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); - if (!outFileStream.good()) { - throw jexception(jerrno::JERR__FILEIO, getCurrentFileName(), "RecoveryManager", "checkJournalAlignment"); - } - outFileStream.seekp(currentPosn); - - // Prepare write buffer containing a single empty record (1 dblk) - void* writeBuffer = std::malloc(QLS_DBLK_SIZE_BYTES); - if (writeBuffer == 0) { - throw jexception(jerrno::JERR__MALLOC, "RecoveryManager", "checkJournalAlignment"); - } - const uint32_t xmagic = QLS_EMPTY_MAGIC; - ::memcpy(writeBuffer, (const void*)&xmagic, sizeof(xmagic)); - ::memset((char*)writeBuffer + sizeof(xmagic), QLS_CLEAN_CHAR, QLS_DBLK_SIZE_BYTES - sizeof(xmagic)); - - // Write as many empty records as are needed to get to sblk boundary - while (currentPosn % QLS_SBLK_SIZE_BYTES) { - outFileStream.write((const char*)writeBuffer, QLS_DBLK_SIZE_BYTES); - if (outFileStream.fail()) { - throw jexception(jerrno::JERR_RCVM_WRITE, "RecoveryManager", "checkJournalAlignment"); - } - std::ostringstream oss2; - oss2 << std::hex << "Recover phase write: Wrote filler record: fid=0x" << start_fid; - oss2 << " offs=0x" << currentPosn; - journalLogRef_.log(JournalLog::LOG_NOTICE, queueName_, oss2.str()); - currentPosn = outFileStream.tellp(); - } - outFileStream.close(); - std::free(writeBuffer); - journalLogRef_.log(JournalLog::LOG_INFO, queueName_, "Bad record alignment fixed."); - } - lastRecord(start_fid, currentPosn); -} - -bool RecoveryManager::decodeRecord(jrec& record, - std::size_t& cumulativeSizeRead, - ::rec_hdr_t& headerRecord, - const uint64_t start_fid, - const std::streampos recordOffset) -{ - if (highestRecordId_ == 0) { - highestRecordId_ = headerRecord._rid; - } else if (headerRecord._rid - highestRecordId_ < 0x8000000000000000ULL) { // RFC 1982 comparison for unsigned 64-bit - highestRecordId_ = headerRecord._rid; - } - - bool done = false; - while (!done) { - try { - done = record.decode(headerRecord, &inFileStream_, cumulativeSizeRead, recordOffset); - } - catch (const jexception& e) { - if (e.err_code() == jerrno::JERR_JREC_BADRECTAIL) { - std::ostringstream oss; - oss << jerrno::err_msg(e.err_code()) << e.additional_info(); - journalLogRef_.log(JournalLog::LOG_INFO, queueName_, oss.str()); - } else { - journalLogRef_.log(JournalLog::LOG_INFO, queueName_, e.what()); - } - checkJournalAlignment(start_fid, recordOffset); - return false; - } - if (!done && needNextFile()) { - if (!getNextFile(false)) { - checkJournalAlignment(start_fid, recordOffset); - return false; - } - } - } - return true; -} - -std::string RecoveryManager::getCurrentFileName() const { - return currentJournalFileItr_->second->journalFilePtr_->getFqFileName(); -} - -uint64_t RecoveryManager::getCurrentFileNumber() const { - return currentJournalFileItr_->first; -} - -bool RecoveryManager::getFile(const uint64_t fileNumber, bool jumpToFirstRecordOffsetFlag) { - if (inFileStream_.is_open()) { - inFileStream_.close(); -//std::cout << " f=" << getCurrentFileName() << "]" << std::flush; // DEBUG - inFileStream_.clear(); // clear eof flag, req'd for older versions of c++ - } - currentJournalFileItr_ = fileNumberMap_.find(fileNumber); - if (currentJournalFileItr_ == fileNumberMap_.end()) { - return false; - } - inFileStream_.open(getCurrentFileName().c_str(), std::ios_base::in | std::ios_base::binary); - if (!inFileStream_.good()) { - throw jexception(jerrno::JERR__FILEIO, getCurrentFileName(), "RecoveryManager", "getFile"); - } -//std::cout << " [F=" << getCurrentFileName() << std::flush; // DEBUG - - if (!readFileHeader()) { - return false; - } - std::streamoff foffs = jumpToFirstRecordOffsetFlag ? firstRecordOffset_ : QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES; - inFileStream_.seekg(foffs); - return true; -} - -bool RecoveryManager::getNextFile(bool jumpToFirstRecordOffsetFlag) { - if (fileNumberMap_.empty()) { - return false; - } - if (inFileStream_.is_open()) { - inFileStream_.close(); -//std::cout << " .f=" << getCurrentFileName() << "]" << std::flush; // DEBUG - currentJournalFileItr_->second->completedDblkCount_ = efpFileSize_kib_ * 1024 / QLS_DBLK_SIZE_BYTES; - if (++currentJournalFileItr_ == fileNumberMap_.end()) { - return false; - } - inFileStream_.clear(); // clear eof flag, req'd for older versions of c++ - } - inFileStream_.open(getCurrentFileName().c_str(), std::ios_base::in | std::ios_base::binary); - if (!inFileStream_.good()) { - throw jexception(jerrno::JERR__FILEIO, getCurrentFileName(), "RecoveryManager", "getNextFile"); - } -//std::cout << " [.F=" << getCurrentFileName() << std::flush; // DEBUG - - if (!readFileHeader()) { - return false; - } - std::streamoff foffs = jumpToFirstRecordOffsetFlag ? firstRecordOffset_ : QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES; - inFileStream_.seekg(foffs); - return true; -} - -bool RecoveryManager::getNextRecordHeader() -{ - std::size_t cum_size_read = 0; - void* xidp = 0; - rec_hdr_t h; - - bool hdr_ok = false; - uint64_t file_id = currentJournalFileItr_->second->journalFilePtr_->getFileSeqNum(); - std::streampos file_pos = 0; - if (inFileStream_.is_open()) { - inFileStream_.clear(); - file_pos = inFileStream_.tellg(); - } - if (file_pos == std::streampos(-1)) { - std::ostringstream oss; - oss << "tellg() failure: fail=" << (inFileStream_.fail()?"T":"F") << " bad=" << (inFileStream_.bad()?"T":"F"); - oss << " eof=" << (inFileStream_.eof()?"T":"F") << " good=" << (inFileStream_.good()?"T":"F"); - oss << " rdstate=0x" << std::hex << inFileStream_.rdstate() << std::dec; - throw jexception(jerrno::JERR_RCVM_STREAMBAD, oss.str(), "RecoveryManager", "getNextRecordHeader"); - } - while (!hdr_ok) { - if (needNextFile()) { - if (!getNextFile(true)) { - lastRecord(file_id, file_pos); - return false; - } - } - file_id = currentJournalFileItr_->second->journalFilePtr_->getFileSeqNum(); - file_pos = inFileStream_.tellg(); - if (file_pos == std::streampos(-1)) { - std::ostringstream oss; - oss << "tellg() failure: fail=" << (inFileStream_.fail()?"T":"F") << " bad=" << (inFileStream_.bad()?"T":"F"); - oss << " eof=" << (inFileStream_.eof()?"T":"F") << " good=" << (inFileStream_.good()?"T":"F"); - oss << " rdstate=0x" << std::hex << inFileStream_.rdstate() << std::dec; - throw jexception(jerrno::JERR_RCVM_STREAMBAD, oss.str(), "RecoveryManager", "getNextRecordHeader"); - } - inFileStream_.read((char*)&h, sizeof(rec_hdr_t)); - if (inFileStream_.gcount() == sizeof(rec_hdr_t)) { - hdr_ok = true; - } else { - if (needNextFile()) { - if (!getNextFile(true)) { - lastRecord(file_id, file_pos); - return false; - } - } - } - } - - uint64_t start_fid = getCurrentFileNumber(); // fid may increment in decode() if record folds over file boundary - switch(h._magic) { - case QLS_ENQ_MAGIC: - { -//std::cout << " 0x" << std::hex << file_pos << ".e.0x" << h._rid << std::dec << std::flush; // DEBUG - if (::rec_hdr_check(&h, QLS_ENQ_MAGIC, QLS_JRNL_VERSION, currentSerial_) != 0) { - checkJournalAlignment(file_id, file_pos); - return false; - } - enq_rec er; - if (!decodeRecord(er, cum_size_read, h, start_fid, file_pos)) { - return false; - } - if (!er.is_transient()) { // Ignore transient msgs - fileNumberMap_[start_fid]->journalFilePtr_->incrEnqueuedRecordCount(); - if (er.xid_size()) { - er.get_xid(&xidp); - if (xidp == 0) { - throw jexception(jerrno::JERR_RCVM_NULLXID, "ENQ", "RecoveryManager", "getNextRecordHeader"); - } - std::string xid((char*)xidp, er.xid_size()); - transactionMapRef_.insert_txn_data(xid, txn_data_t(h._rid, 0, start_fid, file_pos, true, false, false)); - if (transactionMapRef_.set_aio_compl(xid, h._rid) < txn_map::TMAP_OK) { // fail - xid or rid not found - std::ostringstream oss; - oss << std::hex << "_tmap.set_aio_compl: txn_enq xid=\"" << xid << "\" rid=0x" << h._rid; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "RecoveryManager", "getNextRecordHeader"); - } - } else { - if (enqueueMapRef_.insert_pfid(h._rid, start_fid, file_pos) < enq_map::EMAP_OK) { // fail - // The only error code emap::insert_pfid() returns is enq_map::EMAP_DUP_RID. - std::ostringstream oss; - oss << std::hex << "rid=0x" << h._rid << " _pfid=0x" << start_fid; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "RecoveryManager", "getNextRecordHeader"); - } - } - } - } - break; - case QLS_DEQ_MAGIC: - { -//std::cout << " 0x" << std::hex << file_pos << ".d.0x" << h._rid << std::dec << std::flush; // DEBUG - if (::rec_hdr_check(&h, QLS_DEQ_MAGIC, QLS_JRNL_VERSION, currentSerial_) != 0) { - checkJournalAlignment(file_id, file_pos); - return false; - } - deq_rec dr; - if (!decodeRecord(dr, cum_size_read, h, start_fid, file_pos)) { - return false; - } - if (dr.xid_size()) { - // If the enqueue is part of a pending txn, it will not yet be in emap - enqueueMapRef_.lock(dr.deq_rid()); // ignore not found error - dr.get_xid(&xidp); - if (xidp == 0) { - throw jexception(jerrno::JERR_RCVM_NULLXID, "DEQ", "RecoveryManager", "getNextRecordHeader"); - } - std::string xid((char*)xidp, dr.xid_size()); - transactionMapRef_.insert_txn_data(xid, txn_data_t(dr.rid(), dr.deq_rid(), start_fid, file_pos, - false, false, dr.is_txn_coml_commit())); - if (transactionMapRef_.set_aio_compl(xid, dr.rid()) < txn_map::TMAP_OK) { // fail - xid or rid not found - std::ostringstream oss; - oss << std::hex << "_tmap.set_aio_compl: txn_deq xid=\"" << xid << "\" rid=0x" << dr.rid(); - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "RecoveryManager", "getNextRecordHeader"); - } - } else { - uint64_t enq_fid; - if (enqueueMapRef_.get_remove_pfid(dr.deq_rid(), enq_fid, true) == enq_map::EMAP_OK) { // ignore not found error - fileNumberMap_[enq_fid]->journalFilePtr_->decrEnqueuedRecordCount(); - } - } - } - break; - case QLS_TXA_MAGIC: - { -//std::cout << " 0x" << std::hex << file_pos << ".a.0x" << h._rid << std::dec << std::flush; // DEBUG - if (::rec_hdr_check(&h, QLS_TXA_MAGIC, QLS_JRNL_VERSION, currentSerial_) != 0) { - checkJournalAlignment(file_id, file_pos); - return false; - } - txn_rec ar; - if (!decodeRecord(ar, cum_size_read, h, start_fid, file_pos)) { - return false; - } - // Delete this txn from tmap, unlock any locked records in emap - ar.get_xid(&xidp); - if (xidp == 0) { - throw jexception(jerrno::JERR_RCVM_NULLXID, "ABT", "RecoveryManager", "getNextRecordHeader"); - } - std::string xid((char*)xidp, ar.xid_size()); - txn_data_list_t tdl = transactionMapRef_.get_remove_tdata_list(xid); // tdl will be empty if xid not found - for (tdl_itr_t itr = tdl.begin(); itr != tdl.end(); itr++) { - if (itr->enq_flag_) { - fileNumberMap_[itr->fid_]->journalFilePtr_->decrEnqueuedRecordCount(); - } else { - enqueueMapRef_.unlock(itr->drid_); // ignore not found error - } - } - } - break; - case QLS_TXC_MAGIC: - { -//std::cout << " 0x" << std::hex << file_pos << ".c.0x" << h._rid << std::dec << std::flush; // DEBUG - if (::rec_hdr_check(&h, QLS_TXC_MAGIC, QLS_JRNL_VERSION, currentSerial_) != 0) { - checkJournalAlignment(file_id, file_pos); - return false; - } - txn_rec cr; - if (!decodeRecord(cr, cum_size_read, h, start_fid, file_pos)) { - return false; - } - // Delete this txn from tmap, process records into emap - cr.get_xid(&xidp); - if (xidp == 0) { - throw jexception(jerrno::JERR_RCVM_NULLXID, "CMT", "RecoveryManager", "getNextRecordHeader"); - } - std::string xid((char*)xidp, cr.xid_size()); - txn_data_list_t tdl = transactionMapRef_.get_remove_tdata_list(xid); // tdl will be empty if xid not found - for (tdl_itr_t itr = tdl.begin(); itr != tdl.end(); itr++) { - if (itr->enq_flag_) { // txn enqueue -//std::cout << "[rid=0x" << std::hex << itr->rid_ << std::dec << " fid=" << itr->fid_ << " fpos=0x" << std::hex << itr->foffs_ << "]" << std::dec << std::flush; // DEBUG - if (enqueueMapRef_.insert_pfid(itr->rid_, itr->fid_, itr->foffs_) < enq_map::EMAP_OK) { // fail - // The only error code emap::insert_pfid() returns is enq_map::EMAP_DUP_RID. - std::ostringstream oss; - oss << std::hex << "rid=0x" << itr->rid_ << " _pfid=0x" << itr->fid_; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "RecoveryManager", "getNextRecordHeader"); - } - } else { // txn dequeue - uint64_t enq_fid; - if (enqueueMapRef_.get_remove_pfid(itr->drid_, enq_fid, true) == enq_map::EMAP_OK) // ignore not found error - fileNumberMap_[enq_fid]->journalFilePtr_->decrEnqueuedRecordCount(); - } - } - } - break; - case QLS_EMPTY_MAGIC: - { -//std::cout << ".x" << std::flush; // DEBUG - uint32_t rec_dblks = jrec::size_dblks(sizeof(::rec_hdr_t)); - inFileStream_.ignore(rec_dblks * QLS_DBLK_SIZE_BYTES - sizeof(::rec_hdr_t)); - checkFileStreamOk(false); - if (needNextFile()) { - file_pos += rec_dblks * QLS_DBLK_SIZE_BYTES; - if (!getNextFile(false)) { - lastRecord(start_fid, file_pos); - return false; - } - } - } - break; - case 0: -//std::cout << " 0x" << std::hex << file_pos << ".0" << std::dec << std::endl << std::flush; // DEBUG - checkJournalAlignment(getCurrentFileNumber(), file_pos); - return false; - default: -//std::cout << " 0x" << std::hex << file_pos << ".?" << std::dec << std::endl << std::flush; // DEBUG - // Stop as this is the overwrite boundary. - checkJournalAlignment(getCurrentFileNumber(), file_pos); - return false; - } - return true; -} - -void RecoveryManager::lastRecord(const uint64_t file_id, const std::streamoff endOffset) { - endOffset_ = endOffset; - initial_fid_ = file_id; - fileNumberMap_[file_id]->completedDblkCount_ = endOffset_ / QLS_DBLK_SIZE_BYTES; - - // Remove any files in fileNumberMap_ beyond initial_fid_ - fileNumberMapItr_t unwantedFirstItr = fileNumberMap_.find(file_id); - if (++unwantedFirstItr != fileNumberMap_.end()) { - fileNumberMapItr_t itr = unwantedFirstItr; - notNeededFilesList_.push_back(unwantedFirstItr->second->journalFilePtr_->getFqFileName()); - while (++itr != fileNumberMap_.end()) { - notNeededFilesList_.push_back(itr->second->journalFilePtr_->getFqFileName()); - delete itr->second->journalFilePtr_; - delete itr->second; - } - fileNumberMap_.erase(unwantedFirstItr, fileNumberMap_.end()); - } -} - -bool RecoveryManager::needNextFile() { - if (inFileStream_.is_open()) { - return inFileStream_.eof() || inFileStream_.tellg() >= std::streampos(efpFileSize_kib_ * 1024); - } - return true; -} - -void RecoveryManager::prepareRecordList() { - // Set up recordIdList_ from enqueue map and transaction map - recordIdList_.clear(); - - // Extract records from enqueue list - std::vector ridList; - enqueueMapRef_.rid_list(ridList); - qpid::linearstore::journal::enq_map::emap_data_struct_t eds; - for (std::vector::const_iterator i=ridList.begin(); i!=ridList.end(); ++i) { - enqueueMapRef_.get_data(*i, eds); - recordIdList_.push_back(RecoveredRecordData_t(*i, eds._pfid, eds._file_posn, false)); - } - - // Extract records from pending transaction enqueues - std::vector xidList; - transactionMapRef_.xid_list(xidList); - for (std::vector::const_iterator j=xidList.begin(); j!=xidList.end(); ++j) { - qpid::linearstore::journal::txn_data_list_t tdsl = transactionMapRef_.get_tdata_list(*j); - for (qpid::linearstore::journal::tdl_itr_t k=tdsl.begin(); k!=tdsl.end(); ++k) { - if (k->enq_flag_) { - recordIdList_.push_back(RecoveredRecordData_t(k->rid_, k->fid_, k->foffs_, true)); - } - } - } - - std::sort(recordIdList_.begin(), recordIdList_.end(), recordIdListCompare); - recordIdListConstItr_ = recordIdList_.begin(); -} - -void RecoveryManager::readJournalData(char* target, - const std::streamsize readSize) { - std::streamoff bytesRead = 0; - while (bytesRead < readSize) { - std::streampos file_pos = inFileStream_.tellg(); - if (file_pos == std::streampos(-1)) { - std::ostringstream oss; - oss << "tellg() failure: fail=" << (inFileStream_.fail()?"T":"F") << " bad=" << (inFileStream_.bad()?"T":"F"); - throw jexception(jerrno::JERR_RCVM_STREAMBAD, oss.str(), "RecoveryManager", "readJournalData"); - } - inFileStream_.read(target + bytesRead, readSize - bytesRead); - std::streamoff thisReadSize = inFileStream_.gcount(); - if (thisReadSize < readSize) { - if (needNextFile()) { - getNextFile(false); - } - file_pos = inFileStream_.tellg(); - if (file_pos == std::streampos(-1)) { - std::ostringstream oss; - oss << "tellg() failure: fail=" << (inFileStream_.fail()?"T":"F") << " bad=" << (inFileStream_.bad()?"T":"F"); - throw jexception(jerrno::JERR_RCVM_STREAMBAD, oss.str(), "RecoveryManager", "readJournalData"); - } - } - bytesRead += thisReadSize; - } -} - -bool RecoveryManager::readFileHeader() { - file_hdr_t fhdr; - inFileStream_.read((char*)&fhdr, sizeof(fhdr)); - checkFileStreamOk(true); - if (::file_hdr_check(&fhdr, QLS_FILE_MAGIC, QLS_JRNL_VERSION, efpFileSize_kib_, QLS_MAX_QUEUE_NAME_LEN) != 0) { - firstRecordOffset_ = fhdr._fro; - currentSerial_ = fhdr._rhdr._serial; - } else { - inFileStream_.close(); - if (currentJournalFileItr_ == fileNumberMap_.begin()) { - journalEmptyFlag_ = true; - } - return false; - } - return true; -} - -// static private -bool RecoveryManager::readJournalFileHeader(const std::string& journalFileName, - ::file_hdr_t& fileHeaderRef, - std::string& queueName) { - const std::size_t headerBlockSize = QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024; - char buffer[headerBlockSize]; - std::ifstream ifs(journalFileName.c_str(), std::ifstream::in | std::ifstream::binary); - if (!ifs.good()) { - std::ostringstream oss; - oss << "File=" << journalFileName; - throw jexception(jerrno::JERR_RCVM_OPENRD, oss.str(), "RecoveryManager", "readJournalFileHeader"); - } - ifs.read(buffer, headerBlockSize); - if (!ifs) { - std::streamsize s = ifs.gcount(); - ifs.close(); - std::ostringstream oss; - oss << "File=" << journalFileName << "; attempted_read_size=" << headerBlockSize << "; actual_read_size=" << s; - throw jexception(jerrno::JERR_RCVM_READ, oss.str(), "RecoveryManager", "readJournalFileHeader"); - } - ifs.close(); - ::memcpy(&fileHeaderRef, buffer, sizeof(::file_hdr_t)); - if (::file_hdr_check(&fileHeaderRef, QLS_FILE_MAGIC, QLS_JRNL_VERSION, 0, QLS_MAX_QUEUE_NAME_LEN)) { - return false; - } - queueName.assign(buffer + sizeof(::file_hdr_t), fileHeaderRef._queue_name_len); - return true; -} - -void RecoveryManager::removeEmptyFiles(EmptyFilePool* emptyFilePoolPtr) { - while (fileNumberMap_.begin()->second->journalFilePtr_->getEnqueuedRecordCount() == 0 && fileNumberMap_.size() > 1) { - RecoveredFileData_t* rfdp = fileNumberMap_.begin()->second; - emptyFilePoolPtr->returnEmptyFileSymlink(rfdp->journalFilePtr_->getFqFileName()); - delete rfdp->journalFilePtr_; - delete rfdp; - fileNumberMap_.erase(fileNumberMap_.begin()->first); - } -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h b/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h deleted file mode 100644 index 55cc6f8329..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_RECOVERYSTATE_H_ -#define QPID_LINEARSTORE_JOURNAL_RECOVERYSTATE_H_ - -#include -#include -#include "qpid/linearstore/journal/LinearFileController.h" -#include -#include - -struct file_hdr_t; -struct rec_hdr_t; - -namespace qpid { -namespace linearstore { -namespace journal { - -class data_tok; -class enq_map; -class EmptyFilePool; -class EmptyFilePoolManager; -class JournalLog; -class jrec; -class txn_map; - -struct RecoveredRecordData_t { - uint64_t recordId_; - uint64_t fileId_; - std::streampos fileOffset_; - bool pendingTransaction_; - RecoveredRecordData_t(const uint64_t rid, const uint64_t fid, const std::streampos foffs, bool ptxn); -}; - -struct RecoveredFileData_t { - JournalFile* journalFilePtr_; - uint32_t completedDblkCount_; - RecoveredFileData_t(JournalFile* journalFilePtr, const uint32_t completedDblkCount); -}; - -bool recordIdListCompare(RecoveredRecordData_t a, RecoveredRecordData_t b); - -class RecoveryManager -{ -protected: - // Types - typedef std::vector stringList_t; - typedef stringList_t::const_iterator stringListConstItr_t; - typedef std::map fileNumberMap_t; - typedef fileNumberMap_t::iterator fileNumberMapItr_t; - typedef fileNumberMap_t::const_iterator fileNumberMapConstItr_t; - typedef std::vector recordIdList_t; - typedef recordIdList_t::const_iterator recordIdListConstItr_t; - - // Location and identity - const std::string journalDirectory_; - const std::string queueName_; - enq_map& enqueueMapRef_; - txn_map& transactionMapRef_; - JournalLog& journalLogRef_; - - // Initial journal analysis data - fileNumberMap_t fileNumberMap_; ///< File number - JournalFilePtr map - stringList_t notNeededFilesList_; ///< Files not needed and to be returned to EFP - stringList_t uninitFileList_; ///< File name of uninitialized journal files found during header analysis - bool journalEmptyFlag_; ///< Journal data files empty - std::streamoff firstRecordOffset_; ///< First record offset in ffid - std::streamoff endOffset_; ///< End offset (first byte past last record) - uint64_t highestRecordId_; ///< Highest rid found - uint64_t highestFileNumber_; ///< Highest file number found - bool lastFileFullFlag_; ///< Last file is full - uint64_t initial_fid_; ///< File id where initial write after recovery will occur - - // State for recovery of individual enqueued records - uint64_t currentSerial_; - uint32_t efpFileSize_kib_; - fileNumberMapConstItr_t currentJournalFileItr_; - std::string currentFileName_; - std::ifstream inFileStream_; - recordIdList_t recordIdList_; - recordIdListConstItr_t recordIdListConstItr_; - -public: - RecoveryManager(const std::string& journalDirectory, - const std::string& queuename, - enq_map& enqueueMapRef, - txn_map& transactionMapRef, - JournalLog& journalLogRef); - virtual ~RecoveryManager(); - - void analyzeJournals(const std::vector* preparedTransactionListPtr, - EmptyFilePoolManager* emptyFilePoolManager, - EmptyFilePool** emptyFilePoolPtrPtr); - std::streamoff getEndOffset() const; - uint64_t getHighestFileNumber() const; - uint64_t getHighestRecordId() const; - bool isLastFileFull() const; - bool readNextRemainingRecord(void** const dataPtrPtr, - std::size_t& dataSize, - void** const xidPtrPtr, - std::size_t& xidSize, - bool& transient, - bool& external, - data_tok* const dtokp, - bool ignore_pending_txns); - void recoveryComplete(); - void setLinearFileControllerJournals(lfcAddJournalFileFn fnPtr, - LinearFileController* lfcPtr); - std::string toString(const std::string& jid, const uint16_t indent) const; -protected: - void analyzeJournalFileHeaders(efpIdentity_t& efpIdentity); - void checkFileStreamOk(bool checkEof); - void checkJournalAlignment(const uint64_t start_fid, const std::streampos recordPosition); - bool decodeRecord(jrec& record, - std::size_t& cumulativeSizeRead, - ::rec_hdr_t& recordHeader, - const uint64_t start_fid, - const std::streampos recordOffset); - std::string getCurrentFileName() const; - uint64_t getCurrentFileNumber() const; - bool getFile(const uint64_t fileNumber, bool jumpToFirstRecordOffsetFlag); - bool getNextFile(bool jumpToFirstRecordOffsetFlag); - bool getNextRecordHeader(); - void lastRecord(const uint64_t file_id, const std::streamoff endOffset); - bool needNextFile(); - void prepareRecordList(); - bool readFileHeader(); - void readJournalData(char* target, const std::streamsize size); - void removeEmptyFiles(EmptyFilePool* emptyFilePoolPtr); - - static bool readJournalFileHeader(const std::string& journalFileName, - ::file_hdr_t& fileHeaderRef, - std::string& queueName); -}; - -}}} - -#endif // QPID_LINEARSTORE_JOURNAL_RECOVERYSTATE_H_ diff --git a/qpid/cpp/src/qpid/linearstore/journal/aio.h b/qpid/cpp/src/qpid/linearstore/journal/aio.h deleted file mode 100644 index 14589e7580..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/aio.h +++ /dev/null @@ -1,201 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_AIO_H -#define QPID_LINEARSTORE_JOURNAL_AIO_H - -#include -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -typedef iocb aio_cb; -typedef io_event aio_event; - -/** - * \brief This class is a C++ wrapper class for the libaio functions used by the journal. Note that only those - * functions used by the journal are included here. This is not a complete implementation of all libaio functions. - */ -class aio -{ -public: - /* - * \brief Initialize an AIO context. Causes kernel resources to be initialized for - * AIO operations. - * - * \param maxevents The maximum number of events to be handled - * \param ctxp Pointer to context struct to be initialized - */ - static inline int queue_init(int maxevents, io_context_t* ctxp) - { - return ::io_queue_init(maxevents, ctxp); - } - - /* - * \brief Release an AIO context. Causes kernel resources previously initialized to - * be released. - * - * \param ctx AIO context struct to be released - */ - static inline int queue_release(io_context_t ctx) - { - return ::io_queue_release(ctx); - } - - /* - * \brief Submit asynchronous I/O blocks for processing - * - * The io_submit() system call queues nr I/O request blocks for processing in the AIO context ctx. - * The iocbpp argument should be an array of nr AIO control blocks, which will be submitted to context ctx. - * - * \param ctx AIO context - * \param nr Number of AIO operations - * \param aios Array of nr pointers to AIO control blocks, one for each AIO operation - * \return On success, io_submit() returns the number of iocbs submitted (which may be 0 if nr is zero). - * A negative number indicates an error: - * - -EAGAIN Insufficient resources are available to queue any iocbs. - * - -EBADF The file descriptor specified in the first iocb is invalid. - * - -EFAULT One of the data structures points to invalid data. - * - -EINVAL The AIO context specified by ctx_id is invalid. nr is less than 0. The iocb at *iocbpp[0] - * is not properly initialized, or the operation specified is invalid for the file descriptor - * in the iocb. - */ - static inline int submit(io_context_t ctx, long nr, aio_cb* aios[]) - { - return ::io_submit(ctx, nr, aios); - } - - /* - * \brief Get list of completed AIO operations - * - * The io_getevents() system call attempts to read at least min_nr events and up to nr events from the - * completion queue of the AIO context specified by ctx_id. The timeout argument specifies the amount of time - * to wait for events, where a NULL timeout waits until at least min_nr events have been seen. Note that timeout - * is relative. - * - * \param ctx AIO context - * \param min_nr Minimum number of events to return, will wait until min_nr events are accumulated or until timeout - * \param nr Number of events to return - * \param events Pointer to array of aio_event structs, one for each completed event - * \param timeout Time to wait for min_nr events; 0 will cause an indefinite wait for min_nr events - * \return On success, number of events read: 0 if no events are available, or less than min_nr - * if the timeout has elapsed. A negative number indicates an error: - * - -EFAULT Either events or timeout is an invalid pointer. - * - -EINVAL ctx_id is invalid. min_nr is out of range or nr is out of range. - * - -EINTR Interrupted by a signal handler; see signal(7). - */ - static inline int getevents(io_context_t ctx, long min_nr, long nr, aio_event* events, timespec* const timeout) - { - return ::io_getevents(ctx, min_nr, nr, events, timeout); - } - - /** - * \brief This function allows iocbs to be initialized with a pointer that can be re-used. This prepares an - * aio_cb struct for read use. (This is a wrapper for libaio's ::io_prep_pread() function.) - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for read. - * \param buf Pointer to buffer in which read data is to be placed. MUST BE PAGE_ALIGNED. - * \param count Number of bytes to read - buffer must be large enough. - * \param offset Offset within file from which data will be read. - */ - static inline void prep_pread(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - ::io_prep_pread(aiocbp, fd, buf, count, offset); - } - - /** - * \brief Special version of libaio's io_prep_pread() which preserves the value of the data pointer. This allows - * iocbs to be initialized with a pointer that can be re-used. This prepares a aio_cb struct for read use. - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for read. - * \param buf Pointer to buffer in which read data is to be placed. MUST BE PAGE_ALIGNED. - * \param count Number of bytes to read - buffer must be large enough. - * \param offset Offset within file from which data will be read. - */ - static inline void prep_pread_2(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - std::memset((void*) ((char*) aiocbp + sizeof(void*)), 0, sizeof(aio_cb) - sizeof(void*)); - aiocbp->aio_fildes = fd; - aiocbp->aio_lio_opcode = IO_CMD_PREAD; - aiocbp->aio_reqprio = 0; - aiocbp->u.c.buf = buf; - aiocbp->u.c.nbytes = count; - aiocbp->u.c.offset = offset; - } - - /** - * \brief This function allows iocbs to be initialized with a pointer that can be re-used. This function prepares - * an aio_cb struct for write use. (This is a wrapper for libaio's ::io_prep_pwrite() function.) - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for write. - * \param buf Pointer to buffer in which data to be written is located. MUST BE PAGE_ALIGNED. - * \param count Number of bytes to write. - * \param offset Offset within file to which data will be written. - */ - static inline void prep_pwrite(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - ::io_prep_pwrite(aiocbp, fd, buf, count, offset); - } - - /** - * \brief Special version of libaio's io_prep_pwrite() which preserves the value of the data pointer. This allows - * iocbs to be initialized with a pointer that can be re-used. This function prepares an aio_cb struct for write - * use. - * - * \param aiocbp Pointer to the aio_cb struct to be prepared. - * \param fd File descriptor to be used for write. - * \param buf Pointer to buffer in which data to be written is located. MUST BE PAGE_ALIGNED. - * \param count Number of bytes to write. - * \param offset Offset within file to which data will be written. - */ - static inline void prep_pwrite_2(aio_cb* aiocbp, int fd, void* buf, std::size_t count, int64_t offset) - { - std::memset((void*) ((char*) aiocbp + sizeof(void*)), 0, sizeof(aio_cb) - sizeof(void*)); - aiocbp->aio_fildes = fd; - aiocbp->aio_lio_opcode = IO_CMD_PWRITE; - aiocbp->aio_reqprio = 0; - aiocbp->u.c.buf = buf; - aiocbp->u.c.nbytes = count; - aiocbp->u.c.offset = offset; - } - - /** - * \brief Function to check the alignment of memory. - * - * \param ptr Pointer to be checked - * \param byte_count Alignment count (or boundary) - * \returns true if ptr is aligned with byte_count, false otherwise - */ - static inline bool is_aligned(const void* ptr, uint64_t byte_count) - { - return ((uintptr_t)(ptr)) % (byte_count) == 0; - } -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_AIO_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/aio_callback.h b/qpid/cpp/src/qpid/linearstore/journal/aio_callback.h deleted file mode 100644 index f21b62617b..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/aio_callback.h +++ /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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_AIO_CALLBACK_H -#define QPID_LINEARSTORE_JOURNAL_AIO_CALLBACK_H - -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -class data_tok; - -class aio_callback -{ -public: - virtual ~aio_callback() {} - virtual void wr_aio_cb(std::vector& dtokl) = 0; - virtual void rd_aio_cb(std::vector& pil) = 0; -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_AIO_CALLBACK_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/data_tok.cpp b/qpid/cpp/src/qpid/linearstore/journal/data_tok.cpp deleted file mode 100644 index 3952c403a1..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/data_tok.cpp +++ /dev/null @@ -1,136 +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/linearstore/journal/data_tok.h" - -#include -#include "qpid/linearstore/journal/slock.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -// Static members - -uint64_t data_tok::_cnt = 0; -smutex data_tok::_mutex; - -data_tok::data_tok(): - _wstate(NONE), - _dsize(0), - _dblks_written(0), - _pg_cnt(0), - _fid(0), - _rid(0), - _xid(), - _dequeue_rid(0), - _external_rid(false) -{ - slock s(_mutex); - _icnt = _cnt++; -} - -data_tok::~data_tok() {} - -const char* -data_tok::wstate_str() const -{ - return wstate_str(_wstate); -} - -const char* -data_tok::wstate_str(write_state wstate) -{ - switch (wstate) - { - case NONE: - return "NONE"; - case ENQ_CACHED: - return "ENQ_CACHED"; - case ENQ_PART: - return "ENQ_PART"; - case ENQ_SUBM: - return "ENQ_SUBM"; - case ENQ: - return "ENQ"; - case DEQ_CACHED: - return "DEQ_CACHED"; - case DEQ_PART: - return "DEQ_PART"; - case DEQ_SUBM: - return "DEQ_SUBM"; - case DEQ: - return "DEQ"; - case ABORT_CACHED: - return "ABORT_CACHED"; - case ABORT_PART: - return "ABORT_PART"; - case ABORT_SUBM: - return "ABORT_SUBM"; - case ABORTED: - return "ABORTED"; - case COMMIT_CACHED: - return "COMMIT_CACHED"; - case COMMIT_PART: - return "COMMIT_PART"; - case COMMIT_SUBM: - return "COMMIT_SUBM"; - case COMMITTED: - return "COMMITTED"; - } - // Not using default: forces compiler to ensure all cases are covered. - return ""; -} - -void -data_tok::reset() -{ - _wstate = NONE; - _dsize = 0; - _dblks_written = 0; - _pg_cnt = 0; - _fid = 0; - _rid = 0; - _xid.clear(); -} - -// debug aid -std::string -data_tok::status_str() const -{ - std::ostringstream oss; - oss << std::hex << std::setfill('0'); - oss << "dtok id=0x" << _icnt << "; ws=" << wstate_str()/* << "; rs=" << rstate_str()*/; - oss << "; fid=0x" << _fid << "; rid=0x" << _rid << "; xid="; - for (unsigned i=0; i<_xid.size(); i++) - { - if (isprint(_xid[i])) - oss << _xid[i]; - else - oss << "/" << std::setw(2) << (int)((char)_xid[i]); - } - oss << "; drid=0x" << _dequeue_rid << " extrid=" << (_external_rid?"T":"F"); - oss << "; ds=0x" << _dsize << "; dw=0x" << _dblks_written/* << "; dr=0x" << _dblks_read*/; - oss << "; pc=0x" << _pg_cnt; - return oss.str(); -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/data_tok.h b/qpid/cpp/src/qpid/linearstore/journal/data_tok.h deleted file mode 100644 index 67e0ec9683..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/data_tok.h +++ /dev/null @@ -1,133 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_DATA_TOK_H -#define QPID_LINEARSTORE_JOURNAL_DATA_TOK_H - -namespace qpid { -namespace linearstore { -namespace journal { -class data_tok; -}}} - -#include -#include "qpid/linearstore/journal/smutex.h" - -namespace qpid { -namespace linearstore { -namespace journal { - - /** - * \class data_tok - * \brief Data block token (data_tok) used to track wstate of a data block through asynchronous - * I/O process - */ - class data_tok - { - public: - // TODO: Fix this, separate write state from operation - // ie: wstate = NONE, CACHED, PART, SUBM, COMPL - // op = ENQUEUE, DEQUEUE, ABORT, COMMIT - enum write_state - { - NONE, ///< Data block not sent to journal - ENQ_CACHED, ///< Data block enqueue written to page cache - ENQ_PART, ///< Data block part-submitted to AIO, waiting for page buffer to free up - ENQ_SUBM, ///< Data block enqueue submitted to AIO - ENQ, ///< Data block enqueue AIO write complete (enqueue complete) - DEQ_CACHED, ///< Data block dequeue written to page cache - DEQ_PART, ///< Data block part-submitted to AIO, waiting for page buffer to free up - DEQ_SUBM, ///< Data block dequeue submitted to AIO - DEQ, ///< Data block dequeue AIO write complete (dequeue complete) - ABORT_CACHED, - ABORT_PART, - ABORT_SUBM, - ABORTED, - COMMIT_CACHED, - COMMIT_PART, - COMMIT_SUBM, - COMMITTED - }; - - protected: - static smutex _mutex; - static uint64_t _cnt; - uint64_t _icnt; - write_state _wstate; ///< Enqueued / dequeued state of data - std::size_t _dsize; ///< Data size in bytes - uint32_t _dblks_written; ///< Data blocks read/written - uint32_t _pg_cnt; ///< Page counter - incr for each page containing part of data - uint64_t _fid; ///< FID containing header of enqueue record - uint64_t _rid; ///< RID of data set by enqueue operation - std::string _xid; ///< XID set by enqueue operation - uint64_t _dequeue_rid; ///< RID of data set by dequeue operation - bool _external_rid; ///< Flag to indicate external setting of rid - - public: - data_tok(); - virtual ~data_tok(); - - inline uint64_t id() const { return _icnt; } - inline write_state wstate() const { return _wstate; } - const char* wstate_str() const; - static const char* wstate_str(write_state wstate); - inline bool is_writable() const { return _wstate == NONE || _wstate == ENQ_PART; } - inline bool is_enqueued() const { return _wstate == ENQ; } - inline bool is_readable() const { return _wstate == ENQ; } - inline bool is_dequeueable() const { return _wstate == ENQ || _wstate == DEQ_PART; } - inline void set_wstate(const write_state wstate) { _wstate = wstate; } - inline std::size_t dsize() const { return _dsize; } - inline void set_dsize(std::size_t dsize) { _dsize = dsize; } - - inline uint32_t dblocks_written() const { return _dblks_written; } - inline void incr_dblocks_written(uint32_t dblks_written) - { _dblks_written += dblks_written; } - inline void set_dblocks_written(uint32_t dblks_written) { _dblks_written = dblks_written; } - - inline uint32_t pg_cnt() const { return _pg_cnt; } - inline uint32_t incr_pg_cnt() { return ++_pg_cnt; } - inline uint32_t decr_pg_cnt() { assert(_pg_cnt != 0); return --_pg_cnt; } - - inline uint64_t fid() const { return _fid; } - inline void set_fid(const uint64_t fid) { _fid = fid; } - inline uint64_t rid() const { return _rid; } - inline void set_rid(const uint64_t rid) { _rid = rid; } - inline uint64_t dequeue_rid() const {return _dequeue_rid; } - inline void set_dequeue_rid(const uint64_t rid) { _dequeue_rid = rid; } - inline bool external_rid() const { return _external_rid; } - inline void set_external_rid(const bool external_rid) { _external_rid = external_rid; } - - inline bool has_xid() const { return !_xid.empty(); } - inline const std::string& xid() const { return _xid; } - inline void clear_xid() { _xid.clear(); } - inline void set_xid(const std::string& xid) { _xid.assign(xid); } - inline void set_xid(const void* xidp, const std::size_t xid_len) - { _xid.assign((const char*)xidp, xid_len); } - - void reset(); - - // debug aid - std::string status_str() const; - }; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_DATA_TOK_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp b/qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp deleted file mode 100644 index 90ca27d082..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp +++ /dev/null @@ -1,313 +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/linearstore/journal/deq_rec.h" - -#include -#include -#include "qpid/linearstore/journal/Checksum.h" -#include "qpid/linearstore/journal/jexception.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -deq_rec::deq_rec(): - _xidp(0), - _xid_buff(0) -{ - ::deq_hdr_init(&_deq_hdr, QLS_DEQ_MAGIC, QLS_JRNL_VERSION, 0, 0, 0, 0, 0); - ::rec_tail_copy(&_deq_tail, &_deq_hdr._rhdr, 0); -} - -deq_rec::~deq_rec() -{ - clean(); -} - -void -deq_rec::reset(const uint64_t serial, const uint64_t rid, const uint64_t drid, const void* const xidp, - const std::size_t xidlen, const bool txn_coml_commit) -{ - _deq_hdr._rhdr._serial = serial; - _deq_hdr._rhdr._rid = rid; - ::set_txn_coml_commit(&_deq_hdr, txn_coml_commit); - _deq_hdr._deq_rid = drid; - _deq_hdr._xidsize = xidlen; - _xidp = xidp; - _xid_buff = 0; - _deq_tail._serial = serial; - _deq_tail._rid = rid; - _deq_tail._checksum = 0UL; -} - -uint32_t -deq_rec::encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum) -{ - assert(wptr != 0); - assert(max_size_dblks > 0); - if (_xidp == 0) - assert(_deq_hdr._xidsize == 0); - - std::size_t rec_offs = rec_offs_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t rem = max_size_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t wr_cnt = 0; - - if (rec_offs_dblks) // Continuation of split dequeue record (over 2 or more pages) - { - if (size_dblks(rec_size()) - rec_offs_dblks > max_size_dblks) // Further split required - { - rec_offs -= sizeof(_deq_hdr); - std::size_t wsize = _deq_hdr._xidsize > rec_offs ? _deq_hdr._xidsize - rec_offs : 0; - std::size_t wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= _deq_hdr._xidsize - wsize2; - checksum.addData((unsigned char*)wptr, wr_cnt); - if (rem) - { - _deq_tail._checksum = checksum.getChecksum(); - wsize = sizeof(_deq_tail) > rec_offs ? sizeof(_deq_tail) - rec_offs : 0; - wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy((char*)wptr + wr_cnt, (char*)&_deq_tail + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= sizeof(_deq_tail) - wsize2; - } - assert(rem == 0); - assert(rec_offs == 0); - } - else // No further split required - { - rec_offs -= sizeof(_deq_hdr); - std::size_t wsize = _deq_hdr._xidsize > rec_offs ? _deq_hdr._xidsize - rec_offs : 0; - if (wsize) - { - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - checksum.addData((unsigned char*)wptr, wr_cnt); - } - rec_offs -= _deq_hdr._xidsize - wsize; - _deq_tail._checksum = checksum.getChecksum(); - wsize = sizeof(_deq_tail) > rec_offs ? sizeof(_deq_tail) - rec_offs : 0; - if (wsize) - { - std::memcpy((char*)wptr + wr_cnt, (char*)&_deq_tail + rec_offs, wsize); - wr_cnt += wsize; -#ifdef QLS_CLEAN - std::size_t rec_offs = rec_offs_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t dblk_rec_size = size_dblks(rec_size() - rec_offs) * QLS_DBLK_SIZE_BYTES; - std::memset((char*)wptr + wr_cnt, QLS_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - rec_offs -= sizeof(_deq_tail) - wsize; - assert(rec_offs == 0); - } - } - else // Start at beginning of data record - { - // Assumption: the header will always fit into the first dblk - std::memcpy(wptr, (void*)&_deq_hdr, sizeof(_deq_hdr)); - wr_cnt = sizeof(_deq_hdr); - if (size_dblks(rec_size()) > max_size_dblks) // Split required - can only occur with xid - { - std::size_t wsize; - rem -= sizeof(_deq_hdr); - if (rem) - { - wsize = rem >= _deq_hdr._xidsize ? _deq_hdr._xidsize : rem; - std::memcpy((char*)wptr + wr_cnt, _xidp, wsize); - wr_cnt += wsize; - rem -= wsize; - } - checksum.addData((unsigned char*)wptr, wr_cnt); - if (rem) - { - _deq_tail._checksum = checksum.getChecksum(); - wsize = rem >= sizeof(_deq_tail) ? sizeof(_deq_tail) : rem; - std::memcpy((char*)wptr + wr_cnt, (void*)&_deq_tail, wsize); - wr_cnt += wsize; - rem -= wsize; - } - assert(rem == 0); - } - else // No split required - { - if (_deq_hdr._xidsize) - { - std::memcpy((char*)wptr + wr_cnt, _xidp, _deq_hdr._xidsize); - wr_cnt += _deq_hdr._xidsize; - checksum.addData((unsigned char*)wptr, wr_cnt); - _deq_tail._checksum = checksum.getChecksum(); - std::memcpy((char*)wptr + wr_cnt, (void*)&_deq_tail, sizeof(_deq_tail)); - wr_cnt += sizeof(_deq_tail); - } -#ifdef QLS_CLEAN - std::size_t dblk_rec_size = size_dblks(rec_size()) * QLS_DBLK_SIZE_BYTES; - std::memset((char*)wptr + wr_cnt, QLS_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - } - return size_dblks(wr_cnt); -} - -bool -deq_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start) -{ - if (rec_offs == 0) - { - ::rec_hdr_copy(&_deq_hdr._rhdr, &h); - ifsp->read((char*)&_deq_hdr._deq_rid, sizeof(_deq_hdr._deq_rid)); - ifsp->read((char*)&_deq_hdr._xidsize, sizeof(_deq_hdr._xidsize)); - rec_offs = sizeof(::deq_hdr_t); - // Read header, allocate (if req'd) for xid - if (_deq_hdr._xidsize) - { - _xid_buff = std::malloc(_deq_hdr._xidsize); - MALLOC_CHK(_xid_buff, "_buff", "enq_rec", "rcv_decode"); - } - } - if (rec_offs < sizeof(_deq_hdr) + _deq_hdr._xidsize) - { - // Read xid (or continue reading xid) - std::size_t offs = rec_offs - sizeof(_deq_hdr); - ifsp->read((char*)_xid_buff + offs, _deq_hdr._xidsize - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < _deq_hdr._xidsize - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - if (rec_offs < sizeof(_deq_hdr) + - (_deq_hdr._xidsize ? _deq_hdr._xidsize + sizeof(rec_tail_t) : 0)) - { - // Read tail (or continue reading tail) - std::size_t offs = rec_offs - sizeof(_deq_hdr) - _deq_hdr._xidsize; - ifsp->read((char*)&_deq_tail + offs, sizeof(rec_tail_t) - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < sizeof(rec_tail_t) - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - check_rec_tail(rec_start); - } - ifsp->ignore(rec_size_dblks() * QLS_DBLK_SIZE_BYTES - rec_size()); - assert(!ifsp->fail() && !ifsp->bad()); - return true; -} - -std::size_t -deq_rec::get_xid(void** const xidpp) -{ - if (!_xid_buff) - { - *xidpp = 0; - return 0; - } - *xidpp = _xid_buff; - return _deq_hdr._xidsize; -} - -std::string& -deq_rec::str(std::string& str) const -{ - std::ostringstream oss; - oss << "deq_rec: m=" << _deq_hdr._rhdr._magic; - oss << " v=" << (int)_deq_hdr._rhdr._version; - oss << " rid=" << _deq_hdr._rhdr._rid; - oss << " drid=" << _deq_hdr._deq_rid; - if (_xidp) - oss << " xid=\"" << _xidp << "\""; - str.append(oss.str()); - return str; -} - -std::size_t -deq_rec::xid_size() const -{ - return _deq_hdr._xidsize; -} - -std::size_t -deq_rec::rec_size() const -{ - return sizeof(deq_hdr_t) + (_deq_hdr._xidsize ? _deq_hdr._xidsize + sizeof(rec_tail_t) : 0); -} - -void -deq_rec::check_rec_tail(const std::streampos rec_start) const { - Checksum checksum; - checksum.addData((const unsigned char*)&_deq_hdr, sizeof(::deq_hdr_t)); - if (_deq_hdr._xidsize > 0) { - checksum.addData((const unsigned char*)_xid_buff, _deq_hdr._xidsize); - } - uint32_t cs = checksum.getChecksum(); - uint16_t res = ::rec_tail_check(&_deq_tail, &_deq_hdr._rhdr, cs); - if (res != 0) { - std::stringstream oss; - oss << std::endl << " Record offset: 0x" << std::hex << rec_start; - if (res & ::REC_TAIL_MAGIC_ERR_MASK) { - oss << std::endl << " Magic: expected 0x" << ~_deq_hdr._rhdr._magic << "; found 0x" << _deq_tail._xmagic; - } - if (res & ::REC_TAIL_SERIAL_ERR_MASK) { - oss << std::endl << " Serial: expected 0x" << _deq_hdr._rhdr._serial << "; found 0x" << _deq_tail._serial; - } - if (res & ::REC_TAIL_RID_ERR_MASK) { - oss << std::endl << " Record Id: expected 0x" << _deq_hdr._rhdr._rid << "; found 0x" << _deq_tail._rid; - } - if (res & ::REC_TAIL_CHECKSUM_ERR_MASK) { - oss << std::endl << " Checksum: expected 0x" << cs << "; found 0x" << _deq_tail._checksum; - } - throw jexception(jerrno::JERR_JREC_BADRECTAIL, oss.str(), "deq_rec", "check_rec_tail"); - } -} - -void -deq_rec::clean() -{ - if (_xid_buff) { - std::free(_xid_buff); - _xid_buff = 0; - } -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/deq_rec.h b/qpid/cpp/src/qpid/linearstore/journal/deq_rec.h deleted file mode 100644 index 9f55032e76..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/deq_rec.h +++ /dev/null @@ -1,70 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_DEQ_REQ_H -#define QPID_LINEARSTORE_JOURNAL_DEQ_REQ_H - -#include "qpid/linearstore/journal/jrec.h" -#include "qpid/linearstore/journal/utils/deq_hdr.h" -#include "qpid/linearstore/journal/utils/rec_tail.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -/** -* \class deq_rec -* \brief Class to handle a single journal dequeue record. -*/ -class deq_rec : public jrec -{ -private: - ::deq_hdr_t _deq_hdr; ///< Local instance of dequeue header struct - const void* _xidp; ///< xid pointer for encoding (writing to disk) - void* _xid_buff; ///< Pointer to buffer to receive xid read from disk - ::rec_tail_t _deq_tail; ///< Local instance of enqueue tail struct, only encoded if XID is present - -public: - deq_rec(); - virtual ~deq_rec(); - - void reset(const uint64_t serial, const uint64_t rid, const uint64_t drid, const void* const xidp, - const std::size_t xidlen, const bool txn_coml_commit); - uint32_t encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum); - bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start); - - inline bool is_txn_coml_commit() const { return ::is_txn_coml_commit(&_deq_hdr); } - inline uint64_t rid() const { return _deq_hdr._rhdr._rid; } - inline uint64_t deq_rid() const { return _deq_hdr._deq_rid; } - std::size_t get_xid(void** const xidpp); - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return 0; } // This record never carries data - std::size_t xid_size() const; - std::size_t rec_size() const; - void check_rec_tail(const std::streampos rec_start) const; - -private: - virtual void clean(); -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_DEQ_REQ_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/enq_map.cpp b/qpid/cpp/src/qpid/linearstore/journal/enq_map.cpp deleted file mode 100644 index 4eaaa64992..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/enq_map.cpp +++ /dev/null @@ -1,181 +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/linearstore/journal/enq_map.h" - -#include "qpid/linearstore/journal/slock.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -// static return/error codes -int16_t enq_map::EMAP_DUP_RID = -3; -int16_t enq_map::EMAP_LOCKED = -2; -int16_t enq_map::EMAP_RID_NOT_FOUND = -1; -int16_t enq_map::EMAP_OK = 0; -int16_t enq_map::EMAP_FALSE = 0; -int16_t enq_map::EMAP_TRUE = 1; - -enq_map::enq_map(): - _map(){} - -enq_map::~enq_map() {} - - -short -enq_map::insert_pfid(const uint64_t rid, const uint64_t pfid, const std::streampos file_posn) -{ - return insert_pfid(rid, pfid, file_posn, false); -} - -short -enq_map::insert_pfid(const uint64_t rid, const uint64_t pfid, const std::streampos file_posn, const bool locked) -{ - std::pair ret; - emap_data_struct_t rec(pfid, file_posn, locked); - { - slock s(_mutex); - ret = _map.insert(emap_param(rid, rec)); - } - if (ret.second == false) - return EMAP_DUP_RID; - return EMAP_OK; -} - -short -enq_map::get_pfid(const uint64_t rid, uint64_t& pfid) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - if (itr->second._lock) - return EMAP_LOCKED; - pfid = itr->second._pfid; - return EMAP_OK; -} - -short -enq_map::get_remove_pfid(const uint64_t rid, uint64_t& pfid, const bool txn_flag) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - if (itr->second._lock && !txn_flag) // locked, but not a commit/abort - return EMAP_LOCKED; - pfid = itr->second._pfid; - _map.erase(itr); - return EMAP_OK; -} - -short -enq_map::get_file_posn(const uint64_t rid, std::streampos& file_posn) { - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - if (itr->second._lock) - return EMAP_LOCKED; - file_posn = itr->second._file_posn; - return EMAP_OK; -} - -short -enq_map::get_data(const uint64_t rid, emap_data_struct_t& eds) { - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - eds._pfid = itr->second._pfid; - eds._file_posn = itr->second._file_posn; - eds._lock = itr->second._lock; - return EMAP_OK; -} - -bool -enq_map::is_enqueued(const uint64_t rid, bool ignore_lock) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return false; - if (!ignore_lock && itr->second._lock) // locked - return false; - return true; -} - -short -enq_map::lock(const uint64_t rid) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - itr->second._lock = true; - return EMAP_OK; -} - -short -enq_map::unlock(const uint64_t rid) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - itr->second._lock = false; - return EMAP_OK; -} - -short -enq_map::is_locked(const uint64_t rid) -{ - slock s(_mutex); - emap_itr itr = _map.find(rid); - if (itr == _map.end()) // not found in map - return EMAP_RID_NOT_FOUND; - return itr->second._lock ? EMAP_TRUE : EMAP_FALSE; -} - -void -enq_map::rid_list(std::vector& rv) -{ - rv.clear(); - { - slock s(_mutex); - for (emap_itr itr = _map.begin(); itr != _map.end(); itr++) - rv.push_back(itr->first); - } -} - -void -enq_map::pfid_list(std::vector& fv) -{ - fv.clear(); - { - slock s(_mutex); - for (emap_itr itr = _map.begin(); itr != _map.end(); itr++) - fv.push_back(itr->second._pfid); - } -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/enq_map.h b/qpid/cpp/src/qpid/linearstore/journal/enq_map.h deleted file mode 100644 index 912a583ab9..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/enq_map.h +++ /dev/null @@ -1,101 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_ENQ_MAP_H -#define QPID_LINEARSTORE_JOURNAL_ENQ_MAP_H - -#include "qpid/linearstore/journal/smutex.h" -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -/** -* \class enq_map -* \brief Class for storing the physical file id (pfid) and a transaction locked flag for each enqueued -* data block using the record id (rid) as a key. This is the primary mechanism for -* deterimining the enqueue low water mark: if a pfid exists in this map, then there is -* at least one still-enqueued record in that file. (The transaction map must also be -* clear, however.) -* -* Map rids against pfid and lock status. As records are enqueued, they are added to this -* map, and as they are dequeued, they are removed. An enqueue is locked when a transactional -* dequeue is pending that has been neither committed nor aborted. -*
-*   key      data
-*
-*   rid1 --- [ pfid, txn_lock ]
-*   rid2 --- [ pfid, txn_lock ]
-*   rid3 --- [ pfid, txn_lock ]
-*   ...
-* 
-*/ -class enq_map -{ -public: - // return/error codes - static short EMAP_DUP_RID; - static short EMAP_LOCKED; - static short EMAP_RID_NOT_FOUND; - static short EMAP_OK; - static short EMAP_FALSE; - static short EMAP_TRUE; - - typedef struct emap_data_struct_t { - uint64_t _pfid; - std::streampos _file_posn; - bool _lock; - emap_data_struct_t() : _pfid(0), _file_posn(0), _lock(false) {} - emap_data_struct_t(const uint64_t pfid, const std::streampos file_posn, const bool lock) : _pfid(pfid), _file_posn(file_posn), _lock(lock) {} - } emqp_data_struct_t; - typedef std::pair emap_param; - typedef std::map emap; - typedef emap::iterator emap_itr; - -private: - emap _map; - smutex _mutex; - -public: - enq_map(); - virtual ~enq_map(); - - short insert_pfid(const uint64_t rid, const uint64_t pfid, const std::streampos file_posn); // 0=ok; -3=duplicate rid; - short insert_pfid(const uint64_t rid, const uint64_t pfid, const std::streampos file_posn, const bool locked); // 0=ok; -3=duplicate rid; - short get_pfid(const uint64_t rid, uint64_t& pfid); // >=0=pfid; -1=rid not found; -2=locked - short get_remove_pfid(const uint64_t rid, uint64_t& pfid, const bool txn_flag = false); // >=0=pfid; -1=rid not found; -2=locked - short get_file_posn(const uint64_t rid, std::streampos& file_posn); // -1=rid not found; -2=locked - short get_data(const uint64_t rid, emap_data_struct_t& eds); - bool is_enqueued(const uint64_t rid, bool ignore_lock = false); - short lock(const uint64_t rid); // 0=ok; -1=rid not found - short unlock(const uint64_t rid); // 0=ok; -1=rid not found - short is_locked(const uint64_t rid); // 1=true; 0=false; -1=rid not found - inline void clear() { _map.clear(); } - inline bool empty() const { return _map.empty(); } - inline uint32_t size() const { return uint32_t(_map.size()); } - void rid_list(std::vector& rv); - void pfid_list(std::vector& fv); -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_ENQ_MAP_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp b/qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp deleted file mode 100644 index 0fecd90cbf..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp +++ /dev/null @@ -1,397 +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/linearstore/journal/enq_rec.h" - -#include -#include -#include "qpid/linearstore/journal/Checksum.h" -#include "qpid/linearstore/journal/jexception.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -enq_rec::enq_rec(): - jrec(), // superclass - _xidp(0), - _data(0), - _xid_buff(0), - _data_buff(0) -{ - ::enq_hdr_init(&_enq_hdr, QLS_ENQ_MAGIC, QLS_JRNL_VERSION, 0, 0, 0, 0, false); - ::rec_tail_copy(&_enq_tail, &_enq_hdr._rhdr, 0); -} - -enq_rec::~enq_rec() -{ - clean(); -} - -void -enq_rec::reset(const uint64_t serial, const uint64_t rid, const void* const dbuf, const std::size_t dlen, - const void* const xidp, const std::size_t xidlen, const bool transient, const bool external) -{ - _enq_hdr._rhdr._serial = serial; - _enq_hdr._rhdr._rid = rid; - ::set_enq_transient(&_enq_hdr, transient); - ::set_enq_external(&_enq_hdr, external); - _enq_hdr._xidsize = xidlen; - _enq_hdr._dsize = dlen; - _xidp = xidp; - _data = dbuf; - _enq_tail._serial = serial; - _enq_tail._rid = rid; -} - -uint32_t -enq_rec::encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum) -{ - assert(wptr != 0); - assert(max_size_dblks > 0); - if (_xidp == 0) - assert(_enq_hdr._xidsize == 0); - - std::size_t rec_offs = rec_offs_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t rem = max_size_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t wr_cnt = 0; - if (rec_offs_dblks) // Continuation of split data record (over 2 or more pages) - { - if (size_dblks(rec_size()) - rec_offs_dblks > max_size_dblks) // Further split required - { - rec_offs -= sizeof(_enq_hdr); - std::size_t wsize = _enq_hdr._xidsize > rec_offs ? _enq_hdr._xidsize - rec_offs : 0; - std::size_t wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt = wsize; - rem -= wsize; - } - rec_offs -= _enq_hdr._xidsize - wsize2; - if (rem && !::is_enq_external(&_enq_hdr)) - { - wsize = _enq_hdr._dsize > rec_offs ? _enq_hdr._dsize - rec_offs : 0; - wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy((char*)wptr + wr_cnt, (const char*)_data + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= _enq_hdr._dsize - wsize2; - } - checksum.addData((unsigned char*)wptr, wr_cnt); - if (rem) - { - _enq_tail._checksum = checksum.getChecksum(); - wsize = sizeof(_enq_tail) > rec_offs ? sizeof(_enq_tail) - rec_offs : 0; - wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy((char*)wptr + wr_cnt, (char*)&_enq_tail + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= sizeof(_enq_tail) - wsize2; - } - assert(rem == 0); - assert(rec_offs == 0); - } - else // No further split required - { - rec_offs -= sizeof(_enq_hdr); - std::size_t xid_wsize = _enq_hdr._xidsize > rec_offs ? _enq_hdr._xidsize - rec_offs : 0; - if (xid_wsize) - { - std::memcpy(wptr, (const char*)_xidp + rec_offs, xid_wsize); - wr_cnt += xid_wsize; - } - rec_offs -= _enq_hdr._xidsize - xid_wsize; - std::size_t data_wsize = _enq_hdr._dsize > rec_offs ? _enq_hdr._dsize - rec_offs : 0; - if (data_wsize && !::is_enq_external(&_enq_hdr)) - { - std::memcpy((char*)wptr + wr_cnt, (const char*)_data + rec_offs, data_wsize); - wr_cnt += data_wsize; - } - rec_offs -= _enq_hdr._dsize - data_wsize; - if (xid_wsize || data_wsize) { - checksum.addData((unsigned char*)wptr, wr_cnt); - } - _enq_tail._checksum = checksum.getChecksum(); - std::size_t wsize = sizeof(_enq_tail) > rec_offs ? sizeof(_enq_tail) - rec_offs : 0; - if (wsize) - { - std::memcpy((char*)wptr + wr_cnt, (char*)&_enq_tail + rec_offs, wsize); - wr_cnt += wsize; -#ifdef QLS_CLEAN - std::size_t rec_offs = rec_offs_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t dblk_rec_size = size_dblks(rec_size() - rec_offs) * QLS_DBLK_SIZE_BYTES; - std::memset((char*)wptr + wr_cnt, QLS_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - rec_offs -= sizeof(_enq_tail) - wsize; - assert(rec_offs == 0); - } - } - else // Start at beginning of data record - { - // Assumption: the header will always fit into the first dblk - std::memcpy(wptr, (void*)&_enq_hdr, sizeof(_enq_hdr)); - wr_cnt = sizeof(_enq_hdr); - if (size_dblks(rec_size()) > max_size_dblks) // Split required - { - std::size_t wsize; - rem -= sizeof(_enq_hdr); - if (rem) - { - wsize = rem >= _enq_hdr._xidsize ? _enq_hdr._xidsize : rem; - std::memcpy((char*)wptr + wr_cnt, _xidp, wsize); - wr_cnt += wsize; - rem -= wsize; - } - if (rem && !::is_enq_external(&_enq_hdr)) - { - wsize = rem >= _enq_hdr._dsize ? _enq_hdr._dsize : rem; - std::memcpy((char*)wptr + wr_cnt, _data, wsize); - wr_cnt += wsize; - rem -= wsize; - } - checksum.addData((unsigned char*)wptr, wr_cnt); - if (rem) - { - _enq_tail._checksum = checksum.getChecksum(); - wsize = rem >= sizeof(_enq_tail) ? sizeof(_enq_tail) : rem; - std::memcpy((char*)wptr + wr_cnt, (void*)&_enq_tail, wsize); - wr_cnt += wsize; - rem -= wsize; - } - assert(rem == 0); - } - else // No split required - { - if (_enq_hdr._xidsize) - { - std::memcpy((char*)wptr + wr_cnt, _xidp, _enq_hdr._xidsize); - wr_cnt += _enq_hdr._xidsize; - } - if (!::is_enq_external(&_enq_hdr)) - { - std::memcpy((char*)wptr + wr_cnt, _data, _enq_hdr._dsize); - wr_cnt += _enq_hdr._dsize; - } - checksum.addData((unsigned char*)wptr, wr_cnt); - _enq_tail._checksum = checksum.getChecksum(); - std::memcpy((char*)wptr + wr_cnt, (void*)&_enq_tail, sizeof(_enq_tail)); - wr_cnt += sizeof(_enq_tail); -#ifdef QLS_CLEAN - std::size_t dblk_rec_size = size_dblks(rec_size()) * QLS_DBLK_SIZE_BYTES; - std::memset((char*)wptr + wr_cnt, QLS_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - } - return size_dblks(wr_cnt); -} - -bool -enq_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start) -{ - if (rec_offs == 0) - { - // Read header, allocate (if req'd) for xid - ::rec_hdr_copy(&_enq_hdr._rhdr, &h); - ifsp->read((char*)&_enq_hdr._xidsize, sizeof(_enq_hdr._xidsize)); - ifsp->read((char*)&_enq_hdr._dsize, sizeof(_enq_hdr._dsize)); - rec_offs = sizeof(::enq_hdr_t); - if (_enq_hdr._xidsize > 0) - { - _xid_buff = std::malloc(_enq_hdr._xidsize); - MALLOC_CHK(_xid_buff, "_xid_buff", "enq_rec", "decode"); - } - if (_enq_hdr._dsize > 0) - { - _data_buff = std::malloc(_enq_hdr._dsize); - MALLOC_CHK(_data_buff, "_data_buff", "enq_rec", "decode") - } - } - if (rec_offs < sizeof(_enq_hdr) + _enq_hdr._xidsize) - { - // Read xid (or continue reading xid) - std::size_t offs = rec_offs - sizeof(_enq_hdr); - ifsp->read((char*)_xid_buff + offs, _enq_hdr._xidsize - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < _enq_hdr._xidsize - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - if (!::is_enq_external(&_enq_hdr)) - { - if (rec_offs < sizeof(_enq_hdr) + _enq_hdr._xidsize + _enq_hdr._dsize) - { - // Read data (or continue reading data) - std::size_t offs = rec_offs - sizeof(_enq_hdr) - _enq_hdr._xidsize; - ifsp->read((char*)_data_buff + offs, _enq_hdr._dsize - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < _enq_hdr._dsize - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - } - if (rec_offs < sizeof(_enq_hdr) + _enq_hdr._xidsize + - (::is_enq_external(&_enq_hdr) ? 0 : _enq_hdr._dsize) + sizeof(rec_tail_t)) - { - // Read tail (or continue reading tail) - std::size_t offs = rec_offs - sizeof(_enq_hdr) - _enq_hdr._xidsize; - if (!::is_enq_external(&_enq_hdr)) - offs -= _enq_hdr._dsize; - ifsp->read((char*)&_enq_tail + offs, sizeof(rec_tail_t) - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < sizeof(rec_tail_t) - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - check_rec_tail(rec_start); - } - ifsp->ignore(rec_size_dblks() * QLS_DBLK_SIZE_BYTES - rec_size()); - assert(!ifsp->fail() && !ifsp->bad()); - return true; -} - -std::size_t -enq_rec::get_xid(void** const xidpp) -{ - if (!_xid_buff || !_enq_hdr._xidsize) { - *xidpp = 0; - return 0; - } - *xidpp = _xid_buff; - return _enq_hdr._xidsize; -} - -std::size_t -enq_rec::get_data(void** const datapp) -{ - if (!_data_buff) { - *datapp = 0; - return 0; - } - if (::is_enq_external(&_enq_hdr)) - *datapp = 0; - else - *datapp = _data_buff; - return _enq_hdr._dsize; -} - -std::string& -enq_rec::str(std::string& str) const -{ - std::ostringstream oss; - oss << "enq_rec: m=" << _enq_hdr._rhdr._magic; - oss << " v=" << (int)_enq_hdr._rhdr._version; - oss << " rid=" << _enq_hdr._rhdr._rid; - if (_xidp) - oss << " xid=\"" << _xidp << "\""; - oss << " len=" << _enq_hdr._dsize; - str.append(oss.str()); - return str; -} - -std::size_t -enq_rec::rec_size() const -{ - return rec_size(_enq_hdr._xidsize, _enq_hdr._dsize, ::is_enq_external(&_enq_hdr)); -} - -std::size_t -enq_rec::rec_size(const std::size_t xidsize, const std::size_t dsize, const bool external) -{ - if (external) - return sizeof(enq_hdr_t) + xidsize + sizeof(rec_tail_t); - return sizeof(enq_hdr_t) + xidsize + dsize + sizeof(rec_tail_t); -} - -void -enq_rec::check_rec_tail(const std::streampos rec_start) const { - Checksum checksum; - checksum.addData((const unsigned char*)&_enq_hdr, sizeof(::enq_hdr_t)); - if (_enq_hdr._xidsize > 0) { - checksum.addData((const unsigned char*)_xid_buff, _enq_hdr._xidsize); - } - if (_enq_hdr._dsize > 0) { - checksum.addData((const unsigned char*)_data_buff, _enq_hdr._dsize); - } - uint32_t cs = checksum.getChecksum(); - uint16_t res = ::rec_tail_check(&_enq_tail, &_enq_hdr._rhdr, cs); - if (res != 0) { - std::stringstream oss; - oss << std::endl << " Record offset: 0x" << std::hex << rec_start; - if (res & ::REC_TAIL_MAGIC_ERR_MASK) { - oss << std::endl << " Magic: expected 0x" << ~_enq_hdr._rhdr._magic << "; found 0x" << _enq_tail._xmagic; - } - if (res & ::REC_TAIL_SERIAL_ERR_MASK) { - oss << std::endl << " Serial: expected 0x" << _enq_hdr._rhdr._serial << "; found 0x" << _enq_tail._serial; - } - if (res & ::REC_TAIL_RID_ERR_MASK) { - oss << std::endl << " Record Id: expected 0x" << _enq_hdr._rhdr._rid << "; found 0x" << _enq_tail._rid; - } - if (res & ::REC_TAIL_CHECKSUM_ERR_MASK) { - oss << std::endl << " Checksum: expected 0x" << cs << "; found 0x" << _enq_tail._checksum; - } - throw jexception(jerrno::JERR_JREC_BADRECTAIL, oss.str(), "enq_rec", "check_rec_tail"); - } -} - -void -enq_rec::clean() { - if (_xid_buff) { - std::free(_xid_buff); - _xid_buff = 0; - } - if (_data_buff) { - std::free(_data_buff); - _data_buff = 0; - } -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/enq_rec.h b/qpid/cpp/src/qpid/linearstore/journal/enq_rec.h deleted file mode 100644 index d85cde42f5..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/enq_rec.h +++ /dev/null @@ -1,74 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_ENQ_REC_H -#define QPID_LINEARSTORE_JOURNAL_ENQ_REC_H - -#include "qpid/linearstore/journal/jrec.h" -#include "qpid/linearstore/journal/utils/enq_hdr.h" -#include "qpid/linearstore/journal/utils/rec_tail.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -/** -* \class enq_rec -* \brief Class to handle a single journal enqueue record. -*/ -class enq_rec : public jrec -{ -private: - ::enq_hdr_t _enq_hdr; ///< Local instance of enqueue header struct - const void* _xidp; ///< xid pointer for encoding (for writing to disk) - const void* _data; ///< Pointer to data to be written to disk - void* _xid_buff; - void* _data_buff; - ::rec_tail_t _enq_tail; ///< Local instance of enqueue tail struct - -public: - enq_rec(); - virtual ~enq_rec(); - - void reset(const uint64_t serial, const uint64_t rid, const void* const dbuf, const std::size_t dlen, - const void* const xidp, const std::size_t xidlen, const bool transient, const bool external); - uint32_t encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum); - bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start); - - std::size_t get_xid(void** const xidpp); - std::size_t get_data(void** const datapp); - inline bool is_transient() const { return ::is_enq_transient(&_enq_hdr); } - inline bool is_external() const { return ::is_enq_external(&_enq_hdr); } - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return _enq_hdr._dsize; } - inline std::size_t xid_size() const { return _enq_hdr._xidsize; } - std::size_t rec_size() const; - static std::size_t rec_size(const std::size_t xidsize, const std::size_t dsize, const bool external); - inline uint64_t rid() const { return _enq_hdr._rhdr._rid; } - void check_rec_tail(const std::streampos rec_start) const; - -private: - virtual void clean(); -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_ENQ_REC_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/enums.h b/qpid/cpp/src/qpid/linearstore/journal/enums.h deleted file mode 100644 index 90ec355955..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/enums.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_ENUMS_H -#define QPID_LINEARSTORE_JOURNAL_ENUMS_H - -namespace qpid { -namespace linearstore { -namespace journal { - -// TODO: Change this to flags, as multiple of these conditions may exist simultaneously -/** -* \brief Enumeration of possible return states from journal read and write operations. -*/ -enum _iores -{ - RHM_IORES_SUCCESS = 0, ///< Success: IO operation completed noramlly. - RHM_IORES_PAGE_AIOWAIT, ///< IO operation suspended - next page is waiting for AIO. - RHM_IORES_FILE_AIOWAIT, ///< IO operation suspended - next file is waiting for AIO. - RHM_IORES_EMPTY, ///< During read operations, nothing further is available to read. - RHM_IORES_TXPENDING ///< Operation blocked by pending transaction. -}; -typedef _iores iores; - -static inline const char* iores_str(iores res) -{ - switch (res) - { - case RHM_IORES_SUCCESS: return "RHM_IORES_SUCCESS"; - case RHM_IORES_PAGE_AIOWAIT: return "RHM_IORES_PAGE_AIOWAIT"; - case RHM_IORES_FILE_AIOWAIT: return "RHM_IORES_FILE_AIOWAIT"; - case RHM_IORES_EMPTY: return "RHM_IORES_EMPTY"; - case RHM_IORES_TXPENDING: return "RHM_IORES_TXPENDING"; - } - return ""; -} - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_ENUMS_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/jcfg.h b/qpid/cpp/src/qpid/linearstore/journal/jcfg.h deleted file mode 100644 index b33a419a9d..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jcfg.h +++ /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. - * - */ - -#include -#include - -#ifndef QPID_QLS_JRNL_JCFG_H -#define QPID_QLS_JRNL_JCFG_H - -#define QLS_SBLK_SIZE_BYTES 4096 /**< Disk softblock size in bytes, should match size used on disk media */ -#define QLS_AIO_ALIGN_BOUNDARY_BYTES QLS_SBLK_SIZE_BYTES /** Memory alignment boundary used for DMA */ -/** -* Rule: Data block size (QLS_DBLK_SIZE_BYTES) MUST be a power of 2 AND -* a power of 2 factor of the disk softblock size (QLS_SBLK_SIZE_BYTES): -*
-* n * QLS_DBLK_SIZE_BYTES == QLS_SBLK_SIZE_BYTES (n = 1,2,4,8...)
-* 
-*/ -#define QLS_DBLK_SIZE_BYTES 128 /**< Data block size in bytes (CANNOT BE LESS THAN 32!) */ -#define QLS_SBLK_SIZE_DBLKS (QLS_SBLK_SIZE_BYTES / QLS_DBLK_SIZE_BYTES) /**< Disk softblock size in multiples of QLS_DBLK_SIZE_BYTES */ -#define QLS_SBLK_SIZE_KIB (QLS_SBLK_SIZE_BYTES / 1024) /**< Disk softblock size in KiB */ - -#define QLS_WMGR_DEF_PAGE_SIZE_KIB 32 /**< Journal write page size in KiB (default) */ -#define QLS_WMGR_DEF_PAGE_SIZE_SBLKS (QLS_WMGR_DEF_PAGE_SIZE_KIB / QLS_SBLK_SIZE_KIB) /**< Journal write page size in softblocks (default) */ -#define QLS_WMGR_DEF_PAGES 32 /**< Number of pages to use in wmgr (default) */ - -#define QLS_WMGR_MAXDTOKPP 1024 /**< Max. dtoks (data blocks) per page in wmgr */ -#define QLS_WMGR_MAXWAITUS 100 /**< Max. wait time (us) before submitting AIO */ - -#define QLS_JRNL_FILE_EXTENSION ".jrnl" /**< Extension for journal data files */ -#define QLS_TXA_MAGIC 0x61534c51 /**< ("QLSa" in little endian) Magic for dtx abort hdrs */ -#define QLS_TXC_MAGIC 0x63534c51 /**< ("QLSc" in little endian) Magic for dtx commit hdrs */ -#define QLS_DEQ_MAGIC 0x64534c51 /**< ("QLSd" in little endian) Magic for deq rec hdrs */ -#define QLS_ENQ_MAGIC 0x65534c51 /**< ("QLSe" in little endian) Magic for enq rec hdrs */ -#define QLS_FILE_MAGIC 0x66534c51 /**< ("QLSf" in little endian) Magic for file hdrs */ -#define QLS_EMPTY_MAGIC 0x78534c51 /**< ("QLSx" in little endian) Magic for empty dblk */ -#define QLS_JRNL_VERSION 2 /**< Version (of file layout) */ -#define QLS_JRNL_FHDR_RES_SIZE_SBLKS 1 /**< Journal file header reserved size in sblks (as defined by QLS_SBLK_SIZE_BYTES) */ -#define QLS_MAX_QUEUE_NAME_LEN (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES) - sizeof(file_hdr_t) - -#define QLS_CLEAN /**< If defined, writes QLS_CLEAN_CHAR to all filled areas on disk */ -#define QLS_CLEAN_CHAR 0xff /**< Char used to clear empty space on disk */ - -namespace qpid { -namespace linearstore { - - const int QLS_RAND_WIDTH = (int)(::log((RAND_MAX + 1ULL))/::log(2)); - const int QLS_RAND_SHIFT1 = 64 - QLS_RAND_WIDTH; - const int QLS_RAND_SHIFT2 = QLS_RAND_SHIFT1 - QLS_RAND_WIDTH; - const int QLS_RAND_MASK = (int)::pow(2, QLS_RAND_SHIFT2) - 1; - -}} - -#endif /* ifndef QPID_QLS_JRNL_JCFG_H */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp b/qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp deleted file mode 100644 index cc31f2e1df..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp +++ /dev/null @@ -1,440 +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/linearstore/journal/jcntl.h" - -#include -#include "qpid/linearstore/journal/data_tok.h" -#include "qpid/linearstore/journal/JournalLog.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -#define AIO_CMPL_TIMEOUT_SEC 5 -#define AIO_CMPL_TIMEOUT_NSEC 0 -#define FINAL_AIO_CMPL_TIMEOUT_SEC 15 -#define FINAL_AIO_CMPL_TIMEOUT_NSEC 0 - -// Static -timespec jcntl::_aio_cmpl_timeout; ///< Timeout for blocking libaio returns -timespec jcntl::_final_aio_cmpl_timeout; ///< Timeout for blocking libaio returns when stopping or finalizing -bool jcntl::_init = init_statics(); -bool jcntl::init_statics() -{ - _aio_cmpl_timeout.tv_sec = AIO_CMPL_TIMEOUT_SEC; - _aio_cmpl_timeout.tv_nsec = AIO_CMPL_TIMEOUT_NSEC; - _final_aio_cmpl_timeout.tv_sec = FINAL_AIO_CMPL_TIMEOUT_SEC; - _final_aio_cmpl_timeout.tv_nsec = FINAL_AIO_CMPL_TIMEOUT_NSEC; - return true; -} - - -// Functions - -jcntl::jcntl(const std::string& jid, - const std::string& jdir, - JournalLog& jrnl_log): - _jid(jid), - _jdir(jdir), - _init_flag(false), - _stop_flag(false), - _readonly_flag(false), - _jrnl_log(jrnl_log), - _linearFileController(*this), - _emptyFilePoolPtr(0), - _emap(), - _tmap(), - _wmgr(this, _emap, _tmap, _linearFileController), - _recoveryManager(_jdir.dirname(), _jid, _emap, _tmap, jrnl_log) -{} - -jcntl::~jcntl() -{ - if (_init_flag && !_stop_flag) - try { stop(true); } - catch (const jexception& e) { std::cerr << e << std::endl; } - _linearFileController.finalize(); -} - -void -jcntl::initialize(EmptyFilePool* efpp, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - aio_callback* const cbp) -{ - _init_flag = false; - _stop_flag = false; - _readonly_flag = false; - - _emap.clear(); - _tmap.clear(); - - _linearFileController.finalize(); - _jdir.clear_dir(); // Clear any existing journal files - _linearFileController.initialize(_jdir.dirname(), efpp, 0ULL); - _linearFileController.getNextJournalFile(); - _wmgr.initialize(cbp, wcache_pgsize_sblks, wcache_num_pages, QLS_WMGR_MAXDTOKPP, QLS_WMGR_MAXWAITUS, 0); - _init_flag = true; -} - -void -jcntl::recover(EmptyFilePoolManager* efpmp, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - aio_callback* const cbp, - const std::vector* prep_txn_list_ptr, - uint64_t& highest_rid) -{ - _init_flag = false; - _stop_flag = false; - _readonly_flag = false; - - _emap.clear(); - _tmap.clear(); - - _linearFileController.finalize(); - - // Verify journal dir and journal files - _jdir.verify_dir(); - _recoveryManager.analyzeJournals(prep_txn_list_ptr, efpmp, &_emptyFilePoolPtr); - assert(_emptyFilePoolPtr != 0); - - highest_rid = _recoveryManager.getHighestRecordId(); - _jrnl_log.log(/*LOG_DEBUG*/JournalLog::LOG_INFO, _jid, _recoveryManager.toString(_jid, 5U)); - _linearFileController.initialize(_jdir.dirname(), _emptyFilePoolPtr, _recoveryManager.getHighestFileNumber()); - _recoveryManager.setLinearFileControllerJournals(&qpid::linearstore::journal::LinearFileController::addJournalFile, &_linearFileController); - if (_recoveryManager.isLastFileFull()) { - _linearFileController.getNextJournalFile(); - } - _wmgr.initialize(cbp, wcache_pgsize_sblks, wcache_num_pages, QLS_WMGR_MAXDTOKPP, QLS_WMGR_MAXWAITUS, - (_recoveryManager.isLastFileFull() ? 0 : _recoveryManager.getEndOffset())); - - _readonly_flag = true; - _init_flag = true; -} - -void -jcntl::recover_complete() -{ - if (!_readonly_flag) - throw jexception(jerrno::JERR_JCNTL_NOTRECOVERED, "jcntl", "recover_complete"); - _recoveryManager.recoveryComplete(); - _readonly_flag = false; -} - -void -jcntl::delete_jrnl_files() -{ - stop(true); // wait for AIO to complete - _linearFileController.purgeEmptyFilesToEfp(); - _jdir.delete_dir(); -} - - -iores -jcntl::enqueue_data_record(const void* const data_buff, - const std::size_t tot_data_len, - const std::size_t this_data_len, - data_tok* dtokp, - const bool transient) -{ - iores r; - check_wstatus("enqueue_data_record"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.enqueue(data_buff, tot_data_len, this_data_len, dtokp, 0, 0, false, transient, false), r, - dtokp)) ; - } - return r; -} - -iores -jcntl::enqueue_extern_data_record(const std::size_t tot_data_len, - data_tok* dtokp, - const bool transient) -{ - iores r; - check_wstatus("enqueue_extern_data_record"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.enqueue(0, tot_data_len, 0, dtokp, 0, 0, false, transient, true), r, dtokp)) ; - } - return r; -} - -iores -jcntl::enqueue_txn_data_record(const void* const data_buff, - const std::size_t tot_data_len, - const std::size_t this_data_len, - data_tok* dtokp, - const std::string& xid, - const bool tpc_flag, - const bool transient) -{ - iores r; - check_wstatus("enqueue_tx_data_record"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.enqueue(data_buff, tot_data_len, this_data_len, dtokp, xid.data(), xid.size(), - tpc_flag, transient, false), r, dtokp)) ; - } - return r; -} - -iores -jcntl::enqueue_extern_txn_data_record(const std::size_t tot_data_len, - data_tok* dtokp, - const std::string& xid, - const bool tpc_flag, - const bool transient) -{ - iores r; - check_wstatus("enqueue_extern_txn_data_record"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.enqueue(0, tot_data_len, 0, dtokp, xid.data(), xid.size(), tpc_flag, transient, - true), r, dtokp)) ; - } - return r; -} - -iores -jcntl::read_data_record(void** const datapp, - std::size_t& dsize, - void** const xidpp, - std::size_t& xidsize, - bool& transient, - bool& external, - data_tok* const dtokp, - bool ignore_pending_txns) -{ - check_rstatus("read_data"); - if (_recoveryManager.readNextRemainingRecord(datapp, dsize, xidpp, xidsize, transient, external, dtokp, ignore_pending_txns)) { - return RHM_IORES_SUCCESS; - } - return RHM_IORES_EMPTY; -} - -iores -jcntl::dequeue_data_record(data_tok* const dtokp, - const bool txn_coml_commit) -{ - iores r; - check_wstatus("dequeue_data"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.dequeue(dtokp, 0, 0, false, txn_coml_commit), r, dtokp)) ; - } - return r; -} - -iores -jcntl::dequeue_txn_data_record(data_tok* const dtokp, - const std::string& xid, - const bool tpc_flag, - const bool txn_coml_commit) -{ - iores r; - check_wstatus("dequeue_data"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.dequeue(dtokp, xid.data(), xid.size(), tpc_flag, txn_coml_commit), r, dtokp)) ; - } - return r; -} - -iores -jcntl::txn_abort(data_tok* const dtokp, - const std::string& xid) -{ - iores r; - check_wstatus("txn_abort"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.abort(dtokp, xid.data(), xid.size()), r, dtokp)) ; - } - return r; -} - -iores -jcntl::txn_commit(data_tok* const dtokp, - const std::string& xid) -{ - iores r; - check_wstatus("txn_commit"); - { - slock s(_wr_mutex); - while (handle_aio_wait(_wmgr.commit(dtokp, xid.data(), xid.size()), r, dtokp)) ; - } - return r; -} - -bool -jcntl::is_txn_synced(const std::string& xid) -{ - slock s(_wr_mutex); - bool res = _wmgr.is_txn_synced(xid); - return res; -} - -int32_t -jcntl::get_wr_events(timespec* const timeout) -{ - stlock t(_wr_mutex); - if (!t.locked()) - return jerrno::LOCK_TAKEN; - return _wmgr.get_events(timeout, false); -} - -void -jcntl::stop(const bool block_till_aio_cmpl) -{ - if (_readonly_flag) - check_rstatus("stop"); - else - check_wstatus("stop"); - _stop_flag = true; - if (!_readonly_flag) - flush(block_till_aio_cmpl); -} - -LinearFileController& -jcntl::getLinearFileControllerRef() { - return _linearFileController; -} - -// static -std::string -jcntl::str2hexnum(const std::string& str) { - if (str.empty()) { - return ""; - } - std::ostringstream oss; - oss << "(" << str.size() << ")0x" << std::hex; - for (unsigned i=str.size(); i>0; --i) { - oss << std::setfill('0') << std::setw(2) << (uint16_t)(uint8_t)str[i-1]; - } - return oss.str(); -} - -iores -jcntl::flush(const bool block_till_aio_cmpl) -{ - if (!_init_flag) - return RHM_IORES_SUCCESS; - if (_readonly_flag) - throw jexception(jerrno::JERR_JCNTL_READONLY, "jcntl", "flush"); - iores res; - { - slock s(_wr_mutex); - res = _wmgr.flush(); - } - if (block_till_aio_cmpl) - aio_cmpl_wait(); - return res; -} - -// Protected/Private functions - -void -jcntl::check_wstatus(const char* fn_name) const -{ - if (!_init_flag) - throw jexception(jerrno::JERR__NINIT, "jcntl", fn_name); - if (_readonly_flag) - throw jexception(jerrno::JERR_JCNTL_READONLY, "jcntl", fn_name); - if (_stop_flag) - throw jexception(jerrno::JERR_JCNTL_STOPPED, "jcntl", fn_name); -} - -void -jcntl::check_rstatus(const char* fn_name) const -{ - if (!_init_flag) - throw jexception(jerrno::JERR__NINIT, "jcntl", fn_name); - if (_stop_flag) - throw jexception(jerrno::JERR_JCNTL_STOPPED, "jcntl", fn_name); -} - - -void -jcntl::aio_cmpl_wait() -{ - //while (_wmgr.get_aio_evt_rem()) - while (true) - { - uint32_t aer; - { - slock s(_wr_mutex); - aer = _wmgr.get_aio_evt_rem(); - } - if (aer == 0) break; // no events left - if (get_wr_events(&_aio_cmpl_timeout) == jerrno::AIO_TIMEOUT) - throw jexception(jerrno::JERR_JCNTL_AIOCMPLWAIT, "jcntl", "aio_cmpl_wait"); - } -} - - -bool -jcntl::handle_aio_wait(const iores res, iores& resout, const data_tok* dtp) -{ - resout = res; - if (res == RHM_IORES_PAGE_AIOWAIT) - { - while (_wmgr.curr_pg_blocked()) - { - if (_wmgr.get_aio_evt_rem() == 0) { -//std::cout << "&&&&&& jcntl::handle_aio_wait() " << _wmgr.status_str() << std::endl; // DEBUG - throw jexception("_wmgr.curr_pg_blocked() with no events remaining"); // TODO - complete exception - } - if (_wmgr.get_events(&_aio_cmpl_timeout, false) == jerrno::AIO_TIMEOUT) - { - std::ostringstream oss; - oss << "get_events() returned JERR_JCNTL_AIOCMPLWAIT; wmgr_status: " << _wmgr.status_str(); - _jrnl_log.log(JournalLog::LOG_CRITICAL, _jid, oss.str()); - throw jexception(jerrno::JERR_JCNTL_AIOCMPLWAIT, "jcntl", "handle_aio_wait"); - } - } - return true; - } - else if (res == RHM_IORES_FILE_AIOWAIT) - { -// while (_wmgr.curr_file_blocked()) -// { -// if (_wmgr.get_events(pmgr::UNUSED, &_aio_cmpl_timeout) == jerrno::AIO_TIMEOUT) -// { -// std::ostringstream oss; -// oss << "get_events() returned JERR_JCNTL_AIOCMPLWAIT; wmgr_status: " << _wmgr.status_str(); -// this->log(LOG_CRITICAL, oss.str()); -// throw jexception(jerrno::JERR_JCNTL_AIOCMPLWAIT, "jcntl", "handle_aio_wait"); -// } -// } -// _wrfc.wr_reset(); - resout = RHM_IORES_SUCCESS; - data_tok::write_state ws = dtp->wstate(); - return ws == data_tok::ENQ_PART || ws == data_tok::DEQ_PART || ws == data_tok::ABORT_PART || - ws == data_tok::COMMIT_PART; - } - return false; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/jcntl.h b/qpid/cpp/src/qpid/linearstore/journal/jcntl.h deleted file mode 100644 index 94c00d2fab..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jcntl.h +++ /dev/null @@ -1,570 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_JCNTL_H -#define QPID_LINEARSTORE_JOURNAL_JCNTL_H - -#include -#include "qpid/linearstore/journal/jdir.h" -#include "qpid/linearstore/journal/RecoveryManager.h" -#include "qpid/linearstore/journal/wmgr.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -class EmptyFilePool; -class EmptyFilePoolManager; -class JournalLog; - -/** -* \brief Access and control interface for the journal. This is the top-level class for the -* journal. -* -* This is the top-level journal class; one instance of this class controls one instance of the -* journal and all its files and associated control structures. Besides this class, the only -* other class that needs to be used at a higher level is the data_tok class, one instance of -* which is used per data block written to the journal, and is used to track its status through -* the AIO enqueue, read and dequeue process. -*/ -class jcntl -{ -protected: - /** - * \brief Journal ID - * - * This string uniquely identifies this journal instance. It will most likely be associated - * with the identity of the message queue with which it is associated. - */ - // TODO: This is not included in any files at present, add to file_hdr? - std::string _jid; - - /** - * \brief Journal directory - * - * This string stores the path to the journal directory. It may be absolute or relative, and - * should not end in a file separator character. (e.g. "/fastdisk/jdata" is correct, - * "/fastdisk/jdata/" is not.) - */ - jdir _jdir; - - /** - * \brief Initialized flag - * - * This flag starts out set to false, is set to true once this object has been initialized, - * either by calling initialize() or recover(). - */ - bool _init_flag; - - /** - * \brief Stopped flag - * - * This flag starts out false, and is set to true when stop() is called. At this point, the - * journal will no longer accept messages until either initialize() or recover() is called. - * There is no way other than through initialization to reset this flag. - */ - // TODO: It would be helpful to distinguish between states stopping and stopped. If stop(true) is called, - // then we are stopping, but must wait for all outstanding aios to return before being finally stopped. During - // this period, however, no new enqueue/dequeue/read requests may be accepted. - bool _stop_flag; - - /** - * \brief Read-only state flag used during recover. - * - * When true, this flag prevents journal write operations (enqueue and dequeue), but - * allows read to occur. It is used during recovery, and is reset when recovered() is - * called. - */ - bool _readonly_flag; - - // Journal control structures - JournalLog& _jrnl_log; ///< Ref to Journal Log instance - LinearFileController _linearFileController; ///< Linear File Controller - EmptyFilePool* _emptyFilePoolPtr; ///< Pointer to Empty File Pool for this queue - enq_map _emap; ///< Enqueue map for low water mark management - txn_map _tmap; ///< Transaction map open transactions - wmgr _wmgr; ///< Write page manager which manages AIO - RecoveryManager _recoveryManager; ///< Recovery data used for recovery - smutex _wr_mutex; ///< Mutex for journal writes - -public: - static timespec _aio_cmpl_timeout; ///< Timeout for blocking libaio returns - static timespec _final_aio_cmpl_timeout; ///< Timeout for blocking libaio returns when stopping or finalizing - - /** - * \brief Journal constructor. - * - * Constructor which sets the physical file location and base name. - * - * \param jid A unique identifier for this journal instance. - * \param jdir The directory which will contain the journal files. - * \param base_filename The string which will be used to start all journal filenames. - */ - jcntl(const std::string& jid, - const std::string& jdir, - JournalLog& jrnl_log); - - /** - * \brief Destructor. - */ - virtual ~jcntl(); - - inline const std::string& id() const { return _jid; } - - inline const std::string& jrnl_dir() const { return _jdir.dirname(); } - - /** - * \brief Initialize the journal for storing data. - * - * Initialize the journal by creating new journal data files and initializing internal - * control structures. When complete, the journal will be empty, and ready to store data. - * - * NOTE: Any existing journal will be ignored by this operation. To use recover - * the data from an existing journal, use recover(). - * - * NOTE: If NULL is passed to the deque pointers, they will be internally created - * and deleted. - * - * NOTE: If NULL is passed to the callbacks, internal default callbacks will be - * used. - * - * \param num_jfiles The number of journal files to be created. - * \param auto_expand If true, allows journal file auto-expansion. In this mode, the journal will automatically - * add files to the journal if it runs out of space. No more than ae_max_jfiles may be added. If false, then - * no files are added and an exception will be thrown if the journal runs out of file space. - * \param ae_max_jfiles Upper limit of journal files for auto-expand mode. When auto_expand is true, this is the - * maximum total number of files allowed in the journal (original plus those added by auto-expand mode). If - * this number of files exist and the journal runs out of space, an exception will be thrown. This number - * must be greater than the num_jfiles parameter value but cannot exceed the maximum number of files for a - * single journal; if num_jfiles is already at its maximum value, then auto-expand will be disabled. - * \param jfsize_sblks The size of each journal file expressed in softblocks. - * \param wcache_num_pages The number of write cache pages to create. - * \param wcache_pgsize_sblks The size in sblks of each write cache page. - * \param cbp Pointer to object containing callback functions for read and write operations. May be 0 (NULL). - * - * \exception TODO - */ - void initialize(EmptyFilePool* efpp, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - aio_callback* const cbp); - - /** - * /brief Initialize journal by recovering state from previously written journal. - * - * Initialize journal by recovering state from previously written journal. The journal files - * are analyzed, and all records that have not been dequeued and that remain in the journal - * will be available for reading. The journal is placed in a read-only state until - * recovered() is called; any calls to enqueue or dequeue will fail with an exception - * in this state. - * - * NOTE: If NULL is passed to the deque pointers, they will be internally created - * and deleted. - * - * NOTE: If NULL is passed to the callbacks, internal default callbacks will be - * used. - * - * \param num_jfiles The number of journal files to be created. - * \param auto_expand If true, allows journal file auto-expansion. In this mode, the journal will automatically - * add files to the journal if it runs out of space. No more than ae_max_jfiles may be added. If false, then - * no files are added and an exception will be thrown if the journal runs out of file space. - * \param ae_max_jfiles Upper limit of journal files for auto-expand mode. When auto_expand is true, this is the - * maximum total number of files allowed in the journal (original plus those added by auto-expand mode). If - * this number of files exist and the journal runs out of space, an exception will be thrown. This number - * must be greater than the num_jfiles parameter value but cannot exceed the maximum number of files for a - * single journal; if num_jfiles is already at its maximum value, then auto-expand will be disabled. - * \param jfsize_sblks The size of each journal file expressed in softblocks. - * \param wcache_num_pages The number of write cache pages to create. - * \param wcache_pgsize_sblks The size in sblks of each write cache page. - * \param cbp Pointer to object containing callback functions for read and write operations. May be 0 (NULL). - * \param prep_txn_list_ptr - * \param highest_rid Returns the highest rid found in the journal during recover - * - * \exception TODO - */ - void recover(EmptyFilePoolManager* efpm, - const uint16_t wcache_num_pages, - const uint32_t wcache_pgsize_sblks, - aio_callback* const cbp, - const std::vector* prep_txn_list_ptr, - uint64_t& highest_rid); - - /** - * \brief Notification to the journal that recovery is complete and that normal operation - * may resume. - * - * This call notifies the journal that recovery is complete and that normal operation - * may resume. The read pointers are reset so that all records read as a part of recover - * may be re-read during normal operation. The read-only flag is then reset, allowing - * enqueue and dequeue operations to resume. - * - * \exception TODO - */ - void recover_complete(); - - /** - * \brief Stops journal and deletes all journal files. - * - * Clear the journal directory of all journal files matching the base filename. - * - * \exception TODO - */ - void delete_jrnl_files(); - - /** - * \brief Enqueue data. - * - * Enqueue data or part thereof. If a large data block is being written, then it may be - * enqueued in parts by setting this_data_len to the size of the data being written in this - * call. The total data size must be known in advance, however, as this is written into the - * record header on the first record write. The state of the write (i.e. how much has been - * written so far) is maintained in the data token dtokp. Partial writes will return in state - * ENQ_PART. - * - * Note that a return value of anything other than RHM_IORES_SUCCESS implies that this write - * operation did not complete successfully or was partially completed. The action taken under - * these conditions depends on the value of the return. For example, RHM_IORES_AIO_WAIT - * implies that all pages in the write page cache are waiting for AIO operations to return, - * and that the call should be remade after waiting a bit. - * - * Example: If a write of 99 kB is divided into three equal parts, then the following states - * and returns would characterize a successful operation: - *
-    *                            dtok.    dtok.   dtok.
-    * Pperation         Return   wstate() dsize() written() Comment
-    * -----------------+--------+--------+-------+---------+------------------------------------
-    *                            NONE     0       0         Value of dtok before op
-    * edr(99000, 33000) SUCCESS  ENQ_PART 99000   33000     Enqueue part 1
-    * edr(99000, 33000) AIO_WAIT ENQ_PART 99000   50000     Enqueue part 2, not completed
-    * edr(99000, 33000) SUCCESS  ENQ_PART 99000   66000     Enqueue part 2 again
-    * edr(99000, 33000) SUCCESS  ENQ      99000   99000     Enqueue part 3
-    * 
- * - * \param data_buff Pointer to data to be enqueued for this enqueue operation. - * \param tot_data_len Total data length. - * \param this_data_len Amount to be written in this enqueue operation. - * \param dtokp Pointer to data token which contains the details of the enqueue operation. - * \param transient Flag indicating transient persistence (ie, ignored on recover). - * - * \exception TODO - */ - iores enqueue_data_record(const void* const data_buff, - const std::size_t tot_data_len, - const std::size_t this_data_len, - data_tok* dtokp, - const bool transient); - - iores enqueue_extern_data_record(const std::size_t tot_data_len, - data_tok* dtokp, - const bool transient); - - /** - * \brief Enqueue data. - * - * \param data_buff Pointer to data to be enqueued for this enqueue operation. - * \param tot_data_len Total data length. - * \param this_data_len Amount to be written in this enqueue operation. - * \param dtokp Pointer to data token which contains the details of the enqueue operation. - * \param xid String containing xid. An empty string (i.e. length=0) will be considered - * non-transactional. - * \param transient Flag indicating transient persistence (ie, ignored on recover). - * - * \exception TODO - */ - iores enqueue_txn_data_record(const void* const data_buff, - const std::size_t tot_data_len, - const std::size_t this_data_len, - data_tok* dtokp, - const std::string& xid, - const bool tpc_flag, - const bool transient); - - iores enqueue_extern_txn_data_record(const std::size_t tot_data_len, - data_tok* dtokp, - const std::string& xid, - const bool tpc_flag, - const bool transient); - - /** - * \brief Reads data from the journal. It is the responsibility of the reader to free - * the memory that is allocated through this call - see below for details. - * - * Reads the next non-dequeued data record from the journal. - * - * Note that this call allocates memory into which the data and XID are copied. It - * is the responsibility of the caller to free this memory. The memory for the data and - * XID are allocated in a single call, and the XID precedes the data in the memory space. - * Thus, where an XID exists, freeing the XID pointer will free both the XID and data memory. - * However, if an XID does not exist for the message, the XID pointer xidpp is set to NULL, - * and it is the data pointer datapp that must be freed. Should neither an XID nor data be - * present (ie an empty record), then no memory is allocated, and both pointers will be NULL. - * In this case, there is no need to free memory. - * - * TODO: Fix this lousy interface. The caller should NOT be required to clean up these - * pointers! Rather use a struct, or better still, let the data token carry the data and - * xid pointers and lengths, and have the data token both allocate and delete. - * - * \param datapp Pointer to pointer that will be set to point to memory allocated and - * containing the data. Will be set to NULL if the call fails or there is no data - * in the record. - * \param dsize Ref that will be set to the size of the data. Will be set to 0 if the call - * fails or if there is no data in the record. - * \param xidpp Pointer to pointer that will be set to point to memory allocated and - * containing the XID. Will be set to NULL if the call fails or there is no XID attached - * to this record. - * \param xidsize Ref that will be set to the size of the XID. - * \param transient Ref that will be set true if record is transient. - * \param external Ref that will be set true if record is external. In this case, the data - * pointer datapp will be set to NULL, but dsize will contain the size of the data. - * NOTE: If there is an xid, then xidpp must be freed. - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param ignore_pending_txns When false (default), if the next record to be read is locked - * by a pending transaction, the read fails with RHM_IORES_TXPENDING. However, if set - * to true, then locks are ignored. This is required for reading of the Transaction - * Prepared List (TPL) which may have its entries locked, but may be read from - * time-to-time, and needs all its records (locked and unlocked) to be available. - * - * \exception TODO - */ - iores read_data_record(void** const datapp, - std::size_t& dsize, - void** const xidpp, - std::size_t& xidsize, - bool& transient, - bool& external, - data_tok* const dtokp, - bool ignore_pending_txns); - - /** - * \brief Dequeues (marks as no longer needed) data record in journal. - * - * Dequeues (marks as no longer needed) data record in journal. Note that it is possible - * to use the same data token instance used to enqueue this data; it contains the record ID - * needed to correctly mark this data as dequeued in the journal. Otherwise the RID of the - * record to be dequeued and the write state of ENQ must be manually set in a new or reset - * instance of data_tok. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param txn_coml_commit Only used for preparedXID journal. When used for dequeueing - * prepared XID list items, sets whether the complete() was called in commit or abort - * mode. - * - * \exception TODO - */ - iores dequeue_data_record(data_tok* const dtokp, - const bool txn_coml_commit); - - /** - * \brief Dequeues (marks as no longer needed) data record in journal. - * - * Dequeues (marks as no longer needed) data record in journal as part of a transaction. - * Note that it is possible to use the same data token instance used to enqueue this data; - * it contains the RID needed to correctly mark this data as dequeued in the journal. - * Otherwise the RID of the record to be dequeued and the write state of ENQ must be - * manually set in a new or reset instance of data_tok. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. An empty string (i.e. length=0) will be considered - * non-transactional. - * \param txn_coml_commit Only used for preparedXID journal. When used for dequeueing - * prepared XID list items, sets whether the complete() was called in commit or abort - * mode. - * - * \exception TODO - */ - iores dequeue_txn_data_record(data_tok* const dtokp, - const std::string& xid, - const bool tpc_flag, - const bool txn_coml_commit); - - /** - * \brief Abort the transaction for all records enqueued or dequeued with the matching xid. - * - * Abort the transaction for all records enqueued with the matching xid. All enqueued records - * are effectively deleted from the journal, and can not be read. All dequeued records remain - * as though they had never been dequeued. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. - * - * \exception TODO - */ - iores txn_abort(data_tok* const dtokp, - const std::string& xid); - - /** - * \brief Commit the transaction for all records enqueued or dequeued with the matching xid. - * - * Commit the transaction for all records enqueued with the matching xid. All enqueued - * records are effectively released for reading and dequeueing. All dequeued records are - * removed and can no longer be accessed. - * - * \param dtokp Pointer to data_tok instance for this data, used to track state of data - * through journal. - * \param xid String containing xid. - * - * \exception TODO - */ - iores txn_commit(data_tok* const dtokp, - const std::string& xid); - - /** - * \brief Check whether all the enqueue records for the given xid have reached disk. - * - * \param xid String containing xid. - * - * \exception TODO - */ - bool is_txn_synced(const std::string& xid); - - /** - * \brief Forces a check for returned AIO write events. - * - * Forces a check for returned AIO write events. This is normally performed by enqueue() and - * dequeue() operations, but if these operations cease, then this call needs to be made to - * force the processing of any outstanding AIO operations. - */ - int32_t get_wr_events(timespec* const timeout); - - /** - * \brief Stop the journal from accepting any further requests to read or write data. - * - * This operation is used to stop the journal. This is the normal mechanism for bringing the - * journal to an orderly stop. Any outstanding AIO operations or partially written pages in - * the write page cache will by flushed and will complete. - * - * Note: The journal cannot be restarted without either initializing it or restoring - * it. - * - * \param block_till_aio_cmpl If true, will block the thread while waiting for all - * outstanding AIO operations to complete. - */ - void stop(const bool block_till_aio_cmpl); - - /** - * \brief Force a flush of the write page cache, creating a single AIO write operation. - */ - iores flush(const bool block_till_aio_cmpl); - - inline uint32_t get_enq_cnt() const { return _emap.size(); } // TODO: _emap: Thread safe? - - inline uint32_t get_wr_aio_evt_rem() const { slock l(_wr_mutex); return _wmgr.get_aio_evt_rem(); } - - uint32_t get_wr_outstanding_aio_dblks() const; - - uint32_t get_rd_outstanding_aio_dblks() const; - - LinearFileController& getLinearFileControllerRef(); - - /** - * \brief Check if a particular rid is enqueued. Note that this function will return - * false if the rid is transactionally enqueued and is not committed, or if it is - * locked (i.e. transactionally dequeued, but the dequeue has not been committed). - */ - inline bool is_enqueued(const uint64_t rid, bool ignore_lock) { return _emap.is_enqueued(rid, ignore_lock); } - - inline bool is_locked(const uint64_t rid) { - if (_emap.is_enqueued(rid, true) < enq_map::EMAP_OK) - return false; - return _emap.is_locked(rid) == enq_map::EMAP_TRUE; - } - - inline void enq_rid_list(std::vector& rids) { _emap.rid_list(rids); } - - inline void enq_xid_list(std::vector& xids) { _tmap.xid_list(xids); } - - inline uint32_t get_open_txn_cnt() const { return _tmap.size(); } - - // TODO Make this a const, but txn_map must support const first. - inline txn_map& get_txn_map() { return _tmap; } - - /** - * \brief Check if the journal is stopped. - * - * \return true if the jouranl is stopped; - * false otherwise. - */ - inline bool is_stopped() { return _stop_flag; } - - /** - * \brief Check if the journal is ready to read and write data. - * - * Checks if the journal is ready to read and write data. This function will return - * true if the journal has been either initialized or restored, and the stop() - * function has not been called since the initialization. - * - * Note that the journal may also be stopped if an internal error occurs (such as running out - * of data journal file space). - * - * \return true if the journal is ready to read and write data; - * false otherwise. - */ - inline bool is_ready() const { return _init_flag && !_stop_flag; } - - inline bool is_read_only() const { return _readonly_flag; } - - /** - * \brief Get the journal directory. - * - * This returns the journal directory as set during initialization. This is the directory - * into which the journal files will be written. - */ - inline const std::string& dirname() const { return _jdir.dirname(); } - - // Management instrumentation callbacks - inline virtual void instr_incr_outstanding_aio_cnt() {} - inline virtual void instr_decr_outstanding_aio_cnt() {} - - static std::string str2hexnum(const std::string& str); - -protected: - static bool _init; - static bool init_statics(); - - /** - * \brief Check status of journal before allowing write operations. - */ - void check_wstatus(const char* fn_name) const; - - /** - * \brief Check status of journal before allowing read operations. - */ - void check_rstatus(const char* fn_name) const; - - /** - * \brief Call that blocks while waiting for all outstanding AIOs to complete - */ - void aio_cmpl_wait(); - - /** - * \brief Call that blocks until at least one message returns; used to wait for - * AIO wait conditions to clear. - */ - bool handle_aio_wait(const iores res, iores& resout, const data_tok* dtp); -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_JCNTL_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/jdir.cpp b/qpid/cpp/src/qpid/linearstore/journal/jdir.cpp deleted file mode 100644 index 72b94d0098..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jdir.cpp +++ /dev/null @@ -1,457 +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/linearstore/journal/jdir.h" - -#include -#include -#include -#include "qpid/linearstore/journal/jexception.h" -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -jdir::jdir(const std::string& dirname/*, const std::string& _base_filename*/): - _dirname(dirname)/*, - _base_filename(_base_filename)*/ -{} - -jdir::~jdir() -{} - -// === create_dir === - -void -jdir::create_dir() -{ - create_dir(_dirname); -} - - -void -jdir::create_dir(const char* dirname) -{ - create_dir(std::string(dirname)); -} - - -void -jdir::create_dir(const std::string& dirname) -{ - std::size_t fdp = dirname.find_last_of('/'); - if (fdp != std::string::npos) - { - std::string parent_dir = dirname.substr(0, fdp); - if (!exists(parent_dir)) - create_dir(parent_dir); - } - if (::mkdir(dirname.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) - { - if (errno != EEXIST) // Dir exists, ignore - { - std::ostringstream oss; - oss << "dir=\"" << dirname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_MKDIR, oss.str(), "jdir", "create_dir"); - } - } -} - - -// === clear_dir === - -void -jdir::clear_dir(const bool create_flag) -{ - clear_dir(_dirname/*, _base_filename*/, create_flag); -} - -void -jdir::clear_dir(const char* dirname/*, const char* base_filename*/, const bool create_flag) -{ - clear_dir(std::string(dirname)/*, std::string(base_filename)*/, create_flag); -} - - -void -jdir::clear_dir(const std::string& dirname/*, const std::string& -#ifndef RHM_JOWRITE - base_filename -#endif -*/ - , const bool create_flag) -{ - DIR* dir = open_dir(dirname, "clear_dir", true); - if (!dir && create_flag) { - create_dir(dirname); - dir = open_dir(dirname, "clear_dir", true); - } -//#ifndef RHM_JOWRITE - struct dirent* entry; - bool found = false; - std::string bak_dir; - while ((entry = ::readdir(dir)) != 0) - { - // Ignore . and .. - if (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) - { - if (std::strlen(entry->d_name) >= 3) // 'bak' - { - if (std::strncmp(entry->d_name, "bak", 3) == 0) - { - if (!found) - { - bak_dir = create_bak_dir(dirname/*, base_filename*/); - found = true; - } - std::ostringstream oldname; - oldname << dirname << "/" << entry->d_name; - std::ostringstream newname; - newname << bak_dir << "/" << entry->d_name; - if (::rename(oldname.str().c_str(), newname.str().c_str())) - { - ::closedir(dir); - std::ostringstream oss; - oss << "file=\"" << oldname.str() << "\" dest=\"" << - newname.str() << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "jdir", "clear_dir"); - } - } - } - } - } -// FIXME: Find out why this fails with false alarms/errors from time to time... -// While commented out, there is no error capture from reading dir entries. -// check_err(errno, dir, dirname, "clear_dir"); -//#endif - close_dir(dir, dirname, "clear_dir"); -} - -// === push_down === - -std::string -jdir::push_down(const std::string& dirname, const std::string& target_dir/*, const std::string& bak_dir_base*/) -{ - std::string bak_dir_name = create_bak_dir(dirname/*, bak_dir_base*/); - - DIR* dir = open_dir(dirname, "push_down", false); - // Copy contents of targetDirName into bak dir - struct dirent* entry; - while ((entry = ::readdir(dir)) != 0) - { - // Search for targetDirName in storeDirName - if (std::strcmp(entry->d_name, target_dir.c_str()) == 0) - { - std::ostringstream oldname; - oldname << dirname << "/" << target_dir; - std::ostringstream newname; - newname << bak_dir_name << "/" << target_dir; - if (::rename(oldname.str().c_str(), newname.str().c_str())) - { - ::closedir(dir); - std::ostringstream oss; - oss << "file=\"" << oldname.str() << "\" dest=\"" << newname.str() << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_FMOVE, oss.str(), "jdir", "push_down"); - } - break; - } - } - close_dir(dir, dirname, "push_down"); - return bak_dir_name; -} - -// === verify_dir === - -void -jdir::verify_dir() -{ - verify_dir(_dirname/*, _base_filename*/); -} - -void -jdir::verify_dir(const char* dirname/*, const char* base_filename*/) -{ - verify_dir(std::string(dirname)/*, std::string(base_filename)*/); -} - - -void -jdir::verify_dir(const std::string& dirname/*, const std::string& base_filename*/) -{ - if (!is_dir(dirname)) - { - std::ostringstream oss; - oss << "dir=\"" << dirname << "\""; - throw jexception(jerrno::JERR_JDIR_NOTDIR, oss.str(), "jdir", "verify_dir"); - } - - // Read jinf file, then verify all journal files are present -// jinf ji(dirname + "/" + base_filename + "." + QLS_JRNL_FILE_EXTENSION, true); -// for (uint16_t fnum=0; fnum < ji.num_jfiles(); fnum++) -// { -// std::ostringstream oss; -// oss << dirname << "/" << base_filename << "."; -// oss << std::setw(4) << std::setfill('0') << std::hex << fnum; -// oss << "." << QLS_JRNL_FILE_EXTENSION; -// if (!exists(oss.str())) -// throw jexception(jerrno::JERR_JDIR_NOSUCHFILE, oss.str(), "jdir", "verify_dir"); -// } -} - - -// === delete_dir === - -void -jdir::delete_dir(bool children_only) -{ - delete_dir(_dirname, children_only); -} - -void -jdir::delete_dir(const char* dirname, bool children_only) -{ - delete_dir(std::string(dirname), children_only); -} - -void -jdir::delete_dir(const std::string& dirname, bool children_only) -{ - struct dirent* entry; - struct stat s; - DIR* dir = open_dir(dirname, "delete_dir", true); // true = allow dir does not exist, return 0 - if (!dir) return; - while ((entry = ::readdir(dir)) != 0) - { - // Ignore . and .. - if (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) - { - std::string full_name(dirname + "/" + entry->d_name); - if (::lstat(full_name.c_str(), &s)) - { - ::closedir(dir); - std::ostringstream oss; - oss << "stat: file=\"" << full_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_STAT, oss.str(), "jdir", "delete_dir"); - } - if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) // This is a file or slink - { - if(::unlink(full_name.c_str())) - { - ::closedir(dir); - std::ostringstream oss; - oss << "unlink: file=\"" << entry->d_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_UNLINK, oss.str(), "jdir", "delete_dir"); - } - } - else if (S_ISDIR(s.st_mode)) // This is a dir - { - delete_dir(full_name); - } - else // all other types, throw up! - { - ::closedir(dir); - std::ostringstream oss; - oss << "file=\"" << entry->d_name << "\" is not a dir, file or slink."; - oss << " (mode=0x" << std::hex << s.st_mode << std::dec << ")"; - throw jexception(jerrno::JERR_JDIR_BADFTYPE, oss.str(), "jdir", "delete_dir"); - } - } - } - -// FIXME: Find out why this fails with false alarms/errors from time to time... -// While commented out, there is no error capture from reading dir entries. -// check_err(errno, dir, dirname, "delete_dir"); - // Now dir is empty, close and delete it - close_dir(dir, dirname, "delete_dir"); - - if (!children_only) - if (::rmdir(dirname.c_str())) - { - std::ostringstream oss; - oss << "dir=\"" << dirname << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_RMDIR, oss.str(), "jdir", "delete_dir"); - } -} - - -std::string -jdir::create_bak_dir(const std::string& dirname) -{ - DIR* dir = open_dir(dirname, "create_bak_dir", false); - long dir_num = 0L; - struct dirent* entry; - while ((entry = ::readdir(dir)) != 0) - { - // Ignore . and .. - if (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) - { - if (std::strlen(entry->d_name) == 9) // Format: _bak.XXXX - { - if (std::strncmp(entry->d_name, "_bak.", 5) == 0) - { - long this_dir_num = std::strtol(entry->d_name + 5, 0, 16); - if (this_dir_num > dir_num) - dir_num = this_dir_num; - } - } - } - } -// FIXME: Find out why this fails with false alarms/errors from time to time... -// While commented out, there is no error capture from reading dir entries. -// check_err(errno, dir, dirname, "create_bak_dir"); - close_dir(dir, dirname, "create_bak_dir"); - - std::ostringstream dn; - dn << dirname << "/_bak." << std::hex << std::setw(4) << std::setfill('0') << ++dir_num; - if (::mkdir(dn.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH)) - { - std::ostringstream oss; - oss << "dir=\"" << dn.str() << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_MKDIR, oss.str(), "jdir", "create_bak_dir"); - } - return std::string(dn.str()); -} - -bool -jdir::is_dir(const char* name) -{ - struct stat s; - if (::stat(name, &s)) - { - std::ostringstream oss; - oss << "file=\"" << name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_STAT, oss.str(), "jdir", "is_dir"); - } - return S_ISDIR(s.st_mode); -} - -bool -jdir::is_dir(const std::string& name) -{ - return is_dir(name.c_str()); -} - -bool -jdir::exists(const char* name) -{ - struct stat s; - if (::stat(name, &s)) - { - if (errno == ENOENT) // No such dir or file - return false; - // Throw for any other condition - std::ostringstream oss; - oss << "file=\"" << name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_STAT, oss.str(), "jdir", "exists"); - } - return true; -} - -bool -jdir::exists(const std::string& name) -{ - return exists(name.c_str()); -} - -void -jdir::read_dir(const std::string& name, std::vector& dir_list, const bool incl_dirs, const bool incl_files, const bool incl_links, const bool return_fqfn) { - struct stat s; - if (is_dir(name)) { - DIR* dir = open_dir(name, "read_dir", false); - struct dirent* entry; - while ((entry = ::readdir(dir)) != 0) { - if (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) { // Ignore . and .. - std::string full_name(name + "/" + entry->d_name); - if (::stat(full_name.c_str(), &s)) - { - ::closedir(dir); - std::ostringstream oss; - oss << "stat: file=\"" << full_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_STAT, oss.str(), "jdir", "delete_dir"); - } - if ((S_ISREG(s.st_mode) && incl_files) || (S_ISDIR(s.st_mode) && incl_dirs) || (S_ISLNK(s.st_mode) && incl_links)) { - if (return_fqfn) { - dir_list.push_back(name + "/" + entry->d_name); - } else { - dir_list.push_back(entry->d_name); - } - } - } - } - close_dir(dir, name, "read_dir"); - } -} - -void -jdir::check_err(const int err_num, DIR* dir, const std::string& dir_name, const std::string& fn_name) -{ - if (err_num) - { - std::ostringstream oss; - oss << "dir=\"" << dir_name << "\"" << FORMAT_SYSERR(err_num); - ::closedir(dir); // Try to close, it makes no sense to trap errors here... - throw jexception(jerrno::JERR_JDIR_READDIR, oss.str(), "jdir", fn_name); - } -} - -void -jdir::close_dir(DIR* dir, const std::string& dir_name, const std::string& fn_name) -{ - if (::closedir(dir)) - { - std::ostringstream oss; - oss << "dir=\"" << dir_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_CLOSEDIR, oss.str(), "jdir", fn_name); - } -} - -DIR* -jdir::open_dir(const std::string& dir_name, const std::string& fn_name, const bool test_enoent) -{ - DIR* dir = ::opendir(dir_name.c_str()); - if (!dir) { - if (test_enoent && errno == ENOENT) { - return 0; - } - std::ostringstream oss; - oss << "dir=\"" << dir_name << "\"" << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR_JDIR_OPENDIR, oss.str(), "jdir", fn_name); - } - return dir; -} - -std::ostream& -operator<<(std::ostream& os, const jdir& jdir) -{ - os << jdir._dirname; - return os; -} - -std::ostream& -operator<<(std::ostream& os, const jdir* jdirPtr) -{ - os << jdirPtr->_dirname; - return os; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/jdir.h b/qpid/cpp/src/qpid/linearstore/journal/jdir.h deleted file mode 100644 index 59f21ce499..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jdir.h +++ /dev/null @@ -1,362 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_JDIR_H -#define QPID_LINEARSTORE_JOURNAL_JDIR_H - -#include -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - - /** - * \class jdir - * \brief Class to manage the %journal directory - */ - class jdir - { - private: - std::string _dirname; - //std::string _base_filename; - - public: - - /** - * \brief Sole constructor - * - * \param dirname Name of directory to be managed. - * \param base_filename Filename root used in the creation of %journal files - * and sub-directories. - */ - jdir(const std::string& dirname/*, const std::string& base_filename*/); - - virtual ~jdir(); - - - /** - * \brief Create %journal directory as set in the dirname parameter of the constructor. - * Recursive creation is supported. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - void create_dir(); - - /** - * \brief Static function to create a directory. Recursive creation is supported. - * - * \param dirname C-string containing name of directory. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - static void create_dir(const char* dirname); - - /** - * \brief Static function to create a directory. Recursive creation is supported. - * - * \param dirname String containing name of directory. - * - * \exception jerrno::JERR_JDIR_MKDIR The creation of dirname failed. - */ - static void create_dir(const std::string& dirname); - - - /** - * \brief Clear the %journal directory of files matching the base filename - * by moving them into a subdirectory. This fn uses the dirname and base_filename - * that were set on construction. - * - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - void clear_dir(const bool create_flag = true); - - /** - * \brief Clear the directory dirname of %journal files matching base_filename - * by moving them into a subdirectory. - * - * \param dirname C-string containing name of %journal directory. - * \param base_filename C-string containing base filename of %journal files to be matched - * for moving into subdirectory. - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void clear_dir(const char* dirname/*, const char* base_filename*/, - const bool create_flag = true); - - /** - * \brief Clear the directory dirname of %journal files matching base_filename - * by moving them into a subdirectory. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched - * for moving into subdirectory. - * \param create_flag If set, create dirname if it is non-existent, otherwise throw - * exception - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_FMOVE Moving the files from the %journal directory to the created backup - * directory failed. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void clear_dir(const std::string& dirname/*, const std::string& base_filename*/, - const bool create_flag = true); - - - - /** - * \brief Move (push down) the directory target_dir located in directory dirname into a backup directory - * named _bak_dir_base.XXXX (note prepended underscore), where XXXX is an increasing hex serial number - * starting at 0000. - * - * \param dirname Full path to directory containing directory to be pushed down. - * \param target_dir Name of directory in dirname to be pushed down. - * \param bak_dir_base Base name for backup directory to be created in dirname, into which target_dir will be moved. - * \return Name of backup dir into which target_dir was pushed. - */ - static std::string push_down(const std::string& dirname, const std::string& target_dir/*, const std::string& bak_dir_base*/); - - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - void verify_dir(); - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \param dirname C-string containing name of %journal directory. - * \param base_filename C-string containing base filename of %journal files to be matched for moving into sub-directory. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - static void verify_dir(const char* dirname/*, const char* base_filename*/); - - /** - * \brief Verify that dirname is a valid %journal directory. - * - * The validation reads the .%jinf file, and using this information verifies that all the expected %journal - * (.jdat) files are present. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched for moving into sub-directory. - * - * \exception jerrno::JERR_JDIR_NOTDIR dirname is not a directory - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname - * \exception jerrno::JERR__FILEIO Error reading %jinf file - * \exception jerrno::JERR_JINF_CVALIDFAIL Error validating %jinf file - * \exception jerrno::JERR_JDIR_NOSUCHFILE Expected jdat file is missing - */ - static void verify_dir(const std::string& dirname/*, const std::string& base_filename*/); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - void delete_dir(bool children_only = false ); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param dirname C-string containing name of directory to be deleted. - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - static void delete_dir(const char* dirname, bool children_only = false); - - /** - * \brief Delete the %journal directory and all files and sub--directories that it may - * contain. This is equivilent of rm -rf. - * - * FIXME: links are not handled correctly. - * - * \param dirname String containing name of directory to be deleted. - * \param children_only If true, delete only children of dirname, but leave dirname itself. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_STAT Could not stat dirname. - * \exception jerrno::JERR_JDIR_UNLINK A file could not be deleted. - * \exception jerrno::JERR_JDIR_BADFTYPE A dir entry is neiter a file nor a dir. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_RMDIR A directory could not be deleted. - */ - static void delete_dir(const std::string& dirname, bool children_only = false); - - /** - * \brief Create bakup directory that is next in sequence and move all %journal files - * matching base_filename into it. - * - * In directory dirname, search for existing backup directory using pattern - * "_basename.bak.XXXX" where XXXX is a hexadecimal sequence, and create next directory - * based on highest number found. Move all %journal files which match the base_fileaname - * parameter into this new backup directory. - * - * \param dirname String containing name of %journal directory. - * \param base_filename String containing base filename of %journal files to be matched - * for moving into subdirectory. - * - * \exception jerrno::JERR_JDIR_OPENDIR The %journal directory could not be opened. - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - * \exception jerrno::JERR_JDIR_MKDIR The backup directory could not be deleted. - */ - static std::string create_bak_dir(const std::string& dirname/*, - const std::string& base_filename*/); - - /** - * \brief Return the directory name as a string. - */ - inline const std::string& dirname() const { return _dirname; } - - /** - * \brief Return the %journal base filename name as a string. - */ -// inline const std::string& base_filename() const { return _base_filename; } - - /** - * \brief Test whether the named file is a directory. - * - * \param name Name of file to be tested. - * \return true if the named file is a directory; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool is_dir(const char* name); - - /** - * \brief Test whether the named file is a directory. - * - * \param name Name of file to be tested. - * \return true if the named file is a directory; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool is_dir(const std::string& name); - - - /** - * \brief Test whether the named entity exists on the filesystem. - * - * If stat() fails with error ENOENT, then this will return false. If - * stat() succeeds, then true is returned, irrespective of the file type. - * If stat() fails with any other error, an exception is thrown. - * - * \param name Name of entity to be tested. - * \return true if the named entity exists; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool exists(const char* name); - - /** - * \brief Test whether the named entity exists on the filesystem. - * - * If stat() fails with error ENOENT, then this will return false. If - * stat() succeeds, then true is returned, irrespective of the file type. - * If stat() fails with any other error, an exception is thrown. - * - * \param name Name of entity to be tested. - * \return true if the named entity exists; false - * otherwise. - * \exception jerrno::JERR_JDIR_STAT Could not stat name. - */ - static bool exists(const std::string& name); - - static void read_dir(const std::string& name, std::vector& dir_list, const bool incl_dirs, const bool incl_files, const bool incl_links, const bool return_fqfn); - - /** - * \brief Stream operator - */ - friend std::ostream& operator<<(std::ostream& os, const jdir& jdir); - - /** - * \brief Stream operator - */ - friend std::ostream& operator<<(std::ostream& os, const jdir* jdirPtr); - - private: - /** - * \brief Check for error, if non-zero close DIR handle and throw JERR_JDIR_READDIR - * - * \exception jerrno::JERR_JDIR_READDIR Error while reading contents of dir. - */ - static void check_err(const int err_num, DIR* dir, const std::string& dir_name, const std::string& fn_name); - - /** - * \brief Close a DIR handle, throw JERR_JDIR_CLOSEDIR if error occurs during close - * - * \exception jerrno::JERR_JDIR_CLOSEDIR The directory handle could not be closed. - */ - static void close_dir(DIR* dir, const std::string& dir_name, const std::string& fn_name); - - static DIR* open_dir(const std::string& dir_name, const std::string& fn_name, const bool test_enoent); - }; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_JDIR_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp b/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp deleted file mode 100644 index ce88e7809c..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp +++ /dev/null @@ -1,236 +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/linearstore/journal/jerrno.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -std::map jerrno::_err_map; -std::map::iterator jerrno::_err_map_itr; -bool jerrno::_initialized = jerrno::__init(); - -// generic errors -const uint32_t jerrno::JERR__MALLOC = 0x0100; -const uint32_t jerrno::JERR__UNDERFLOW = 0x0101; -const uint32_t jerrno::JERR__NINIT = 0x0102; -const uint32_t jerrno::JERR__AIO = 0x0103; -const uint32_t jerrno::JERR__FILEIO = 0x0104; -const uint32_t jerrno::JERR__RTCLOCK = 0x0105; -const uint32_t jerrno::JERR__PTHREAD = 0x0106; -const uint32_t jerrno::JERR__TIMEOUT = 0x0107; -const uint32_t jerrno::JERR__UNEXPRESPONSE = 0x0108; -const uint32_t jerrno::JERR__RECNFOUND = 0x0109; -const uint32_t jerrno::JERR__NOTIMPL = 0x010a; -const uint32_t jerrno::JERR__NULL = 0x010b; -const uint32_t jerrno::JERR__SYMLINK = 0x010c; - -// class jcntl -const uint32_t jerrno::JERR_JCNTL_STOPPED = 0x0200; -const uint32_t jerrno::JERR_JCNTL_READONLY = 0x0201; -const uint32_t jerrno::JERR_JCNTL_AIOCMPLWAIT = 0x0202; -const uint32_t jerrno::JERR_JCNTL_UNKNOWNMAGIC = 0x0203; -const uint32_t jerrno::JERR_JCNTL_NOTRECOVERED = 0x0204; -const uint32_t jerrno::JERR_JCNTL_ENQSTATE = 0x0207; -const uint32_t jerrno::JERR_JCNTL_INVALIDENQHDR = 0x0208; - -// class jdir -const uint32_t jerrno::JERR_JDIR_NOTDIR = 0x0300; -const uint32_t jerrno::JERR_JDIR_MKDIR = 0x0301; -const uint32_t jerrno::JERR_JDIR_OPENDIR = 0x0302; -const uint32_t jerrno::JERR_JDIR_READDIR = 0x0303; -const uint32_t jerrno::JERR_JDIR_CLOSEDIR = 0x0304; -const uint32_t jerrno::JERR_JDIR_RMDIR = 0x0305; -const uint32_t jerrno::JERR_JDIR_NOSUCHFILE = 0x0306; -const uint32_t jerrno::JERR_JDIR_FMOVE = 0x0307; -const uint32_t jerrno::JERR_JDIR_STAT = 0x0308; -const uint32_t jerrno::JERR_JDIR_UNLINK = 0x0309; -const uint32_t jerrno::JERR_JDIR_BADFTYPE = 0x030a; - -// class JournalFile -const uint32_t jerrno::JERR_JNLF_OPEN = 0x0400; -const uint32_t jerrno::JERR_JNLF_CLOSE = 0x0401; -const uint32_t jerrno::JERR_JNLF_FILEOFFSOVFL = 0x0402; -const uint32_t jerrno::JERR_JNLF_CMPLOFFSOVFL = 0x0403; - -// class LinearFileController -const uint32_t jerrno::JERR_LFCR_SEQNUMNOTFOUND = 0x0500; - -// class jrec, enq_rec, deq_rec, txn_rec -const uint32_t jerrno::JERR_JREC_BADRECHDR = 0x0700; -const uint32_t jerrno::JERR_JREC_BADRECTAIL = 0x0701; - -// class wmgr -const uint32_t jerrno::JERR_WMGR_BADPGSTATE = 0x0801; -const uint32_t jerrno::JERR_WMGR_BADDTOKSTATE = 0x0802; -const uint32_t jerrno::JERR_WMGR_ENQDISCONT = 0x0803; -const uint32_t jerrno::JERR_WMGR_DEQDISCONT = 0x0804; -const uint32_t jerrno::JERR_WMGR_DEQRIDNOTENQ = 0x0805; -const uint32_t jerrno::JERR_WMGR_BADFH = 0x0806; -const uint32_t jerrno::JERR_WMGR_NOTSBLKALIGNED = 0x0807; - -// class RecoveryManager -const uint32_t jerrno::JERR_RCVM_OPENRD = 0x0900; -const uint32_t jerrno::JERR_RCVM_STREAMBAD = 0x0901; -const uint32_t jerrno::JERR_RCVM_READ = 0x0902; -const uint32_t jerrno::JERR_RCVM_WRITE = 0x0903; -const uint32_t jerrno::JERR_RCVM_NULLXID = 0x0904; -const uint32_t jerrno::JERR_RCVM_NOTDBLKALIGNED = 0x0905; -const uint32_t jerrno::JERR_RCVM_NULLFID = 0x0907; -const uint32_t jerrno::JERR_RCVM_INVALIDEFPID = 0x0908; - -// class data_tok -const uint32_t jerrno::JERR_DTOK_ILLEGALSTATE = 0x0a00; -// const uint32_t jerrno::JERR_DTOK_RIDNOTSET = 0x0a01; - -// class enq_map, txn_map -const uint32_t jerrno::JERR_MAP_DUPLICATE = 0x0b00; -const uint32_t jerrno::JERR_MAP_NOTFOUND = 0x0b01; -const uint32_t jerrno::JERR_MAP_LOCKED = 0x0b02; - -// EFP errors -const uint32_t jerrno::JERR_EFP_BADPARTITIONNAME = 0x0d01; -const uint32_t jerrno::JERR_EFP_BADPARTITIONDIR = 0x0d02; -const uint32_t jerrno::JERR_EFP_BADEFPDIRNAME = 0x0d03; -const uint32_t jerrno::JERR_EFP_NOEFP = 0x0d04; -const uint32_t jerrno::JERR_EFP_EMPTY = 0x0d05; -const uint32_t jerrno::JERR_EFP_LSTAT = 0x0d06; -const uint32_t jerrno::JERR_EFP_BADFILETYPE = 0x0d07; -const uint32_t jerrno::JERR_EFP_FOPEN = 0x0d08; -const uint32_t jerrno::JERR_EFP_FWRITE = 0x0d09; -const uint32_t jerrno::JERR_EFP_MKDIR = 0x0d0a; - -// Negative returns for some functions -const int32_t jerrno::AIO_TIMEOUT = -1; -const int32_t jerrno::LOCK_TAKEN = -2; - - -// static initialization fn - -bool -jerrno::__init() -{ - // generic errors - _err_map[JERR__MALLOC] = "JERR__MALLOC: Buffer memory allocation failed."; - _err_map[JERR__UNDERFLOW] = "JERR__UNDERFLOW: Underflow error"; - _err_map[JERR__NINIT] = "JERR__NINIT: Operation on uninitialized class."; - _err_map[JERR__AIO] = "JERR__AIO: AIO error."; - _err_map[JERR__FILEIO] = "JERR__FILEIO: File read or write failure."; - _err_map[JERR__RTCLOCK] = "JERR__RTCLOCK: Reading real-time clock failed."; - _err_map[JERR__PTHREAD] = "JERR__PTHREAD: pthread failure."; - _err_map[JERR__TIMEOUT] = "JERR__TIMEOUT: Timeout waiting for event."; - _err_map[JERR__UNEXPRESPONSE] = "JERR__UNEXPRESPONSE: Unexpected response to call or event."; - _err_map[JERR__RECNFOUND] = "JERR__RECNFOUND: Record not found."; - _err_map[JERR__NOTIMPL] = "JERR__NOTIMPL: Not implemented"; - _err_map[JERR__NULL] = "JERR__NULL: Operation on null pointer"; - _err_map[JERR__SYMLINK] = "JERR__SYMLINK: Symbolic link operation failed"; - - // class jcntl - _err_map[JERR_JCNTL_STOPPED] = "JERR_JCNTL_STOPPED: Operation on stopped journal."; - _err_map[JERR_JCNTL_READONLY] = "JERR_JCNTL_READONLY: Write operation on read-only journal (during recovery)."; - _err_map[JERR_JCNTL_AIOCMPLWAIT] = "JERR_JCNTL_AIOCMPLWAIT: Timeout waiting for AIOs to complete."; - _err_map[JERR_JCNTL_UNKNOWNMAGIC] = "JERR_JCNTL_UNKNOWNMAGIC: Found record with unknown magic."; - _err_map[JERR_JCNTL_NOTRECOVERED] = "JERR_JCNTL_NOTRECOVERED: Operation requires recover() to be run first."; - _err_map[JERR_JCNTL_ENQSTATE] = "JERR_JCNTL_ENQSTATE: Read error: Record not in ENQ state"; - _err_map[JERR_JCNTL_INVALIDENQHDR] = "JERR_JCNTL_INVALIDENQHDR: Invalid ENQ header"; - - // class jdir - _err_map[JERR_JDIR_NOTDIR] = "JERR_JDIR_NOTDIR: Directory name exists but is not a directory."; - _err_map[JERR_JDIR_MKDIR] = "JERR_JDIR_MKDIR: Directory creation failed."; - _err_map[JERR_JDIR_OPENDIR] = "JERR_JDIR_OPENDIR: Directory open failed."; - _err_map[JERR_JDIR_READDIR] = "JERR_JDIR_READDIR: Directory read failed."; - _err_map[JERR_JDIR_CLOSEDIR] = "JERR_JDIR_CLOSEDIR: Directory close failed."; - _err_map[JERR_JDIR_RMDIR] = "JERR_JDIR_RMDIR: Directory delete failed."; - _err_map[JERR_JDIR_NOSUCHFILE] = "JERR_JDIR_NOSUCHFILE: File does not exist."; - _err_map[JERR_JDIR_FMOVE] = "JERR_JDIR_FMOVE: File move failed."; - _err_map[JERR_JDIR_STAT] = "JERR_JDIR_STAT: File stat failed."; - _err_map[JERR_JDIR_UNLINK] = "JERR_JDIR_UNLINK: File delete failed."; - _err_map[JERR_JDIR_BADFTYPE] = "JERR_JDIR_BADFTYPE: Bad or unknown file type (stat mode)."; - - // class JournalFile - _err_map[JERR_JNLF_OPEN] = "JERR_JNLF_OPEN: Unable to open file for write"; - _err_map[JERR_JNLF_CLOSE] = "JERR_JNLF_CLOSE: Unable to close file"; - _err_map[JERR_JNLF_FILEOFFSOVFL] = "JERR_JNLF_FILEOFFSOVFL: Attempted to increase submitted offset past file size."; - _err_map[JERR_JNLF_CMPLOFFSOVFL] = "JERR_JNLF_CMPLOFFSOVFL: Attempted to increase completed file offset past submitted offset."; - - // class LinearFileController - _err_map[JERR_LFCR_SEQNUMNOTFOUND] = "JERR_LFCR_SEQNUMNOTFOUND: File sequence number not found"; - - // class jrec, enq_rec, deq_rec, txn_rec - _err_map[JERR_JREC_BADRECHDR] = "JERR_JREC_BADRECHDR: Invalid record header."; - _err_map[JERR_JREC_BADRECTAIL] = "JERR_JREC_BADRECTAIL: Invalid record tail."; - - // class wmgr - _err_map[JERR_WMGR_BADPGSTATE] = "JERR_WMGR_BADPGSTATE: Page buffer in illegal state for operation."; - _err_map[JERR_WMGR_BADDTOKSTATE] = "JERR_WMGR_BADDTOKSTATE: Data token in illegal state for operation."; - _err_map[JERR_WMGR_ENQDISCONT] = "JERR_WMGR_ENQDISCONT: Enqueued new dtok when previous enqueue returned partly completed (state ENQ_PART)."; - _err_map[JERR_WMGR_DEQDISCONT] = "JERR_WMGR_DEQDISCONT: Dequeued new dtok when previous dequeue returned partly completed (state DEQ_PART)."; - _err_map[JERR_WMGR_DEQRIDNOTENQ] = "JERR_WMGR_DEQRIDNOTENQ: Dequeue rid is not enqueued."; - _err_map[JERR_WMGR_BADFH] = "JERR_WMGR_BADFH: Bad file handle."; - _err_map[JERR_WMGR_NOTSBLKALIGNED] = "JERR_WMGR_NOTSBLKALIGNED: Offset is not soft block (sblk)-aligned"; - - // class RecoveryManager - _err_map[JERR_RCVM_OPENRD] = "JERR_RCVM_OPENRD: Unable to open file for read"; - _err_map[JERR_RCVM_STREAMBAD] = "JERR_RCVM_STREAMBAD: Read/write stream error"; - _err_map[JERR_RCVM_READ] = "JERR_RCVM_READ: Read error: no or insufficient data to read"; - _err_map[JERR_RCVM_WRITE] = "JERR_RCVM_WRITE: Write error"; - _err_map[JERR_RCVM_NULLXID] = "JERR_RCVM_NULLXID: Null XID when XID length non-null in header"; - _err_map[JERR_RCVM_NOTDBLKALIGNED] = "JERR_RCVM_NOTDBLKALIGNED: Offset is not data block (dblk)-aligned"; - _err_map[JERR_RCVM_NULLFID] = "JERR_RCVM_NULLFID: Null file id (FID)"; - _err_map[JERR_RCVM_INVALIDEFPID] = "JERR_RCVM_INVALIDEFPID: Invalid EFP identity (partition/size)"; - - // class data_tok - _err_map[JERR_DTOK_ILLEGALSTATE] = "JERR_MTOK_ILLEGALSTATE: Attempted to change to illegal state."; - //_err_map[JERR_DTOK_RIDNOTSET] = "JERR_DTOK_RIDNOTSET: Record ID not set."; - - // class enq_map, txn_map - _err_map[JERR_MAP_DUPLICATE] = "JERR_MAP_DUPLICATE: Attempted to insert record into map using duplicate key."; - _err_map[JERR_MAP_NOTFOUND] = "JERR_MAP_NOTFOUND: Key not found in map."; - _err_map[JERR_MAP_LOCKED] = "JERR_MAP_LOCKED: Record ID locked by a pending transaction."; - - // EFP errors - _err_map[JERR_EFP_BADPARTITIONNAME] = "JERR_EFP_BADPARTITIONNAME: Invalid partition name (must be \'pNNN\' where NNN is a non-zero number)"; - _err_map[JERR_EFP_BADEFPDIRNAME] = "JERR_EFP_BADEFPDIRNAME: Bad Empty File Pool directory name (must be \'NNNk\', where NNN is a number which is a multiple of 4)"; - _err_map[JERR_EFP_BADPARTITIONDIR] = "JERR_EFP_BADPARTITIONDIR: Invalid partition directory"; - _err_map[JERR_EFP_NOEFP] = "JERR_EFP_NOEFP: No Empty File Pool found for given partition and empty file size"; - _err_map[JERR_EFP_EMPTY] = "JERR_EFP_EMPTY: Empty File Pool is empty"; - _err_map[JERR_EFP_LSTAT] = "JERR_EFP_LSTAT: lstat() operation failed"; - _err_map[JERR_EFP_BADFILETYPE] = "JERR_EFP_BADFILETYPE: File type incorrect for operation"; - _err_map[JERR_EFP_FOPEN] = "JERR_EFP_FOPEN: Unable to fopen file for write"; - _err_map[JERR_EFP_FWRITE] = "JERR_EFP_FWRITE: Write failed"; - _err_map[JERR_EFP_MKDIR] = "JERR_EFP_MKDIR: Directory creation failed"; - - //_err_map[] = ""; - - return true; -} - -const char* -jerrno::err_msg(const uint32_t err_no) throw () -{ - _err_map_itr = _err_map.find(err_no); - if (_err_map_itr == _err_map.end()) - return ""; - return _err_map_itr->second; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/jerrno.h b/qpid/cpp/src/qpid/linearstore/journal/jerrno.h deleted file mode 100644 index 6e817682ca..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jerrno.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_JERRNO_H -#define QPID_LINEARSTORE_JOURNAL_JERRNO_H - -namespace qpid { -namespace linearstore { -namespace journal { -class jerrno; -}}} - -#include -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - - /** - * \class jerrno - * \brief Class containing static error definitions and static map for error messages. - */ - class jerrno - { - static std::map _err_map; ///< Map of error messages - static std::map::iterator _err_map_itr; ///< Iterator - static bool _initialized; ///< Dummy flag, used to initialise map. - - public: - // generic errors - static const uint32_t JERR__MALLOC; ///< Buffer memory allocation failed - static const uint32_t JERR__UNDERFLOW; ///< Underflow error - static const uint32_t JERR__NINIT; ///< Operation on uninitialized class - static const uint32_t JERR__AIO; ///< AIO failure - static const uint32_t JERR__FILEIO; ///< File read or write failure - static const uint32_t JERR__RTCLOCK; ///< Reading real-time clock failed - static const uint32_t JERR__PTHREAD; ///< pthread failure - static const uint32_t JERR__TIMEOUT; ///< Timeout waiting for an event - static const uint32_t JERR__UNEXPRESPONSE; ///< Unexpected response to call or event - static const uint32_t JERR__RECNFOUND; ///< Record not found - static const uint32_t JERR__NOTIMPL; ///< Not implemented - static const uint32_t JERR__NULL; ///< Operation on null pointer - static const uint32_t JERR__SYMLINK; ///< Symbolic Link operation failed - - // class jcntl - static const uint32_t JERR_JCNTL_STOPPED; ///< Operation on stopped journal - static const uint32_t JERR_JCNTL_READONLY; ///< Write operation on read-only journal - static const uint32_t JERR_JCNTL_AIOCMPLWAIT; ///< Timeout waiting for AIOs to complete - static const uint32_t JERR_JCNTL_UNKNOWNMAGIC; ///< Found record with unknown magic - static const uint32_t JERR_JCNTL_NOTRECOVERED; ///< Req' recover() to be called first - static const uint32_t JERR_JCNTL_ENQSTATE; ///< Read error: Record not in ENQ state - static const uint32_t JERR_JCNTL_INVALIDENQHDR; ///< Invalid ENQ header - - // class jdir - static const uint32_t JERR_JDIR_NOTDIR; ///< Exists but is not a directory - static const uint32_t JERR_JDIR_MKDIR; ///< Directory creation failed - static const uint32_t JERR_JDIR_OPENDIR; ///< Directory open failed - static const uint32_t JERR_JDIR_READDIR; ///< Directory read failed - static const uint32_t JERR_JDIR_CLOSEDIR; ///< Directory close failed - static const uint32_t JERR_JDIR_RMDIR; ///< Directory delete failed - static const uint32_t JERR_JDIR_NOSUCHFILE; ///< File does not exist - static const uint32_t JERR_JDIR_FMOVE; ///< File move failed - static const uint32_t JERR_JDIR_STAT; ///< File stat failed - static const uint32_t JERR_JDIR_UNLINK; ///< File delete failed - static const uint32_t JERR_JDIR_BADFTYPE; ///< Bad or unknown file type (stat mode) - - // class JournalFile - static const uint32_t JERR_JNLF_OPEN; ///< Unable to open file for write - static const uint32_t JERR_JNLF_CLOSE; ///< Unable to close file - static const uint32_t JERR_JNLF_FILEOFFSOVFL; ///< Increased offset past file size - static const uint32_t JERR_JNLF_CMPLOFFSOVFL; ///< Increased cmpl offs past subm offs - - // class LinearFileController - static const uint32_t JERR_LFCR_SEQNUMNOTFOUND; ///< File sequence number not found - - // class jrec, enq_rec, deq_rec, txn_rec - static const uint32_t JERR_JREC_BADRECHDR; ///< Invalid data record header - static const uint32_t JERR_JREC_BADRECTAIL; ///< Invalid data record tail - - // class wmgr - static const uint32_t JERR_WMGR_BADPGSTATE; ///< Page buffer in illegal state. - static const uint32_t JERR_WMGR_BADDTOKSTATE; ///< Data token in illegal state. - static const uint32_t JERR_WMGR_ENQDISCONT; ///< Enq. new dtok when previous part compl. - static const uint32_t JERR_WMGR_DEQDISCONT; ///< Deq. new dtok when previous part compl. - static const uint32_t JERR_WMGR_DEQRIDNOTENQ; ///< Deq. rid not enqueued - static const uint32_t JERR_WMGR_BADFH; ///< Bad file handle - static const uint32_t JERR_WMGR_NOTSBLKALIGNED; ///< Offset is not soft block (sblk)-aligned - - // class RecoveryManager - static const uint32_t JERR_RCVM_OPENRD; ///< Unable to open file for read - static const uint32_t JERR_RCVM_STREAMBAD; ///< Read/write stream error - static const uint32_t JERR_RCVM_READ; ///< Read error: no or insufficient data to read - static const uint32_t JERR_RCVM_WRITE; ///< Write error - static const uint32_t JERR_RCVM_NULLXID; ///< Null XID when XID length non-null in header - static const uint32_t JERR_RCVM_NOTDBLKALIGNED; ///< Offset is not data block (dblk)-aligned - static const uint32_t JERR_RCVM_NULLFID; ///< Null file ID (FID) - static const uint32_t JERR_RCVM_INVALIDEFPID; ///< Invalid EFP identity (partition/size) - - // class data_tok - static const uint32_t JERR_DTOK_ILLEGALSTATE; ///< Attempted to change to illegal state -// static const uint32_t JERR_DTOK_RIDNOTSET; ///< Record ID not set - - // class enq_map, txn_map - static const uint32_t JERR_MAP_DUPLICATE; ///< Attempted to insert using duplicate key - static const uint32_t JERR_MAP_NOTFOUND; ///< Key not found in map - static const uint32_t JERR_MAP_LOCKED; ///< rid locked by pending txn - - // EFP errors - static const uint32_t JERR_EFP_BADPARTITIONNAME; ///< Partition name invalid or of value 0 - static const uint32_t JERR_EFP_BADEFPDIRNAME; ///< Empty File Pool directory name invalid - static const uint32_t JERR_EFP_BADPARTITIONDIR; ///< Invalid partition directory - static const uint32_t JERR_EFP_NOEFP; ///< No EFP found for given partition and file size - static const uint32_t JERR_EFP_EMPTY; ///< EFP empty - static const uint32_t JERR_EFP_LSTAT; ///< lstat operation failed - static const uint32_t JERR_EFP_BADFILETYPE; ///< Bad file type - static const uint32_t JERR_EFP_FOPEN; ///< Unable to fopen file for write - static const uint32_t JERR_EFP_FWRITE; ///< Write failed - static const uint32_t JERR_EFP_MKDIR; ///< Directory creation failed - - // Negative returns for some functions - static const int32_t AIO_TIMEOUT; ///< Timeout waiting for AIO return - static const int32_t LOCK_TAKEN; ///< Attempted to take lock, but it was taken by another thread - /** - * \brief Method to access error message from known error number. - */ - static const char* err_msg(const uint32_t err_no) throw (); - - private: - /** - * \brief Static function to initialize map. - */ - static bool __init(); - }; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_JERRNO_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/jexception.cpp b/qpid/cpp/src/qpid/linearstore/journal/jexception.cpp deleted file mode 100644 index 49f486746a..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jexception.cpp +++ /dev/null @@ -1,168 +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/linearstore/journal/jexception.h" - -#include - -#define CATLEN(p) MAX_MSG_SIZE - std::strlen(p) - 1 - -namespace qpid { -namespace linearstore { -namespace journal { - -jexception::jexception() throw (): - std::exception(), - _err_code(0) -{ - format(); -} - -jexception::jexception(const uint32_t err_code) throw (): - std::exception(), - _err_code(err_code) -{ - format(); -} - -jexception::jexception(const char* additional_info) throw (): - std::exception(), - _err_code(0), - _additional_info(additional_info) -{ - format(); -} - -jexception::jexception(const std::string& additional_info) throw (): - std::exception(), - _err_code(0), - _additional_info(additional_info) -{ - format(); -} - -jexception::jexception(const uint32_t err_code, const char* additional_info) throw (): - std::exception(), - _err_code(err_code), - _additional_info(additional_info) -{ - format(); -} - -jexception::jexception(const uint32_t err_code, const std::string& additional_info) throw (): - std::exception(), - _err_code(err_code), - _additional_info(additional_info) -{ - format(); -} - -jexception::jexception(const uint32_t err_code, const char* throwing_class, - const char* throwing_fn) throw (): - std::exception(), - _err_code(err_code), - _throwing_class(throwing_class), - _throwing_fn(throwing_fn) -{ - format(); -} - -jexception::jexception(const uint32_t err_code, const std::string& throwing_class, - const std::string& throwing_fn) throw (): - std::exception(), - _err_code(err_code), - _throwing_class(throwing_class), - _throwing_fn(throwing_fn) -{ - format(); -} - -jexception::jexception(const uint32_t err_code, const char* additional_info, - const char* throwing_class, const char* throwing_fn) throw (): - std::exception(), - _err_code(err_code), - _additional_info(additional_info), - _throwing_class(throwing_class), - _throwing_fn(throwing_fn) -{ - format(); -} - -jexception::jexception(const uint32_t err_code, const std::string& additional_info, - const std::string& throwing_class, const std::string& throwing_fn) throw (): - std::exception(), - _err_code(err_code), - _additional_info(additional_info), - _throwing_class(throwing_class), - _throwing_fn(throwing_fn) -{ - format(); -} - -jexception::~jexception() throw () -{} - -void -jexception::format() -{ - const bool ai = !_additional_info.empty(); - const bool tc = !_throwing_class.empty(); - const bool tf = !_throwing_fn.empty(); - std::ostringstream oss; - oss << "jexception 0x" << std::hex << std::setfill('0') << std::setw(4) << _err_code << " "; - if (tc) - { - oss << _throwing_class; - if (tf) - oss << "::"; - else - oss << " "; - } - if (tf) - oss << _throwing_fn << "() "; - if (tc || tf) - oss << "threw " << jerrno::err_msg(_err_code); - if (ai) - oss << " (" << _additional_info << ")"; - _what.assign(oss.str()); -} - -const char* -jexception::what() const throw () -{ - return _what.c_str(); -} - -std::ostream& -operator<<(std::ostream& os, const jexception& je) -{ - os << je.what(); - return os; -} - -std::ostream& -operator<<(std::ostream& os, const jexception* jePtr) -{ - os << jePtr->what(); - return os; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/jexception.h b/qpid/cpp/src/qpid/linearstore/journal/jexception.h deleted file mode 100644 index d03ee32e3f..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jexception.h +++ /dev/null @@ -1,125 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_JEXCEPTION_H -#define QPID_LINEARSTORE_JOURNAL_JEXCEPTION_H - -namespace qpid { -namespace linearstore { -namespace journal { -class jexception; -}}} - -#include -#include -#include -#include -#include -#include "qpid/linearstore/journal/jerrno.h" -#include -#include - -// Macro for formatting commom system errors -#define FORMAT_SYSERR(errno) " errno=" << errno << " (" << std::strerror(errno) << ")" - -#define MALLOC_CHK(ptr, var, cls, fn) if(ptr == 0) { \ - clean(); \ - std::ostringstream oss; \ - oss << var << ": malloc() failed: " << FORMAT_SYSERR(errno); \ - throw jexception(jerrno::JERR__MALLOC, oss.str(), cls, fn); \ - } - -// TODO: The following is a temporary bug-tracking aid which forces a core. -// Replace with the commented out version below when BZ484048 is resolved. -#define PTHREAD_CHK(err, pfn, cls, fn) if(err != 0) { \ - std::ostringstream oss; \ - oss << cls << "::" << fn << "(): " << pfn; \ - errno = err; \ - ::perror(oss.str().c_str()); \ - ::abort(); \ - } -/* -#define PTHREAD_CHK(err, pfn, cls, fn) if(err != 0) { \ - std::ostringstream oss; \ - oss << pfn << " failed: " << FORMAT_SYSERR(err); \ - throw jexception(jerrno::JERR__PTHREAD, oss.str(), cls, fn); \ - } -*/ - -#define ASSERT(cond, msg) if(cond == 0) { \ - std::cerr << msg << std::endl; \ - ::abort(); \ - } - -namespace qpid { -namespace linearstore { -namespace journal { - - /** - * \class jexception - * \brief Generic journal exception class - */ - class jexception : public std::exception - { - private: - uint32_t _err_code; - std::string _additional_info; - std::string _throwing_class; - std::string _throwing_fn; - std::string _what; - void format(); - - public: - jexception() throw (); - - jexception(const uint32_t err_code) throw (); - - jexception(const char* additional_info) throw (); - jexception(const std::string& additional_info) throw (); - - jexception(const uint32_t err_code, const char* additional_info) throw (); - jexception(const uint32_t err_code, const std::string& additional_info) throw (); - - jexception(const uint32_t err_code, const char* throwing_class, const char* throwing_fn) - throw (); - jexception(const uint32_t err_code, const std::string& throwing_class, - const std::string& throwing_fn) throw (); - - jexception(const uint32_t err_code, const char* additional_info, - const char* throwing_class, const char* throwing_fn) throw (); - jexception(const uint32_t err_code, const std::string& additional_info, - const std::string& throwing_class, const std::string& throwing_fn) throw (); - - virtual ~jexception() throw (); - virtual const char* what() const throw (); // override std::exception::what() - - inline uint32_t err_code() const throw () { return _err_code; } - inline const std::string additional_info() const throw () { return _additional_info; } - inline const std::string throwing_class() const throw () { return _throwing_class; } - inline const std::string throwing_fn() const throw () { return _throwing_fn; } - - friend std::ostream& operator<<(std::ostream& os, const jexception& je); - friend std::ostream& operator<<(std::ostream& os, const jexception* jePtr); - }; // class jexception - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_JEXCEPTION_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/jrec.h b/qpid/cpp/src/qpid/linearstore/journal/jrec.h deleted file mode 100644 index cad0e5d7a2..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/jrec.h +++ /dev/null @@ -1,122 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_JREC_H -#define QPID_LINEARSTORE_JOURNAL_JREC_H - -#include -#include "qpid/linearstore/journal/jcfg.h" -#include - -struct rec_hdr_t; - -namespace qpid { -namespace linearstore { -namespace journal { - -class Checksum; - -/** -* \class jrec -* \brief Abstract class for all file jrecords, both data and log. This class establishes -* the common data format and structure for these jrecords. -*/ -class jrec -{ -public: - jrec() {} - virtual ~jrec() {} - - /** - * \brief Encode this instance of jrec into the write buffer at the disk-block-aligned - * pointer wptr starting at position rec_offs_dblks in the encoded record to a - * maximum size of max_size_dblks. - * - * This call encodes the content of the data contianed in this instance of jrec into a - * disk-softblock-aligned (defined by JRNL_SBLK_SIZE) buffer pointed to by parameter - * wptr. No more than paramter max_size_dblks data-blocks may be written to the buffer. - * The parameter rec_offs_dblks is the offset in data-blocks within the fully encoded - * data block this instance represents at which to start encoding. - * - * Encoding entails writing the record header (struct enq_hdr), the data and the record tail - * (struct enq_tail). The record must be data-block-aligned (defined by JRNL_DBLK_SIZE), - * thus any remaining space in the final data-block is ignored; the returned value is the - * number of data-blocks consumed from the page by the encode action. Provided the initial - * alignment requirements are met, records may be of arbitrary size and may span multiple - * data-blocks, disk-blocks and/or pages. - * - * Since the record size in data-blocks is known, the general usage pattern is to call - * encode() as many times as is needed to fully encode the data. Each call to encode() - * will encode as much of the record as it can to what remains of the current page cache, - * and will return the number of data-blocks actually encoded. - * - * Example: Assume that record r1 was previously written to page 0, and that this - * is an instance representing record r2. Being larger than the page size ps, r2 would span - * multiple pages as follows: - *
-    *       |<---ps--->|
-    *       +----------+----------+----------+----...
-    *       |      |r2a|   r2b    |  r2c   | |
-    *       |<-r1-><----------r2---------->  |
-    *       +----------+----------+----------+----...
-    * page:      p0         p1         p2
-    * 
- * Encoding record r2 will require multiple calls to encode; one for each page which - * is involved. Record r2 is divided logically into sections r2a, r2b and r2c at the - * points where the page boundaries intersect with the record. Assuming a page size - * of ps, the page boundary pointers are represented by their names p0, p1... and the - * sizes of the record segments are represented by their names r1, r2a, r2b..., the calls - * should be as follows: - *
-    * encode(p0+r1, 0, ps-r1); (returns r2a data-blocks)
-    * encode(p1, r2a, ps);     (returns r2b data-blocks which equals ps)
-    * encode(p2, r2a+r2b, ps); (returns r2c data-blocks)
-    * 
- * - * \param wptr Data-block-aligned pointer to position in page buffer where encoding is to - * take place. - * \param rec_offs_dblks Offset in data-blocks within record from which to start encoding. - * \param max_size_dblks Maximum number of data-blocks to write to pointer wptr. - * \returns Number of data-blocks encoded. - */ - virtual uint32_t encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum) = 0; - virtual bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start) = 0; - - virtual std::string& str(std::string& str) const = 0; - virtual std::size_t data_size() const = 0; - virtual std::size_t xid_size() const = 0; - virtual std::size_t rec_size() const = 0; - inline virtual uint32_t rec_size_dblks() const { return size_dblks(rec_size()); } - static inline uint32_t size_dblks(const std::size_t size) - { return size_blks(size, QLS_DBLK_SIZE_BYTES); } - static inline uint32_t size_sblks(const std::size_t size) - { return size_blks(size, QLS_SBLK_SIZE_BYTES); } - static inline uint32_t size_blks(const std::size_t size, const std::size_t blksize) - { return (size + blksize - 1)/blksize; } - virtual uint64_t rid() const = 0; - -protected: - virtual void clean() = 0; -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JRNL_JREC_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/pmgr.cpp b/qpid/cpp/src/qpid/linearstore/journal/pmgr.cpp deleted file mode 100644 index 764beaa879..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/pmgr.cpp +++ /dev/null @@ -1,192 +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/linearstore/journal/pmgr.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -pmgr::page_cb::page_cb(uint16_t index): - _index(index), - _state(UNUSED), - _frid(0), - _wdblks(0), - _pdtokl(0), - _jfp(0), - _pbuff(0) -{} - -// TODO: almost identical to pmgr::page_state_str() below - resolve -const char* -pmgr::page_cb::state_str() const -{ - switch(_state) - { - case UNUSED: - return "UNUSED"; - case IN_USE: - return "IN_USE"; - case AIO_PENDING: - return "AIO_PENDING"; - } - return ""; -} - -// static -const uint32_t pmgr::_sblkSizeBytes = QLS_SBLK_SIZE_BYTES; - -pmgr::pmgr(jcntl* jc, enq_map& emap, txn_map& tmap): - _cache_pgsize_sblks(0), - _cache_num_pages(0), - _jc(jc), - _emap(emap), - _tmap(tmap), - _page_base_ptr(0), - _page_ptr_arr(0), - _page_cb_arr(0), - _aio_cb_arr(0), - _aio_event_arr(0), - _ioctx(0), - _pg_index(0), - _pg_cntr(0), - _pg_offset_dblks(0), - _aio_evt_rem(0), - _cbp(0), - _enq_rec(), - _deq_rec(), - _txn_rec() -{} - -pmgr::~pmgr() -{ - pmgr::clean(); -} - -void -pmgr::initialize(aio_callback* const cbp, const uint32_t cache_pgsize_sblks, const uint16_t cache_num_pages) -{ - // As static use of this class keeps old values around, clean up first... - pmgr::clean(); - _pg_index = 0; - _pg_cntr = 0; - _pg_offset_dblks = 0; - _aio_evt_rem = 0; - _cache_pgsize_sblks = cache_pgsize_sblks; - _cache_num_pages = cache_num_pages; - _cbp = cbp; - - // 1. Allocate page memory (as a single block) - std::size_t cache_pgsize = _cache_num_pages * _cache_pgsize_sblks * _sblkSizeBytes; - if (::posix_memalign(&_page_base_ptr, QLS_AIO_ALIGN_BOUNDARY_BYTES, cache_pgsize)) - { - clean(); - std::ostringstream oss; - oss << "posix_memalign(): alignment=" << QLS_AIO_ALIGN_BOUNDARY_BYTES << " size=" << cache_pgsize; - oss << FORMAT_SYSERR(errno); - throw jexception(jerrno::JERR__MALLOC, oss.str(), "pmgr", "initialize"); - } - - // 2. Allocate array of page pointers - _page_ptr_arr = (void**)std::malloc(_cache_num_pages * sizeof(void*)); - MALLOC_CHK(_page_ptr_arr, "_page_ptr_arr", "pmgr", "initialize"); - - // 3. Allocate and initialize page control block (page_cb) array - _page_cb_arr = (page_cb*)std::malloc(_cache_num_pages * sizeof(page_cb)); - MALLOC_CHK(_page_cb_arr, "_page_cb_arr", "pmgr", "initialize"); - std::memset(_page_cb_arr, 0, _cache_num_pages * sizeof(page_cb)); - - // 4. Allocate IO control block (iocb) array - _aio_cb_arr = (aio_cb*)std::malloc(_cache_num_pages * sizeof(aio_cb)); - MALLOC_CHK(_aio_cb_arr, "_aio_cb_arr", "pmgr", "initialize"); - - // 5. Set page pointers in _page_ptr_arr, _page_cb_arr and iocbs to pages within page block - for (uint16_t i=0; i<_cache_num_pages; i++) - { - _page_ptr_arr[i] = (void*)((char*)_page_base_ptr + _cache_pgsize_sblks * _sblkSizeBytes * i); - _page_cb_arr[i]._index = i; - _page_cb_arr[i]._state = UNUSED; - _page_cb_arr[i]._pbuff = _page_ptr_arr[i]; - _page_cb_arr[i]._pdtokl = new std::deque; - _page_cb_arr[i]._pdtokl->clear(); - _aio_cb_arr[i].data = (void*)&_page_cb_arr[i]; - } - - // 6. Allocate io_event array, max one event per cache page plus one for each file - const uint16_t max_aio_evts = _cache_num_pages + 1; // One additional event for file header writes - _aio_event_arr = (aio_event*)std::malloc(max_aio_evts * sizeof(aio_event)); - MALLOC_CHK(_aio_event_arr, "_aio_event_arr", "pmgr", "initialize"); - - // 7. Initialize AIO context - if (int ret = aio::queue_init(max_aio_evts, &_ioctx)) - { - std::ostringstream oss; - oss << "io_queue_init() failed: " << FORMAT_SYSERR(-ret); - throw jexception(jerrno::JERR__AIO, oss.str(), "pmgr", "initialize"); - } -} - -void -pmgr::clean() -{ - // Clean up allocated memory here - - if (_ioctx) - aio::queue_release(_ioctx); - - std::free(_page_base_ptr); - _page_base_ptr = 0; - - if (_page_cb_arr) - { - for (int i=0; i<_cache_num_pages; i++) - delete _page_cb_arr[i]._pdtokl; - std::free(_page_ptr_arr); - _page_ptr_arr = 0; - } - - std::free(_page_cb_arr); - _page_cb_arr = 0; - - std::free(_aio_cb_arr); - _aio_cb_arr = 0; - - std::free(_aio_event_arr); - _aio_event_arr = 0; -} - -// TODO: almost identical to pmgr::page_cb::state_str() above - resolve -const char* -pmgr::page_state_str(page_state ps) -{ - switch (ps) - { - case UNUSED: - return "UNUSED"; - case IN_USE: - return "IN_USE"; - case AIO_PENDING: - return "AIO_PENDING"; - } - return ""; -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/pmgr.h b/qpid/cpp/src/qpid/linearstore/journal/pmgr.h deleted file mode 100644 index e618397647..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/pmgr.h +++ /dev/null @@ -1,119 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_PMGR_H -#define QPID_LINEARSTORE_JOURNAL_PMGR_H - -#include -#include "qpid/linearstore/journal/aio.h" -#include "qpid/linearstore/journal/deq_rec.h" -#include "qpid/linearstore/journal/enq_map.h" -#include "qpid/linearstore/journal/enq_rec.h" -#include "qpid/linearstore/journal/txn_map.h" -#include "qpid/linearstore/journal/txn_rec.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -class aio_callback; -class data_tok; -class jcntl; -class JournalFile; - -/** -* \brief Abstract class for managing either read or write page cache of arbitrary size and -* number of cache_num_pages. -*/ -class pmgr -{ -public: - /** - * \brief Enumeration of possible stats of a page within a page cache. - */ - enum page_state - { - UNUSED, ///< A page is uninitialized, contains no data. - IN_USE, ///< Page is in use. - AIO_PENDING ///< An AIO request outstanding. - }; - - /** - * \brief Page control block, carries control and state information for each page in the - * cache. - */ - struct page_cb - { - uint16_t _index; ///< Index of this page - page_state _state; ///< Status of page - uint64_t _frid; ///< First rid in page (used for fhdr init) - uint32_t _wdblks; ///< Total number of dblks in page so far - std::deque* _pdtokl; ///< Page message tokens list - JournalFile* _jfp; ///< Journal file for incrementing compl counts - void* _pbuff; ///< Page buffer - - page_cb(uint16_t index); ///< Convenience constructor - const char* state_str() const; ///< Return state as string for this pcb - }; - -protected: - static const uint32_t _sblkSizeBytes; ///< Disk softblock size - uint32_t _cache_pgsize_sblks; ///< Size of page cache cache_num_pages - uint16_t _cache_num_pages; ///< Number of page cache cache_num_pages - jcntl* _jc; ///< Pointer to journal controller - enq_map& _emap; ///< Ref to enqueue map - txn_map& _tmap; ///< Ref to transaction map - void* _page_base_ptr; ///< Base pointer to page memory - void** _page_ptr_arr; ///< Array of pointers to cache_num_pages in page memory - page_cb* _page_cb_arr; ///< Array of page_cb structs - aio_cb* _aio_cb_arr; ///< Array of iocb structs - aio_event* _aio_event_arr; ///< Array of io_events - io_context_t _ioctx; ///< AIO context for read/write operations - uint16_t _pg_index; ///< Index of current page being used - uint32_t _pg_cntr; ///< Page counter; determines if file rotation req'd - uint32_t _pg_offset_dblks; ///< Page offset (used so far) in data blocks - uint32_t _aio_evt_rem; ///< Remaining AIO events - aio_callback* _cbp; ///< Pointer to callback object - - enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding - deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding - txn_rec _txn_rec; ///< Transaction record used for encoding/decoding - -public: - pmgr(jcntl* jc, enq_map& emap, txn_map& tmap); - virtual ~pmgr(); - - virtual int32_t get_events(timespec* const timeout, bool flush) = 0; - inline uint32_t get_aio_evt_rem() const { return _aio_evt_rem; } - static const char* page_state_str(page_state ps); - inline uint32_t cache_pgsize_sblks() const { return _cache_pgsize_sblks; } - inline uint16_t cache_num_pages() const { return _cache_num_pages; } - -protected: - virtual void initialize(aio_callback* const cbp, const uint32_t cache_pgsize_sblks, - const uint16_t cache_num_pages); - virtual void rotate_page() = 0; - virtual void clean(); -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_PMGR_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/slock.h b/qpid/cpp/src/qpid/linearstore/journal/slock.h deleted file mode 100644 index 12e9e2d08c..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/slock.h +++ /dev/null @@ -1,71 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_SLOCK_H -#define QPID_LINEARSTORE_JOURNAL_SLOCK_H - -#include "qpid/linearstore/journal/smutex.h" -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -// Ultra-simple scoped lock class, auto-releases mutex when it goes out-of-scope -class slock -{ -protected: - const smutex& _sm; -public: - inline slock(const smutex& sm) : _sm(sm) - { - PTHREAD_CHK(::pthread_mutex_lock(_sm.get()), "::pthread_mutex_lock", "slock", "slock"); - } - inline ~slock() - { - PTHREAD_CHK(::pthread_mutex_unlock(_sm.get()), "::pthread_mutex_unlock", "slock", "~slock"); - } -}; - -// Ultra-simple scoped try-lock class, auto-releases mutex when it goes out-of-scope -class stlock -{ -protected: - const smutex& _sm; - bool _locked; -public: - inline stlock(const smutex& sm) : _sm(sm), _locked(false) - { - int ret = ::pthread_mutex_trylock(_sm.get()); - _locked = (ret == 0); // check if lock obtained - if (!_locked && ret != EBUSY) PTHREAD_CHK(ret, "::pthread_mutex_trylock", "stlock", "stlock"); - } - inline ~stlock() - { - if (_locked) - PTHREAD_CHK(::pthread_mutex_unlock(_sm.get()), "::pthread_mutex_unlock", "stlock", "~stlock"); - } - inline bool locked() const { return _locked; } -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_SLOCK_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/smutex.h b/qpid/cpp/src/qpid/linearstore/journal/smutex.h deleted file mode 100644 index b43f55944c..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/smutex.h +++ /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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_SMUTEX_H -#define QPID_LINEARSTORE_JOURNAL_SMUTEX_H - -#include "qpid/linearstore/journal/jexception.h" -#include - -namespace qpid { -namespace linearstore { -namespace journal { - - // Ultra-simple scoped mutex class that allows a posix mutex to be initialized and destroyed with error checks - class smutex - { - protected: - mutable pthread_mutex_t _m; - public: - inline smutex() - { - PTHREAD_CHK(::pthread_mutex_init(&_m, 0), "::pthread_mutex_init", "smutex", "smutex"); - } - inline virtual ~smutex() - { - PTHREAD_CHK(::pthread_mutex_destroy(&_m), "::pthread_mutex_destroy", "smutex", "~smutex"); - } - inline pthread_mutex_t* get() const { return &_m; } - }; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_SMUTEX_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/time_ns.cpp b/qpid/cpp/src/qpid/linearstore/journal/time_ns.cpp deleted file mode 100644 index 39f2cd1d88..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/time_ns.cpp +++ /dev/null @@ -1,41 +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/linearstore/journal/time_ns.h" - -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -const std::string -time_ns::str(int precision) const -{ - const double t = tv_sec + (tv_nsec/1e9); - std::ostringstream oss; - oss.setf(std::ios::fixed, std::ios::floatfield); - oss.precision(precision); - oss << t; - return oss.str(); -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/time_ns.h b/qpid/cpp/src/qpid/linearstore/journal/time_ns.h deleted file mode 100644 index a228d47475..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/time_ns.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_TIME_NS_H -#define QPID_LINEARSTORE_JOURNAL_TIME_NS_H - -#include -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -struct time_ns : public timespec -{ - inline time_ns() { tv_sec = 0; tv_nsec = 0; } - inline time_ns(const std::time_t sec, const long nsec = 0) { tv_sec = sec; tv_nsec = nsec; } - inline time_ns(const time_ns& t) { tv_sec = t.tv_sec; tv_nsec = t.tv_nsec; } - - inline void set_zero() { tv_sec = 0; tv_nsec = 0; } - inline bool is_zero() const { return tv_sec == 0 && tv_nsec == 0; } - inline int now() { if(::clock_gettime(CLOCK_REALTIME, this)) return errno; return 0; } - const std::string str(int precision = 6) const; - - inline time_ns& operator=(const time_ns& rhs) - { tv_sec = rhs.tv_sec; tv_nsec = rhs.tv_nsec; return *this; } - inline time_ns& operator+=(const time_ns& rhs) - { - tv_nsec += rhs.tv_nsec; - if (tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } - tv_sec += rhs.tv_sec; - return *this; - } - inline time_ns& operator+=(const long ns) - { - tv_nsec += ns; - if (tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } - return *this; - } - inline time_ns& operator-=(const long ns) - { - tv_nsec -= ns; - if (tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000L; } - return *this; - } - inline time_ns& operator-=(const time_ns& rhs) - { - tv_nsec -= rhs.tv_nsec; - if (tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000L; } - tv_sec -= rhs.tv_sec; - return *this; - } - inline const time_ns operator+(const time_ns& rhs) - { time_ns t(*this); t += rhs; return t; } - inline const time_ns operator-(const time_ns& rhs) - { time_ns t(*this); t -= rhs; return t; } - inline bool operator==(const time_ns& rhs) - { return tv_sec == rhs.tv_sec && tv_nsec == rhs.tv_nsec; } - inline bool operator!=(const time_ns& rhs) - { return tv_sec != rhs.tv_sec || tv_nsec != rhs.tv_nsec; } - inline bool operator>(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec > rhs.tv_nsec; return tv_sec > rhs.tv_sec; } - inline bool operator>=(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec >= rhs.tv_nsec; return tv_sec >= rhs.tv_sec; } - inline bool operator<(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec < rhs.tv_nsec; return tv_sec < rhs.tv_sec; } - inline bool operator<=(const time_ns& rhs) - { if(tv_sec == rhs.tv_sec) return tv_nsec <= rhs.tv_nsec; return tv_sec <= rhs.tv_sec; } -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_TIME_NS_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/txn_map.cpp b/qpid/cpp/src/qpid/linearstore/journal/txn_map.cpp deleted file mode 100644 index 8336d36b80..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/txn_map.cpp +++ /dev/null @@ -1,263 +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/linearstore/journal/txn_map.h" - -#include "qpid/linearstore/journal/slock.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -// return/error codes -int16_t txn_map::TMAP_RID_NOT_FOUND = -2; -int16_t txn_map::TMAP_XID_NOT_FOUND = -1; -int16_t txn_map::TMAP_OK = 0; -int16_t txn_map::TMAP_NOT_SYNCED = 0; -int16_t txn_map::TMAP_SYNCED = 1; - -txn_data_t::txn_data_t(const uint64_t rid, - const uint64_t drid, - const uint64_t fid, - const uint64_t foffs, - const bool enq_flag, - const bool tpc_flag, - const bool commit_flag): - rid_(rid), - drid_(drid), - fid_(fid), - foffs_(foffs), - enq_flag_(enq_flag), - tpc_flag_(tpc_flag), - commit_flag_(commit_flag), - aio_compl_(false) -{} - -txn_op_stats_t::txn_op_stats_t(const txn_data_list_t& tdl) : - enqCnt(0U), - deqCnt(0U), - tpcCnt(0U), - abortCnt(0U), - commitCnt(0U), - rid(0ULL) -{ - for (tdl_const_itr_t i=tdl.begin(); i!=tdl.end(); ++i) { - if (i->enq_flag_) { - ++enqCnt; - rid = i->rid_; - } else { - ++deqCnt; - if (i->commit_flag_) { - ++commitCnt; - } else { - ++abortCnt; - } - } - if (i->tpc_flag_) { - ++tpcCnt; - } - } - if (tpcCnt > 0 && tpcCnt != tdl.size()) { - throw jexception("Inconsistent 2PC count"); // TODO: complete exception details - } - if (abortCnt > 0 && commitCnt > 0) { - throw jexception("Both abort and commit in same transaction"); // TODO: complete exception details - } -} - -txn_map::txn_map(): - _map()/*, - _pfid_txn_cnt()*/ -{} - -txn_map::~txn_map() {} - -bool -txn_map::insert_txn_data(const std::string& xid, const txn_data_t& td) -{ - bool ok = true; - slock s(_mutex); - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // not found in map - { - txn_data_list_t list; - list.push_back(td); - std::pair ret = _map.insert(xmap_param(xid, list)); - if (!ret.second) // duplicate - ok = false; - } - else - itr->second.push_back(td); - return ok; -} - -const txn_data_list_t -txn_map::get_tdata_list(const std::string& xid) -{ - slock s(_mutex); - return get_tdata_list_nolock(xid); -} - -const txn_data_list_t -txn_map::get_tdata_list_nolock(const std::string& xid) -{ - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // not found in map - return _empty_data_list; - return itr->second; -} - -const txn_data_list_t -txn_map::get_remove_tdata_list(const std::string& xid) -{ - slock s(_mutex); - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // not found in map - return _empty_data_list; - txn_data_list_t list = itr->second; - _map.erase(itr); - return list; -} - -bool -txn_map::in_map(const std::string& xid) -{ - slock s(_mutex); - xmap_itr itr= _map.find(xid); - return itr != _map.end(); -} - -uint32_t -txn_map::enq_cnt() -{ - return cnt(true); -} - -uint32_t -txn_map::deq_cnt() -{ - return cnt(true); -} - -uint32_t -txn_map::cnt(const bool enq_flag) -{ - slock s(_mutex); - uint32_t c = 0; - for (xmap_itr i = _map.begin(); i != _map.end(); i++) - { - for (tdl_itr_t j = i->second.begin(); j < i->second.end(); j++) - { - if (j->enq_flag_ == enq_flag) - c++; - } - } - return c; -} - -int16_t -txn_map::is_txn_synced(const std::string& xid) -{ - slock s(_mutex); - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // not found in map - return TMAP_XID_NOT_FOUND; - bool is_synced = true; - for (tdl_itr_t litr = itr->second.begin(); litr < itr->second.end(); litr++) - { - if (!litr->aio_compl_) - { - is_synced = false; - break; - } - } - return is_synced ? TMAP_SYNCED : TMAP_NOT_SYNCED; -} - -int16_t -txn_map::set_aio_compl(const std::string& xid, const uint64_t rid) -{ - slock s(_mutex); - xmap_itr itr = _map.find(xid); - if (itr == _map.end()) // xid not found in map - return TMAP_XID_NOT_FOUND; - for (tdl_itr_t litr = itr->second.begin(); litr < itr->second.end(); litr++) - { - if (litr->rid_ == rid) - { - litr->aio_compl_ = true; - return TMAP_OK; // rid found - } - } - // xid present, but rid not found - return TMAP_RID_NOT_FOUND; -} - -bool -txn_map::data_exists(const std::string& xid, const uint64_t rid) -{ - bool found = false; - { - slock s(_mutex); - txn_data_list_t tdl = get_tdata_list_nolock(xid); - tdl_itr_t itr = tdl.begin(); - while (itr != tdl.end() && !found) - { - found = itr->rid_ == rid; - itr++; - } - } - return found; -} - -bool -txn_map::is_enq(const uint64_t rid) -{ - bool found = false; - { - slock s(_mutex); - for (xmap_itr i = _map.begin(); i != _map.end() && !found; i++) - { - txn_data_list_t list = i->second; - for (tdl_itr_t j = list.begin(); j < list.end() && !found; j++) - { - if (j->enq_flag_) - found = j->rid_ == rid; - else - found = j->drid_ == rid; - } - } - } - return found; -} - -void -txn_map::xid_list(std::vector& xv) -{ - xv.clear(); - { - slock s(_mutex); - for (xmap_itr itr = _map.begin(); itr != _map.end(); itr++) - xv.push_back(itr->first); - } -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/txn_map.h b/qpid/cpp/src/qpid/linearstore/journal/txn_map.h deleted file mode 100644 index e79c0522d8..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/txn_map.h +++ /dev/null @@ -1,150 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_TXN_MAP_H -#define QPID_LINEARSTORE_JOURNAL_TXN_MAP_H - -#include "qpid/linearstore/journal/smutex.h" -#include -#include - -namespace qpid { -namespace linearstore { -namespace journal { - - /** - * \struct txn_data_struct - * \brief Struct encapsulating transaction data necessary for processing a transaction - * in the journal once it is closed with either a commit or abort. - */ - typedef struct txn_data_t - { - uint64_t rid_; ///< Record id for this operation - uint64_t drid_; ///< Dequeue record id for this operation - uint64_t fid_; ///< File seq number, to be used when transferring to emap on commit - uint64_t foffs_; ///< Offset in file for this record - bool enq_flag_; ///< If true, enq op, otherwise deq op - bool tpc_flag_; ///< 2PC transaction if true - bool commit_flag_; ///< TPL only: (2PC transactions) Records 2PC complete c/a mode - bool aio_compl_; ///< Initially false, set to true when record AIO returns - txn_data_t(const uint64_t rid, - const uint64_t drid, - const uint64_t fid, - const uint64_t foffs, - const bool enq_flag, - const bool tpc_flag, - const bool commit_flag); - } txn_data_t; - typedef std::vector txn_data_list_t; - typedef txn_data_list_t::iterator tdl_itr_t; - typedef txn_data_list_t::const_iterator tdl_const_itr_t; - - typedef struct txn_op_stats_t - { - uint16_t enqCnt; - uint16_t deqCnt; - uint16_t tpcCnt; - uint16_t abortCnt; - uint16_t commitCnt; - uint64_t rid; - txn_op_stats_t(const txn_data_list_t& tdl); - } txn_op_stats_t; - - /** - * \class txn_map - * \brief Class for storing transaction data for each open (ie not committed or aborted) - * xid in the store. If aborted, records are discarded; if committed, they are - * transferred to the enqueue map. - * - * The data is encapsulated by struct txn_data_struct. A vector containing the information - * for each operation included as part of the same transaction is mapped against the - * xid. - * - * The aio_compl flag is set true as each AIO write operation for the enqueue or dequeue - * returns. Checking that all of these flags are true for a given xid is the mechanism - * used to determine if the transaction is syncronized (through method is_txn_synced()). - * - * On transaction commit, then each operation is handled as follows: - * - * If an enqueue (_enq_flag is true), then the rid and pfid are transferred to the enq_map. - * If a dequeue (_enq_flag is false), then the rid stored in the drid field is used to - * remove the corresponding record from the enq_map. - * - * On transaction abort, then each operation is handled as follows: - * - * If an enqueue (_enq_flag is true), then the data is simply discarded. - * If a dequeue (_enq_flag is false), then the lock for the corresponding enqueue in enq_map - * (if not a part of the same transaction) is removed, and the data discarded. - * - *
-    *   key      data
-    *
-    *   xid1 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   xid2 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   xid3 --- vector< [ rid, drid, pfid, enq_flag, commit_flag, aio_compl ] >
-    *   ...
-    * 
- */ - class txn_map - { - public: - // return/error codes - static int16_t TMAP_RID_NOT_FOUND; - static int16_t TMAP_XID_NOT_FOUND; - static int16_t TMAP_OK; - static int16_t TMAP_NOT_SYNCED; - static int16_t TMAP_SYNCED; - - private: - typedef std::pair xmap_param; - typedef std::map xmap; - typedef xmap::iterator xmap_itr; - - xmap _map; - smutex _mutex; - const txn_data_list_t _empty_data_list; - - public: - txn_map(); - virtual ~txn_map(); - - bool insert_txn_data(const std::string& xid, const txn_data_t& td); - const txn_data_list_t get_tdata_list(const std::string& xid); - const txn_data_list_t get_remove_tdata_list(const std::string& xid); - bool in_map(const std::string& xid); - uint32_t enq_cnt(); - uint32_t deq_cnt(); - int16_t is_txn_synced(const std::string& xid); // -1=xid not found; 0=not synced; 1=synced - int16_t set_aio_compl(const std::string& xid, const uint64_t rid); // -2=rid not found; -1=xid not found; 0=done - bool data_exists(const std::string& xid, const uint64_t rid); - bool is_enq(const uint64_t rid); - inline void clear() { _map.clear(); } - inline bool empty() const { return _map.empty(); } - inline size_t size() const { return _map.size(); } - void xid_list(std::vector& xv); - private: - uint32_t cnt(const bool enq_flag); - const txn_data_list_t get_tdata_list_nolock(const std::string& xid); - }; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_TXN_MAP_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp b/qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp deleted file mode 100644 index 298ab608b1..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp +++ /dev/null @@ -1,305 +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/linearstore/journal/txn_rec.h" - -#include -#include -#include "qpid/linearstore/journal/Checksum.h" -#include "qpid/linearstore/journal/jexception.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -txn_rec::txn_rec(): - _xidp(0), - _xid_buff(0) -{ - ::txn_hdr_init(&_txn_hdr, 0, QLS_JRNL_VERSION, 0, 0, 0, 0); - ::rec_tail_init(&_txn_tail, 0, 0, 0, 0); -} - -txn_rec::~txn_rec() -{ - clean(); -} - -void -txn_rec::reset(const bool commitFlag, const uint64_t serial, const uint64_t rid, const void* const xidp, - const std::size_t xidlen) -{ - _txn_hdr._rhdr._magic = commitFlag ? QLS_TXC_MAGIC : QLS_TXA_MAGIC; - _txn_hdr._rhdr._serial = serial; - _txn_hdr._rhdr._rid = rid; - _txn_hdr._xidsize = xidlen; - _xidp = xidp; - _xid_buff = 0; - _txn_tail._xmagic = ~_txn_hdr._rhdr._magic; - _txn_tail._serial = serial; - _txn_tail._rid = rid; - _txn_tail._checksum = 0UL; -} - -uint32_t -txn_rec::encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum) -{ - assert(wptr != 0); - assert(max_size_dblks > 0); - assert(_xidp != 0 && _txn_hdr._xidsize > 0); - - std::size_t rec_offs = rec_offs_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t rem = max_size_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t wr_cnt = 0; - if (rec_offs_dblks) // Continuation of split dequeue record (over 2 or more pages) - { - if (size_dblks(rec_size()) - rec_offs_dblks > max_size_dblks) // Further split required - { - rec_offs -= sizeof(txn_hdr_t); - std::size_t wsize = _txn_hdr._xidsize > rec_offs ? _txn_hdr._xidsize - rec_offs : 0; - std::size_t wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= _txn_hdr._xidsize - wsize2; - checksum.addData((unsigned char*)wptr, wr_cnt); - if (rem) - { - _txn_tail._checksum = checksum.getChecksum(); - wsize = sizeof(_txn_tail) > rec_offs ? sizeof(_txn_tail) - rec_offs : 0; - wsize2 = wsize; - if (wsize) - { - if (wsize > rem) - wsize = rem; - std::memcpy((char*)wptr + wr_cnt, (char*)&_txn_tail + rec_offs, wsize); - wr_cnt += wsize; - rem -= wsize; - } - rec_offs -= sizeof(_txn_tail) - wsize2; - } - assert(rem == 0); - assert(rec_offs == 0); - } - else // No further split required - { - rec_offs -= sizeof(txn_hdr_t); - std::size_t wsize = _txn_hdr._xidsize > rec_offs ? _txn_hdr._xidsize - rec_offs : 0; - if (wsize) - { - std::memcpy(wptr, (const char*)_xidp + rec_offs, wsize); - wr_cnt += wsize; - checksum.addData((unsigned char*)wptr, wr_cnt); - } - rec_offs -= _txn_hdr._xidsize - wsize; - _txn_tail._checksum = checksum.getChecksum(); - wsize = sizeof(_txn_tail) > rec_offs ? sizeof(_txn_tail) - rec_offs : 0; - if (wsize) - { - std::memcpy((char*)wptr + wr_cnt, (char*)&_txn_tail + rec_offs, wsize); - wr_cnt += wsize; -#ifdef QLS_CLEAN - std::size_t rec_offs = rec_offs_dblks * QLS_DBLK_SIZE_BYTES; - std::size_t dblk_rec_size = size_dblks(rec_size() - rec_offs) * QLS_DBLK_SIZE_BYTES; - std::memset((char*)wptr + wr_cnt, QLS_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - rec_offs -= sizeof(_txn_tail) - wsize; - assert(rec_offs == 0); - } - } - else // Start at beginning of data record - { - // Assumption: the header will always fit into the first dblk - std::memcpy(wptr, (void*)&_txn_hdr, sizeof(txn_hdr_t)); - wr_cnt = sizeof(txn_hdr_t); - if (size_dblks(rec_size()) > max_size_dblks) // Split required - { - std::size_t wsize; - rem -= sizeof(txn_hdr_t); - if (rem) - { - wsize = rem >= _txn_hdr._xidsize ? _txn_hdr._xidsize : rem; - std::memcpy((char*)wptr + wr_cnt, _xidp, wsize); - wr_cnt += wsize; - rem -= wsize; - } - checksum.addData((unsigned char*)wptr, wr_cnt); - if (rem) - { - _txn_tail._checksum = checksum.getChecksum(); - wsize = rem >= sizeof(_txn_tail) ? sizeof(_txn_tail) : rem; - std::memcpy((char*)wptr + wr_cnt, (void*)&_txn_tail, wsize); - wr_cnt += wsize; - rem -= wsize; - } - assert(rem == 0); - } - else // No split required - { - std::memcpy((char*)wptr + wr_cnt, _xidp, _txn_hdr._xidsize); - wr_cnt += _txn_hdr._xidsize; - checksum.addData((unsigned char*)wptr, wr_cnt); - _txn_tail._checksum = checksum.getChecksum(); - std::memcpy((char*)wptr + wr_cnt, (void*)&_txn_tail, sizeof(_txn_tail)); - wr_cnt += sizeof(_txn_tail); -#ifdef QLS_CLEAN - std::size_t dblk_rec_size = size_dblks(rec_size()) * QLS_DBLK_SIZE_BYTES; - std::memset((char*)wptr + wr_cnt, QLS_CLEAN_CHAR, dblk_rec_size - wr_cnt); -#endif - } - } - return size_dblks(wr_cnt); -} - -bool -txn_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start) -{ - if (rec_offs == 0) - { - // Read header, allocate for xid - ::rec_hdr_copy(&_txn_hdr._rhdr, &h); - ifsp->read((char*)&_txn_hdr._xidsize, sizeof(_txn_hdr._xidsize)); - rec_offs = sizeof(::txn_hdr_t); - _xid_buff = std::malloc(_txn_hdr._xidsize); - MALLOC_CHK(_xid_buff, "_buff", "txn_rec", "rcv_decode"); - } - if (rec_offs < sizeof(txn_hdr_t) + _txn_hdr._xidsize) - { - // Read xid (or continue reading xid) - std::size_t offs = rec_offs - sizeof(txn_hdr_t); - ifsp->read((char*)_xid_buff + offs, _txn_hdr._xidsize - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < _txn_hdr._xidsize - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - } - if (rec_offs < sizeof(txn_hdr_t) + _txn_hdr._xidsize + sizeof(rec_tail_t)) - { - // Read tail (or continue reading tail) - std::size_t offs = rec_offs - sizeof(txn_hdr_t) - _txn_hdr._xidsize; - ifsp->read((char*)&_txn_tail + offs, sizeof(rec_tail_t) - offs); - std::size_t size_read = ifsp->gcount(); - rec_offs += size_read; - if (size_read < sizeof(rec_tail_t) - offs) - { - assert(ifsp->eof()); - // As we may have read past eof, turn off fail bit - ifsp->clear(ifsp->rdstate()&(~std::ifstream::failbit)); - assert(!ifsp->fail() && !ifsp->bad()); - return false; - } - check_rec_tail(rec_start); - } - ifsp->ignore(rec_size_dblks() * QLS_DBLK_SIZE_BYTES - rec_size()); - assert(!ifsp->fail() && !ifsp->bad()); - assert(_txn_hdr._xidsize > 0); - return true; -} - -std::size_t -txn_rec::get_xid(void** const xidpp) -{ - if (!_xid_buff) - { - *xidpp = 0; - return 0; - } - *xidpp = _xid_buff; - return _txn_hdr._xidsize; -} - -std::string& -txn_rec::str(std::string& str) const -{ - std::ostringstream oss; - if (_txn_hdr._rhdr._magic == QLS_TXA_MAGIC) - oss << "dtxa_rec: m=" << _txn_hdr._rhdr._magic; - else - oss << "dtxc_rec: m=" << _txn_hdr._rhdr._magic; - oss << " v=" << (int)_txn_hdr._rhdr._version; - oss << " rid=" << _txn_hdr._rhdr._rid; - oss << " xid=\"" << _xidp << "\""; - str.append(oss.str()); - return str; -} - -std::size_t -txn_rec::xid_size() const -{ - return _txn_hdr._xidsize; -} - -std::size_t -txn_rec::rec_size() const -{ - return sizeof(txn_hdr_t) + _txn_hdr._xidsize + sizeof(rec_tail_t); -} - -void -txn_rec::check_rec_tail(const std::streampos rec_start) const { - Checksum checksum; - checksum.addData((const unsigned char*)&_txn_hdr, sizeof(::txn_hdr_t)); - if (_txn_hdr._xidsize > 0) { - checksum.addData((const unsigned char*)_xid_buff, _txn_hdr._xidsize); - } - uint32_t cs = checksum.getChecksum(); - uint16_t res = ::rec_tail_check(&_txn_tail, &_txn_hdr._rhdr, cs); - if (res != 0) { - std::stringstream oss; - oss << std::endl << " Record offset: 0x" << std::hex << rec_start; - if (res & ::REC_TAIL_MAGIC_ERR_MASK) { - oss << std::endl << " Magic: expected 0x" << ~_txn_hdr._rhdr._magic << "; found 0x" << _txn_tail._xmagic; - } - if (res & ::REC_TAIL_SERIAL_ERR_MASK) { - oss << std::endl << " Serial: expected 0x" << _txn_hdr._rhdr._serial << "; found 0x" << _txn_tail._serial; - } - if (res & ::REC_TAIL_RID_ERR_MASK) { - oss << std::endl << " Record Id: expected 0x" << _txn_hdr._rhdr._rid << "; found 0x" << _txn_tail._rid; - } - if (res & ::REC_TAIL_CHECKSUM_ERR_MASK) { - oss << std::endl << " Checksum: expected 0x" << cs << "; found 0x" << _txn_tail._checksum; - } - throw jexception(jerrno::JERR_JREC_BADRECTAIL, oss.str(), "txn_rec", "check_rec_tail"); - } -} - -void -txn_rec::clean() -{ - if (_xid_buff) { - std::free(_xid_buff); - _xid_buff = 0; - } -} - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/txn_rec.h b/qpid/cpp/src/qpid/linearstore/journal/txn_rec.h deleted file mode 100644 index 4552071595..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/txn_rec.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_TXN_REC_H -#define QPID_LINEARSTORE_JOURNAL_TXN_REC_H - -#include "qpid/linearstore/journal/jrec.h" -#include "qpid/linearstore/journal/utils/txn_hdr.h" -#include "qpid/linearstore/journal/utils/rec_tail.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -/** -* \class txn_rec -* \brief Class to handle a single journal commit or abort record. -*/ -class txn_rec : public jrec -{ -private: - ::txn_hdr_t _txn_hdr; ///< Local instance of transaction header struct - const void* _xidp; ///< xid pointer for encoding (writing to disk) - void* _xid_buff; ///< Pointer to buffer to receive xid read from disk - ::rec_tail_t _txn_tail; ///< Local instance of enqueue tail struct - -public: - txn_rec(); - virtual ~txn_rec(); - - void reset(const bool commitFlag, const uint64_t serial, const uint64_t rid, const void* const xidp, - const std::size_t xidlen); - uint32_t encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum); - bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start); - - std::size_t get_xid(void** const xidpp); - std::string& str(std::string& str) const; - inline std::size_t data_size() const { return 0; } // This record never carries data - std::size_t xid_size() const; - std::size_t rec_size() const; - inline uint64_t rid() const { return _txn_hdr._rhdr._rid; } - void check_rec_tail(const std::streampos rec_start) const; - -private: - virtual void clean(); -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_TXN_REC_H diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/deq_hdr.c b/qpid/cpp/src/qpid/linearstore/journal/utils/deq_hdr.c deleted file mode 100644 index b55c1c16c8..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/deq_hdr.c +++ /dev/null @@ -1,46 +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 "deq_hdr.h" - -/*static const uint16_t DEQ_HDR_TXNCMPLCOMMIT_MASK = 0x10;*/ - -void deq_hdr_init(deq_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t uflag, - const uint64_t serial, const uint64_t rid, const uint64_t deq_rid, const uint64_t xidsize) { - rec_hdr_init(&dest->_rhdr, magic, version, uflag, serial, rid); - dest->_deq_rid = deq_rid; - dest->_xidsize = xidsize; -} - -void deq_hdr_copy(deq_hdr_t* dest, const deq_hdr_t* src) { - rec_hdr_copy(&dest->_rhdr, &src->_rhdr); - dest->_deq_rid = src->_deq_rid; - dest->_xidsize = src->_xidsize; -} - -bool is_txn_coml_commit(const deq_hdr_t *dh) { - return dh->_rhdr._uflag & DEQ_HDR_TXNCMPLCOMMIT_MASK; -} - -void set_txn_coml_commit(deq_hdr_t *dh, const bool commit) { - dh->_rhdr._uflag = commit ? dh->_rhdr._uflag | DEQ_HDR_TXNCMPLCOMMIT_MASK : // set flag bit - dh->_rhdr._uflag & (~DEQ_HDR_TXNCMPLCOMMIT_MASK); // unset flag bit -} diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/deq_hdr.h b/qpid/cpp/src/qpid/linearstore/journal/utils/deq_hdr.h deleted file mode 100644 index 3392867153..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/deq_hdr.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QPID_LINEARSTORE_JOURNAL_UTILS_DEQ_HDR_H -#define QPID_LINEARSTORE_JOURNAL_UTILS_DEQ_HDR_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 -#include "rec_hdr.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#pragma pack(1) - -/** - * \brief Struct for dequeue record. - * - * Struct for dequeue record. If this record has a non-zero xidsize field (i.e., there is a - * valid XID), then this header is followed by the XID of xidsize bytes and a rec_tail. If, - * on the other hand, this record has a zero xidsize (i.e., there is no XID), then the rec_tail - * is absent. - * - * Note that this record had its own rid distinct from the rid of the record it is dequeueing. - * The rid field below is the rid of the dequeue record itself; the deq-rid field is the rid of a - * previous enqueue record being dequeued by this record. - * - * Record header info in binary format (40 bytes): - *
- *   0                           7
- * +---+---+---+---+---+---+---+---+  -+
- * |     magic     |  ver  | flags |   |
- * +---+---+---+---+---+---+---+---+   |
- * |             serial            |   | struct rec_hdr_t
- * +---+---+---+---+---+---+---+---+   |
- * |              rid              |   |
- * +---+---+---+---+---+---+---+---+  -+
- * |            deq-rid            |
- * +---+---+---+---+---+---+---+---+
- * |            xidsize            |
- * +---+---+---+---+---+---+---+---+
- *
- * deq-rid = dequeue record ID
- * 
- */ -typedef struct deq_hdr_t { - rec_hdr_t _rhdr; /**< Common record header struct */ - uint64_t _deq_rid; /**< Record ID of record being dequeued */ - uint64_t _xidsize; /**< XID size */ -} deq_hdr_t; - -static const uint16_t DEQ_HDR_TXNCMPLCOMMIT_MASK = 0x10; - -void deq_hdr_init(deq_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t uflag, - const uint64_t serial, const uint64_t rid, const uint64_t deq_rid, const uint64_t xidsize); -void deq_hdr_copy(deq_hdr_t* dest, const deq_hdr_t* src); -bool is_txn_coml_commit(const deq_hdr_t *dh); -void set_txn_coml_commit(deq_hdr_t *dh, const bool commit); - -#pragma pack() - -#ifdef __cplusplus -} -#endif - -#endif /* ifndef QPID_LINEARSTORE_JOURNAL_UTILS_DEQ_HDR_H */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/enq_hdr.c b/qpid/cpp/src/qpid/linearstore/journal/utils/enq_hdr.c deleted file mode 100644 index b4e8b62ff1..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/enq_hdr.c +++ /dev/null @@ -1,63 +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 "enq_hdr.h" - -//static const uint16_t ENQ_HDR_TRANSIENT_MASK = 0x10; -//static const uint16_t ENQ_HDR_EXTERNAL_MASK = 0x20; - -void enq_hdr_init(enq_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t uflag, - const uint64_t serial, const uint64_t rid, const uint64_t xidsize, const uint64_t dsize) { - rec_hdr_init(&dest->_rhdr, magic, version, uflag, serial, rid); - dest->_xidsize = xidsize; - dest->_dsize = dsize; -} - -void enq_hdr_copy(enq_hdr_t* dest, const enq_hdr_t* src) { - rec_hdr_copy(&dest->_rhdr, &src->_rhdr); - dest->_xidsize = src->_xidsize; - dest->_dsize = src->_dsize; -} - -bool is_enq_transient(const enq_hdr_t *eh) { - return eh->_rhdr._uflag & ENQ_HDR_TRANSIENT_MASK; -} - -void set_enq_transient(enq_hdr_t *eh, const bool transient) { - eh->_rhdr._uflag = transient ? eh->_rhdr._uflag | ENQ_HDR_TRANSIENT_MASK : - eh->_rhdr._uflag & (~ENQ_HDR_TRANSIENT_MASK); -} - -bool is_enq_external(const enq_hdr_t *eh) { - return eh->_rhdr._uflag & ENQ_HDR_EXTERNAL_MASK; -} - -void set_enq_external(enq_hdr_t *eh, const bool external) { - eh->_rhdr._uflag = external ? eh->_rhdr._uflag | ENQ_HDR_EXTERNAL_MASK : - eh->_rhdr._uflag & (~ENQ_HDR_EXTERNAL_MASK); -} - -bool validate_enq_hdr(enq_hdr_t *eh, const uint32_t magic, const uint16_t version, const uint64_t rid) { - return eh->_rhdr._magic == magic && - eh->_rhdr._version == version && - rid > 0 ? eh->_rhdr._rid == rid /* If rid == 0, don't compare rids */ - : true; -} diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/enq_hdr.h b/qpid/cpp/src/qpid/linearstore/journal/utils/enq_hdr.h deleted file mode 100644 index 00108792bc..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/enq_hdr.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QPID_LINEARSTORE_JOURNAL_UTILS_ENQ_HDR_H -#define QPID_LINEARSTORE_JOURNAL_UTILS_ENQ_HDR_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 -#include "rec_hdr.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#pragma pack(1) - -/** - * \brief Struct for enqueue record. - * - * Struct for enqueue record. In addition to the common data, this header includes both the - * xid and data blob sizes. - * - * This header precedes all enqueue data in journal files. - * - * Record header info in binary format (40 bytes): - *
- *   0                           7
- * +---+---+---+---+---+---+---+---+  -+
- * |     magic     |  ver  | flags |   |
- * +---+---+---+---+---+---+---+---+   |
- * |             serial            |   | struct rec_hdr_t
- * +---+---+---+---+---+---+---+---+   |
- * |              rid              |   |
- * +---+---+---+---+---+---+---+---+  -+
- * |            xidsize            |
- * +---+---+---+---+---+---+---+---+
- * |             dsize             |
- * +---+---+---+---+---+---+---+---+
- * v = file version (If the format or encoding of this file changes, then this
- *     number should be incremented)
- * 
- */ -typedef struct enq_hdr_t { - rec_hdr_t _rhdr; /**< Common record header struct */ - uint64_t _xidsize; /**< XID size in octets */ - uint64_t _dsize; /**< Record data size in octets */ -} enq_hdr_t; - -static const uint16_t ENQ_HDR_TRANSIENT_MASK = 0x10; -static const uint16_t ENQ_HDR_EXTERNAL_MASK = 0x20; - -void enq_hdr_init(enq_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t uflag, - const uint64_t serial, const uint64_t rid, const uint64_t xidsize, const uint64_t dsize); -void enq_hdr_copy(enq_hdr_t* dest, const enq_hdr_t* src); -bool is_enq_transient(const enq_hdr_t *eh); -void set_enq_transient(enq_hdr_t *eh, const bool transient); -bool is_enq_external(const enq_hdr_t *eh); -void set_enq_external(enq_hdr_t *eh, const bool external); -bool validate_enq_hdr(enq_hdr_t *eh, const uint32_t magic, const uint16_t version, const uint64_t rid); - -#pragma pack() - -#ifdef __cplusplus -} -#endif - -#endif /* ifndef QPID_LINEARSTORE_JOURNAL_UTILS_ENQ_HDR_H */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/file_hdr.c b/qpid/cpp/src/qpid/linearstore/journal/utils/file_hdr.c deleted file mode 100644 index 4e6cf1b8fa..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/file_hdr.c +++ /dev/null @@ -1,115 +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 "file_hdr.h" -#include - -void file_hdr_create(file_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t fhdr_size_sblks, - const uint16_t efp_partition, const uint64_t file_size) { - rec_hdr_init(&dest->_rhdr, magic, version, 0, 0, 0); - dest->_fhdr_size_sblks = fhdr_size_sblks; - dest->_efp_partition = efp_partition; - dest->_reserved = 0; - dest->_data_size_kib = file_size; - dest->_fro = 0; - dest->_ts_nsec = 0; - dest->_ts_sec = 0; - dest->_file_number = 0; - dest->_queue_name_len = 0; -} - -int file_hdr_init(void* dest, const uint64_t dest_len, const uint16_t uflag, const uint64_t serial, const uint64_t rid, - const uint64_t fro, const uint64_t file_number, const uint16_t queue_name_len, const char* queue_name) { - file_hdr_t* fhp = (file_hdr_t*)dest; - fhp->_rhdr._uflag = uflag; - fhp->_rhdr._serial = serial; - fhp->_rhdr._rid = rid; - fhp->_fro = fro; - fhp->_file_number = file_number; - if (sizeof(file_hdr_t) + queue_name_len < MAX_FILE_HDR_LEN) { - fhp->_queue_name_len = queue_name_len; - } else { - fhp->_queue_name_len = MAX_FILE_HDR_LEN - sizeof(file_hdr_t); - } - fhp->_queue_name_len = queue_name_len; - memcpy((char*)dest + sizeof(file_hdr_t), queue_name, queue_name_len); - memset((char*)dest + sizeof(file_hdr_t) + queue_name_len, 0, dest_len - sizeof(file_hdr_t) - queue_name_len); - return set_time_now(dest); -} - -int file_hdr_check(file_hdr_t* hdr, const uint32_t magic, const uint16_t version, const uint64_t data_size_kib, const uint16_t max_queue_name_len) { - int err = rec_hdr_check_base(&hdr->_rhdr, magic, version); - if (data_size_kib && hdr->_data_size_kib != data_size_kib) err |= 0x1000; - if (hdr->_queue_name_len > max_queue_name_len) err |= 0x10000; - return err; -} - -void file_hdr_copy(file_hdr_t* dest, const file_hdr_t* src) { - rec_hdr_copy(&dest->_rhdr, &src->_rhdr); - dest->_fhdr_size_sblks = src->_fhdr_size_sblks; // Should this be copied? - dest->_efp_partition = src->_efp_partition; // Should this be copied? - dest->_data_size_kib = src->_data_size_kib; - dest->_fro = src->_fro; - dest->_ts_sec = src->_ts_sec; - dest->_ts_nsec = src->_ts_nsec; - dest->_file_number = src->_file_number; -} - -void file_hdr_reset(file_hdr_t* target) { - target->_rhdr._uflag = 0; - target->_rhdr._serial = 0; - target->_rhdr._rid = 0; - target->_fro = 0; - target->_ts_sec = 0; - target->_ts_nsec = 0; - target->_file_number = 0; - target->_queue_name_len = 0; -} - -int is_file_hdr_reset(file_hdr_t* target) { - return target->_rhdr._uflag == 0 && - target->_rhdr._serial == 0 && - target->_rhdr._rid == 0 && - target->_ts_sec == 0 && - target->_ts_nsec == 0 && - target->_file_number == 0 && - target->_queue_name_len == 0; -} - -int set_time_now(file_hdr_t *fh) -{ - struct timespec ts; - int err = clock_gettime(CLOCK_REALTIME, &ts); - if (err) - return err; - fh->_ts_sec = ts.tv_sec; - fh->_ts_nsec = ts.tv_nsec; - return 0; -} - - -void set_time(file_hdr_t *fh, struct timespec *ts) -{ - fh->_ts_sec = ts->tv_sec; - fh->_ts_nsec = ts->tv_nsec; -} - - diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/file_hdr.h b/qpid/cpp/src/qpid/linearstore/journal/utils/file_hdr.h deleted file mode 100644 index 5987e1871e..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/file_hdr.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef QPID_LINEARSTORE_JOURNAL_UTILS_FILE_HDR_H -#define QPID_LINEARSTORE_JOURNAL_UTILS_FILE_HDR_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 -#include "rec_hdr.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#define MAX_FILE_HDR_LEN 4096 // Set to 1 sblk - -#pragma pack(1) - -/** - * \brief Struct for data common to the head of all journal files. In addition to - * the common data, this includes the record ID and offset of the first record in - * the file. - * - * This header precedes all data in journal files and occupies the first complete - * block in the file. The record ID and offset are updated on each overwrite of the - * file. - * - * File header info in binary format (74 bytes + size of file name in octets): - *
- *   0                           7
- * +---+---+---+---+---+---+---+---+  -+
- * |     magic     |  ver  | flags |   |
- * +---+---+---+---+---+---+---+---+   |
- * |             serial            |   | struct rec_hdr_t
- * +---+---+---+---+---+---+---+---+   |
- * |              rid              |   |
- * +---+---+---+---+---+---+---+---+  -+
- * |  fhs  | partn |   reserved    |
- * +---+---+---+---+---+---+---+---+
- * |           data-size           |
- * +---+---+---+---+---+---+---+---+
- * |              fro              |
- * +---+---+---+---+---+---+---+---+
- * |           timestamp (sec)     |
- * +---+---+---+---+---+---+---+---+
- * |           timestamp (ns)      |
- * +---+---+---+---+---+---+---+---+
- * |          file-number          |
- * +---+---+---+---+---+---+---+---+
- * |  qnl  | Queue Name...         |
- * +-------+                       |
- * |                               |
- * +---+---+---+---+---+---+---+---+
- *
- * ver = Journal version
- * rid = Record ID
- * fhs = File header size in sblks (defined by JRNL_SBLK_SIZE)
- * partn = EFP partition from which this file came
- * fro = First Record Offset
- * qnl = Length of the queue name in octets.
- * 
- */ -typedef struct file_hdr_t { - rec_hdr_t _rhdr; /**< Common record header struct, but rid field is used for rid of first compete record in file */ - uint16_t _fhdr_size_sblks; /**< File header size in sblks (defined by JRNL_SBLK_SIZE) */ - uint16_t _efp_partition; /**< EFP Partition number from which this file was obtained */ - uint32_t _reserved; - uint64_t _data_size_kib; /**< Size of the data part of this file in KiB. (ie file size excluding file header sblk) */ - uint64_t _fro; /**< First Record Offset (FRO) */ - uint64_t _ts_sec; /**< Time stamp (seconds part) */ - uint64_t _ts_nsec; /**< Time stamp (nanoseconds part) */ - uint64_t _file_number; /**< The logical number of this file in a monotonically increasing sequence */ - uint16_t _queue_name_len; /**< Length of the queue name in octets, which follows this struct in the header */ -} file_hdr_t; - -void file_hdr_create(file_hdr_t* dest, const uint32_t magic, const uint16_t version, - const uint16_t fhdr_size_sblks, const uint16_t efp_partition, const uint64_t file_size); -int file_hdr_init(void* dest, const uint64_t dest_len, const uint16_t uflag, const uint64_t serial, const uint64_t rid, - const uint64_t fro, const uint64_t file_number, const uint16_t queue_name_len, - const char* queue_name); -int file_hdr_check(file_hdr_t* hdr, const uint32_t magic, const uint16_t version, const uint64_t data_size_kib, - const uint16_t max_queue_name_len); -void file_hdr_reset(file_hdr_t* target); -int is_file_hdr_reset(file_hdr_t* target); -void file_hdr_copy(file_hdr_t* dest, const file_hdr_t* src); -int set_time_now(file_hdr_t *fh); -void set_time(file_hdr_t *fh, struct timespec *ts); - -#pragma pack() - -#ifdef __cplusplus -} -#endif - -#endif /* ifndef QPID_LINEARSTORE_JOURNAL_UTILS_FILE_HDR_H */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/rec_hdr.c b/qpid/cpp/src/qpid/linearstore/journal/utils/rec_hdr.c deleted file mode 100644 index 32eda8de5a..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/rec_hdr.c +++ /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. - * - */ - -#include "rec_hdr.h" - -void rec_hdr_init(rec_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t uflag, const uint64_t serial, const uint64_t rid) { - dest->_magic = magic; - dest->_version = version; - dest->_uflag = uflag; - dest->_serial = serial; - dest->_rid = rid; -} - -void rec_hdr_copy(rec_hdr_t* dest, const rec_hdr_t* src) { - dest->_magic = src->_magic; - dest->_version = src->_version; - dest->_uflag = src->_uflag; - dest->_serial = src->_serial; - dest->_rid = src->_rid; -} - -int rec_hdr_check_base(rec_hdr_t* header, const uint32_t magic, const uint16_t version) { - int err = 0; - if (header->_magic != magic) err |= 0x1; - if (header->_version != version) err |= 0x10; - return err; -} - -int rec_hdr_check(rec_hdr_t* header, const uint32_t magic, const uint16_t version, const uint64_t serial) { - int err = rec_hdr_check_base(header, magic, version); - if (header->_serial != serial) err |= 0x100; - return err; -} diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/rec_hdr.h b/qpid/cpp/src/qpid/linearstore/journal/utils/rec_hdr.h deleted file mode 100644 index 64349b5ab8..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/rec_hdr.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef QPID_LINEARSTORE_JOURNAL_UTILS_REC_HDR_H -#define QPID_LINEARSTORE_JOURNAL_UTILS_REC_HDR_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 - -#ifdef __cplusplus -extern "C"{ -#endif - -#pragma pack(1) - -/** - * \brief Struct for data common to the head of all journal files and records. - * This includes identification for the file type, the encoding version, endian - * indicator and a record ID. - * - * File header info in binary format (24 bytes): - *
- *   0                           7
- * +---+---+---+---+---+---+---+---+
- * |     magic     |  ver  | uflag |
- * +---+---+---+---+---+---+---+---+
- * |             serial            |
- * +---+---+---+---+---+---+---+---+
- * |              rid              |
- * +---+---+---+---+---+---+---+---+
- *
- * ver = file version (If the format or encoding of this file changes, then this
- *       number should be incremented)
- * rid = Record ID
- * 
- */ -typedef struct rec_hdr_t { - uint32_t _magic; /**< File type identifier (magic number) */ - uint16_t _version; /**< File encoding version */ - uint16_t _uflag; /**< User-defined flags */ - uint64_t _serial; /**< Serial number for this journal file */ - uint64_t _rid; /**< Record ID (rotating 64-bit counter) */ -} rec_hdr_t; - -void rec_hdr_init(rec_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t uflag, const uint64_t serial, const uint64_t rid); -void rec_hdr_copy(rec_hdr_t* dest, const rec_hdr_t* src); -int rec_hdr_check_base(rec_hdr_t* header, const uint32_t magic, const uint16_t version); -int rec_hdr_check(rec_hdr_t* header, const uint32_t magic, const uint16_t version, const uint64_t serial); - -#pragma pack() - -#ifdef __cplusplus -} -#endif - -#endif /* ifndef QPID_LINEARSTORE_JOURNAL_UTILS_REC_HDR_H */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/rec_tail.c b/qpid/cpp/src/qpid/linearstore/journal/utils/rec_tail.c deleted file mode 100644 index 7128c96f32..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/rec_tail.c +++ /dev/null @@ -1,46 +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 "rec_tail.h" - -void rec_tail_init(rec_tail_t* dest, const uint32_t xmagic, const uint32_t checksum, const uint64_t serial, - const uint64_t rid) { - dest->_xmagic = xmagic; - dest->_checksum = checksum; - dest->_serial = serial; - dest->_rid = rid; -} - -void rec_tail_copy(rec_tail_t* dest, const rec_hdr_t* src, const uint32_t checksum) { - dest->_xmagic = ~(src->_magic); - dest->_checksum = checksum; - dest->_serial = src->_serial; - dest->_rid = src->_rid; -} - -uint16_t rec_tail_check(const rec_tail_t* tail, const rec_hdr_t* header, const uint32_t checksum) { - uint16_t err = 0; - if (tail->_xmagic != ~header->_magic) err |= REC_TAIL_MAGIC_ERR_MASK; - if (tail->_serial != header->_serial) err |= REC_TAIL_SERIAL_ERR_MASK; - if (tail->_rid != header->_rid) err |= REC_TAIL_RID_ERR_MASK; - if (tail->_checksum != checksum) err |= REC_TAIL_CHECKSUM_ERR_MASK; - return err; -} diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/rec_tail.h b/qpid/cpp/src/qpid/linearstore/journal/utils/rec_tail.h deleted file mode 100644 index afc71c104a..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/rec_tail.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef QPID_LINEARSTORE_JOURNAL_UTILS_REC_TAIL_H -#define QPID_LINEARSTORE_JOURNAL_UTILS_REC_TAIL_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 -#include "rec_hdr.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#pragma pack(1) - -/** - * \brief Struct for data common to the tail of all records. The magic number - * used here is the binary inverse (1's complement) of the magic used in the - * record header; this minimizes possible confusion with other headers that may - * be present during recovery. The tail is used with all records that have either - * XIDs or data - ie any size-variable content. Currently the only records that - * do NOT use the tail are non-transactional dequeues and filler records. - * - * The checksum is used to verify the xid and/or data portion of the record - * on recovery, and excludes the header and tail. - * - * Record header info in binary format (24 bytes): - *
- *   0                           7
- * +---+---+---+---+---+---+---+---+
- * |   ~(magic)    |   checksum    |
- * +---+---+---+---+---+---+---+---+
- * |             serial            |
- * +---+---+---+---+---+---+---+---+
- * |              rid              |
- * +---+---+---+---+---+---+---+---+
- *
- * ~(magic) = 1's compliment of magic of matching record header
- * rid = Record ID of matching record header
- * 
- */ -typedef struct rec_tail_t { - uint32_t _xmagic; /**< Binary inverse (1's complement) of hdr magic number */ - uint32_t _checksum; /**< Checksum of xid and data (excluding header itself) */ - uint64_t _serial; /**< Serial number for this journal file */ - uint64_t _rid; /**< Record ID (rotating 64-bit counter) */ -} rec_tail_t; - -static const uint16_t REC_TAIL_MAGIC_ERR_MASK = 0x01; -static const uint16_t REC_TAIL_SERIAL_ERR_MASK = 0x02; -static const uint16_t REC_TAIL_RID_ERR_MASK = 0x04; -static const uint16_t REC_TAIL_CHECKSUM_ERR_MASK = 0x08; - -void rec_tail_init(rec_tail_t* dest, const uint32_t xmagic, const uint32_t checksum, const uint64_t serial, - const uint64_t rid); -void rec_tail_copy(rec_tail_t* dest, const rec_hdr_t* src, const uint32_t checksum); -uint16_t rec_tail_check(const rec_tail_t* tail, const rec_hdr_t* header, const uint32_t checksum); - -#pragma pack() - -#ifdef __cplusplus -} -#endif - -#endif /* ifnedf QPID_LINEARSTORE_JOURNAL_UTILS_REC_TAIL_H */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/txn_hdr.c b/qpid/cpp/src/qpid/linearstore/journal/utils/txn_hdr.c deleted file mode 100644 index 58d4cdebe4..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/txn_hdr.c +++ /dev/null @@ -1,33 +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 "txn_hdr.h" - -void txn_hdr_init(txn_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t uflag, - const uint64_t serial, const uint64_t rid, const uint64_t xidsize) { - rec_hdr_init(&dest->_rhdr, magic, version, uflag, serial, rid); - dest->_xidsize = xidsize; -} - -void txn_hdr_copy(txn_hdr_t* dest, const txn_hdr_t* src) { - rec_hdr_copy(&dest->_rhdr, &src->_rhdr); - dest->_xidsize = src->_xidsize; -} diff --git a/qpid/cpp/src/qpid/linearstore/journal/utils/txn_hdr.h b/qpid/cpp/src/qpid/linearstore/journal/utils/txn_hdr.h deleted file mode 100644 index 442a1d373d..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/utils/txn_hdr.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef QPID_LINEARSTORE_JOURNAL_UTILS_TXN_HDR_H -#define QPID_LINEARSTORE_JOURNAL_UTILS_TXN_HDR_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 "rec_hdr.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#pragma pack(1) - -/** - * \brief Struct for transaction commit and abort records. - * - * Struct for local and DTX commit and abort records. Only the magic distinguishes between them. - * Since this record must be used in the context of a valid XID, the xidsize field must not be - * zero. Immediately following this record is the XID itself which is xidsize bytes long, - * followed by a rec_tail. - * - * Note that this record had its own rid distinct from the rids of the record(s) making up the - * transaction it is committing or aborting. - * - * Record header info in binary format (32 bytes): - *
- *   0                           7
- * +---+---+---+---+---+---+---+---+  -+
- * |     magic     |  ver  | flags |   |
- * +---+---+---+---+---+---+---+---+   |
- * |             serial            |   | struct rec_hdr_t
- * +---+---+---+---+---+---+---+---+   |
- * |              rid              |   |
- * +---+---+---+---+---+---+---+---+  -+
- * |            xidsize            |
- * +---+---+---+---+---+---+---+---+
- * 
- */ -typedef struct txn_hdr_t { - rec_hdr_t _rhdr; /**< Common record header struct */ - uint64_t _xidsize; /**< XID size */ -} txn_hdr_t; - -void txn_hdr_init(txn_hdr_t* dest, const uint32_t magic, const uint16_t version, const uint16_t uflag, - const uint64_t serial, const uint64_t rid, const uint64_t xidsize); -void txn_hdr_copy(txn_hdr_t* dest, const txn_hdr_t* src); - -#pragma pack() - -#ifdef __cplusplus -} -#endif - -#endif /* ifndef QPID_LINEARSTORE_JOURNAL_UTILS_TXN_HDR_H */ diff --git a/qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp b/qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp deleted file mode 100644 index 1ff18da663..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp +++ /dev/null @@ -1,1086 +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/linearstore/journal/wmgr.h" - -#include -#include "qpid/linearstore/journal/aio_callback.h" -#include "qpid/linearstore/journal/Checksum.h" -#include "qpid/linearstore/journal/data_tok.h" -#include "qpid/linearstore/journal/jcntl.h" -#include "qpid/linearstore/journal/JournalFile.h" -#include "qpid/linearstore/journal/LinearFileController.h" -#include "qpid/linearstore/journal/utils/file_hdr.h" - -namespace qpid { -namespace linearstore { -namespace journal { - -wmgr::wmgr(jcntl* jc, - enq_map& emap, - txn_map& tmap, - LinearFileController& lfc): - pmgr(jc, emap, tmap), - _lfc(lfc), - _max_dtokpp(0), - _max_io_wait_us(0), - _cached_offset_dblks(0), - _enq_busy(false), - _deq_busy(false), - _abort_busy(false), - _commit_busy(false), - _txn_pending_map() -{} - -wmgr::wmgr(jcntl* jc, - enq_map& emap, - txn_map& tmap, - LinearFileController& lfc, - const uint32_t max_dtokpp, - const uint32_t max_iowait_us): - pmgr(jc, emap, tmap), - _lfc(lfc), - _max_dtokpp(max_dtokpp), - _max_io_wait_us(max_iowait_us), - _cached_offset_dblks(0), - _enq_busy(false), - _deq_busy(false), - _abort_busy(false), - _commit_busy(false), - _txn_pending_map() -{} - -wmgr::~wmgr() -{ - wmgr::clean(); -} - -void -wmgr::initialize(aio_callback* const cbp, - const uint32_t wcache_pgsize_sblks, - const uint16_t wcache_num_pages, - const uint32_t max_dtokpp, - const uint32_t max_iowait_us, - std::size_t end_offset) -{ - _enq_busy = false; - _deq_busy = false; - _abort_busy = false; - _commit_busy = false; - _max_dtokpp = max_dtokpp; - _max_io_wait_us = max_iowait_us; - - initialize(cbp, wcache_pgsize_sblks, wcache_num_pages); - - if (end_offset) - { - if(!aio::is_aligned((const void*)end_offset, QLS_AIO_ALIGN_BOUNDARY_BYTES)) { - std::ostringstream oss; - oss << "Recovery using misaligned end_offset (0x" << std::hex << end_offset << std::dec << ")" << std::endl; - throw jexception(jerrno::JERR_WMGR_NOTSBLKALIGNED, oss.str(), "wmgr", "initialize"); - } - const uint32_t wr_pg_size_dblks = _cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS; - uint32_t data_dblks = (end_offset / QLS_DBLK_SIZE_BYTES) - (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_DBLKS); // exclude file header - _pg_cntr = data_dblks / wr_pg_size_dblks; // Must be set to get file rotation synchronized (this is determined by value of _pg_cntr) - _pg_offset_dblks = data_dblks - (_pg_cntr * wr_pg_size_dblks); - } -} - -iores -wmgr::enqueue(const void* const data_buff, - const std::size_t tot_data_len, - const std::size_t this_data_len, - data_tok* dtokp, - const void* const xid_ptr, - const std::size_t xid_len, - const bool tpc_flag, - const bool transient, - const bool external) -{ -//std::cout << _lfc.status(10) << std::endl; - if (xid_len) - assert(xid_ptr != 0); - - if (_deq_busy || _abort_busy || _commit_busy) { - std::ostringstream oss; - oss << "RHM_IORES_BUSY: enqueue while part way through another op:"; - oss << " _deq_busy=" << (_deq_busy?"T":"F"); - oss << " _abort_busy=" << (_abort_busy?"T":"F"); - oss << " _commit_busy=" << (_commit_busy?"T":"F"); - throw jexception(oss.str()); // TODO: complete exception - } - - if (this_data_len != tot_data_len && !external) { - throw jexception("RHM_IORES_NOTIMPL: partial enqueues not implemented"); // TODO: complete exception; - } - - iores res = pre_write_check(WMGR_ENQUEUE, dtokp, xid_len, tot_data_len, external); - if (res != RHM_IORES_SUCCESS) - return res; - - bool cont = false; - if (_enq_busy) // If enqueue() exited last time with RHM_IORES_FULL or RHM_IORES_PAGE_AIOWAIT - { - if (dtokp->wstate() == data_tok::ENQ_PART) - cont = true; - else - { - std::ostringstream oss; - oss << "This data_tok: id=" << dtokp->id() << " state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_ENQDISCONT, oss.str(), "wmgr", "enqueue"); - } - } - - uint64_t rid = (dtokp->external_rid() | cont) ? dtokp->rid() : _lfc.getNextRecordId(); - _enq_rec.reset(_lfc.getCurrentSerial(), rid, data_buff, tot_data_len, xid_ptr, xid_len, transient, external); - if (!cont) - { - dtokp->set_rid(rid); - dtokp->set_dequeue_rid(0); - if (xid_len) - dtokp->set_xid(xid_ptr, xid_len); - else - dtokp->clear_xid(); - _enq_busy = true; - } -//std::cout << "---+++ wmgr::enqueue() ENQ rid=0x" << std::hex << rid << " po=0x" << _pg_offset_dblks << " cs=0x" << (_cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) << " " << std::dec << std::flush; // DEBUG - bool done = false; - Checksum checksum; - while (!done) - { -//std::cout << "*" << std::flush; // DEBUG - assert(_pg_offset_dblks < _cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS); - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * QLS_DBLK_SIZE_BYTES); - uint32_t data_offs_dblks = dtokp->dblocks_written(); - uint32_t ret = _enq_rec.encode(wptr, data_offs_dblks, - (_cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) - _pg_offset_dblks, checksum); - - // Remember fid which contains the record header in case record is split over several files - if (data_offs_dblks == 0) { - dtokp->set_fid(_lfc.getCurrentFileSeqNum()); - } - _pg_offset_dblks += ret; - _cached_offset_dblks += ret; - dtokp->incr_dblocks_written(ret); - dtokp->incr_pg_cnt(); - _page_cb_arr[_pg_index]._pdtokl->push_back(dtokp); - - // Is the encoding of this record complete? - if (dtokp->dblocks_written() >= _enq_rec.rec_size_dblks()) - { -//std::cout << "!" << std::flush; // DEBUG - // TODO: Incorrect - must set state to ENQ_CACHED; ENQ_SUBM is set when AIO returns. - dtokp->set_wstate(data_tok::ENQ_SUBM); - dtokp->set_dsize(tot_data_len); - // Only add this data token to page token list when submit is complete, this way - // long multi-page messages have their token on the page containing the END of the - // message. AIO callbacks will then only process this token when entire message is - // enqueued. - _lfc.incrEnqueuedRecordCount(dtokp->fid()); -//std::cout << "[0x" << std::hex << _lfc.getEnqueuedRecordCount(dtokp->fid()) << std::dec << std::flush; // DEBUG - - if (xid_len) // If part of transaction, add to transaction map - { - std::string xid((const char*)xid_ptr, xid_len); - _tmap.insert_txn_data(xid, txn_data_t(rid, 0, dtokp->fid(), 0, true, tpc_flag, false)); - } - else - { - if (_emap.insert_pfid(rid, dtokp->fid(), 0) < enq_map::EMAP_OK) // fail - { - // The only error code emap::insert_pfid() returns is enq_map::EMAP_DUP_RID. - std::ostringstream oss; - oss << std::hex << "rid=0x" << rid << " _pfid=0x" << dtokp->fid(); - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "wmgr", "enqueue"); - } - } - - done = true; - } else { -//std::cout << "$" << std::flush; // DEBUG - dtokp->set_wstate(data_tok::ENQ_PART); - } - - file_header_check(rid, cont, _enq_rec.rec_size_dblks() - data_offs_dblks); - flush_check(res, cont, done, rid); - } - if (dtokp->wstate() >= data_tok::ENQ_SUBM) - _enq_busy = false; -//std::cout << " res=" << iores_str(res) << " _enq_busy=" << (_enq_busy?"T":"F") << std::endl << std::flush; // DEBUG - return res; -} - -iores -wmgr::dequeue(data_tok* dtokp, - const void* const xid_ptr, - const std::size_t xid_len, - const bool tpc_flag, - const bool txn_coml_commit) -{ - if (xid_len) - assert(xid_ptr != 0); - - if (_enq_busy || _abort_busy || _commit_busy) { - std::ostringstream oss; - oss << "RHM_IORES_BUSY: dequeue while part way through another op:"; - oss << " _enq_busy=" << (_enq_busy?"T":"F"); - oss << " _abort_busy=" << (_abort_busy?"T":"F"); - oss << " _commit_busy=" << (_commit_busy?"T":"F"); - throw jexception(oss.str()); // TODO: complete exception - } - - iores res = pre_write_check(WMGR_DEQUEUE, dtokp); - if (res != RHM_IORES_SUCCESS) - return res; - - bool cont = false; - if (_deq_busy) // If dequeue() exited last time with RHM_IORES_FULL or RHM_IORES_PAGE_AIOWAIT - { - if (dtokp->wstate() == data_tok::DEQ_PART) - cont = true; - else - { - std::ostringstream oss; - oss << "This data_tok: id=" << dtokp->id() << " state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_DEQDISCONT, oss.str(), "wmgr", "dequeue"); - } - } - - const bool ext_rid = dtokp->external_rid(); - uint64_t rid = (ext_rid | cont) ? dtokp->rid() : _lfc.getNextRecordId(); - uint64_t dequeue_rid = (ext_rid | cont) ? dtokp->dequeue_rid() : dtokp->rid(); - _deq_rec.reset(_lfc.getCurrentSerial(), rid, dequeue_rid, xid_ptr, xid_len, txn_coml_commit); - if (!cont) - { - if (!ext_rid) - { - dtokp->set_rid(rid); - dtokp->set_dequeue_rid(dequeue_rid); - } - if (xid_len) - dtokp->set_xid(xid_ptr, xid_len); - else - dtokp->clear_xid(); - dequeue_check(dtokp->xid(), dequeue_rid); - dtokp->set_dblocks_written(0); // Reset dblks_written from previous op - _deq_busy = true; - } -//std::cout << "---+++ wmgr::dequeue() DEQ rid=0x" << std::hex << rid << " drid=0x" << dequeue_rid << " " << std::dec << std::flush; // DEBUG - std::string xid((const char*)xid_ptr, xid_len); - bool done = false; - Checksum checksum; - while (!done) - { -//std::cout << "*" << std::flush; // DEBUG - assert(_pg_offset_dblks < _cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS); - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * QLS_DBLK_SIZE_BYTES); - uint32_t data_offs_dblks = dtokp->dblocks_written(); - uint32_t ret = _deq_rec.encode(wptr, data_offs_dblks, - (_cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) - _pg_offset_dblks, checksum); - - if (data_offs_dblks == 0) { - uint64_t fid; - short eres = _emap.get_pfid(dtokp->dequeue_rid(), fid); - if (eres == enq_map::EMAP_OK) { - dtokp->set_fid(fid); - } else if (xid_len > 0) { - txn_data_list_t tdl = _tmap.get_tdata_list(xid); - bool found = false; - for (tdl_const_itr_t i=tdl.begin(); i!=tdl.end() && !found; ++i) { - if (i->rid_ == dtokp->dequeue_rid()) { - found = true; - dtokp->set_fid(i->fid_); - break; - } - } - if (!found) { - throw jexception("rid found in neither emap nor tmap, transactional"); - } - } else { - throw jexception("rid not found in emap, non-transactional"); - } - } - _pg_offset_dblks += ret; - _cached_offset_dblks += ret; - dtokp->incr_dblocks_written(ret); - dtokp->incr_pg_cnt(); - _page_cb_arr[_pg_index]._pdtokl->push_back(dtokp); - - // Is the encoding of this record complete? - if (dtokp->dblocks_written() >= _deq_rec.rec_size_dblks()) - { -//std::cout << "!" << std::flush; // DEBUG - // TODO: Incorrect - must set state to ENQ_CACHED; ENQ_SUBM is set when AIO returns. - dtokp->set_wstate(data_tok::DEQ_SUBM); - - if (xid_len) // If part of transaction, add to transaction map - { - // If the enqueue is part of a pending txn, it will not yet be in emap - _emap.lock(dequeue_rid); // ignore rid not found error - std::string xid((const char*)xid_ptr, xid_len); - _tmap.insert_txn_data(xid, txn_data_t(rid, dequeue_rid, dtokp->fid(), 0, false, tpc_flag, false)); - } - else - { - uint64_t fid; - short eres = _emap.get_remove_pfid(dtokp->dequeue_rid(), fid); - if (eres < enq_map::EMAP_OK) // fail - { - if (eres == enq_map::EMAP_RID_NOT_FOUND) - { - std::ostringstream oss; - oss << std::hex << "emap: rid=0x" << rid; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "dequeue"); - } - if (eres == enq_map::EMAP_LOCKED) - { - std::ostringstream oss; - oss << std::hex << "rid=0x" << rid; - throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "dequeue"); - } - } - } - - done = true; - } else { -//std::cout << "$" << std::flush; // DEBUG - dtokp->set_wstate(data_tok::DEQ_PART); - } - - file_header_check(rid, cont, _deq_rec.rec_size_dblks() - data_offs_dblks); - flush_check(res, cont, done, rid); - } - if (dtokp->wstate() >= data_tok::DEQ_SUBM) - _deq_busy = false; -//std::cout << " res=" << iores_str(res) << " _deq_busy=" << (_deq_busy?"T":"F") << std::endl << std::flush; // DEBUG - return res; -} - -iores -wmgr::abort(data_tok* dtokp, - const void* const xid_ptr, - const std::size_t xid_len) -{ - // commit and abort MUST have a valid xid - assert(xid_ptr != 0 && xid_len > 0); - - if (_enq_busy || _deq_busy || _commit_busy) { - std::ostringstream oss; - oss << "RHM_IORES_BUSY: abort while part way through another op:"; - oss << " _enq_busy=" << (_enq_busy?"T":"F"); - oss << " _deq_busy=" << (_deq_busy?"T":"F"); - oss << " _commit_busy=" << (_commit_busy?"T":"F"); - throw jexception(oss.str()); // TODO: complete exception - } - - iores res = pre_write_check(WMGR_ABORT, dtokp); - if (res != RHM_IORES_SUCCESS) - return res; - - bool cont = false; - if (_abort_busy) // If abort() exited last time with RHM_IORES_FULL or RHM_IORES_PAGE_AIOWAIT - { - if (dtokp->wstate() == data_tok::ABORT_PART) - cont = true; - else - { - std::ostringstream oss; - oss << "This data_tok: id=" << dtokp->id() << " state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_DEQDISCONT, oss.str(), "wmgr", "abort"); - } - } - - uint64_t rid = (dtokp->external_rid() | cont) ? dtokp->rid() : _lfc.getNextRecordId(); - _txn_rec.reset(false, _lfc.getCurrentSerial(), rid, xid_ptr, xid_len); - if (!cont) - { - dtokp->set_rid(rid); - dtokp->set_dequeue_rid(0); - dtokp->set_xid(xid_ptr, xid_len); - dtokp->set_dblocks_written(0); // Reset dblks_written from previous op - _abort_busy = true; - } - bool done = false; - Checksum checksum; - while (!done) - { - assert(_pg_offset_dblks < _cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS); - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * QLS_DBLK_SIZE_BYTES); - uint32_t data_offs_dblks = dtokp->dblocks_written(); - uint32_t ret = _txn_rec.encode(wptr, data_offs_dblks, - (_cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) - _pg_offset_dblks, checksum); - - // Remember fid which contains the record header in case record is split over several files - if (data_offs_dblks == 0) - dtokp->set_fid(_lfc.getCurrentFileSeqNum()); - _pg_offset_dblks += ret; - _cached_offset_dblks += ret; - dtokp->incr_dblocks_written(ret); - dtokp->incr_pg_cnt(); - _page_cb_arr[_pg_index]._pdtokl->push_back(dtokp); - - // Is the encoding of this record complete? - if (dtokp->dblocks_written() >= _txn_rec.rec_size_dblks()) - { - dtokp->set_wstate(data_tok::ABORT_SUBM); - - // Delete this txn from tmap, unlock any locked records in emap - std::string xid((const char*)xid_ptr, xid_len); - txn_data_list_t tdl = _tmap.get_remove_tdata_list(xid); // tdl will be empty if xid not found - fidl_t fidl; - for (tdl_itr_t itr = tdl.begin(); itr != tdl.end(); itr++) - { - if (!itr->enq_flag_) - _emap.unlock(itr->drid_); // ignore rid not found error - if (itr->enq_flag_) { - fidl.push_back(itr->fid_); - } - } - std::pair res = _txn_pending_map.insert(std::pair(xid, fidl)); - if (!res.second) - { - std::ostringstream oss; - oss << std::hex << "_txn_pending_set: xid=\"" << xid << "\""; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "wmgr", "abort"); - } - - done = true; - } else { - dtokp->set_wstate(data_tok::ABORT_PART); - } - - file_header_check(rid, cont, _txn_rec.rec_size_dblks() - data_offs_dblks); - flush_check(res, cont, done, rid); - } - if (dtokp->wstate() >= data_tok::ABORT_SUBM) - _abort_busy = false; - return res; -} - -iores -wmgr::commit(data_tok* dtokp, - const void* const xid_ptr, - const std::size_t xid_len) -{ - // commit and abort MUST have a valid xid - assert(xid_ptr != 0 && xid_len > 0); - - if (_enq_busy || _deq_busy || _abort_busy) { - std::ostringstream oss; - oss << "RHM_IORES_BUSY: commit while part way through another op:"; - oss << " _enq_busy=" << (_enq_busy?"T":"F"); - oss << " _deq_busy=" << (_deq_busy?"T":"F"); - oss << " _abort_busy=" << (_abort_busy?"T":"F"); - throw jexception(oss.str()); // TODO: complete exception - } - - iores res = pre_write_check(WMGR_COMMIT, dtokp); - if (res != RHM_IORES_SUCCESS) - return res; - - bool cont = false; - if (_commit_busy) // If commit() exited last time with RHM_IORES_FULL or RHM_IORES_PAGE_AIOWAIT - { - if (dtokp->wstate() == data_tok::COMMIT_PART) - cont = true; - else - { - std::ostringstream oss; - oss << "This data_tok: id=" << dtokp->id() << " state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_DEQDISCONT, oss.str(), "wmgr", "commit"); - } - } - - uint64_t rid = (dtokp->external_rid() | cont) ? dtokp->rid() : _lfc.getNextRecordId(); - _txn_rec.reset(true, _lfc.getCurrentSerial(), rid, xid_ptr, xid_len); - if (!cont) - { - dtokp->set_rid(rid); - dtokp->set_dequeue_rid(0); - dtokp->set_xid(xid_ptr, xid_len); - dtokp->set_dblocks_written(0); // Reset dblks_written from previous op - _commit_busy = true; - } - bool done = false; - Checksum checksum; - while (!done) - { - assert(_pg_offset_dblks < _cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS); - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * QLS_DBLK_SIZE_BYTES); - uint32_t data_offs_dblks = dtokp->dblocks_written(); - uint32_t ret = _txn_rec.encode(wptr, data_offs_dblks, - (_cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) - _pg_offset_dblks, checksum); - - // Remember fid which contains the record header in case record is split over several files - if (data_offs_dblks == 0) - dtokp->set_fid(_lfc.getCurrentFileSeqNum()); - _pg_offset_dblks += ret; - _cached_offset_dblks += ret; - dtokp->incr_dblocks_written(ret); - dtokp->incr_pg_cnt(); - _page_cb_arr[_pg_index]._pdtokl->push_back(dtokp); - - // Is the encoding of this record complete? - if (dtokp->dblocks_written() >= _txn_rec.rec_size_dblks()) - { - dtokp->set_wstate(data_tok::COMMIT_SUBM); - - // Delete this txn from tmap, process records into emap - std::string xid((const char*)xid_ptr, xid_len); - txn_data_list_t tdl = _tmap.get_remove_tdata_list(xid); // tdl will be empty if xid not found - fidl_t fidl; - for (tdl_itr_t itr = tdl.begin(); itr != tdl.end(); itr++) - { - if (itr->enq_flag_) // txn enqueue - { - if (_emap.insert_pfid(itr->rid_, itr->fid_, 0) < enq_map::EMAP_OK) // fail - { - // The only error code emap::insert_pfid() returns is enq_map::EMAP_DUP_RID. - std::ostringstream oss; - oss << std::hex << "rid=0x" << itr->rid_ << " _pfid=0x" << itr->fid_; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "wmgr", "commit"); - } - } - else // txn dequeue - { - uint64_t fid; - short eres = _emap.get_remove_pfid(itr->drid_, fid, true); - if (eres < enq_map::EMAP_OK) // fail - { - if (eres == enq_map::EMAP_RID_NOT_FOUND) - { - std::ostringstream oss; - oss << std::hex << "emap: rid=0x" << itr->drid_; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "commit"); - } - if (eres == enq_map::EMAP_LOCKED) - { - std::ostringstream oss; - oss << std::hex << "rid=0x" << itr->drid_; - throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "commit"); - } - } - fidl.push_back(fid); - } - } - std::pair res = _txn_pending_map.insert(std::pair(xid, fidl)); - if (!res.second) - { - std::ostringstream oss; - oss << std::hex << "_txn_pending_set: xid=\"" << xid << "\""; - throw jexception(jerrno::JERR_MAP_DUPLICATE, oss.str(), "wmgr", "commit"); - } - - done = true; - } else { - dtokp->set_wstate(data_tok::COMMIT_PART); - } - - file_header_check(rid, cont, _txn_rec.rec_size_dblks() - data_offs_dblks); - flush_check(res, cont, done, rid); - } - if (dtokp->wstate() >= data_tok::COMMIT_SUBM) - _commit_busy = false; - return res; -} - -void -wmgr::file_header_check(const uint64_t rid, - const bool cont, - const uint32_t rec_dblks_rem) -{ - if (_lfc.isEmpty()) // File never written (i.e. no header or data) - { -//std::cout << "e" << std::flush; - std::size_t fro = 0; - if (cont) { - bool file_fit = rec_dblks_rem <= _lfc.dataSize_sblks() * QLS_SBLK_SIZE_DBLKS; // Will fit within this journal file - bool file_full = rec_dblks_rem == _lfc.dataSize_sblks() * QLS_SBLK_SIZE_DBLKS; // Will exactly fill this journal file - if (file_fit && !file_full) { - fro = (rec_dblks_rem + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_DBLKS)) * QLS_DBLK_SIZE_BYTES; - } - } else { - fro = QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES; - } - _lfc.asyncFileHeaderWrite(_ioctx, 0, rid, fro); - _aio_evt_rem++; - } -} - -void -wmgr::flush_check(iores& res, - bool& cont, - bool& done, const uint64_t /*rid*/) // DEBUG -{ - // Is page is full, flush - if (_pg_offset_dblks >= _cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) - { -//std::cout << "^" << _pg_offset_dblks << ">=" << (_cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) << std::flush; - res = write_flush(); - assert(res == RHM_IORES_SUCCESS); - - if (_page_cb_arr[_pg_index]._state == AIO_PENDING && !done) - { - res = RHM_IORES_PAGE_AIOWAIT; - done = true; - } - - // If file is full, rotate to next file - uint32_t dataSize_pgs = _lfc.dataSize_sblks() / _cache_pgsize_sblks; - if (_pg_cntr >= dataSize_pgs) - { -//std::cout << _pg_cntr << ">=" << fileSize_pgs << std::flush; - get_next_file(); - if (!done) { - cont = true; - } -//std::cout << "***** wmgr::flush_check(): GET NEXT FILE: rid=0x" << std::hex << rid << std::dec << " res=" << iores_str(res) << " cont=" << (cont?"T":"F") << " done=" << (done?"T":"F") << std::endl; // DEBUG - } - } -} - -iores -wmgr::flush() -{ - iores res = write_flush(); - uint32_t dataSize_pgs = _lfc.dataSize_sblks() / _cache_pgsize_sblks; - if (res == RHM_IORES_SUCCESS && _pg_cntr >= dataSize_pgs) { - get_next_file(); - } - return res; -} - -iores -wmgr::write_flush() -{ - iores res = RHM_IORES_SUCCESS; - // Don't bother flushing an empty page or one that is still in state AIO_PENDING - if (_cached_offset_dblks) - { - if (_page_cb_arr[_pg_index]._state == AIO_PENDING) { -//std::cout << "#" << std::flush; // DEBUG - res = RHM_IORES_PAGE_AIOWAIT; - } else { - if (_page_cb_arr[_pg_index]._state != IN_USE) - { - std::ostringstream oss; - oss << "pg_index=" << _pg_index << " state=" << _page_cb_arr[_pg_index].state_str(); - throw jexception(jerrno::JERR_WMGR_BADPGSTATE, oss.str(), "wmgr", "write_flush"); - } - - // Send current page using AIO - - // In manual flushes, dblks may not coincide with sblks, add filler records ("RHMx") if necessary. - dblk_roundup(); - - std::size_t pg_offs = (_pg_offset_dblks - _cached_offset_dblks) * QLS_DBLK_SIZE_BYTES; - aio_cb* aiocbp = &_aio_cb_arr[_pg_index]; - _lfc.asyncPageWrite(_ioctx, aiocbp, (char*)_page_ptr_arr[_pg_index] + pg_offs, _cached_offset_dblks); - _page_cb_arr[_pg_index]._state = AIO_PENDING; - _aio_evt_rem++; -//std::cout << "." << _aio_evt_rem << std::flush; // DEBUG - _cached_offset_dblks = 0; - _jc->instr_incr_outstanding_aio_cnt(); - - rotate_page(); // increments _pg_index, resets _pg_offset_dblks if req'd - if (_page_cb_arr[_pg_index]._state == UNUSED) - _page_cb_arr[_pg_index]._state = IN_USE; - } - } - get_events(0, false); - if (_page_cb_arr[_pg_index]._state == UNUSED) - _page_cb_arr[_pg_index]._state = IN_USE; - return res; -} - -void -wmgr::get_next_file() -{ - _pg_cntr = 0; -//std::cout << "&&&&& wmgr::get_next_file(): " << status_str() << std::flush << std::endl; // DEBUG - _lfc.getNextJournalFile(); -} - -int32_t -wmgr::get_events(timespec* const timeout, - bool flush) -{ - if (_aio_evt_rem == 0) // no events to get - return 0; - - int ret = 0; - if ((ret = aio::getevents(_ioctx, flush ? _aio_evt_rem : 1, _aio_evt_rem, _aio_event_arr, timeout)) < 0) - { - if (ret == -EINTR) // Interrupted by signal - return 0; - std::ostringstream oss; - oss << "io_getevents() failed: " << std::strerror(-ret) << " (" << ret << ") ctx_id=" << _ioctx; - oss << " min_nr=" << (flush ? _aio_evt_rem : 1) << " nr=" << _aio_evt_rem; - throw jexception(jerrno::JERR__AIO, oss.str(), "wmgr", "get_events"); - } - - if (ret == 0 && timeout) - return jerrno::AIO_TIMEOUT; - - int32_t tot_data_toks = 0; - for (int i=0; idata); // This page control block (pcb) - long aioret = (long)_aio_event_arr[i].res; - if (aioret < 0) { - std::ostringstream oss; - oss << "AIO write operation failed: " << std::strerror(-aioret) << " (" << aioret << ")" << std::endl; - oss << " data=" << _aio_event_arr[i].data << std::endl; - oss << " obj=" << _aio_event_arr[i].obj << std::endl; - oss << " res=" << _aio_event_arr[i].res << std::endl; - oss << " res2=" << _aio_event_arr[i].res2 << std::endl; - oss << " iocb->data=" << aiocbp->data << std::endl; - oss << " iocb->key=" << aiocbp->key << std::endl; - oss << " iocb->aio_lio_opcode=" << aiocbp->aio_lio_opcode << std::endl; - oss << " iocb->aio_reqprio=" << aiocbp->aio_reqprio << std::endl; - oss << " iocb->aio_fildes=" << aiocbp->aio_fildes << std::endl; - oss << " iocb->u.c.buf=" << aiocbp->u.c.buf << std::endl; - oss << " iocb->u.c.nbytes=0x" << std::hex << aiocbp->u.c.nbytes << std::dec << " (" << aiocbp->u.c.nbytes << ")" << std::endl; - oss << " iocb->u.c.offset=0x" << std::hex << aiocbp->u.c.offset << std::dec << " (" << aiocbp->u.c.offset << ")" << std::endl; - oss << " iocb->u.c.flags=0x" << std::hex << aiocbp->u.c.flags << std::dec << " (" << aiocbp->u.c.flags << ")" << std::endl; - oss << " iocb->u.c.resfd=" << aiocbp->u.c.resfd << std::endl; - if (pcbp) { - oss << " Page Control Block: (iocb->data):" << std::endl; - oss << " pcb.index=" << pcbp->_index << std::endl; - oss << " pcb.state=" << pcbp->_state << " (" << pmgr::page_state_str(pcbp->_state) << ")" << std::endl; - oss << " pcb.frid=0x" << std::hex << pcbp->_frid << std::dec << std::endl; - oss << " pcb.wdblks=0x" << std::hex << pcbp->_wdblks << std::dec << std::endl; - oss << " pcb.pdtokl.size=" << pcbp->_pdtokl->size() << std::endl; - oss << " pcb.pbuff=" << pcbp->_pbuff << std::endl; - oss << " JournalFile (pcb.jfp):" << std::endl; - oss << pcbp->_jfp->status_str(6) << std::endl; - } else { - file_hdr_t* fhp = (file_hdr_t*)aiocbp->u.c.buf; - oss << "fnum=" << fhp->_file_number; - oss << " qname=" << std::string((char*)fhp + sizeof(file_hdr_t), fhp->_queue_name_len); - } - throw jexception(jerrno::JERR__AIO, oss.str(), "wmgr", "get_events"); - } - if (pcbp) // Page writes have pcb - { -//std::cout << "p"; // DEBUG - uint32_t s = pcbp->_pdtokl->size(); - std::vector dtokl; - dtokl.reserve(s); - for (uint32_t k=0; k_pdtokl->at(k); - if (dtokp->decr_pg_cnt() == 0) - { - pending_txn_map_itr_t it; - switch (dtokp->wstate()) - { - case data_tok::ENQ_SUBM: - dtokl.push_back(dtokp); - tot_data_toks++; - dtokp->set_wstate(data_tok::ENQ); - if (dtokp->has_xid()) - // Ignoring return value here. A non-zero return can signify that the transaction - // has committed or aborted, and which was completed prior to the aio returning. - _tmap.set_aio_compl(dtokp->xid(), dtokp->rid()); - break; - case data_tok::DEQ_SUBM: - if (!dtokp->has_xid()) { - _lfc.decrEnqueuedRecordCount(dtokp->fid()); - } - dtokl.push_back(dtokp); - tot_data_toks++; - dtokp->set_wstate(data_tok::DEQ); - if (dtokp->has_xid()) - // Ignoring return value - see note above. - _tmap.set_aio_compl(dtokp->xid(), dtokp->rid()); - break; - case data_tok::ABORT_SUBM: - dtokl.push_back(dtokp); - tot_data_toks++; - dtokp->set_wstate(data_tok::ABORTED); - it = _txn_pending_map.find(dtokp->xid()); - if (it == _txn_pending_map.end()) - { - std::ostringstream oss; - oss << std::hex << "_txn_pending_set: abort xid=\"" - << qpid::linearstore::journal::jcntl::str2hexnum(dtokp->xid()) << "\""; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "get_events"); - } - for (fidl_itr_t i=it->second.begin(); i!=it->second.end(); ++i) { - _lfc.decrEnqueuedRecordCount(*i); - } - _txn_pending_map.erase(it); - break; - case data_tok::COMMIT_SUBM: - dtokl.push_back(dtokp); - tot_data_toks++; - dtokp->set_wstate(data_tok::COMMITTED); - it = _txn_pending_map.find(dtokp->xid()); - if (it == _txn_pending_map.end()) - { - std::ostringstream oss; - oss << std::hex << "_txn_pending_set: commit xid=\"" - << qpid::linearstore::journal::jcntl::str2hexnum(dtokp->xid()) << "\""; - throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "get_events"); - } - for (fidl_itr_t i=it->second.begin(); i!=it->second.end(); ++i) { - _lfc.decrEnqueuedRecordCount(*i); - } - _txn_pending_map.erase(it); - break; - case data_tok::ENQ_PART: - case data_tok::DEQ_PART: - case data_tok::ABORT_PART: - case data_tok::COMMIT_PART: - // ignore these - break; - default: - // throw for anything else - std::ostringstream oss; - oss << "dtok_id=" << dtokp->id() << " dtok_state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_BADDTOKSTATE, oss.str(), "wmgr", - "get_events"); - } - } - } - - // Increment the completed write offset - // NOTE: We cannot use _wrfc here, as it may have rotated since submitting count. - // Use stored pointer to fcntl in the pcb instead. - pcbp->_jfp->addCompletedDblkCount(pcbp->_wdblks); - pcbp->_jfp->decrOutstandingAioOperationCount(); - _jc->instr_decr_outstanding_aio_cnt(); - - // Clean up this pcb's data_tok list - pcbp->_pdtokl->clear(); - pcbp->_state = UNUSED; -//std::cout << "c" << pcbp->_index << pcbp->state_str(); // DEBUG - - // Perform AIO return callback - if (_cbp && tot_data_toks) - _cbp->wr_aio_cb(dtokl); - } - else // File header writes have no pcb - { -//std::cout << "f"; // DEBUG - file_hdr_t* fhp = (file_hdr_t*)aiocbp->u.c.buf; - _lfc.addWriteCompletedDblkCount(fhp->_file_number, QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_DBLKS); - _lfc.decrOutstandingAioOperationCount(fhp->_file_number); - } - } - - return tot_data_toks; -} - -bool -wmgr::is_txn_synced(const std::string& xid) -{ - // Ignore xid not found error here - if (_tmap.is_txn_synced(xid) == txn_map::TMAP_NOT_SYNCED) - return false; - // Check for outstanding commit/aborts - pending_txn_map_itr_t it = _txn_pending_map.find(xid); - return it == _txn_pending_map.end(); -} - -void -wmgr::initialize(aio_callback* const cbp, - const uint32_t wcache_pgsize_sblks, - const uint16_t wcache_num_pages) -{ - - pmgr::initialize(cbp, wcache_pgsize_sblks, wcache_num_pages); - wmgr::clean(); - _page_cb_arr[0]._state = IN_USE; - _cached_offset_dblks = 0; - _enq_busy = false; -} - -iores -wmgr::pre_write_check(const _op_type op, - const data_tok* const dtokp, - const std::size_t /*xidsize*/, - const std::size_t /*dsize*/, - const bool /*external*/) const -{ - // Check status of current file - // TODO: Replace for LFC -/* - if (!_wrfc.is_wr_reset()) - { - if (!_wrfc.wr_reset()) - return RHM_IORES_FULL; - } -*/ - - // Check status of current page is ok for writing - if (_page_cb_arr[_pg_index]._state != IN_USE) - { - if (_page_cb_arr[_pg_index]._state == UNUSED) - _page_cb_arr[_pg_index]._state = IN_USE; - else if (_page_cb_arr[_pg_index]._state == AIO_PENDING) - return RHM_IORES_PAGE_AIOWAIT; - else - { - std::ostringstream oss; - oss << "jrnl=" << _jc->id() << " op=" << _op_str[op]; - oss << " index=" << _pg_index << " pg_state=" << _page_cb_arr[_pg_index].state_str(); - throw jexception(jerrno::JERR_WMGR_BADPGSTATE, oss.str(), "wmgr", "pre_write_check"); - } - } - - // operation-specific checks - switch (op) - { - case WMGR_ENQUEUE: - { - if (!dtokp->is_writable()) - { - std::ostringstream oss; - oss << "jrnl=" << _jc->id() << " op=" << _op_str[op]; - oss << " dtok_id=" << dtokp->id() << " dtok_state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_BADDTOKSTATE, oss.str(), "wmgr", - "pre_write_check"); - } - } - break; - case WMGR_DEQUEUE: - if (!dtokp->is_dequeueable()) - { - std::ostringstream oss; - oss << "jrnl=" << _jc->id() << " op=" << _op_str[op]; - oss << " dtok_id=" << dtokp->id() << " dtok_state=" << dtokp->wstate_str(); - throw jexception(jerrno::JERR_WMGR_BADDTOKSTATE, oss.str(), "wmgr", - "pre_write_check"); - } - break; - case WMGR_ABORT: - break; - case WMGR_COMMIT: - break; - } - - return RHM_IORES_SUCCESS; -} - -void -wmgr::dequeue_check(const std::string& xid, - const uint64_t drid) -{ - // First check emap - bool found = false; - uint64_t fid; - short eres = _emap.get_pfid(drid, fid); - if (eres < enq_map::EMAP_OK) { // fail - if (eres == enq_map::EMAP_RID_NOT_FOUND) { - if (xid.size()) { - found = _tmap.data_exists(xid, drid); - } - } else if (eres == enq_map::EMAP_LOCKED) { - std::ostringstream oss; - oss << std::hex << "drid=0x" << drid; - throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "dequeue_check"); - } - } else { - found = true; - } - if (!found) { - std::ostringstream oss; - oss << "jrnl=" << _jc->id() << " drid=0x" << std::hex << drid; - throw jexception(jerrno::JERR_WMGR_DEQRIDNOTENQ, oss.str(), "wmgr", "dequeue_check"); - } -} - -void -wmgr::dblk_roundup() -{ - const uint32_t xmagic = QLS_EMPTY_MAGIC; - uint32_t wdblks = jrec::size_blks(_cached_offset_dblks, QLS_SBLK_SIZE_DBLKS) * QLS_SBLK_SIZE_DBLKS; - while (_cached_offset_dblks < wdblks) - { -//std::cout << "^0x" << std::hex << _cached_offset_dblks << "<0x" << wdblks << std::dec << std::flush; - void* wptr = (void*)((char*)_page_ptr_arr[_pg_index] + _pg_offset_dblks * QLS_DBLK_SIZE_BYTES); - std::memcpy(wptr, (const void*)&xmagic, sizeof(xmagic)); -#ifdef QLS_CLEAN - std::memset((char*)wptr + sizeof(xmagic), QLS_CLEAN_CHAR, QLS_DBLK_SIZE_BYTES - sizeof(xmagic)); -#endif - _pg_offset_dblks++; - _cached_offset_dblks++; - } -} - -void -wmgr::rotate_page() -{ -//std::cout << "^^^^^ wmgr::rotate_page() " << status_str() << " pi=" << _pg_index; // DEBUG - if (_pg_offset_dblks >= _cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) - { - _pg_offset_dblks = 0; - _pg_cntr++; - } - if (++_pg_index >= _cache_num_pages) - _pg_index = 0; -//std::cout << "->" << _pg_index << std::endl; // DEBUG -} - -void -wmgr::clean() { - // Clean up allocated memory here -} - -const std::string -wmgr::status_str() const -{ - std::ostringstream oss; - oss << "wmgr: pi=" << _pg_index << " pc=" << _pg_cntr; - oss << " po=" << _pg_offset_dblks << " aer=" << _aio_evt_rem; - oss << " edac=" << (_enq_busy?"T":"F") << (_deq_busy?"T":"F"); - oss << (_abort_busy?"T":"F") << (_commit_busy?"T":"F"); - oss << " ps=["; - for (int i=0; i<_cache_num_pages; i++) - { - switch (_page_cb_arr[i]._state) - { - case UNUSED: oss << "-"; break; - case IN_USE: oss << "U"; break; - case AIO_PENDING: oss << "A"; break; - default: oss << _page_cb_arr[i]._state; - } - } - oss << "] "; - return oss.str(); -} - -// static - -const char* wmgr::_op_str[] = {"enqueue", "dequeue", "abort", "commit"}; - -}}} diff --git a/qpid/cpp/src/qpid/linearstore/journal/wmgr.h b/qpid/cpp/src/qpid/linearstore/journal/wmgr.h deleted file mode 100644 index 99da20bab9..0000000000 --- a/qpid/cpp/src/qpid/linearstore/journal/wmgr.h +++ /dev/null @@ -1,156 +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. - * - */ - -#ifndef QPID_LINEARSTORE_JOURNAL_WMGR_H -#define QPID_LINEARSTORE_JOURNAL_WMGR_H - -#include -#include -#include "qpid/linearstore/journal/enums.h" -#include "qpid/linearstore/journal/pmgr.h" -#include - -namespace qpid { -namespace linearstore { -namespace journal { - -class LinearFileController; - -/** -* \brief Class for managing a write page cache of arbitrary size and number of pages. -* -* The write page cache works on the principle of caching the write data within a page until -* that page is either full or flushed; this initiates a single AIO write operation to store -* the data on disk. -* -* The maximum disk throughput is achieved by keeping the write operations of uniform size. -* Waiting for a page cache to fill achieves this; and in high data volume/throughput situations -* achieves the optimal disk throughput. Calling flush() forces a write of the current page cache -* no matter how full it is, and disrupts the uniformity of the write operations. This should -* normally only be done if throughput drops and there is a danger of a page of unwritten data -* waiting around for excessive time. -* -* The usual tradeoff between data storage latency and throughput performance applies. -*/ -class wmgr : public pmgr -{ -private: - typedef std::vector fidl_t; - typedef fidl_t::iterator fidl_itr_t; - typedef std::map pending_txn_map_t; - typedef pending_txn_map_t::iterator pending_txn_map_itr_t; - - LinearFileController& _lfc; ///< Linear File Controller ref - uint32_t _max_dtokpp; ///< Max data writes per page - uint32_t _max_io_wait_us; ///< Max wait in microseconds till submit - uint32_t _cached_offset_dblks; ///< Amount of unwritten data in page (dblocks) - - // TODO: Convert _enq_busy etc into a proper threadsafe lock - // TODO: Convert to enum? Are these encodes mutually exclusive? - bool _enq_busy; ///< Flag true if enqueue is in progress - bool _deq_busy; ///< Flag true if dequeue is in progress - bool _abort_busy; ///< Flag true if abort is in progress - bool _commit_busy; ///< Flag true if commit is in progress - - enum _op_type { WMGR_ENQUEUE = 0, WMGR_DEQUEUE, WMGR_ABORT, WMGR_COMMIT }; - static const char* _op_str[]; - - enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding - deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding - txn_rec _txn_rec; ///< Transaction record used for encoding/decoding - pending_txn_map_t _txn_pending_map; ///< Set containing xids of pending commits/aborts - -public: - wmgr(jcntl* jc, - enq_map& emap, - txn_map& tmap, - LinearFileController& lfc); - wmgr(jcntl* jc, - enq_map& emap, - txn_map& tmap, - LinearFileController& lfc, - const uint32_t max_dtokpp, - const uint32_t max_iowait_us); - virtual ~wmgr(); - - void initialize(aio_callback* const cbp, - const uint32_t wcache_pgsize_sblks, - const uint16_t wcache_num_pages, - const uint32_t max_dtokpp, - const uint32_t max_iowait_us, - std::size_t end_offset); - iores enqueue(const void* const data_buff, - const std::size_t tot_data_len, - const std::size_t this_data_len, - data_tok* dtokp, - const void* const xid_ptr, - const std::size_t xid_len, - const bool tpc_flag, - const bool transient, - const bool external); - iores dequeue(data_tok* dtokp, - const void* const xid_ptr, - const std::size_t xid_len, - const bool tpc_flag, - const bool txn_coml_commit); - iores abort(data_tok* dtokp, - const void* const xid_ptr, - const std::size_t xid_len); - iores commit(data_tok* dtokp, - const void* const xid_ptr, - const std::size_t xid_len); - iores flush(); - int32_t get_events(timespec* const timeout, - bool flush); - bool is_txn_synced(const std::string& xid); - inline bool curr_pg_blocked() const { return _page_cb_arr[_pg_index]._state != UNUSED; } - inline uint32_t unflushed_dblks() { return _cached_offset_dblks; } - - // Debug aid - const std::string status_str() const; - -private: - void initialize(aio_callback* const cbp, - const uint32_t wcache_pgsize_sblks, - const uint16_t wcache_num_pages); - iores pre_write_check(const _op_type op, - const data_tok* const dtokp, - const std::size_t xidsize = 0, - const std::size_t dsize = 0, - const bool external = false) const; - void dequeue_check(const std::string& xid, - const uint64_t drid); - void file_header_check(const uint64_t rid, - const bool cont, - const uint32_t rec_dblks_rem); - void flush_check(iores& res, - bool& cont, - bool& done, const uint64_t rid); - iores write_flush(); - void get_next_file(); - void dblk_roundup(); - void rotate_page(); - void clean(); -}; - -}}} - -#endif // ifndef QPID_LINEARSTORE_JOURNAL_WMGR_H diff --git a/qpid/cpp/src/qpid/linearstore/management-schema.xml b/qpid/cpp/src/qpid/linearstore/management-schema.xml deleted file mode 100644 index ebd388593e..0000000000 --- a/qpid/cpp/src/qpid/linearstore/management-schema.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qpid/cpp/src/qpid/log/Helpers.h b/qpid/cpp/src/qpid/log/Helpers.h deleted file mode 100644 index 82ef8244be..0000000000 --- a/qpid/cpp/src/qpid/log/Helpers.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef QPID_LOG_HELPERS_H -#define QPID_LOG_HELPERS_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 - -#include - -namespace qpid { -namespace log { - -/** @file Helper classes for logging complex types */ - -/// @internal -template -struct ListFormatter { - typedef typename boost::range_const_iterator::type Iterator; - boost::iterator_range range; - const char* separator; - - ListFormatter(const Range& r, const char* s=", ") : range(r), separator(s) {} -}; - -/// @internal -template -std::ostream& operator<<(std::ostream& out, const ListFormatter& sl) { - typename ListFormatter::Iterator i = sl.range.begin(); - if (i != sl.range.end()) out << *(i++); - while (i != sl.range.end()) out << sl.separator << *(i++); - return out; -} - -/** Return a formatting object with operator << - * to stream range as a separated list. - *@param range: a range - all standard containers are ranges, - * as is a pair of iterators. - *@param separator: printed between elements, default ", " - */ -template -ListFormatter formatList(const Range& range, const char* separator=", ") { - return ListFormatter(range, separator); -} - -/** Return a formatting object with operator << - * to stream the range defined by iterators [begin, end) - * as a separated list. - *@param begin, end: Beginning and end of range. - *@param separator: printed between elements, default ", " - */ -template -ListFormatter > formatList(U begin, V end, const char* separator=", ") { - return formatList(std::make_pair(begin,end), separator); -} - - -}} // namespace qpid::log - - - -#endif /*!QPID_LOG_HELPERS_H*/ diff --git a/qpid/cpp/src/qpid/log/Logger.cpp b/qpid/cpp/src/qpid/log/Logger.cpp deleted file mode 100644 index fc254f2857..0000000000 --- a/qpid/cpp/src/qpid/log/Logger.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * - * 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/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/SinkOptions.h" -#include "qpid/memory.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/DisableExceptionLogging.h" - -#include "boost/version.hpp" -#if (BOOST_VERSION >= 104000) -#include -#else -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - - -namespace qpid { -namespace log { - -using namespace std; - -typedef sys::Mutex::ScopedLock ScopedLock; - -inline void Logger::enable_unlocked(Statement* s) { - s->enabled=selector.isEnabled(s->level, s->function, s->category); -} - -Logger& Logger::instance() { -#if (BOOST_VERSION >= 104000) - return boost::serialization::singleton::get_mutable_instance(); -#else - return boost::details::pool::singleton_default::instance(); -#endif -} - -Logger::Logger() : flags(0) { - // Disable automatic logging in Exception constructors to avoid - // re-entrant use of logger singleton if there is an error in - // option parsing. - DisableExceptionLogging del; - - // Initialize myself from env variables so all programs - // (e.g. tests) can use logging even if they don't parse - // command line args. - Options opts; - opts.parse(0, 0); - configure(opts); -} - -Logger::~Logger() {} - -void Logger::select(const Selector& s) { - ScopedLock l(lock); - selector=s; - std::for_each(statements.begin(), statements.end(), - boost::bind(&Logger::enable_unlocked, this, _1)); -} - -Logger::Output::Output() {} -Logger::Output::~Output() {} - -void Logger::log(const Statement& s, const std::string& msg) { - // Format the message outside the lock. - std::ostringstream os; - if (!prefix.empty()) - os << prefix << ": "; - if (flags&TIME) { - if (flags&HIRES) - qpid::sys::outputHiresNow(os); - else - qpid::sys::outputFormattedNow(os); - } - if (flags&CATEGORY) - os << "[" << CategoryTraits::name(s.category) << "] "; - if (flags&LEVEL) - os << LevelTraits::name(s.level) << " "; - if (flags&THREAD) - os << "[0x" << hex << qpid::sys::Thread::logId() << "] "; - if (flags&FILE) - os << s.file << ":"; - if (flags&LINE) - os << dec << s.line << ":"; - if ((flags&FUNCTION) && s.function) - os << s.function << ":"; - if (flags & (FILE|LINE|FUNCTION)) - os << " "; - os << msg << endl; - std::string formatted=os.str(); - { - ScopedLock l(lock); - std::for_each(outputs.begin(), outputs.end(), - boost::bind(&Output::log, _1, s, formatted)); - } -} - -void Logger::output(std::auto_ptr out) { - ScopedLock l(lock); - outputs.push_back(out.release()); -} - -void Logger::clear() { - select(Selector()); // locked - format(0); // locked - ScopedLock l(lock); - outputs.clear(); -} - -void Logger::format(int formatFlags) { - ScopedLock l(lock); - flags=formatFlags; -} - -static int bitIf(bool test, int bit) { - return test ? bit : 0; -} - -int Logger::format(const Options& opts) { - int flags= - bitIf(opts.level, LEVEL) | - bitIf(opts.time, TIME) | - bitIf(opts.source, (FILE|LINE)) | - bitIf(opts.function, FUNCTION) | - bitIf(opts.thread, THREAD) | - bitIf(opts.hiresTs, HIRES) | - bitIf(opts.category, CATEGORY); - format(flags); - return flags; -} - -void Logger::add(Statement& s) { - ScopedLock l(lock); - enable_unlocked(&s); - statements.insert(&s); -} - -void Logger::configure(const Options& opts) { - clear(); - Options o(opts); - if (o.trace) - o.selectors.push_back("trace+"); - format(o); - select(Selector(o)); - options = opts; - setPrefix(opts.prefix); - options.sinkOptions->setup(this); -} - -void Logger::reconfigure(const std::vector& selectors) { - Options o(options); - o.selectors = selectors; - o.deselectors.clear(); - select(Selector(o)); - options = o; // Don't update options till selectors has been validated. -} - -void Logger::setPrefix(const std::string& p) { prefix = p; } - - -bool Logger::getHiresTimestamp() -{ - return flags & HIRES; -} - - -void Logger::setHiresTimestamp(bool setting) -{ - ScopedLock l(lock); - if (setting) - flags |= HIRES; - else - flags &= ~HIRES; -} - -}} // namespace qpid::log diff --git a/qpid/cpp/src/qpid/log/Logger.h b/qpid/cpp/src/qpid/log/Logger.h deleted file mode 100644 index 8c4beb0785..0000000000 --- a/qpid/cpp/src/qpid/log/Logger.h +++ /dev/null @@ -1,122 +0,0 @@ -#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 -#include -#include -#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& 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 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 Outputs; - typedef std::set 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.cpp b/qpid/cpp/src/qpid/log/Options.cpp deleted file mode 100644 index f816124b4e..0000000000 --- a/qpid/cpp/src/qpid/log/Options.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * 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/Options.h" -#include "qpid/log/SinkOptions.h" -#include "qpid/log/Statement.h" -#include "qpid/Options.h" -#include -#include -#include - -namespace qpid { -namespace log { - -Options::Options(const std::string& argv0_, const std::string& name_) : - qpid::Options(name_), - argv0(argv0_), - name(name_), - time(true), - level(true), - thread(false), - source(false), - function(false), - hiresTs(false), - category(true), - trace(false), - sinkOptions (SinkOptions::create(argv0_)) -{ - selectors.push_back("notice+"); - - addOptions() - ("trace,t", optValue(trace), "Enables all logging" ) - ("log-enable", optValue(selectors, "RULE"), - ("Enables logging for selected levels and components. " - "RULE is in the form 'LEVEL[+-][:PATTERN]'\n" - "LEVEL is one of: \n\t "+getLevels()+"\n" - "PATTERN is a logging category name, or a namespace-qualified " - "function name or name fragment. " - "Logging category names are: \n\t "+getCategories()+"\n" - "For example:\n" - "\t'--log-enable warning+'\n" - "logs all warning, error and critical messages.\n" - "\t'--log-enable trace+:Broker'\n" - "logs all category 'Broker' messages.\n" - "\t'--log-enable debug:framing'\n" - "logs debug messages from all functions with 'framing' in the namespace or function name.\n" - "This option can be used multiple times").c_str()) - ("log-disable", optValue(deselectors, "RULE"), - ("Disables logging for selected levels and components. " - "RULE is in the form 'LEVEL[+-][:PATTERN]'\n" - "LEVEL is one of: \n\t "+getLevels()+"\n" - "PATTERN is a logging category name, or a namespace-qualified " - "function name or name fragment. " - "Logging category names are: \n\t "+getCategories()+"\n" - "For example:\n" - "\t'--log-disable warning-'\n" - "disables logging all warning, notice, info, debug, and trace messages.\n" - "\t'--log-disable trace:Broker'\n" - "disables all category 'Broker' trace messages.\n" - "\t'--log-disable debug-:qmf::'\n" - "disables logging debug and trace messages from all functions with 'qmf::' in the namespace.\n" - "This option can be used multiple times").c_str()) - ("log-time", optValue(time, "yes|no"), "Include time in log messages") - ("log-level", optValue(level,"yes|no"), "Include severity level in log messages") - ("log-source", optValue(source,"yes|no"), "Include source file:line in log messages") - ("log-thread", optValue(thread,"yes|no"), "Include thread ID in log messages") - ("log-function", optValue(function,"yes|no"), "Include function signature in log messages") - ("log-hires-timestamp", optValue(hiresTs,"yes|no"), "Use hi-resolution timestamps in log messages") - ("log-category", optValue(category,"yes|no"), "Include category in log messages") - ("log-prefix", optValue(prefix,"STRING"), "Prefix to prepend to all log messages") - ; - add(*sinkOptions); -} - -Options::Options(const Options &o) : - qpid::Options(o.name), - argv0(o.argv0), - name(o.name), - selectors(o.selectors), - deselectors(o.deselectors), - time(o.time), - level(o.level), - thread(o.thread), - source(o.source), - function(o.function), - hiresTs(o.hiresTs), - category(o.category), - trace(o.trace), - prefix(o.prefix), - sinkOptions (SinkOptions::create(o.argv0)) -{ - *sinkOptions = *o.sinkOptions; -} - -Options& Options::operator=(const Options& x) { - if (this != &x) { - argv0 = x.argv0; - name = x.name; - selectors = x.selectors; - deselectors = x.deselectors; - time = x.time; - level= x.level; - thread = x.thread; - source = x.source; - function = x.function; - hiresTs = x.hiresTs; - category = x.category; - trace = x.trace; - prefix = x.prefix; - *sinkOptions = *x.sinkOptions; - } - return *this; -} - -std::string getLevels() -{ - std::ostringstream levels; - levels << LevelTraits::name(Level(0)); - for (int i = 1; i < LevelTraits::COUNT; ++i) - levels << " " << LevelTraits::name(Level(i)); - return levels.str(); -} - -std::string getCategories() -{ - std::ostringstream categories; - categories << CategoryTraits::name(Category(0)); - for (int i = 1; i < CategoryTraits::COUNT; ++i) - categories << " " << CategoryTraits::name(Category(i)); - return categories.str(); -} - -}} // namespace qpid::log diff --git a/qpid/cpp/src/qpid/log/Options.h b/qpid/cpp/src/qpid/log/Options.h deleted file mode 100644 index ed534168e8..0000000000 --- a/qpid/cpp/src/qpid/log/Options.h +++ /dev/null @@ -1,57 +0,0 @@ -#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 -#include - -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 selectors; - std::vector deselectors; - bool time, level, thread, source, function, hiresTs, category; - bool trace; - std::string prefix; - std::auto_ptr sinkOptions; -}; - -/** Get a string list of the allowed levels */ -QPID_COMMON_EXTERN std::string getLevels(); - -/** Get a string list of the allowed categories */ -QPID_COMMON_EXTERN std::string getCategories(); - -}} // namespace qpid::log - -#endif /*!QPID_LOG_OPTIONS_H*/ diff --git a/qpid/cpp/src/qpid/log/OstreamOutput.cpp b/qpid/cpp/src/qpid/log/OstreamOutput.cpp deleted file mode 100644 index 9b6ec1f8aa..0000000000 --- a/qpid/cpp/src/qpid/log/OstreamOutput.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * 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/OstreamOutput.h" -#include - -using namespace std; - -namespace qpid { -namespace log { - -OstreamOutput::OstreamOutput(std::ostream& o) : out(&o) {} - -OstreamOutput::OstreamOutput(const std::string& file) - : out(new ofstream(file.c_str(), ios_base::out | ios_base::app)), - mine(out) -{ - if (!out->good()) - throw std::runtime_error("Can't open log file: "+file); -} - -void OstreamOutput::log(const Statement&, const std::string& m) { - *out << m << flush; -} - -}} // namespace qpid::log diff --git a/qpid/cpp/src/qpid/log/OstreamOutput.h b/qpid/cpp/src/qpid/log/OstreamOutput.h deleted file mode 100644 index 12fd4ce425..0000000000 --- a/qpid/cpp/src/qpid/log/OstreamOutput.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef QPID_LOG_OSTREAMOUTPUT_H -#define QPID_LOG_OSTREAMOUTPUT_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/Logger.h" -#include -#include -#include - -namespace qpid { -namespace log { - -/** - * OstreamOutput is a reusable logging sink that directs logging to a C++ - * ostream. - */ -class OstreamOutput : public qpid::log::Logger::Output { -public: - QPID_COMMON_EXTERN OstreamOutput(std::ostream& o); - QPID_COMMON_EXTERN OstreamOutput(const std::string& file); - - virtual void log(const Statement&, const std::string& m); - -private: - std::ostream* out; - boost::scoped_ptr mine; -}; - -}} // namespace qpid::log - -#endif /*!QPID_LOG_OSTREAMOUTPUT_H*/ diff --git a/qpid/cpp/src/qpid/log/Selector.cpp b/qpid/cpp/src/qpid/log/Selector.cpp deleted file mode 100644 index a517cb34f4..0000000000 --- a/qpid/cpp/src/qpid/log/Selector.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/* - * - * 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/Selector.h" -#include "qpid/log/Options.h" -#include -#include -#include - -namespace qpid { -namespace log { - -using namespace std; - -const char LOG_SYMBOL_DISABLE ('!'); -const char LOG_SYMBOL_SEPERATOR(':'); -const char LOG_SYMBOL_AND_ABOVE('+'); -const char LOG_SYMBOL_AND_BELOW('-'); - -// -// Parse an enable or disable entry into usable fields. -// Throws if 'level' field is not recognized. -// -SelectorElement::SelectorElement(const std::string cliEntry) : - level(qpid::log::debug), - category(qpid::log::unspecified), - isDisable(false), - isCategory(false), - isLevelAndAbove(false), - isLevelAndBelow(false) -{ - if (cliEntry.empty()) - return; - std::string working(cliEntry); - if (LOG_SYMBOL_DISABLE == working[0]) { - isDisable = true; - working = working.substr(1); - } - size_t c=working.find(LOG_SYMBOL_SEPERATOR); - if (c==string::npos) { - levelStr=working; - } else { - levelStr=working.substr(0,c); - patternStr=working.substr(c+1); - } - if (!levelStr.empty()) { - if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_ABOVE) { - isLevelAndAbove = true; - levelStr = levelStr.substr(0, levelStr.size()-1); - } else if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_BELOW) { - isLevelAndBelow = true; - levelStr = levelStr.substr(0, levelStr.size()-1); - } - } - level = LevelTraits::level(levelStr); // throws if bad level name - isCategory = CategoryTraits::isCategory(patternStr); - if (isCategory) { - category = CategoryTraits::category(patternStr); - } -} - -// Empty selector -Selector::Selector() { - reset(); -} - - -// Selector from options -Selector::Selector(const Options& opt){ - reset(); - for_each(opt.selectors.begin(), opt.selectors.end(), - boost::bind(&Selector::enable, this, _1)); - for_each(opt.deselectors.begin(), opt.deselectors.end(), - boost::bind(&Selector::disable, this, _1)); -} - - -// Selector from single level -Selector::Selector(Level l, const std::string& s) { - reset(); - enable(l, s); -} - - -// Selector from single enable -Selector::Selector(const std::string& selector) { - reset(); - enable(selector); -} - - -/** - * Process a single CLI --log-enable option - */ -void Selector::enable(const string& enableStr) { - if (enableStr.empty()) - return; - SelectorElement se(enableStr); - if (se.isDisable) { - // Disable statements are allowed in an enable string as a convenient - // way to process management strings that have enable/disable mixed. - disable(enableStr); - } else if (se.isLevelAndAbove) { - for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) { - if (se.isCategory) { - enableFlags[lvl][se.category] = true; - } else { - enable(Level(lvl), se.patternStr); - } - } - } else if (se.isLevelAndBelow) { - for (int lvl = se.level; lvl >= 0; --lvl) { - if (se.isCategory) { - enableFlags[lvl][se.category] = true; - } else { - enable(Level(lvl), se.patternStr); - } - } - } else { - if (se.isCategory) { - enableFlags[se.level][se.category] = true; - } else { - enable(se.level, se.patternStr); - } - } -} - -void Selector::disable(const string& disableStr) { - if (disableStr.empty()) - return; - SelectorElement se(disableStr); - if (se.isLevelAndAbove) { - for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) { - if (se.isCategory) { - disableFlags[lvl][se.category] = true; - } else { - disable(Level(lvl), se.patternStr); - } - } - } else if (se.isLevelAndBelow) { - for (int lvl = se.level; lvl >= 0; --lvl) { - if (se.isCategory) { - disableFlags[lvl][se.category] = true; - } else { - disable(Level(lvl), se.patternStr); - } - } - } else { - if (se.isCategory) { - disableFlags[se.level][se.category] = true; - } else { - disable(se.level, se.patternStr); - } - } -} - - -/** -* Enable/disable messages with level in levels where the file -* name contains substring. -*/ -void Selector::enable(Level level, const std::string& substring) { - enabledFunctions[level].push_back(substring); -} - - -void Selector::disable(Level level, const std::string& substring) { - disabledFunctions[level].push_back(substring); -} - - -void Selector::reset() { - // Initialize fields in a Selector that are not automatically set - for (int lt = 0; lt < LevelTraits::COUNT; ++lt) - for (int ct = 0; ct < CategoryTraits::COUNT; ++ct) - enableFlags[lt][ct] = disableFlags[lt][ct] = false; -} - - -bool Selector::lookupFuncName(Level level, const char* function, FunctionNameTable& table) { - const char* functionEnd = function+::strlen(function); - for (std::vector::iterator i=table[level].begin(); - i != table[level].end(); - ++i) - { - if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd) - return true; - } - return false; -} - - -bool Selector::isEnabled(Level level, const char* function) { - return lookupFuncName(level, function, enabledFunctions); -} - -bool Selector::isDisabled(Level level, const char* function) { - return lookupFuncName(level, function, disabledFunctions); -} - -// -// isEnabled -// -// Determines if all the fields in this Selector enable or disable a -// level/function/category set from an actual QPID_LOG Statement. -// -bool Selector::isEnabled(Level level, const char* function, Category category) { - if (level==critical) - return true; // critical cannot be disabled - if (isDisabled(level, function)) - return false; // Disabled by function name - if (disableFlags[level][category]) - return false; // Disabled by category name - if (isEnabled(level, function)) - return true; // Enabled by function name - if (enableFlags[level][category]) - return true; // Enabled by category name - else - return false; // Unspecified defaults to disabled -} - -}} // namespace qpid::log diff --git a/qpid/cpp/src/qpid/log/Selector.h b/qpid/cpp/src/qpid/log/Selector.h deleted file mode 100644 index 1d025e9646..0000000000 --- a/qpid/cpp/src/qpid/log/Selector.h +++ /dev/null @@ -1,99 +0,0 @@ -#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 - -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 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 deleted file mode 100644 index 7ec2cfbc17..0000000000 --- a/qpid/cpp/src/qpid/log/SinkOptions.h +++ /dev/null @@ -1,64 +0,0 @@ -#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 - -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.cpp b/qpid/cpp/src/qpid/log/Statement.cpp deleted file mode 100644 index 86b069fd91..0000000000 --- a/qpid/cpp/src/qpid/log/Statement.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * - * 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/log/Logger.h" -#include -#include -#include -#include -#include - -namespace qpid { -namespace log { - -namespace { -struct NonPrint { bool operator()(unsigned char c) { return !isprint(c) && !isspace(c); } }; - -const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -std::string quote(const std::string& str) { - NonPrint nonPrint; - size_t n = std::count_if(str.begin(), str.end(), nonPrint); - if (n==0) return str; - std::string ret; - ret.reserve(str.size()+3*n); // Avoid extra allocations. - for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) { - if (nonPrint(*i)) { - ret.push_back('\\'); - ret.push_back('x'); - ret.push_back(hex[((*i) >> 4)&0xf]); - ret.push_back(hex[(*i) & 0xf]); - } - else ret.push_back(*i); - } - return ret; -} -} - -// -// Instance of name hints -// -class CategoryFileNameHints { -public: - CategoryFileNameHints(){ - hintList.push_back(std::make_pair("AsynchIo", network)); - hintList.push_back(std::make_pair("TCP", network)); - hintList.push_back(std::make_pair("epoll", network)); - hintList.push_back(std::make_pair("Pollable", network)); - hintList.push_back(std::make_pair("Socket", network)); - - hintList.push_back(std::make_pair("Sasl", security)); - hintList.push_back(std::make_pair("Ssl", security)); - hintList.push_back(std::make_pair("Acl", security)); - hintList.push_back(std::make_pair("acl", security)); - hintList.push_back(std::make_pair("cyrus", security)); - - hintList.push_back(std::make_pair("amqp_", protocol)); - hintList.push_back(std::make_pair("framing", protocol)); - - hintList.push_back(std::make_pair("management", management)); - hintList.push_back(std::make_pair("qmf", management)); - hintList.push_back(std::make_pair("console", management)); - hintList.push_back(std::make_pair("Management", management)); - - hintList.push_back(std::make_pair("cluster", ha)); - hintList.push_back(std::make_pair("qpid/ha", ha)); - hintList.push_back(std::make_pair("qpid\\ha", ha)); - hintList.push_back(std::make_pair("replication", ha)); - hintList.push_back(std::make_pair("ClusterSafe", ha)); - - hintList.push_back(std::make_pair("broker", broker)); - hintList.push_back(std::make_pair("SessionState",broker)); - hintList.push_back(std::make_pair("DataDir", broker)); - hintList.push_back(std::make_pair("qpidd", broker)); - hintList.push_back(std::make_pair("xml", broker)); - hintList.push_back(std::make_pair("QpidBroker", broker)); - - hintList.push_back(std::make_pair("store", store)); - - hintList.push_back(std::make_pair("assert", system)); - hintList.push_back(std::make_pair("Exception", system)); - hintList.push_back(std::make_pair("sys", system)); - hintList.push_back(std::make_pair("SCM", system)); - - hintList.push_back(std::make_pair("tests", test)); - - hintList.push_back(std::make_pair("messaging", messaging)); - hintList.push_back(std::make_pair("types", messaging)); - - hintList.push_back(std::make_pair("client", client)); - } - - static Category categoryOf(const char*const fName); - -private: - std::list > hintList; -}; - -static CategoryFileNameHints filenameHints; - -Category CategoryFileNameHints::categoryOf(const char* const fName) { - for (std::list >::iterator - it = filenameHints.hintList.begin(); - it != filenameHints.hintList.end(); - ++it) { - if (strstr(fName, (const char* const)it->first) != 0) { - return it->second; - } - } - return unspecified; -} - - -void Statement::categorize(Statement& s) { - // given a statement and it's category - // if the category is Unspecified then try to find a - // better category based on the path and file name. - if (s.category == log::unspecified) { - s.category = CategoryFileNameHints::categoryOf(s.file); - } else { - // already has a category so leave it alone - } -} - - -void Statement::log(const std::string& message) { - Logger::instance().log(*this, quote(message)); -} - - -Statement::Initializer::Initializer(Statement& s) : statement(s) { - // QPID-3891: - // From the given BOOST_CURRENT_FUNCTION name extract only the - // namespace-qualified-functionName, skipping return and calling args. - // Given: - // qpid::name::space::Function(args) - // Return: - // "qpid::name::space::Function". - if (s.function) { - const char* end = s.function + strlen(s.function); - const char* fEnd = std::find(s.function, end, '('); - typedef std::reverse_iterator Reverse; - const char* fBegin = find(Reverse(fEnd), Reverse(s.function), ' ').base(); - size_t n = fEnd - fBegin; - char* name = new char[n+1]; - std::copy(fBegin, fEnd, name); - name[n] = '\0'; - s.function = name; - } - Statement::categorize(s); - Logger::instance().add(s); -} - -Statement::Initializer::~Initializer() { - delete[] const_cast(statement.function); - statement.function = 0; -} - - -namespace { -const char* names[LevelTraits::COUNT] = { - "trace", "debug", "info", "notice", "warning", "error", "critical" -}; - -const char* catNames[CategoryTraits::COUNT] = { - "Security", "Broker", "Management", "Protocol", "System", "HA", "Messaging", - "Store", "Network", "Test", "Client", "Application", "Model", "Unspecified" -}; - -} // namespace -Level LevelTraits::level(const char* name) { - for (int i =0; i < LevelTraits::COUNT; ++i) { - if (strcmp(names[i], name)==0) - return Level(i); - } - throw std::runtime_error(std::string("Invalid log level name: ")+name); -} - -const char* LevelTraits::name(Level l) { - return names[l]; -} - -bool CategoryTraits::isCategory(const std::string& name) { - for (int i =0; i < CategoryTraits::COUNT; ++i) { - if (strcmp(catNames[i], name.c_str())==0) - return true; - } - return false; -} - -Category CategoryTraits::category(const char* name) { - for (int i =0; i < CategoryTraits::COUNT; ++i) { - if (strcmp(catNames[i], name)==0) - return Category(i); - } - throw std::runtime_error(std::string("Invalid log category name: ")+name); -} - -const char* CategoryTraits::name(Category c) { - return catNames[c]; -} - -}} // namespace qpid::log diff --git a/qpid/cpp/src/qpid/log/Statement.h b/qpid/cpp/src/qpid/log/Statement.h deleted file mode 100644 index 410ffaaa3d..0000000000 --- a/qpid/cpp/src/qpid/log/Statement.h +++ /dev/null @@ -1,244 +0,0 @@ -#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 - -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 - * External_application - * Model - * Unspecified - */ -enum Category { security, broker, management, protocol, system, ha, messaging, - store, network, test, client, external_application, 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); - QPID_COMMON_EXTERN ~Initializer(); - 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/log/posix/SinkOptions.cpp b/qpid/cpp/src/qpid/log/posix/SinkOptions.cpp deleted file mode 100644 index 210022551e..0000000000 --- a/qpid/cpp/src/qpid/log/posix/SinkOptions.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * - * 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/posix/SinkOptions.h" -#include "qpid/log/SinkOptions.h" -#include "qpid/log/Logger.h" -#include "qpid/log/OstreamOutput.h" -#include "qpid/OptionsTemplates.h" -#include "qpid/memory.h" -#include "qpid/Exception.h" - -#include -#include -#include -#include - -#include - -using std::string; -using qpid::Exception; - -namespace qpid { - -template po::value_semantic* create_value(log::posix::SyslogFacility& val, const std::string& arg); - -namespace log { -namespace posix { - -namespace { - -// SyslogFacilities maps from syslog values to the text equivalents. -class SyslogFacilities { -public: - typedef std::map ByName; - typedef std::map ByValue; - - SyslogFacilities() { - struct NameValue { const char* name; int value; }; - NameValue nameValue[] = { - { "AUTH", LOG_AUTH }, -#ifdef HAVE_LOG_AUTHPRIV - { "AUTHPRIV", LOG_AUTHPRIV }, -#endif - { "CRON", LOG_CRON }, - { "DAEMON", LOG_DAEMON }, -#ifdef HAVE_LOG_FTP - { "FTP", LOG_FTP }, -#endif - { "KERN", LOG_KERN }, - { "LOCAL0", LOG_LOCAL0 }, - { "LOCAL1", LOG_LOCAL1 }, - { "LOCAL2", LOG_LOCAL2 }, - { "LOCAL3", LOG_LOCAL3 }, - { "LOCAL4", LOG_LOCAL4 }, - { "LOCAL5", LOG_LOCAL5 }, - { "LOCAL6", LOG_LOCAL6 }, - { "LOCAL7", LOG_LOCAL7 }, - { "LPR", LOG_LPR }, - { "MAIL", LOG_MAIL }, - { "NEWS", LOG_NEWS }, - { "SYSLOG", LOG_SYSLOG }, - { "USER", LOG_USER }, - { "UUCP", LOG_UUCP } - }; - for (size_t i = 0; i < sizeof(nameValue)/sizeof(nameValue[0]); ++i) { - byName.insert(ByName::value_type(nameValue[i].name, nameValue[i].value)); - // Recognise with and without LOG_ prefix e.g.: AUTH and LOG_AUTH - byName.insert(ByName::value_type(string("LOG_")+nameValue[i].name, nameValue[i].value)); - byValue.insert(ByValue::value_type(nameValue[i].value, string("LOG_")+nameValue[i].name)); - } - } - - int value(const string& name) const { - string key(name); - std::transform(key.begin(), key.end(), key.begin(), ::toupper); - ByName::const_iterator i = byName.find(key); - if (i == byName.end()) - throw Exception("Not a valid syslog facility: " + name); - return i->second; - } - - string name(int value) const { - ByValue::const_iterator i = byValue.find(value); - if (i == byValue.end()) - throw Exception("Not a valid syslog value: " + boost::lexical_cast(value)); - return i->second; - } - - private: - ByName byName; - ByValue byValue; -}; - -// 'priorities' maps qpid log levels to syslog priorities. They are in -// order of qpid log levels and must map to: -// "trace", "debug", "info", "notice", "warning", "error", "critical" -static int priorities[qpid::log::LevelTraits::COUNT] = { - LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_NOTICE, - LOG_WARNING, LOG_ERR, LOG_CRIT -}; - -std::string basename(const std::string path) { - size_t i = path.find_last_of('/'); - return path.substr((i == std::string::npos) ? 0 : i+1); -} - -} // namespace - -std::ostream& operator<<(std::ostream& o, const SyslogFacility& f) { - return o << SyslogFacilities().name(f.value); -} - -std::istream& operator>>(std::istream& i, SyslogFacility& f) { - std::string name; - i >> name; - f.value = SyslogFacilities().value(name); - return i; -} - -class SyslogOutput : public qpid::log::Logger::Output { -public: - SyslogOutput(const std::string& logName, const SyslogFacility& logFacility) - : name(logName), facility(logFacility.value) - { - ::openlog(name.c_str(), LOG_PID, facility); - } - - virtual ~SyslogOutput() { - ::closelog(); - } - - virtual void log(const Statement& s, const std::string& m) - { - syslog(priorities[s.level], "%s", m.c_str()); - } - -private: - std::string name; - int facility; -}; - -SinkOptions::SinkOptions(const std::string& argv0) - : qpid::log::SinkOptions(), - logToStderr(true), - logToStdout(false), - logToSyslog(false), - syslogName(basename(argv0)), - syslogFacility(LOG_DAEMON) { - - addOptions() - ("log-to-stderr", optValue(logToStderr, "yes|no"), "Send logging output to stderr") - ("log-to-stdout", optValue(logToStdout, "yes|no"), "Send logging output to stdout") - ("log-to-file", optValue(logFile, "FILE"), "Send log output to FILE.") - ("log-to-syslog", optValue(logToSyslog, "yes|no"), "Send logging output to syslog;\n\tcustomize using --syslog-name and --syslog-facility") - ("syslog-name", optValue(syslogName, "NAME"), "Name to use in syslog messages") - ("syslog-facility", optValue(syslogFacility,"LOG_XXX"), "Facility to use in syslog messages") - ; - -} - -qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs) { - const SinkOptions *prhs = dynamic_cast(&rhs); - if (this != prhs) { - logToStderr = prhs->logToStderr; - logToStdout = prhs->logToStdout; - logToSyslog = prhs->logToSyslog; - logFile = prhs->logFile; - syslogName = prhs->syslogName; - syslogFacility.value = prhs->syslogFacility.value; - } - return *this; -} - -void SinkOptions::detached(void) { - if (logToStderr && !logToStdout && !logToSyslog && logFile.empty()) { - logToStderr = false; - logToSyslog = true; - } -} - -// The Logger acting on these options calls setup() to request any -// Sinks be set up and fed back to the logger. -void SinkOptions::setup(qpid::log::Logger *logger) { - if (logToStderr) - logger->output(make_auto_ptr - (new qpid::log::OstreamOutput(std::clog))); - if (logToStdout) - logger->output(make_auto_ptr - (new qpid::log::OstreamOutput(std::cout))); - - if (logFile.length() > 0) - logger->output(make_auto_ptr - (new qpid::log::OstreamOutput(logFile))); - - if (logToSyslog) - logger->output(make_auto_ptr - (new SyslogOutput(syslogName, syslogFacility))); - -} - -} // namespace qpid::log::posix - -SinkOptions* SinkOptions::create(const std::string& argv0) { - return new qpid::log::posix::SinkOptions (argv0); -} - -}} // namespace qpid::log diff --git a/qpid/cpp/src/qpid/log/posix/SinkOptions.h b/qpid/cpp/src/qpid/log/posix/SinkOptions.h deleted file mode 100644 index d929c29025..0000000000 --- a/qpid/cpp/src/qpid/log/posix/SinkOptions.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_LOG_POSIX_SINKOPTIONS_H -#define QPID_LOG_POSIX_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/log/SinkOptions.h" -#include - -namespace qpid { -namespace log { -namespace posix { - -/** - * Provides a type that can be passed to << and >> operators to convert - * syslog facility values to/from strings. - */ -struct SyslogFacility { - int value; - SyslogFacility(int i=0) : value(i) {} -}; - -struct SinkOptions : public qpid::log::SinkOptions { - SinkOptions(const std::string& argv0); - virtual ~SinkOptions() {} - - virtual qpid::log::SinkOptions& operator=(const qpid::log::SinkOptions& rhs); - - // 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); - - // The Logger acting on these options calls setup() to request any - // Sinks be set up and fed back to the logger. - virtual void setup(qpid::log::Logger *logger); - - bool logToStderr; - bool logToStdout; - bool logToSyslog; - std::string logFile; - std::string syslogName; - SyslogFacility syslogFacility; -}; - -}}} // namespace qpid::log::posix - -#endif /*!QPID_LOG_POSIX_SINKOPTIONS_H*/ diff --git a/qpid/cpp/src/qpid/log/windows/SinkOptions.cpp b/qpid/cpp/src/qpid/log/windows/SinkOptions.cpp deleted file mode 100644 index 0c74bea64e..0000000000 --- a/qpid/cpp/src/qpid/log/windows/SinkOptions.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * 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/windows/SinkOptions.h" -#include "qpid/log/SinkOptions.h" -#include "qpid/log/Logger.h" -#include "qpid/log/OstreamOutput.h" -#include "qpid/memory.h" -#include "qpid/Exception.h" -#include -#include -#include - -#include - -using qpid::Exception; - -namespace qpid { -namespace log { -namespace windows { - -namespace { - -// 'eventTypes' maps qpid log levels to Windows event types. They are in -// order of qpid log levels and must map to: -// "trace", "debug", "info", "notice", "warning", "error", "critical" -static int eventTypes[qpid::log::LevelTraits::COUNT] = { - EVENTLOG_INFORMATION_TYPE, /* trace */ - EVENTLOG_INFORMATION_TYPE, /* debug */ - EVENTLOG_INFORMATION_TYPE, /* info */ - EVENTLOG_INFORMATION_TYPE, /* notice */ - EVENTLOG_WARNING_TYPE, /* warning */ - EVENTLOG_ERROR_TYPE, /* error */ - EVENTLOG_ERROR_TYPE /* critical */ -}; - -} // namespace - -class EventLogOutput : public qpid::log::Logger::Output { -public: - EventLogOutput(const std::string& /*sourceName*/) : logHandle(0) - { - logHandle = OpenEventLog(0, "Application"); - } - - virtual ~EventLogOutput() { - if (logHandle) - CloseEventLog(logHandle); - } - - virtual void log(const Statement& s, const std::string& m) - { - if (logHandle) { - const char *msg = m.c_str(); - ReportEvent(logHandle, - eventTypes[s.level], - 0, /* category unused */ - 0, /* event id */ - 0, /* user security id */ - 1, /* number of strings */ - 0, /* no event-specific data */ - &msg, - 0); - } - } - -private: - HANDLE logHandle; -}; - -SinkOptions::SinkOptions(const std::string& /*argv0*/) - : qpid::log::SinkOptions(), - logToStderr(true), - logToStdout(false), - logToEventLog(false), - eventSource("Application") -{ - addOptions() - ("log-to-stderr", optValue(logToStderr, "yes|no"), "Send logging output to stderr") - ("log-to-stdout", optValue(logToStdout, "yes|no"), "Send logging output to stdout") - ("log-to-file", optValue(logFile, "FILE"), "Send log output to FILE.") - ("log-to-eventlog", optValue(logToEventLog, "yes|no"), "Send logging output to event log;\n\tcustomize using --syslog-name and --syslog-facility") - ("eventlog-source-name", optValue(eventSource, "Application"), "Event source to log to") - ; - -} - -qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs) { - const SinkOptions *prhs = dynamic_cast(&rhs); - if (this != prhs) { - logToStderr = prhs->logToStderr; - logToStdout = prhs->logToStdout; - logToEventLog = prhs->logToEventLog; - eventSource = prhs->eventSource; - logFile = prhs->logFile; - } - return *this; -} - -void SinkOptions::detached(void) { - if (logToStderr && !logToStdout && !logToEventLog) { - logToStderr = false; - logToEventLog = true; - } -} - -// The Logger acting on these options calls setup() to request any -// Sinks be set up and fed back to the logger. -void SinkOptions::setup(qpid::log::Logger *logger) { - if (logToStderr) - logger->output(make_auto_ptr - (new qpid::log::OstreamOutput(std::clog))); - if (logToStdout) - logger->output(make_auto_ptr - (new qpid::log::OstreamOutput(std::cout))); - - if (logFile.length() > 0) - logger->output(make_auto_ptr - (new qpid::log::OstreamOutput(logFile))); - - if (logToEventLog) - logger->output(make_auto_ptr - (new EventLogOutput(eventSource))); - -} - -} // namespace windows - -SinkOptions* SinkOptions::create(const std::string& argv0) { - return new qpid::log::windows::SinkOptions (argv0); -} - -}} // namespace qpid::log diff --git a/qpid/cpp/src/qpid/log/windows/SinkOptions.h b/qpid/cpp/src/qpid/log/windows/SinkOptions.h deleted file mode 100644 index f270c504a2..0000000000 --- a/qpid/cpp/src/qpid/log/windows/SinkOptions.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_LOG_WINDOWS_SINKOPTIONS_H -#define QPID_LOG_WINDOWS_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/log/SinkOptions.h" -#include - -namespace qpid { -namespace log { -namespace windows { - -struct QPID_COMMON_CLASS_EXTERN SinkOptions : public qpid::log::SinkOptions { - QPID_COMMON_EXTERN SinkOptions(const std::string& argv0); - virtual ~SinkOptions() {} - - QPID_COMMON_EXTERN virtual qpid::log::SinkOptions& operator=(const qpid::log::SinkOptions& rhs); - - // This allows the caller to indicate that there's no normal outputs - // available. For example, when running as a service. In these cases, the - // platform's "syslog"-type output should replace the default stderr - // unless some other sink has been selected. - QPID_COMMON_EXTERN virtual void detached(void); - - // The Logger acting on these options calls setup() to request any - // Sinks be set up and fed back to the logger. - QPID_COMMON_EXTERN virtual void setup(qpid::log::Logger *logger); - - bool logToStderr; - bool logToStdout; - bool logToEventLog; - std::string eventSource; - std::string logFile; -}; - -}}} // namespace qpid::log::windows - -#endif /*!QPID_LOG_WINDOWS_SINKOPTIONS_H*/ diff --git a/qpid/cpp/src/qpid/management/Args.h b/qpid/cpp/src/qpid/management/Args.h deleted file mode 100644 index 5d1cb7e01d..0000000000 --- a/qpid/cpp/src/qpid/management/Args.h +++ /dev/null @@ -1,44 +0,0 @@ -#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.cpp b/qpid/cpp/src/qpid/management/Buffer.cpp deleted file mode 100644 index 0ad6e9a851..0000000000 --- a/qpid/cpp/src/qpid/management/Buffer.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/management/Buffer.h" -#include "qpid/framing/Buffer.h" -#include "qpid/amqp_0_10/Codecs.h" - -using namespace std; - -namespace qpid { -namespace management { - -Buffer::Buffer(char* data, uint32_t size) : impl(new framing::Buffer(data, size)) {} -Buffer::~Buffer() { delete impl; } -void Buffer::reset() { impl->reset(); } -uint32_t Buffer::available() { return impl->available(); } -uint32_t Buffer::getSize() { return impl->getSize(); } -uint32_t Buffer::getPosition() { return impl->getPosition(); } -void Buffer::setPosition(uint32_t p) { impl->setPosition(p); } -char* Buffer::getPointer() { return impl->getPointer(); } -void Buffer::putOctet(uint8_t i) { impl->putOctet(i); } -void Buffer::putShort(uint16_t i) { impl->putShort(i); } -void Buffer::putLong(uint32_t i) { impl->putLong(i); } -void Buffer::putLongLong(uint64_t i) { impl->putLongLong(i); } -void Buffer::putInt8(int8_t i) { impl->putInt8(i); } -void Buffer::putInt16(int16_t i) { impl->putInt16(i); } -void Buffer::putInt32(int32_t i) { impl->putInt32(i); } -void Buffer::putInt64(int64_t i) { impl->putInt64(i); } -void Buffer::putFloat(float i) { impl->putFloat(i); } -void Buffer::putDouble(double i) { impl->putDouble(i); } -void Buffer::putBin128(const uint8_t* i) { impl->putBin128(i); } -uint8_t Buffer::getOctet() { return impl->getOctet(); } -uint16_t Buffer::getShort() { return impl->getShort(); } -uint32_t Buffer::getLong() { return impl->getLong(); } -uint64_t Buffer::getLongLong() { return impl->getLongLong(); } -int8_t Buffer:: getInt8() { return impl-> getInt8(); } -int16_t Buffer::getInt16() { return impl->getInt16(); } -int32_t Buffer::getInt32() { return impl->getInt32(); } -int64_t Buffer::getInt64() { return impl->getInt64(); } -float Buffer::getFloat() { return impl->getFloat(); } -double Buffer::getDouble() { return impl->getDouble(); } -void Buffer::putShortString(const string& i) { impl->putShortString(i); } -void Buffer::putMediumString(const string& i) { impl->putMediumString(i); } -void Buffer::putLongString(const string& i) { impl->putLongString(i); } -void Buffer::getShortString(string& i) { impl->getShortString(i); } -void Buffer::getMediumString(string& i) { impl->getMediumString(i); } -void Buffer::getLongString(string& i) { impl->getLongString(i); } -void Buffer::getBin128(uint8_t* i) { impl->getBin128(i); } -void Buffer::putRawData(const string& i) { impl->putRawData(i); } -void Buffer::getRawData(string& s, uint32_t size) { impl->getRawData(s, size); } -void Buffer::putRawData(const uint8_t* data, size_t size) { impl->putRawData(data, size); } -void Buffer::getRawData(uint8_t* data, size_t size) { impl->getRawData(data, size); } - -void Buffer::putMap(const types::Variant::Map& i) -{ - string encoded; - amqp_0_10::MapCodec::encode(i, encoded); - impl->putRawData(encoded); -} - -void Buffer::putList(const types::Variant::List& i) -{ - string encoded; - amqp_0_10::ListCodec::encode(i, encoded); - impl->putRawData(encoded); -} - -void Buffer::getMap(types::Variant::Map& map) -{ - string encoded; - uint32_t saved = impl->getPosition(); - uint32_t length = impl->getLong(); - impl->setPosition(saved); - impl->getRawData(encoded, length + sizeof(uint32_t)); - amqp_0_10::MapCodec::decode(encoded, map); -} - -void Buffer::getList(types::Variant::List& list) -{ - string encoded; - uint32_t saved = impl->getPosition(); - uint32_t length = impl->getLong(); - impl->setPosition(saved); - impl->getRawData(encoded, length + sizeof(uint32_t)); - amqp_0_10::ListCodec::decode(encoded, list); -} - -}} diff --git a/qpid/cpp/src/qpid/management/Buffer.h b/qpid/cpp/src/qpid/management/Buffer.h deleted file mode 100644 index 1ac52bf276..0000000000 --- a/qpid/cpp/src/qpid/management/Buffer.h +++ /dev/null @@ -1,105 +0,0 @@ -#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 - -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.cpp b/qpid/cpp/src/qpid/management/ConnectionSettings.cpp deleted file mode 100644 index 1421a26867..0000000000 --- a/qpid/cpp/src/qpid/management/ConnectionSettings.cpp +++ /dev/null @@ -1,40 +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/ConnectionSettings.h" -#include "qpid/Version.h" - -qpid::management::ConnectionSettings::ConnectionSettings() : - protocol("tcp"), - host("localhost"), - port(5672), - locale("en_US"), - heartbeat(0), - maxChannels(32767), - maxFrameSize(65535), - bounds(2), - tcpNoDelay(false), - service(qpid::saslName), - minSsf(0), - maxSsf(256) -{} - -qpid::management::ConnectionSettings::~ConnectionSettings() {} - diff --git a/qpid/cpp/src/qpid/management/ConnectionSettings.h b/qpid/cpp/src/qpid/management/ConnectionSettings.h deleted file mode 100644 index b631ffa658..0000000000 --- a/qpid/cpp/src/qpid/management/ConnectionSettings.h +++ /dev/null @@ -1,118 +0,0 @@ -#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 - -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.cpp b/qpid/cpp/src/qpid/management/Manageable.cpp deleted file mode 100644 index 651215ffb5..0000000000 --- a/qpid/cpp/src/qpid/management/Manageable.cpp +++ /dev/null @@ -1,53 +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" - -using namespace qpid::management; -using std::string; - -string Manageable::StatusText (status_t status, string text) -{ - if ((status & STATUS_USER) == STATUS_USER) - return text; - - switch (status) - { - case STATUS_OK : return "OK"; - case STATUS_UNKNOWN_OBJECT : return "UnknownObject"; - case STATUS_UNKNOWN_METHOD : return "UnknownMethod"; - case STATUS_NOT_IMPLEMENTED : return "NotImplemented"; - case STATUS_PARAMETER_INVALID : return "InvalidParameter"; - case STATUS_FEATURE_NOT_IMPLEMENTED : return "FeatureNotImplemented"; - case STATUS_FORBIDDEN : return "Forbidden"; - } - - return "??"; -} - -Manageable::status_t Manageable::ManagementMethod (uint32_t, Args&, std::string&) -{ - return STATUS_UNKNOWN_METHOD; -} - -bool Manageable::AuthorizeMethod(uint32_t, Args&, const std::string&) -{ - return true; -} - diff --git a/qpid/cpp/src/qpid/management/Manageable.h b/qpid/cpp/src/qpid/management/Manageable.h deleted file mode 100644 index 5b263e195d..0000000000 --- a/qpid/cpp/src/qpid/management/Manageable.h +++ /dev/null @@ -1,79 +0,0 @@ -#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/CommonImportExport.h" -#include "qpid/management/Args.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/sys/IntegerTypes.h" - -#include - -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. - // - virtual ManagementObject::shared_ptr GetManagementObject() const = 0; - - // 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 deleted file mode 100644 index 516babce61..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementAgent.cpp +++ /dev/null @@ -1,2832 +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. - * - */ - - -// NOTE on use of log levels: The criteria for using trace vs. debug -// is to use trace for log messages that are generated for each -// unbatched stats/props notification and debug for everything else. - -#include "qpid/management/ManagementAgent.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/log/Statement.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Broker.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/Thread.h" -#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" -#include "qpid/amqp_0_10/Codecs.h" -#include -#include -#include -#include -#include - -#include -#include - -namespace qpid { -namespace management { - -using boost::intrusive_ptr; -using qpid::framing::Uuid; -using qpid::types::Variant; -using qpid::amqp_0_10::MapCodec; -using qpid::amqp_0_10::ListCodec; -using namespace qpid::framing; -using namespace qpid::broker; -using namespace qpid; -using namespace std; -namespace _qmf = qmf::org::apache::qpid::broker; - - -namespace { -const size_t qmfV1BufferSize(65536); -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; -} - -struct ScopedManagementContext -{ - const Connection* context; - - ScopedManagementContext(const Connection* p) : context(p) - { - if (p) setManagementExecutionContext(*p); - } - - management::ObjectId getObjectId() const - { - return context ? context->getObjectId() : management::ObjectId(); - } - std::string getUserId() const - { - return context ? context->getUserId() : std::string(); - } - std::string getMgmtId() const - { - return context ? context->getMgmtId() : std::string(); - } - - - ~ScopedManagementContext() - { - resetManagementExecutionContext(); - } -}; - -typedef boost::function0 FireFunction; -struct Periodic : public qpid::sys::TimerTask -{ - FireFunction fireFunction; - qpid::sys::Timer* timer; - - Periodic (FireFunction f, qpid::sys::Timer* t, uint32_t seconds); - virtual ~Periodic (); - void fire (); -}; - -Periodic::Periodic (FireFunction f, qpid::sys::Timer* t, uint32_t _seconds) - : TimerTask(sys::Duration((_seconds ? _seconds : 1) * sys::TIME_SEC), - "ManagementAgent::periodicProcessing"), - fireFunction(f), timer(t) {} - -Periodic::~Periodic() {} - -void Periodic::fire() -{ - setupNextFire(); - timer->add(this); - fireFunction(); -} - -} - - -static Variant::Map mapEncodeSchemaId(const string& pname, - const string& cname, - const string& type, - const uint8_t *md5Sum) -{ - Variant::Map map_; - - map_["_package_name"] = pname; - map_["_class_name"] = cname; - map_["_type"] = type; - map_["_hash"] = qpid::types::Uuid(md5Sum); - return map_; -} - - -ManagementAgent::RemoteAgent::~RemoteAgent () -{ - QPID_LOG(debug, "Remote Agent removed bank=[" << brokerBank << "." << agentBank << "]"); - if (mgmtObject != 0) { - mgmtObject->resourceDestroy(); - agent.deleteObjectNow(mgmtObject->getObjectId()); - mgmtObject.reset(); - } -} - -ManagementAgent::ManagementAgent (const bool qmfV1, const bool qmfV2) : - threadPoolSize(1), publish(true), interval(10), broker(0), timer(0), protocols(0), - startTime(sys::now()), - suppressed(false), disallowAllV1Methods(false), - vendorNameKey(defaultVendorName), productNameKey(defaultProductName), - qmf1Support(qmfV1), qmf2Support(qmfV2), maxReplyObjs(100) -{ - nextObjectId = 1; - brokerBank = 1; - bootSequence = 1; - nextRemoteBank = 10; - nextRequestSequence = 1; - clientWasAdded = false; - attrMap["_vendor"] = defaultVendorName; - attrMap["_product"] = defaultProductName; - - memstat = _qmf::Memory::shared_ptr(new qmf::org::apache::qpid::broker::Memory(this, 0, "amqp-broker")); - addObject(memstat, "amqp-broker"); -} - -ManagementAgent::~ManagementAgent () -{ - { - sys::Mutex::ScopedLock lock (userLock); - - // Reset the shared pointers to exchanges. If this is not done now, the exchanges - // will stick around until dExchange and mExchange are implicitly destroyed (long - // after this destructor completes). Those exchanges hold references to management - // objects that will be invalid. - dExchange.reset(); - mExchange.reset(); - v2Topic.reset(); - v2Direct.reset(); - - remoteAgents.clear(); - } -} - -void ManagementAgent::configure(const string& _dataDir, bool _publish, uint16_t _interval, - qpid::broker::Broker* _broker, int _threads) -{ - dataDir = _dataDir; - publish = _publish; - interval = _interval; - broker = _broker; - threadPoolSize = _threads; - ManagementObject::maxThreads = threadPoolSize; - sendQueue.reset( - new EventQueue(boost::bind(&ManagementAgent::sendEvents, this, _1), broker->getPoller())); - sendQueue->start(); - 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()) - { - uuid.generate(); - QPID_LOG (info, "ManagementAgent has no data directory, generated new broker ID: " - << uuid); - } - else - { - string filename(dataDir + "/.mbrokerdata"); - ifstream inFile(filename.c_str ()); - - if (inFile.good()) - { - inFile >> uuid; - inFile >> bootSequence; - inFile >> nextRemoteBank; - inFile.close(); - if (uuid.isNull()) { - uuid.generate(); - QPID_LOG (info, "No stored broker ID found - ManagementAgent generated broker ID: " << uuid); - } else - QPID_LOG (info, "ManagementAgent restored broker ID: " << uuid); - - // if sequence goes beyond a 12-bit field, skip zero and wrap to 1. - bootSequence++; - if (bootSequence & 0xF000) - bootSequence = 1; - writeData(); - } - else - { - uuid.generate(); - QPID_LOG (info, "ManagementAgent generated broker ID: " << uuid); - writeData(); - } - - QPID_LOG (debug, "ManagementAgent boot sequence: " << bootSequence); - } -} - -void ManagementAgent::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; - string inst; - if (instance.empty()) { - if (uuid.isNull()) - { - throw Exception("ManagementAgent::configure() must be called if default name is used."); - } - inst = uuid.str(); - } else - inst = instance; - - name_address = vendor + ":" + product + ":" + inst; - attrMap["_instance"] = inst; - attrMap["_name"] = name_address; - - vendorNameKey = keyifyNameStr(vendor); - productNameKey = keyifyNameStr(product); - instanceNameKey = keyifyNameStr(inst); -} - - -void ManagementAgent::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& ManagementAgent::getAddress() -{ - return name_address; -} - - -void ManagementAgent::writeData () -{ - string filename (dataDir + "/.mbrokerdata"); - ofstream outFile (filename.c_str ()); - - if (outFile.good()) - { - outFile << uuid << " " << bootSequence << " " << nextRemoteBank << endl; - outFile.close(); - } -} - -void ManagementAgent::setExchange(qpid::broker::Exchange::shared_ptr _mexchange, - qpid::broker::Exchange::shared_ptr _dexchange) -{ - mExchange = _mexchange; - dExchange = _dexchange; -} - -void ManagementAgent::setExchangeV2(qpid::broker::Exchange::shared_ptr _texchange, - qpid::broker::Exchange::shared_ptr _dexchange) -{ - v2Topic = _texchange; - v2Direct = _dexchange; -} - -void ManagementAgent::registerClass (const string& packageName, - const string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall) -{ - sys::Mutex::ScopedLock lock(userLock); - PackageMap::iterator pIter = findOrAddPackageLH(packageName); - addClassLH(ManagementItem::CLASS_KIND_TABLE, pIter, className, md5Sum, schemaCall); -} - -void ManagementAgent::registerEvent (const string& packageName, - const string& eventName, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall) -{ - sys::Mutex::ScopedLock lock(userLock); - PackageMap::iterator pIter = findOrAddPackageLH(packageName); - addClassLH(ManagementItem::CLASS_KIND_EVENT, pIter, eventName, md5Sum, schemaCall); -} - -// Deprecated: V1 objects -ObjectId ManagementAgent::addObject(ManagementObject::shared_ptr object, uint64_t persistId, bool persistent) -{ - uint16_t sequence; - uint64_t objectNum; - - sys::Mutex::ScopedLock lock(addLock); - sequence = persistent ? 0 : bootSequence; - objectNum = persistId ? persistId : nextObjectId++; - - ObjectId objId(0 /*flags*/, sequence, brokerBank, objectNum); - objId.setV2Key(*object); // let object generate the v2 key - - object->setObjectId(objId); - - newManagementObjects.push_back(object); - QPID_LOG(debug, "Management object (V1) added: " << objId.getV2Key()); - return objId; -} - - - -ObjectId ManagementAgent::addObject(ManagementObject::shared_ptr object, - const string& key, - bool persistent) -{ - uint16_t sequence; - - sequence = persistent ? 0 : bootSequence; - - ObjectId objId(0 /*flags*/, sequence, brokerBank); - if (key.empty()) { - objId.setV2Key(*object); // let object generate the key - } else { - objId.setV2Key(key); - } - - object->setObjectId(objId); - { - sys::Mutex::ScopedLock lock(addLock); - newManagementObjects.push_back(object); - } - QPID_LOG(debug, "Management object added: " << objId.getV2Key()); - return objId; -} - -void ManagementAgent::raiseEvent(const ManagementEvent& event, severity_t severity) -{ - static const std::string severityStr[] = { - "emerg", "alert", "crit", "error", "warn", - "note", "info", "debug" - }; - uint8_t sev = (severity == SEV_DEFAULT) ? event.getSeverity() : (uint8_t) severity; - - if (qmf1Support) { - char buffer[qmfV1BufferSize]; - Buffer outBuffer(buffer, qmfV1BufferSize); - - encodeHeader(outBuffer, 'e'); - outBuffer.putShortString(event.getPackageName()); - outBuffer.putShortString(event.getEventName()); - outBuffer.putBin128(event.getMd5Sum()); - outBuffer.putLongLong(sys::Duration::FromEpoch()); - outBuffer.putOctet(sev); - string sBuf; - event.encode(sBuf); - outBuffer.putRawData(sBuf); - sendBuffer(outBuffer, mExchange, - "console.event.1.0." + event.getPackageName() + "." + event.getEventName()); - QPID_LOG(debug, "SEND raiseEvent (v1) class=" << event.getPackageName() << "." << event.getEventName()); - } - - if (qmf2Support) { - Variant::Map map_; - Variant::Map schemaId; - Variant::Map values; - Variant::Map headers; - - map_["_schema_id"] = mapEncodeSchemaId(event.getPackageName(), - event.getEventName(), - "_event", - event.getMd5Sum()); - event.mapEncode(values); - map_["_values"] = values; - map_["_timestamp"] = uint64_t(sys::Duration::FromEpoch()); - map_["_severity"] = sev; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_event"; - headers["qmf.agent"] = name_address; - - stringstream key; - key << "agent.ind.event." << keyifyNameStr(event.getPackageName()) - << "." << keyifyNameStr(event.getEventName()) - << "." << severityStr[sev] - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - key << "." << instanceNameKey; - - - string content; - Variant::List list_; - list_.push_back(map_); - ListCodec::encode(list_, content); - sendBuffer(content, "", headers, "amqp/list", v2Topic, key.str()); - QPID_LOG(debug, "SEND raiseEvent (v2) class=" << event.getPackageName() << "." << event.getEventName()); - } -} - -void ManagementAgent::clientAdded (const string& routingKey) -{ - sys::Mutex::ScopedLock lock(userLock); - - // - // If this routing key is not relevant to object updates, exit. - // - if ((routingKey.compare(0, 1, "#") != 0) && - (routingKey.compare(0, 9, "console.#") != 0) && - (routingKey.compare(0, 12, "console.obj.") != 0)) - return; - - // - // Mark local objects for full-update. - // - clientWasAdded = true; - - // - // If the routing key is relevant for local objects only, don't involve - // any of the remote agents. - // - if (routingKey.compare(0, 39, "console.obj.*.*.org.apache.qpid.broker.") == 0) - return; - - std::list rkeys; - - for (RemoteAgentMap::iterator aIter = remoteAgents.begin(); - aIter != remoteAgents.end(); - aIter++) { - rkeys.push_back(aIter->second->routingKey); - } - - while (rkeys.size()) { - char localBuffer[16]; - Buffer outBuffer(localBuffer, 16); - - encodeHeader(outBuffer, 'x'); - sendBuffer(outBuffer, dExchange, rkeys.front()); - QPID_LOG(debug, "SEND ConsoleAddedIndication to=" << rkeys.front()); - rkeys.pop_front(); - } -} - -void ManagementAgent::encodeHeader (Buffer& buf, uint8_t opcode, uint32_t seq) -{ - buf.putOctet ('A'); - buf.putOctet ('M'); - buf.putOctet ('2'); - buf.putOctet (opcode); - buf.putLong (seq); -} - -bool ManagementAgent::checkHeader (Buffer& buf, uint8_t *opcode, uint32_t *seq) -{ - 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 ManagementAgent::sendBuffer(Buffer& buf, - qpid::broker::Exchange::shared_ptr exchange, - const string& routingKey) -{ - if (suppressed) { - QPID_LOG(debug, "Suppressing management message to " << routingKey); - return; - } - if (exchange.get() == 0) return; - - intrusive_ptr transfer(new qpid::broker::amqp_0_10::MessageTransfer()); - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange->getName (), 0, 0))); - AMQFrame header((AMQHeaderBody())); - AMQFrame content((AMQContentBody())); - - size_t length = buf.getPosition(); - buf.reset(); - content.castBody()->decode(buf, length); - - method.setEof(false); - header.setBof(false); - header.setEof(false); - content.setBof(false); - - transfer->getFrames().append(method); - transfer->getFrames().append(header); - - MessageProperties* props = - transfer->getFrames().getHeaders()->get(true); - props->setContentLength(length); - - DeliveryProperties* dp = - transfer->getFrames().getHeaders()->get(true); - dp->setRoutingKey(routingKey); - - transfer->getFrames().append(content); - transfer->setIsManagementMessage(true); - Message msg(transfer, transfer); - sendQueue->push(make_pair(exchange, msg)); - buf.reset(); -} - - -void ManagementAgent::sendBuffer(Buffer& buf, - const string& exchange, - const string& routingKey) -{ - qpid::broker::Exchange::shared_ptr ex(broker->getExchanges().get(exchange)); - if (ex.get() != 0) - sendBuffer(buf, ex, routingKey); -} - - -void ManagementAgent::sendBuffer(const string& data, - const string& cid, - const Variant::Map& headers, - const string& content_type, - qpid::broker::Exchange::shared_ptr exchange, - const string& routingKey, - uint64_t ttl_msec) -{ - Variant::Map::const_iterator i; - - if (suppressed) { - QPID_LOG(debug, "Suppressing management message to " << routingKey); - return; - } - if (exchange.get() == 0) return; - - intrusive_ptr transfer(new qpid::broker::amqp_0_10::MessageTransfer); - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange->getName (), 0, 0))); - AMQFrame header((AMQHeaderBody())); - AMQFrame content((AMQContentBody(data))); - - method.setEof(false); - header.setBof(false); - header.setEof(false); - content.setBof(false); - - transfer->getFrames().append(method); - transfer->getFrames().append(header); - - MessageProperties* props = - transfer->getFrames().getHeaders()->get(true); - props->setContentLength(data.length()); - if (!cid.empty()) { - props->setCorrelationId(cid); - } - props->setContentType(content_type); - props->setAppId("qmf2"); - - for (i = headers.begin(); i != headers.end(); ++i) { - props->getApplicationHeaders().setString(i->first, i->second.asString()); - } - - DeliveryProperties* dp = - transfer->getFrames().getHeaders()->get(true); - dp->setRoutingKey(routingKey); - if (ttl_msec) { - dp->setTtl(ttl_msec); - } - transfer->getFrames().append(content); - transfer->computeRequiredCredit(); - transfer->setIsManagementMessage(true); - transfer->computeExpiration(); - Message msg(transfer, transfer); - - sendQueue->push(make_pair(exchange, msg)); -} - - -void ManagementAgent::sendBuffer(const string& data, - const string& cid, - const Variant::Map& headers, - const string& content_type, - const string& exchange, - const string& routingKey, - uint64_t ttl_msec) -{ - qpid::broker::Exchange::shared_ptr ex(broker->getExchanges().get(exchange)); - if (ex.get() != 0) - sendBuffer(data, cid, headers, content_type, ex, routingKey, ttl_msec); -} - - -/** Objects that have been added since the last periodic poll are temporarily - * saved in the newManagementObjects list. This allows objects to be - * added without needing to block on the userLock (objectLock is used instead). - * These new objects need to be integrated into the object database - * (managementObjects) *before* they can be properly managed. This routine - * performs the integration. - * - * Note well: objects on the newManagementObjects list may have been - * marked as "deleted", and, possibly re-added. This would result in - * duplicate object ids. To avoid clashes, don't put deleted objects - * into the active object database. - */ -void ManagementAgent::moveNewObjects() -{ - sys::Mutex::ScopedLock lock(addLock); - sys::Mutex::ScopedLock objLock (objectLock); - while (!newManagementObjects.empty()) { - ManagementObject::shared_ptr object = newManagementObjects.back(); - newManagementObjects.pop_back(); - - if (object->isDeleted()) { - DeletedObject::shared_ptr dptr(new DeletedObject(object, qmf1Support, qmf2Support)); - pendingDeletedObjs[dptr->getKey()].push_back(dptr); - } else { // add to active object list, check for duplicates. - ObjectId oid = object->getObjectId(); - ManagementObjectMap::iterator destIter = managementObjects.find(oid); - if (destIter != managementObjects.end()) { - // duplicate found. It is OK if the old object has been marked - // deleted, just replace the old with the new. - ManagementObject::shared_ptr oldObj = destIter->second; - if (!oldObj->isDeleted()) { - // Duplicate non-deleted objects? This is a user error - oids must be unique. - // for now, leak the old object (safer than deleting - may still be referenced) - // and complain loudly... - QPID_LOG(error, "Detected two management objects with the same identifier: " << oid); - oldObj->resourceDestroy(); - } - DeletedObject::shared_ptr dptr(new DeletedObject(oldObj, qmf1Support, qmf2Support)); - pendingDeletedObjs[dptr->getKey()].push_back(dptr); - // QPID-3666: be sure to replace the -index- also, as non-key members of - // the index object may be different for the new object! So erase the - // entry, rather than []= assign here: - managementObjects.erase(destIter); - } - managementObjects[oid] = object; - } - } -} - -void ManagementAgent::periodicProcessing (void) -{ -#define HEADROOM 4096 - sys::Mutex::ScopedLock lock (userLock); - debugSnapshot("Management agent periodic processing"); - string routingKey; - string sBuf; - - moveNewObjects(); - - // - // If we're publishing updates, get the latest memory statistics and uptime now - // - if (publish) { - uint64_t uptime = sys::Duration(startTime, sys::now()); - boost::dynamic_pointer_cast<_qmf::Broker>(broker->GetManagementObject())->set_uptime(uptime); - qpid::sys::MemStat::loadMemInfo(memstat.get()); - } - - // - // Use a copy of the management object map to avoid holding the objectLock - // - ManagementObjectVector localManagementObjects; - { - sys::Mutex::ScopedLock objLock(objectLock); - std::transform(managementObjects.begin(), managementObjects.end(), - std::back_inserter(localManagementObjects), - boost::bind(&ManagementObjectMap::value_type::second, _1)); - } - - // - // Clear the been-here flag on all objects in the map. - // - for (ManagementObjectVector::iterator iter = localManagementObjects.begin(); - iter != localManagementObjects.end(); - iter++) { - ManagementObject::shared_ptr object = *iter; - object->setFlags(0); - if (clientWasAdded) { - object->setForcePublish(true); - } - } - - clientWasAdded = false; - - // first send the pending deletes before sending updates. This prevents a - // "false delete" scenario: if an object was deleted then re-added during - // the last poll cycle, it will have a delete entry and an active entry. - // if we sent the active update first, _then_ the delete update, clients - // would incorrectly think the object was deleted. See QPID-2997 - // - bool objectsDeleted = moveDeletedObjects(); - PendingDeletedObjsMap localPendingDeletedObjs; - { - sys::Mutex::ScopedLock objLock(objectLock); - localPendingDeletedObjs.swap(pendingDeletedObjs); - } - - // - // If we are not publishing updates, just clear the pending deletes. There's no - // need to tell anybody. - // - if (!publish) - localPendingDeletedObjs.clear(); - - ResizableBuffer msgBuffer(qmfV1BufferSize); - if (!localPendingDeletedObjs.empty()) { - for (PendingDeletedObjsMap::iterator mIter = localPendingDeletedObjs.begin(); - mIter != localPendingDeletedObjs.end(); - mIter++) { - std::string packageName; - std::string className; - msgBuffer.reset(); - uint32_t v1Objs = 0; - uint32_t v2Objs = 0; - Variant::List list_; - - size_t pos = mIter->first.find(":"); - packageName = mIter->first.substr(0, pos); - className = mIter->first.substr(pos+1); - - for (DeletedObjectList::iterator lIter = mIter->second.begin(); - lIter != mIter->second.end(); lIter++) { - msgBuffer.makeAvailable(HEADROOM); // Make sure there's buffer space. - std::string oid = (*lIter)->objectId; - if (!(*lIter)->encodedV1Config.empty()) { - encodeHeader(msgBuffer, 'c'); - msgBuffer.putRawData((*lIter)->encodedV1Config); - QPID_LOG(trace, "Deleting V1 properties " << oid - << " len=" << (*lIter)->encodedV1Config.size()); - v1Objs++; - } - if (!(*lIter)->encodedV1Inst.empty()) { - encodeHeader(msgBuffer, 'i'); - msgBuffer.putRawData((*lIter)->encodedV1Inst); - QPID_LOG(trace, "Deleting V1 statistics " << oid - << " len=" << (*lIter)->encodedV1Inst.size()); - v1Objs++; - } - if (v1Objs >= maxReplyObjs) { - v1Objs = 0; - stringstream key; - key << "console.obj.1.0." << packageName << "." << className; - size_t contentSize = msgBuffer.getPosition(); - sendBuffer(msgBuffer, mExchange, key.str()); - QPID_LOG(debug, "SEND V1 Multicast ContentInd V1 (delete) to=" - << key.str() << " len=" << contentSize); - } - - if (!(*lIter)->encodedV2.empty()) { - QPID_LOG(trace, "Deleting V2 " << "map=" << (*lIter)->encodedV2); - list_.push_back((*lIter)->encodedV2); - if (++v2Objs >= maxReplyObjs) { - v2Objs = 0; - - string content; - ListCodec::encode(list_, content); - list_.clear(); - if (content.length()) { - stringstream key; - Variant::Map headers; - key << "agent.ind.data." << keyifyNameStr(packageName) - << "." << keyifyNameStr(className) - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - key << "." << instanceNameKey; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - sendBuffer(content, "", headers, "amqp/list", v2Topic, key.str(), 0); - QPID_LOG(debug, "SEND Multicast ContentInd V2 (delete) to=" << key.str() << " len=" << content.length()); - } - } - } - } // end current list - - // send any remaining objects... - - if (v1Objs) { - stringstream key; - key << "console.obj.1.0." << packageName << "." << className; - size_t contentSize = msgBuffer.getPosition(); - sendBuffer(msgBuffer, mExchange, key.str()); - QPID_LOG(debug, "SEND V1 Multicast ContentInd V1 (delete) to=" << key.str() << " len=" << contentSize); - } - - if (!list_.empty()) { - string content; - ListCodec::encode(list_, content); - list_.clear(); - if (content.length()) { - stringstream key; - Variant::Map headers; - key << "agent.ind.data." << keyifyNameStr(packageName) - << "." << keyifyNameStr(className) - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - key << "." << instanceNameKey; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - sendBuffer(content, "", headers, "amqp/list", v2Topic, key.str(), 0); - QPID_LOG(debug, "SEND Multicast ContentInd V2 (delete) to=" << key.str() << " len=" << content.length()); - } - } - } // end map - } - - // - // Process the entire object map. - // - // If publish is disabled, don't send any updates. - // - while (publish) { - msgBuffer.reset(); - Variant::List list_; - uint32_t pcount; - uint32_t scount; - uint32_t v1Objs, v2Objs; - ManagementObjectVector::iterator baseIter; - std::string packageName; - std::string className; - - for (baseIter = localManagementObjects.begin(); - baseIter != localManagementObjects.end(); - baseIter++) { - ManagementObject::shared_ptr baseObject = *baseIter; - // - // Skip until we find a base object requiring processing... - // - if (baseObject->getFlags() == 0) { - packageName = baseObject->getPackageName(); - className = baseObject->getClassName(); - break; - } - } - - if (baseIter == localManagementObjects.end()) - break; // done - all objects processed - - pcount = scount = 0; - v1Objs = 0; - v2Objs = 0; - list_.clear(); - msgBuffer.reset(); - - for (ManagementObjectVector::iterator iter = baseIter; - iter != localManagementObjects.end(); - iter++) { - msgBuffer.makeAvailable(HEADROOM); // Make sure there's buffer space - ManagementObject::shared_ptr baseObject = *baseIter; - ManagementObject::shared_ptr object = *iter; - bool send_stats, send_props; - if (baseObject->isSameClass(*object) && object->getFlags() == 0) { - object->setFlags(1); - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - // skip any objects marked deleted since our first pass. Deal with them - // on the next periodic cycle... - if (object->isDeleted()) { - continue; - } - - send_props = (object->getConfigChanged() || object->getForcePublish()); - send_stats = (object->hasInst() && (object->getInstChanged() || object->getForcePublish())); - - if (send_props && qmf1Support) { - size_t pos = msgBuffer.getPosition(); - encodeHeader(msgBuffer, 'c'); - sBuf.clear(); - object->writeProperties(sBuf); - msgBuffer.putRawData(sBuf); - QPID_LOG(trace, "Changed V1 properties " - << object->getObjectId().getV2Key() - << " len=" << msgBuffer.getPosition()-pos); - ++v1Objs; - } - - if (send_stats && qmf1Support) { - size_t pos = msgBuffer.getPosition(); - encodeHeader(msgBuffer, 'i'); - sBuf.clear(); - object->writeStatistics(sBuf); - msgBuffer.putRawData(sBuf); - QPID_LOG(trace, "Changed V1 statistics " - << object->getObjectId().getV2Key() - << " len=" << msgBuffer.getPosition()-pos); - ++v1Objs; - } - - if ((send_stats || send_props) && qmf2Support) { - 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(), - "_data", - object->getMd5Sum()); - object->writeTimestamps(map_); - object->mapEncodeValues(values, send_props, send_stats); - map_["_values"] = values; - list_.push_back(map_); - v2Objs++; - QPID_LOG(trace, "Changed V2" - << (send_stats? " statistics":"") - << (send_props? " properties":"") - << " map=" << map_); - } - - if (send_props) pcount++; - if (send_stats) scount++; - - object->setForcePublish(false); - - if ((qmf1Support && (v1Objs >= maxReplyObjs)) || - (qmf2Support && (v2Objs >= maxReplyObjs))) - break; // have enough objects, send an indication... - } - } - - if (pcount || scount) { - if (qmf1Support) { - if (msgBuffer.getPosition() > 0) { - stringstream key; - key << "console.obj.1.0." << packageName << "." << className; - size_t contentSize = msgBuffer.getPosition(); - sendBuffer(msgBuffer, mExchange, key.str()); - QPID_LOG(debug, "SEND V1 Multicast ContentInd to=" << key.str() - << " props=" << pcount - << " stats=" << scount - << " len=" << contentSize); - } - } - - if (qmf2Support) { - string content; - ListCodec::encode(list_, content); - if (content.length()) { - stringstream key; - Variant::Map headers; - key << "agent.ind.data." << keyifyNameStr(packageName) - << "." << keyifyNameStr(className) - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - key << "." << instanceNameKey; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - sendBuffer(content, "", headers, "amqp/list", v2Topic, key.str(), 0); - QPID_LOG(debug, "SEND Multicast ContentInd to=" << key.str() - << " props=" << pcount - << " stats=" << scount - << " len=" << content.length()); - } - } - } - } // end processing updates for all objects - - if (objectsDeleted) { - sys::Mutex::ScopedLock lock (userLock); - deleteOrphanedAgentsLH(); - } - - // heartbeat generation. Note that heartbeats need to be sent even if publish is disabled. - - if (qmf1Support) { - char msgChars[qmfV1BufferSize]; - Buffer msgBuffer(msgChars, qmfV1BufferSize); - encodeHeader(msgBuffer, 'h'); - msgBuffer.putLongLong(sys::Duration::FromEpoch()); - - routingKey = "console.heartbeat.1.0"; - sendBuffer(msgBuffer, mExchange, routingKey); - QPID_LOG(debug, "SEND HeartbeatInd to=" << routingKey); - } - - if (qmf2Support) { - std::stringstream addr_key; - - addr_key << "agent.ind.heartbeat." << vendorNameKey << "." << productNameKey; - if (!instanceNameKey.empty()) - addr_key << "." << instanceNameKey; - - Variant::Map map; - Variant::Map headers; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_agent_heartbeat_indication"; - headers["qmf.agent"] = name_address; - - map["_values"] = attrMap; - map["_values"].asMap()["_timestamp"] = uint64_t(sys::Duration::FromEpoch()); - map["_values"].asMap()["_heartbeat_interval"] = interval; - map["_values"].asMap()["_epoch"] = bootSequence; - - string content; - 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. - sendBuffer(content, "", headers, "amqp/map", v2Topic, addr_key.str(), interval * 2 * 1000); - - QPID_LOG(debug, "SENT AgentHeartbeat name=" << name_address); - } -} - -void ManagementAgent::deleteObjectNow(const ObjectId& oid) -{ - ManagementObject::shared_ptr object; - { - sys::Mutex::ScopedLock lock(objectLock); - ManagementObjectMap::iterator iter = managementObjects.find(oid); - if (iter == managementObjects.end()) - return; - object = iter->second; - if (!object->isDeleted()) - return; - managementObjects.erase(oid); - } - -#define DNOW_BUFSIZE 2048 - char msgChars[DNOW_BUFSIZE]; - Buffer msgBuffer(msgChars, DNOW_BUFSIZE); - Variant::List list_; - stringstream v1key, v2key; - - if (publish && qmf1Support) { - string sBuf; - - v1key << "console.obj.1.0." << object->getPackageName() << "." << object->getClassName(); - encodeHeader(msgBuffer, 'c'); - object->writeProperties(sBuf); - msgBuffer.putRawData(sBuf); - } - - if (publish && qmf2Support) { - Variant::Map map_; - Variant::Map values; - - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - "_data", - object->getMd5Sum()); - object->writeTimestamps(map_); - object->mapEncodeValues(values, true, false); - map_["_values"] = values; - list_.push_back(map_); - v2key << "agent.ind.data." << keyifyNameStr(object->getPackageName()) - << "." << keyifyNameStr(object->getClassName()) - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - v2key << "." << instanceNameKey; - } - - object.reset(); - - // object deleted, ok to drop lock now. - - if (publish && qmf1Support) { - sendBuffer(msgBuffer, mExchange, v1key.str()); - QPID_LOG(debug, "SEND Immediate(delete) ContentInd to=" << v1key.str()); - } - - if (publish && qmf2Support) { - Variant::Map headers; - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - string content; - ListCodec::encode(list_, content); - sendBuffer(content, "", headers, "amqp/list", v2Topic, v2key.str(), 0); - QPID_LOG(debug, "SEND Immediate(delete) ContentInd to=" << v2key.str()); - } -} - -void ManagementAgent::sendCommandComplete(const string& replyToKey, uint32_t sequence, - uint32_t code, const string& text) -{ - ResizableBuffer outBuffer (qmfV1BufferSize); - - encodeHeader (outBuffer, 'z', sequence); - outBuffer.putLong (code); - outBuffer.putShortString (text); - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND CommandCompleteInd code=" << code << " text=" << text << " to=" << - replyToKey << " seq=" << sequence); -} - -void ManagementAgent::sendException(const string& rte, const string& rtk, const string& cid, - const string& text, uint32_t code, bool viaLocal) -{ - static const string addr_exchange("qmf.default.direct"); - - Variant::Map map; - Variant::Map headers; - Variant::Map values; - string content; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_exception"; - headers["qmf.agent"] = viaLocal ? "broker" : name_address; - - values["error_code"] = code; - values["error_text"] = text; - map["_values"] = values; - - MapCodec::encode(map, content); - sendBuffer(content, cid, headers, "amqp/map", rte, rtk); - - QPID_LOG(debug, "SENT Exception code=" << code <<" text=" << text); -} - -bool ManagementAgent::dispatchCommand (Deliverable& deliverable, - const string& routingKey, - const FieldTable* /*args*/, - const bool topic, - int qmfVersion) -{ - Message& msg = ((DeliverableMessage&) deliverable).getMessage (); - - if (topic && qmfVersion == 1) { - - // qmf1 is bound only to the topic management exchange. - // Parse the routing key. This management broker should act as though it - // is bound to the exchange to match the following keys: - // - // agent.1.0.# - // broker - // schema.# - - if (routingKey == "broker") { - dispatchAgentCommand(msg); - return false; - } - - if (routingKey.length() > 6) { - - if (routingKey.compare(0, 9, "agent.1.0") == 0) { - dispatchAgentCommand(msg); - return false; - } - - if (routingKey.compare(0, 8, "agent.1.") == 0) { - return authorizeAgentMessage(msg); - } - - if (routingKey.compare(0, 7, "schema.") == 0) { - dispatchAgentCommand(msg); - return true; - } - } - } - - if (qmfVersion == 2) { - - if (topic) { - // Intercept messages bound to: - // "console.ind.locate.# - process these messages, and also allow them to be forwarded. - if (routingKey == "console.request.agent_locate") { - dispatchAgentCommand(msg); - return true; - } - - } else { // direct exchange - - // Intercept messages bound to: - // "broker" - generic alias for the local broker - // "" - the broker agent's proper name - // and do not forward them futher - if (routingKey == "broker" || routingKey == name_address) { - dispatchAgentCommand(msg, routingKey == "broker"); - return false; - } - } - } - - return true; -} - -void ManagementAgent::handleMethodRequest(Buffer& inBuffer, const string& replyToKey, uint32_t sequence, const string& userId) -{ - moveNewObjects(); - - string methodName; - string packageName; - string className; - uint8_t hash[16]; - ResizableBuffer outBuffer (qmfV1BufferSize); - AclModule* acl = broker->getAcl(); - string inArgs; - - string sBuf; - inBuffer.getRawData(sBuf, 16); - ObjectId objId; - objId.decode(sBuf); - inBuffer.getShortString(packageName); - inBuffer.getShortString(className); - inBuffer.getBin128(hash); - inBuffer.getShortString(methodName); - inBuffer.getRawData(inArgs, inBuffer.available()); - - QPID_LOG(debug, "RECV MethodRequest (v1) class=" << packageName << ":" << className << "(" << Uuid(hash) << ") method=" << - methodName << " replyTo=" << replyToKey); - - encodeHeader(outBuffer, 'm', sequence); - - if (disallowAllV1Methods) { - outBuffer.putLong(Manageable::STATUS_FORBIDDEN); - outBuffer.putMediumString("QMFv1 methods forbidden on this broker, use QMFv2"); - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND MethodResponse status=FORBIDDEN reason='All QMFv1 Methods Forbidden' seq=" << sequence); - return; - } - - DisallowedMethods::const_iterator i = disallowed.find(make_pair(className, methodName)); - if (i != disallowed.end()) { - outBuffer.putLong(Manageable::STATUS_FORBIDDEN); - outBuffer.putMediumString(i->second); - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND MethodResponse status=FORBIDDEN text=" << i->second << " seq=" << sequence); - return; - } - - if (acl != 0) { - map params; - params[acl::PROP_SCHEMAPACKAGE] = packageName; - params[acl::PROP_SCHEMACLASS] = className; - - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_METHOD, methodName, ¶ms)) { - outBuffer.putLong(Manageable::STATUS_FORBIDDEN); - outBuffer.putMediumString(Manageable::StatusText(Manageable::STATUS_FORBIDDEN)); - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND MethodResponse status=FORBIDDEN" << " seq=" << sequence); - return; - } - } - - ManagementObject::shared_ptr object; - { - sys::Mutex::ScopedLock lock(objectLock); - ManagementObjectMap::iterator iter = numericFind(objId); - if (iter != managementObjects.end()) - object = iter->second; - } - - if (!object || object->isDeleted()) { - outBuffer.putLong (Manageable::STATUS_UNKNOWN_OBJECT); - outBuffer.putMediumString(Manageable::StatusText (Manageable::STATUS_UNKNOWN_OBJECT)); - } else { - if ((object->getPackageName() != packageName) || - (object->getClassName() != className)) { - outBuffer.putLong (Manageable::STATUS_PARAMETER_INVALID); - outBuffer.putMediumString(Manageable::StatusText (Manageable::STATUS_PARAMETER_INVALID)); - } - else { - uint32_t pos = outBuffer.getPosition(); - try { - string outBuf; - object->doMethod(methodName, inArgs, outBuf, userId); - outBuffer.putRawData(outBuf); - } catch(exception& e) { - outBuffer.setPosition(pos);; - outBuffer.putLong(Manageable::STATUS_EXCEPTION); - outBuffer.putMediumString(e.what()); - } - } - } - - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND MethodResponse (v1) to=" << replyToKey << " seq=" << sequence); -} - - -void ManagementAgent::handleMethodRequest (const string& body, const string& rte, const string& rtk, - const string& cid, const string& userId, bool viaLocal) -{ - moveNewObjects(); - - string methodName; - Variant::Map inMap; - MapCodec::decode(body, inMap); - Variant::Map::const_iterator oid, mid; - string content; - string error; - uint32_t errorCode(0); - - Variant::Map outMap; - Variant::Map headers; - - headers["method"] = "response"; - headers["qmf.opcode"] = "_method_response"; - headers["qmf.agent"] = viaLocal ? "broker" : name_address; - - 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, viaLocal); - return; - } - - ObjectId objId; - Variant::Map inArgs; - Variant::Map callMap; - - try { - // coversions 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(); - } - } catch(exception& e) { - sendException(rte, rtk, cid, e.what(), Manageable::STATUS_EXCEPTION, viaLocal); - return; - } - - ManagementObject::shared_ptr object; - { - sys::Mutex::ScopedLock lock(objectLock); - ManagementObjectMap::iterator iter = managementObjects.find(objId); - if (iter != managementObjects.end()) - object = iter->second; - } - - if (!object || object->isDeleted()) { - stringstream estr; - estr << "No object found with ID=" << objId; - sendException(rte, rtk, cid, estr.str(), 1, viaLocal); - return; - } - - // validate - AclModule* acl = broker->getAcl(); - DisallowedMethods::const_iterator i; - - i = disallowed.find(make_pair(object->getClassName(), methodName)); - if (i != disallowed.end()) { - sendException(rte, rtk, cid, i->second, Manageable::STATUS_FORBIDDEN, viaLocal); - return; - } - - if (acl != 0) { - map params; - params[acl::PROP_SCHEMAPACKAGE] = object->getPackageName(); - params[acl::PROP_SCHEMACLASS] = object->getClassName(); - - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_METHOD, methodName, ¶ms)) { - sendException(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_FORBIDDEN), - Manageable::STATUS_FORBIDDEN, viaLocal); - return; - } - } - - // invoke the method - - QPID_LOG(debug, "RECV MethodRequest (v2) class=" << object->getPackageName() - << ":" << object->getClassName() << " method=" << - methodName << " replyTo=" << rte << "/" << rtk << " objId=" << objId << " inArgs=" << inArgs); - - try { - object->doMethod(methodName, inArgs, callMap, userId); - errorCode = callMap["_status_code"].asUint32(); - if (errorCode == 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 - error = callMap["_status_text"].asString(); - } catch(exception& e) { - sendException(rte, rtk, cid, e.what(), Manageable::STATUS_EXCEPTION, viaLocal); - return; - } - - if (errorCode != 0) { - sendException(rte, rtk, cid, error, errorCode, viaLocal); - return; - } - - MapCodec::encode(outMap, content); - sendBuffer(content, cid, headers, "amqp/map", rte, rtk); - QPID_LOG(debug, "SEND MethodResponse (v2) to=" << rte << "/" << rtk << " seq=" << cid << " map=" << outMap); -} - - -void ManagementAgent::handleBrokerRequest (Buffer&, const string& replyToKey, uint32_t sequence) -{ - ResizableBuffer outBuffer (qmfV1BufferSize); - - QPID_LOG(debug, "RECV BrokerRequest replyTo=" << replyToKey); - - encodeHeader (outBuffer, 'b', sequence); - uuid.encode (outBuffer); - - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND BrokerResponse to=" << replyToKey); -} - -void ManagementAgent::handlePackageQuery (Buffer&, const string& replyToKey, uint32_t sequence) -{ - QPID_LOG(debug, "RECV PackageQuery replyTo=" << replyToKey); - ResizableBuffer outBuffer (qmfV1BufferSize); - - { - sys::Mutex::ScopedLock lock(userLock); - for (PackageMap::iterator pIter = packages.begin (); - pIter != packages.end (); - pIter++) - { - encodeHeader (outBuffer, 'p', sequence); - encodePackageIndication (outBuffer, pIter); - } - } - - if (outBuffer.getPosition() > 0) { - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND PackageInd to=" << replyToKey << " seq=" << sequence); - } - - sendCommandComplete(replyToKey, sequence); -} - -void ManagementAgent::handlePackageInd (Buffer& inBuffer, const string& replyToKey, uint32_t sequence) -{ - string packageName; - - inBuffer.getShortString(packageName); - - QPID_LOG(debug, "RECV PackageInd package=" << packageName << " replyTo=" << replyToKey << " seq=" << sequence); - - sys::Mutex::ScopedLock lock(userLock); - findOrAddPackageLH(packageName); -} - -void ManagementAgent::handleClassQuery(Buffer& inBuffer, const string& replyToKey, uint32_t sequence) -{ - string packageName; - - inBuffer.getShortString(packageName); - - QPID_LOG(debug, "RECV ClassQuery package=" << packageName << " replyTo=" << replyToKey << " seq=" << sequence); - - typedef std::pair _ckeyType; - std::list<_ckeyType> classes; - { - sys::Mutex::ScopedLock lock(userLock); - PackageMap::iterator pIter = packages.find(packageName); - if (pIter != packages.end()) - { - ClassMap &cMap = pIter->second; - for (ClassMap::iterator cIter = cMap.begin(); - cIter != cMap.end(); - cIter++) { - if (cIter->second.hasSchema()) { - classes.push_back(make_pair(cIter->first, cIter->second.kind)); - } - } - } - } - - while (classes.size()) { - ResizableBuffer outBuffer(qmfV1BufferSize); - - encodeHeader(outBuffer, 'q', sequence); - encodeClassIndication(outBuffer, packageName, classes.front().first, classes.front().second); - - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND ClassInd class=" << packageName << ":" << classes.front().first.name << - "(" << Uuid(classes.front().first.hash) << ") to=" << replyToKey << " seq=" << sequence); - classes.pop_front(); - } - sendCommandComplete(replyToKey, sequence); -} - -void ManagementAgent::handleClassInd (Buffer& inBuffer, const string& replyToKey, uint32_t) -{ - string packageName; - SchemaClassKey key; - - uint8_t kind = inBuffer.getOctet(); - inBuffer.getShortString(packageName); - inBuffer.getShortString(key.name); - inBuffer.getBin128(key.hash); - - QPID_LOG(debug, "RECV ClassInd class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << - "), replyTo=" << replyToKey); - - sys::Mutex::ScopedLock lock(userLock); - PackageMap::iterator pIter = findOrAddPackageLH(packageName); - ClassMap::iterator cIter = pIter->second.find(key); - if (cIter == pIter->second.end() || !cIter->second.hasSchema()) { - ResizableBuffer outBuffer (qmfV1BufferSize); - uint32_t sequence = nextRequestSequence++; - - // Schema Request - encodeHeader (outBuffer, 'S', sequence); - outBuffer.putShortString(packageName); - key.encode(outBuffer); - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND SchemaRequest class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << - "), to=" << replyToKey << " seq=" << sequence); - - if (cIter != pIter->second.end()) - pIter->second.erase(key); - - pIter->second.insert(pair(key, SchemaClass(kind, sequence))); - } -} - -void ManagementAgent::SchemaClass::appendSchema(Buffer& buf) -{ - // If the management package is attached locally (embedded in the broker or - // linked in via plug-in), call the schema handler directly. If the package - // is from a remote management agent, send the stored schema information. - - if (writeSchemaCall != 0) { - string schema; - writeSchemaCall(schema); - buf.putRawData(schema); - } else - buf.putRawData(reinterpret_cast(&data[0]), data.size()); -} - -void ManagementAgent::handleSchemaRequest(Buffer& inBuffer, const string& rte, const string& rtk, uint32_t sequence) -{ - string packageName; - SchemaClassKey key; - - inBuffer.getShortString (packageName); - key.decode(inBuffer); - - QPID_LOG(debug, "RECV SchemaRequest class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << - "), replyTo=" << rte << "/" << rtk << " seq=" << sequence); - - sys::Mutex::ScopedLock lock(userLock); - PackageMap::iterator pIter = packages.find(packageName); - if (pIter != packages.end()) { - ClassMap& cMap = pIter->second; - ClassMap::iterator cIter = cMap.find(key); - if (cIter != cMap.end()) { - ResizableBuffer outBuffer(qmfV1BufferSize); - SchemaClass& classInfo = cIter->second; - - if (classInfo.hasSchema()) { - encodeHeader(outBuffer, 's', sequence); - classInfo.appendSchema(outBuffer); - sendBuffer(outBuffer, rte, rtk); - QPID_LOG(debug, "SEND SchemaResponse to=" << rte << "/" << rtk << " seq=" << sequence); - } - else - sendCommandComplete(rtk, sequence, 1, "Schema not available"); - } - else - sendCommandComplete(rtk, sequence, 1, "Class key not found"); - } - else - sendCommandComplete(rtk, sequence, 1, "Package not found"); -} - -void ManagementAgent::handleSchemaResponse(Buffer& inBuffer, const string& /*replyToKey*/, uint32_t sequence) -{ - string packageName; - SchemaClassKey key; - - uint32_t pos = inBuffer.getPosition(); - inBuffer.getOctet(); - inBuffer.getShortString(packageName); - key.decode(inBuffer); - inBuffer.setPosition(pos);; - - QPID_LOG(debug, "RECV SchemaResponse class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << ")" << " seq=" << sequence); - - sys::Mutex::ScopedLock lock(userLock); - PackageMap::iterator pIter = packages.find(packageName); - if (pIter != packages.end()) { - ClassMap& cMap = pIter->second; - ClassMap::iterator cIter = cMap.find(key); - if (cIter != cMap.end() && cIter->second.pendingSequence == sequence) { - size_t length = validateSchema(inBuffer, cIter->second.kind); - if (length == 0) { - QPID_LOG(warning, "Management Agent received invalid schema response: " << packageName << "." << key.name); - cMap.erase(key); - } else { - cIter->second.data.resize(length); - inBuffer.getRawData(reinterpret_cast(&cIter->second.data[0]), length); - - // Publish a class-indication message - ResizableBuffer outBuffer(qmfV1BufferSize); - - encodeHeader(outBuffer, 'q'); - encodeClassIndication(outBuffer, pIter->first, cIter->first, cIter->second.kind); - sendBuffer(outBuffer, mExchange, "schema.class"); - QPID_LOG(debug, "SEND ClassInd class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << ")" << - " to=schema.class"); - } - } - } -} - -bool ManagementAgent::bankInUse (uint32_t bank) -{ - for (RemoteAgentMap::iterator aIter = remoteAgents.begin(); - aIter != remoteAgents.end(); - aIter++) - if (aIter->second->agentBank == bank) - return true; - return false; -} - -uint32_t ManagementAgent::allocateNewBank () -{ - while (bankInUse (nextRemoteBank)) - nextRemoteBank++; - - uint32_t allocated = nextRemoteBank++; - writeData (); - return allocated; -} - -uint32_t ManagementAgent::assignBankLH (uint32_t requestedBank) -{ - if (requestedBank == 0 || bankInUse (requestedBank)) - return allocateNewBank (); - return requestedBank; -} - -void ManagementAgent::deleteOrphanedAgentsLH() -{ - list deleteList; - - for (RemoteAgentMap::const_iterator aIter = remoteAgents.begin(); aIter != remoteAgents.end(); aIter++) { - bool found = false; - - for (ManagementObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - iter++) { - if (iter->first == aIter->first && !iter->second->isDeleted()) { - found = true; - break; - } - } - - if (!found) - deleteList.push_back(aIter->first); - } - - for (list::const_iterator dIter = deleteList.begin(); dIter != deleteList.end(); dIter++) - remoteAgents.erase(*dIter); -} - -void ManagementAgent::handleAttachRequest (Buffer& inBuffer, const string& replyToKey, uint32_t sequence, const ObjectId& connectionRef) -{ - string label; - uint32_t requestedBrokerBank, requestedAgentBank; - uint32_t assignedBank; - Uuid systemId; - - moveNewObjects(); - - sys::Mutex::ScopedLock lock(userLock); - deleteOrphanedAgentsLH(); - RemoteAgentMap::iterator aIter = remoteAgents.find(connectionRef); - if (aIter != remoteAgents.end()) { - // There already exists an agent on this session. Reject the request. - sendCommandComplete(replyToKey, sequence, 1, "Connection already has remote agent"); - return; - } - - inBuffer.getShortString(label); - systemId.decode(inBuffer); - requestedBrokerBank = inBuffer.getLong(); - requestedAgentBank = inBuffer.getLong(); - - QPID_LOG(debug, "RECV (Agent)AttachRequest label=" << label << " reqBrokerBank=" << requestedBrokerBank << - " reqAgentBank=" << requestedAgentBank << " replyTo=" << replyToKey << " seq=" << sequence); - - assignedBank = assignBankLH(requestedAgentBank); - - boost::shared_ptr agent(new RemoteAgent(*this)); - agent->brokerBank = brokerBank; - agent->agentBank = assignedBank; - agent->routingKey = replyToKey; - agent->connectionRef = connectionRef; - agent->mgmtObject = _qmf::Agent::shared_ptr(new _qmf::Agent (this, agent.get())); - agent->mgmtObject->set_connectionRef(agent->connectionRef); - agent->mgmtObject->set_label (label); - agent->mgmtObject->set_registeredTo (broker->GetManagementObject()->getObjectId()); - agent->mgmtObject->set_systemId ((const unsigned char*)systemId.data()); - agent->mgmtObject->set_brokerBank (brokerBank); - agent->mgmtObject->set_agentBank (assignedBank); - addObject (agent->mgmtObject, 0); - remoteAgents[connectionRef] = agent; - - QPID_LOG(debug, "Remote Agent registered bank=[" << brokerBank << "." << assignedBank << "] replyTo=" << replyToKey); - - // Send an Attach Response - ResizableBuffer outBuffer (qmfV1BufferSize); - - encodeHeader (outBuffer, 'a', sequence); - outBuffer.putLong (brokerBank); - outBuffer.putLong (assignedBank); - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND AttachResponse brokerBank=" << brokerBank << " agentBank=" << assignedBank << - " to=" << replyToKey << " seq=" << sequence); -} - -void ManagementAgent::handleGetQuery(Buffer& inBuffer, const string& replyToKey, uint32_t sequence, const string& userId) -{ - FieldTable ft; - FieldTable::ValuePtr value; - AclModule* acl = broker->getAcl(); - - moveNewObjects(); - - ft.decode(inBuffer); - - QPID_LOG(debug, "RECV GetQuery (v1) query=" << ft << " seq=" << sequence); - - value = ft.get("_class"); - if (value.get() == 0 || !value->convertsTo()) { - value = ft.get("_objectid"); - if (value.get() == 0 || !value->convertsTo()) - return; - - ObjectId selector(value->get()); - - ManagementObject::shared_ptr object; - { - sys::Mutex::ScopedLock lock(objectLock); - ManagementObjectMap::iterator iter = numericFind(selector); - if (iter != managementObjects.end()) - object = iter->second; - } - - if (object) { - ResizableBuffer outBuffer (qmfV1BufferSize); - if (acl != 0) { - map params; - params[acl::PROP_SCHEMACLASS] = object->getClassName(); - - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_QUERY, object->getObjectId().getV2Key(), ¶ms)) { - throw framing::UnauthorizedAccessException(QPID_MSG("unauthorized-access: ACL denied QMF query of object " << object->getObjectId().getV2Key() << " from " << userId)); - } - } - - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - if (!object->isDeleted()) { - string sBuf; - encodeHeader(outBuffer, 'g', sequence); - object->writeProperties(sBuf); - outBuffer.putRawData(sBuf); - sBuf.clear(); - object->writeStatistics(sBuf, true); - outBuffer.putRawData(sBuf); - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND GetResponse (v1) to=" << replyToKey << " seq=" << sequence); - } - } - sendCommandComplete(replyToKey, sequence); - return; - } - - string className (value->get()); - std::list matches; - - if (acl != 0) { - map params; - params[acl::PROP_SCHEMACLASS] = className; - - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_QUERY, className /* class-wide query */, ¶ms)) { - throw framing::UnauthorizedAccessException(QPID_MSG("unauthorized-access: ACL denied QMF query of object class " << className << " from " << userId)); - } - } - - if (className == "memory") - qpid::sys::MemStat::loadMemInfo(memstat.get()); - - if (className == "broker") { - uint64_t uptime = sys::Duration(startTime, sys::now()); - boost::dynamic_pointer_cast<_qmf::Broker>(broker->GetManagementObject())->set_uptime(uptime); - } - - - // build up a set of all objects to be dumped - { - sys::Mutex::ScopedLock lock(objectLock); - for (ManagementObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - iter++) { - ManagementObject::shared_ptr object = iter->second; - if (object->getClassName () == className) { - matches.push_back(object); - } - } - } - - // send them - ResizableBuffer outBuffer (qmfV1BufferSize); - while (matches.size()) { - ManagementObject::shared_ptr object = matches.front(); - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - if (!object->isDeleted()) { - string sProps, sStats; - object->writeProperties(sProps); - object->writeStatistics(sStats, true); - - size_t len = 8 + sProps.length() + sStats.length(); // 8 == size of header in bytes. - if (len > qmfV1BufferSize) { - QPID_LOG(error, "Object " << object->getObjectId() << " too large for output buffer - discarded!"); - } else { - if (outBuffer.available() < len) { // not enough room in current buffer, send it. - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND GetResponse (v1) to=" << replyToKey << " seq=" << sequence); - continue; // lock dropped, need to re-find _SAME_ objid as it may have been deleted. - } - encodeHeader(outBuffer, 'g', sequence); - outBuffer.putRawData(sProps); - outBuffer.putRawData(sStats); - } - } - matches.pop_front(); - } - - if (outBuffer.getPosition() > 0) { - sendBuffer(outBuffer, dExchange, replyToKey); - QPID_LOG(debug, "SEND GetResponse (v1) to=" << replyToKey << " seq=" << sequence); - } - - sendCommandComplete(replyToKey, sequence); -} - - -void ManagementAgent::handleGetQuery(const string& body, const string& rte, const string& rtk, const string& cid, const std::string& userId, bool viaLocal) -{ - moveNewObjects(); - - Variant::Map inMap; - Variant::Map::const_iterator i; - Variant::Map headers; - AclModule* acl = broker->getAcl(); - - MapCodec::decode(body, inMap); - QPID_LOG(debug, "RECV GetQuery (v2): map=" << inMap << " seq=" << cid); - - headers["method"] = "response"; - headers["qmf.opcode"] = "_query_response"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = viaLocal ? "broker" : name_address; - - /* - * 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") { - sendException(rte, rtk, cid, "Query for _what => '" + i->second.asString() + "' not supported"); - return; - } - - string className; - string packageName; - - /* - * Handle the _schema_id element, if supplied. - */ - 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(); - } - - if (className == "memory") - qpid::sys::MemStat::loadMemInfo(memstat.get()); - - if (className == "broker") { - uint64_t uptime = sys::Duration(startTime, sys::now()); - boost::dynamic_pointer_cast<_qmf::Broker>(broker->GetManagementObject())->set_uptime(uptime); - } - - /* - * 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) { - Variant::List list_; - ObjectId objId(i->second.asMap()); - - ManagementObject::shared_ptr object; - { - sys::Mutex::ScopedLock lock (objectLock); - ManagementObjectMap::iterator iter = managementObjects.find(objId); - if (iter != managementObjects.end()) - object = iter->second; - } - if (object) { - if (acl != 0) { - map params; - params[acl::PROP_SCHEMACLASS] = object->getClassName(); - - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_QUERY, object->getObjectId().getV2Key(), ¶ms)) { - throw framing::UnauthorizedAccessException(QPID_MSG("unauthorized-access: ACL denied QMF query of object " << object->getObjectId().getV2Key() << " from " << userId)); - } - } - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - if (!object->isDeleted()) { - Variant::Map map_; - Variant::Map values; - Variant::Map oidMap; - - object->writeTimestamps(map_); - object->mapEncodeValues(values, true, true); // write both stats and properties - objId.mapEncode(oidMap); - map_["_values"] = values; - map_["_object_id"] = oidMap; - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - "_data", - object->getMd5Sum()); - list_.push_back(map_); - } - - string content; - - ListCodec::encode(list_, content); - sendBuffer(content, cid, headers, "amqp/list", rte, rtk); - QPID_LOG(debug, "SENT QueryResponse (query by object_id) to=" << rte << "/" << rtk); - return; - } - } else { - // send class-based result. - if (acl != 0) { - map params; - params[acl::PROP_SCHEMACLASS] = className; - - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_QUERY, className /* class-wide query */, ¶ms)) { - throw framing::UnauthorizedAccessException(QPID_MSG("unauthorized-access: ACL denied QMF query of object class " << className << " from " << userId)); - } - } - Variant::List _list; - Variant::List _subList; - unsigned int objCount = 0; - - ManagementObjectVector localManagementObjects; - { - sys::Mutex::ScopedLock objLock(objectLock); - std::transform(managementObjects.begin(), managementObjects.end(), - std::back_inserter(localManagementObjects), - boost::bind(&ManagementObjectMap::value_type::second, _1)); - } - - for (ManagementObjectVector::iterator iter = localManagementObjects.begin(); - iter != localManagementObjects.end(); - iter++) { - ManagementObject::shared_ptr object = *iter; - if (object->getClassName() == className && - (packageName.empty() || object->getPackageName() == packageName)) { - - - if (!object->isDeleted()) { - Variant::Map map_; - Variant::Map values; - Variant::Map oidMap; - - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - object->writeTimestamps(map_); - object->mapEncodeValues(values, true, true); // write both stats and properties - object->getObjectId().mapEncode(oidMap); - - map_["_values"] = values; - map_["_object_id"] = oidMap; - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - "_data", - object->getMd5Sum()); - _subList.push_back(map_); - if (++objCount >= maxReplyObjs) { - objCount = 0; - _list.push_back(_subList); - _subList.clear(); - } - } - } - } - - if (_subList.size()) - _list.push_back(_subList); - - headers["partial"] = Variant(); - string content; - while (_list.size() > 1) { - ListCodec::encode(_list.front().asList(), content); - sendBuffer(content, cid, headers, "amqp/list", rte, rtk); - _list.pop_front(); - QPID_LOG(debug, "SENT QueryResponse (partial, query by schema_id) to=" << rte << "/" << rtk << " len=" << content.length()); - } - headers.erase("partial"); - ListCodec::encode(_list.size() ? _list.front().asList() : Variant::List(), content); - sendBuffer(content, cid, headers, "amqp/list", rte, rtk); - QPID_LOG(debug, "SENT QueryResponse (query by schema_id) to=" << rte << "/" << rtk << " len=" << content.length()); - return; - } - - // Unrecognized query - Send empty message to indicate CommandComplete - string content; - ListCodec::encode(Variant::List(), content); - sendBuffer(content, cid, headers, "amqp/list", rte, rtk); - QPID_LOG(debug, "SENT QueryResponse (empty) to=" << rte << "/" << rtk); -} - - -void ManagementAgent::handleLocateRequest(const string&, const string& rte, const string& rtk, const string& cid) -{ - QPID_LOG(debug, "RCVD AgentLocateRequest"); - - Variant::Map map; - Variant::Map headers; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_agent_locate_response"; - headers["qmf.agent"] = name_address; - - map["_values"] = attrMap; - map["_values"].asMap()["_timestamp"] = uint64_t(sys::Duration::FromEpoch()); - map["_values"].asMap()["_heartbeat_interval"] = interval; - map["_values"].asMap()["_epoch"] = bootSequence; - - string content; - MapCodec::encode(map, content); - sendBuffer(content, cid, headers, "amqp/map", rte, rtk); - clientWasAdded = true; - - QPID_LOG(debug, "SENT AgentLocateResponse replyTo=" << rte << "/" << rtk); -} - - -bool ManagementAgent::authorizeAgentMessage(Message& msg) -{ - sys::Mutex::ScopedLock lock(userLock); - ResizableBuffer inBuffer (qmfV1BufferSize); - uint32_t sequence = 0; - bool methodReq = false; - bool mapMsg = false; - string packageName; - string className; - string methodName; - string cid; - - boost::intrusive_ptr transfer = protocols->translate(msg); - // - // If the message is larger than our working buffer size (or if it - // could not be converted to an 0-10 messgae-transfer), we can't - // determine if it's authorized or not. In this case, return true - // (authorized) if there is no ACL in place, otherwise return - // false; - // - if (!transfer || transfer->getContentSize() > qmfV1BufferSize) - return broker->getAcl() == 0; - - inBuffer.putRawData(transfer->getContent()); - uint32_t bufferLen = inBuffer.getPosition(); - inBuffer.reset(); - - const framing::MessageProperties* p = - transfer ? transfer->getFrames().getHeaders()->get() : 0; - - const framing::FieldTable *headers = p ? &p->getApplicationHeaders() : 0; - - if (headers && p->getAppId() == "qmf2") - { - mapMsg = true; - - if (p && p->hasCorrelationId()) { - cid = p->getCorrelationId(); - } - - if (headers->getAsString("qmf.opcode") == "_method_request") - { - methodReq = true; - - // extract object id and method name - - string body; - inBuffer.getRawData(body, bufferLen); - Variant::Map inMap; - MapCodec::decode(body, inMap); - Variant::Map::const_iterator oid, mid; - - ObjectId objId; - - if ((oid = inMap.find("_object_id")) == inMap.end() || - (mid = inMap.find("_method_name")) == inMap.end()) { - QPID_LOG(warning, - "Missing fields in QMF authorize req received."); - return false; - } - - try { - // coversions will throw if input is invalid. - objId = ObjectId(oid->second.asMap()); - methodName = mid->second.getString(); - } catch(exception& /*e*/) { - QPID_LOG(warning, - "Badly formatted QMF authorize req received."); - return false; - } - - // look up schema for object to get package and class name - sys::Mutex::ScopedLock lock(objectLock); - ManagementObjectMap::iterator iter = managementObjects.find(objId); - - if (iter == managementObjects.end() || iter->second->isDeleted()) { - QPID_LOG(debug, "ManagementAgent::authorizeAgentMessage: stale object id " << - objId); - return false; - } - - packageName = iter->second->getPackageName(); - className = iter->second->getClassName(); - } - } else { // old style binary message format - - uint8_t opcode; - - if (!checkHeader(inBuffer, &opcode, &sequence)) - return false; - - if (opcode == 'M') { - methodReq = true; - - // extract method name & schema package and class name - - uint8_t hash[16]; - inBuffer.getLongLong(); // skip over object id - inBuffer.getLongLong(); - inBuffer.getShortString(packageName); - inBuffer.getShortString(className); - inBuffer.getBin128(hash); - inBuffer.getShortString(methodName); - - } - } - - if (methodReq) { - map params; - AclModule* acl = broker->getAcl(); - if (acl == 0) - return true; - - string userId = msg.getUserId(); - params[acl::PROP_SCHEMAPACKAGE] = packageName; - params[acl::PROP_SCHEMACLASS] = className; - - if (acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_METHOD, methodName, ¶ms)) - return true; - - // authorization failed, send reply if replyTo present - - boost::intrusive_ptr transfer = protocols->translate(msg); - const framing::MessageProperties* p = - transfer ? transfer->getFrames().getHeaders()->get() : 0; - if (p && p->hasReplyTo()) { - const framing::ReplyTo& rt = p->getReplyTo(); - string rte = rt.getExchange(); - string rtk = rt.getRoutingKey(); - string cid; - if (p && p->hasCorrelationId()) - cid = p->getCorrelationId(); - - if (mapMsg) { - sendException(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_FORBIDDEN), - Manageable::STATUS_FORBIDDEN, false); - } else { - - ResizableBuffer outBuffer(qmfV1BufferSize); - - encodeHeader(outBuffer, 'm', sequence); - outBuffer.putLong(Manageable::STATUS_FORBIDDEN); - outBuffer.putMediumString(Manageable::StatusText(Manageable::STATUS_FORBIDDEN)); - sendBuffer(outBuffer, rte, rtk); - } - - QPID_LOG(debug, "SEND MethodResponse status=FORBIDDEN" << " seq=" << sequence); - } - - return false; - } - - return true; -} - -void ManagementAgent::dispatchAgentCommand(Message& msg, bool viaLocal) -{ - string rte; - string rtk; - - boost::intrusive_ptr transfer = protocols->translate(msg); - const framing::MessageProperties* p = transfer ? - transfer->getFrames().getHeaders()->get() : 0; - if (p && p->hasReplyTo()) { - const framing::ReplyTo& rt = p->getReplyTo(); - rte = rt.getExchange(); - rtk = rt.getRoutingKey(); - } - else - return; - - ResizableBuffer inBuffer(qmfV1BufferSize); - uint8_t opcode; - - if (transfer->getContentSize() > qmfV1BufferSize) { - QPID_LOG(debug, "ManagementAgent::dispatchAgentCommandLH: Message too large: " << - transfer->getContentSize()); - return; - } - - inBuffer.putRawData(transfer->getContent()); - uint32_t bufferLen = inBuffer.getPosition(); - inBuffer.reset(); - - ScopedManagementContext context(msg.getPublisher()); - const framing::FieldTable *headers = p ? &p->getApplicationHeaders() : 0; - if (headers && p->getAppId() == "qmf2") - { - string opcode = headers->getAsString("qmf.opcode"); - string contentType = headers->getAsString("qmf.content"); - string body; - string cid; - inBuffer.getRawData(body, bufferLen); - { - if (p && p->hasCorrelationId()) { - cid = p->getCorrelationId(); - } - - if (opcode == "_method_request") - return handleMethodRequest(body, rte, rtk, cid, context.getUserId(), viaLocal); - else if (opcode == "_query_request") - return handleGetQuery(body, rte, rtk, cid, context.getUserId(), viaLocal); - else if (opcode == "_agent_locate_request") - return handleLocateRequest(body, rte, rtk, cid); - } - QPID_LOG(warning, "Support for QMF Opcode [" << opcode << "] TBD!!!"); - return; - } - - // old preV2 binary messages - while (inBuffer.getPosition() < bufferLen) { - uint32_t sequence; - if (!checkHeader(inBuffer, &opcode, &sequence)) - return; - - if (opcode == 'B') handleBrokerRequest (inBuffer, rtk, sequence); - else if (opcode == 'P') handlePackageQuery (inBuffer, rtk, sequence); - else if (opcode == 'p') handlePackageInd (inBuffer, rtk, sequence); - else if (opcode == 'Q') handleClassQuery (inBuffer, rtk, sequence); - else if (opcode == 'q') handleClassInd (inBuffer, rtk, sequence); - else if (opcode == 'S') handleSchemaRequest (inBuffer, rte, rtk, sequence); - else if (opcode == 's') handleSchemaResponse (inBuffer, rtk, sequence); - else if (opcode == 'A') handleAttachRequest (inBuffer, rtk, sequence, context.getObjectId()); - else if (opcode == 'G') handleGetQuery (inBuffer, rtk, sequence, context.getMgmtId()); - else if (opcode == 'M') handleMethodRequest (inBuffer, rtk, sequence, context.getMgmtId()); - } -} - -ManagementAgent::PackageMap::iterator ManagementAgent::findOrAddPackageLH(string name) -{ - PackageMap::iterator pIter = packages.find (name); - if (pIter != packages.end ()) - return pIter; - - // No such package found, create a new map entry. - pair result = - packages.insert(pair(name, ClassMap())); - QPID_LOG (debug, "ManagementAgent added package " << name); - - // Publish a package-indication message - ResizableBuffer outBuffer (qmfV1BufferSize); - - encodeHeader (outBuffer, 'p'); - encodePackageIndication (outBuffer, result.first); - sendBuffer(outBuffer, mExchange, "schema.package"); - QPID_LOG(debug, "SEND PackageInd package=" << name << " to=schema.package"); - - return result.first; -} - -void ManagementAgent::addClassLH(uint8_t kind, - 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. - QPID_LOG (debug, "ManagementAgent added class " << pIter->first << ":" << - key.name); - - cMap.insert(pair(key, SchemaClass(kind, schemaCall))); - cIter = cMap.find(key); -} - -void ManagementAgent::encodePackageIndication(Buffer& buf, - PackageMap::iterator pIter) -{ - buf.putShortString((*pIter).first); -} - -void ManagementAgent::encodeClassIndication(Buffer& buf, - const std::string packageName, - const SchemaClassKey key, - uint8_t kind) -{ - buf.putOctet(kind); - buf.putShortString(packageName); - key.encode(buf); -} - -size_t ManagementAgent::validateSchema(Buffer& inBuffer, uint8_t kind) -{ - if (kind == ManagementItem::CLASS_KIND_TABLE) - return validateTableSchema(inBuffer); - else if (kind == ManagementItem::CLASS_KIND_EVENT) - return validateEventSchema(inBuffer); - return 0; -} - -size_t ManagementAgent::validateTableSchema(Buffer& inBuffer) -{ - uint32_t start = inBuffer.getPosition(); - uint32_t end; - string text; - uint8_t hash[16]; - - try { - uint8_t kind = inBuffer.getOctet(); - if (kind != ManagementItem::CLASS_KIND_TABLE) - return 0; - - inBuffer.getShortString(text); - inBuffer.getShortString(text); - inBuffer.getBin128(hash); - - uint8_t superType = 0; //inBuffer.getOctet(); - - uint16_t propCount = inBuffer.getShort(); - uint16_t statCount = inBuffer.getShort(); - uint16_t methCount = inBuffer.getShort(); - - if (superType == 1) { - inBuffer.getShortString(text); - inBuffer.getShortString(text); - inBuffer.getBin128(hash); - } - - for (uint16_t idx = 0; idx < propCount + statCount; idx++) { - FieldTable ft; - ft.decode(inBuffer); - } - - for (uint16_t idx = 0; idx < methCount; idx++) { - FieldTable ft; - ft.decode(inBuffer); - if (!ft.isSet("argCount")) - return 0; - int argCount = ft.getAsInt("argCount"); - for (int mIdx = 0; mIdx < argCount; mIdx++) { - FieldTable aft; - aft.decode(inBuffer); - } - } - } catch (exception& /*e*/) { - return 0; - } - - end = inBuffer.getPosition(); - inBuffer.setPosition(start); // restore original position - return end - start; -} - -size_t ManagementAgent::validateEventSchema(Buffer& inBuffer) -{ - uint32_t start = inBuffer.getPosition(); - uint32_t end; - string text; - uint8_t hash[16]; - - try { - uint8_t kind = inBuffer.getOctet(); - if (kind != ManagementItem::CLASS_KIND_EVENT) - return 0; - - inBuffer.getShortString(text); - inBuffer.getShortString(text); - inBuffer.getBin128(hash); - - uint8_t superType = 0; //inBuffer.getOctet(); - - uint16_t argCount = inBuffer.getShort(); - - if (superType == 1) { - inBuffer.getShortString(text); - inBuffer.getShortString(text); - inBuffer.getBin128(hash); - } - for (uint16_t idx = 0; idx < argCount; idx++) { - FieldTable ft; - ft.decode(inBuffer); - } - } catch (exception& /*e*/) { - return 0; - } - - end = inBuffer.getPosition(); - inBuffer.setPosition(start); // restore original position - return end - start; -} - -ManagementObjectMap::iterator ManagementAgent::numericFind(const ObjectId& oid) -{ - ManagementObjectMap::iterator iter = managementObjects.begin(); - for (; iter != managementObjects.end(); iter++) { - if (oid.equalV1(iter->first)) - break; - } - - return iter; -} - -void ManagementAgent::disallow(const string& className, const string& methodName, const string& message) { - disallowed[make_pair(className, methodName)] = message; -} - -void ManagementAgent::SchemaClassKey::mapEncode(Variant::Map& _map) const { - _map["_cname"] = name; - _map["_hash"] = qpid::types::Uuid(hash); -} - -void ManagementAgent::SchemaClassKey::mapDecode(const Variant::Map& _map) { - Variant::Map::const_iterator i; - - if ((i = _map.find("_cname")) != _map.end()) { - name = i->second.asString(); - } - - if ((i = _map.find("_hash")) != _map.end()) { - const qpid::types::Uuid& uuid = i->second.asUuid(); - memcpy(hash, uuid.data(), uuid.size()); - } -} - -void ManagementAgent::SchemaClassKey::encode(qpid::framing::Buffer& buffer) const { - buffer.checkAvailable(encodedBufSize()); - buffer.putShortString(name); - buffer.putBin128(hash); -} - -void ManagementAgent::SchemaClassKey::decode(qpid::framing::Buffer& buffer) { - buffer.checkAvailable(encodedBufSize()); - buffer.getShortString(name); - buffer.getBin128(hash); -} - -uint32_t ManagementAgent::SchemaClassKey::encodedBufSize() const { - return 1 + name.size() + 16 /* bin128 */; -} - -void ManagementAgent::SchemaClass::mapEncode(Variant::Map& _map) const { - _map["_type"] = kind; - _map["_pending_sequence"] = pendingSequence; - _map["_data"] = data; -} - -void ManagementAgent::SchemaClass::mapDecode(const Variant::Map& _map) { - Variant::Map::const_iterator i; - - if ((i = _map.find("_type")) != _map.end()) { - kind = i->second; - } - if ((i = _map.find("_pending_sequence")) != _map.end()) { - pendingSequence = i->second; - } - if ((i = _map.find("_data")) != _map.end()) { - data = i->second.asString(); - } -} - -void ManagementAgent::RemoteAgent::mapEncode(Variant::Map& map_) const { - Variant::Map _objId, _values; - - map_["_brokerBank"] = brokerBank; - map_["_agentBank"] = agentBank; - map_["_routingKey"] = routingKey; - - connectionRef.mapEncode(_objId); - map_["_object_id"] = _objId; - - mgmtObject->mapEncodeValues(_values, true, false); - map_["_values"] = _values; -} - -void ManagementAgent::RemoteAgent::mapDecode(const Variant::Map& map_) { - Variant::Map::const_iterator i; - - if ((i = map_.find("_brokerBank")) != map_.end()) { - brokerBank = i->second; - } - - if ((i = map_.find("_agentBank")) != map_.end()) { - agentBank = i->second; - } - - if ((i = map_.find("_routingKey")) != map_.end()) { - routingKey = i->second.getString(); - } - - if ((i = map_.find("_object_id")) != map_.end()) { - connectionRef.mapDecode(i->second.asMap()); - } - - mgmtObject = _qmf::Agent::shared_ptr(new _qmf::Agent(&agent, this)); - - if ((i = map_.find("_values")) != map_.end()) { - mgmtObject->mapDecodeValues(i->second.asMap()); - } - - // TODO aconway 2010-03-04: see comment in encode(), readProperties doesn't set v2key. - mgmtObject->set_connectionRef(connectionRef); -} - -namespace { -bool isDeletedMap(const ManagementObjectMap::value_type& value) { - return value.second->isDeleted(); -} - -bool isDeletedVector(const ManagementObjectVector::value_type& value) { - return value->isDeleted(); -} - -string summarizeMap(const char* name, const ManagementObjectMap& map) { - ostringstream o; - size_t deleted = std::count_if(map.begin(), map.end(), isDeletedMap); - o << map.size() << " " << name << " (" << deleted << " deleted), "; - return o.str(); -} - -string summarizeVector(const char* name, const ManagementObjectVector& map) { - ostringstream o; - size_t deleted = std::count_if(map.begin(), map.end(), isDeletedVector); - o << map.size() << " " << name << " (" << deleted << " deleted), "; - return o.str(); -} - -string dumpMap(const ManagementObjectMap& map) { - ostringstream o; - for (ManagementObjectMap::const_iterator i = map.begin(); i != map.end(); ++i) { - o << endl << " " << i->second->getObjectId().getV2Key() - << (i->second->isDeleted() ? " (deleted)" : ""); - } - return o.str(); -} - -string dumpVector(const ManagementObjectVector& map) { - ostringstream o; - for (ManagementObjectVector::const_iterator i = map.begin(); i != map.end(); ++i) { - o << endl << " " << (*i)->getObjectId().getV2Key() - << ((*i)->isDeleted() ? " (deleted)" : ""); - } - return o.str(); -} - -} // namespace - -string ManagementAgent::summarizeAgents() { - ostringstream msg; - if (!remoteAgents.empty()) { - msg << remoteAgents.size() << " agents("; - for (RemoteAgentMap::const_iterator i=remoteAgents.begin(); - i != remoteAgents.end(); ++i) - msg << " " << i->second->routingKey; - msg << "), "; - } - return msg.str(); -} - - -void ManagementAgent::debugSnapshot(const char* title) { - sys::Mutex::ScopedLock lock(addLock); - sys::Mutex::ScopedLock objLock (objectLock); - QPID_LOG(debug, title << ": management snapshot: " - << packages.size() << " packages, " - << summarizeMap("objects", managementObjects) - << summarizeVector("new objects ", newManagementObjects) - << pendingDeletedObjs.size() << " pending deletes" - << summarizeAgents()); - - QPID_LOG_IF(trace, managementObjects.size(), - title << ": objects" << dumpMap(managementObjects)); - QPID_LOG_IF(trace, newManagementObjects.size(), - title << ": new objects" << dumpVector(newManagementObjects)); -} - - -Variant::Map ManagementAgent::toMap(const FieldTable& from) -{ - Variant::Map map; - qpid::amqp_0_10::translate(from, map); - return map; -} - -// construct a DeletedObject from a management object. -ManagementAgent::DeletedObject::DeletedObject(ManagementObject::shared_ptr src, bool v1, bool v2) - : packageName(src->getPackageName()), - className(src->getClassName()) -{ - bool send_stats = (src->hasInst() && (src->getInstChanged() || src->getForcePublish())); - - stringstream oid; - oid << src->getObjectId(); - objectId = oid.str(); - - if (v1) { - src->writeProperties(encodedV1Config); - if (send_stats) { - src->writeStatistics(encodedV1Inst); - } - } - - if (v2) { - Variant::Map map_; - Variant::Map values; - Variant::Map oid; - - src->getObjectId().mapEncode(oid); - map_["_object_id"] = oid; - map_["_schema_id"] = mapEncodeSchemaId(src->getPackageName(), - src->getClassName(), - "_data", - src->getMd5Sum()); - src->writeTimestamps(map_); - src->mapEncodeValues(values, true, send_stats); - map_["_values"] = values; - - encodedV2 = map_; - } -} - -// Remove Deleted objects, and save for later publishing... -bool ManagementAgent::moveDeletedObjects() { - typedef vector > DeleteList; - - sys::Mutex::ScopedLock lock (objectLock); - - DeleteList deleteList; - for (ManagementObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - ++iter) - { - ManagementObject::shared_ptr object = iter->second; - if (object->isDeleted()) deleteList.push_back(*iter); - } - - // Iterate in reverse over deleted object list - for (DeleteList::reverse_iterator iter = deleteList.rbegin(); - iter != deleteList.rend(); - iter++) - { - ManagementObject::shared_ptr delObj = iter->second; - assert(delObj->isDeleted()); - DeletedObject::shared_ptr dptr(new DeletedObject(delObj, qmf1Support, qmf2Support)); - - pendingDeletedObjs[dptr->getKey()].push_back(dptr); - managementObjects.erase(iter->first); - } - return !deleteList.empty(); -} - -ManagementAgent::EventQueue::Batch::const_iterator ManagementAgent::sendEvents( - const EventQueue::Batch& batch) -{ - EventQueue::Batch::const_iterator i; - for (i = batch.begin(); i != batch.end(); ++i) { - DeliverableMessage deliverable (i->second, 0); - try { - i->first->route(deliverable); - } catch(exception& e) { - QPID_LOG(warning, "ManagementAgent failed to route event: " << e.what()); - } - } - return i; -} - -namespace { -QPID_TSS const Connection* currentPublisher = 0; -} - -void setManagementExecutionContext(const Connection& p) -{ - currentPublisher = &p; -} - -void resetManagementExecutionContext() -{ - currentPublisher = 0; -} - -const Connection* getCurrentPublisher() -{ - return currentPublisher; -} - -}} - diff --git a/qpid/cpp/src/qpid/management/ManagementAgent.h b/qpid/cpp/src/qpid/management/ManagementAgent.h deleted file mode 100644 index 81bf542766..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementAgent.h +++ /dev/null @@ -1,388 +0,0 @@ -#ifndef _ManagementAgent_ -#define _ManagementAgent_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/BrokerImportExport.h" -#include "qpid/Options.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/Mutex.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/management/ManagementEvent.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Agent.h" -#include "qmf/org/apache/qpid/broker/Memory.h" -#include "qpid/sys/MemStat.h" -#include "qpid/sys/PollableQueue.h" -#include "qpid/types/Variant.h" -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { -class Connection; -class ProtocolRegistry; -} -namespace sys { -class Timer; -} -namespace management { - -class ManagementAgent -{ -private: - - int threadPoolSize; - -public: - typedef enum { - SEV_EMERG = 0, - SEV_ALERT = 1, - SEV_CRIT = 2, - SEV_ERROR = 3, - SEV_WARN = 4, - SEV_NOTE = 5, - SEV_INFO = 6, - SEV_DEBUG = 7, - SEV_DEFAULT = 8 - } severity_t; - - - ManagementAgent (const bool qmfV1, const bool qmfV2); - virtual ~ManagementAgent (); - - /** Called before plugins are initialized */ - void configure (const std::string& dataDir, bool publish, uint16_t interval, - qpid::broker::Broker* broker, int threadPoolSize); - - 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 setInterval(uint16_t _interval) { interval = _interval; } - void setExchange(qpid::broker::Exchange::shared_ptr mgmtExchange, - qpid::broker::Exchange::shared_ptr directExchange); - void setExchangeV2(qpid::broker::Exchange::shared_ptr topicExchange, - qpid::broker::Exchange::shared_ptr directExchange); - - int getMaxThreads () { return threadPoolSize; } - QPID_BROKER_EXTERN void registerClass (const std::string& packageName, - const std::string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall); - QPID_BROKER_EXTERN void registerEvent (const std::string& packageName, - const std::string& eventName, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall); - QPID_BROKER_EXTERN ObjectId addObject (ManagementObject::shared_ptr object, - uint64_t persistId = 0, - bool persistent = false); - QPID_BROKER_EXTERN ObjectId addObject (ManagementObject::shared_ptr object, - const std::string& key, - bool persistent = false); - QPID_BROKER_EXTERN void raiseEvent(const ManagementEvent& event, - severity_t severity = SEV_DEFAULT); - QPID_BROKER_EXTERN void clientAdded (const std::string& routingKey); - - bool dispatchCommand (qpid::broker::Deliverable& msg, - const std::string& routingKey, - const framing::FieldTable* args, - const bool topic, - int qmfVersion); - - /** Disallow a method. Attempts to call it will receive an exception with message. */ - void disallow(const std::string& className, const std::string& methodName, const std::string& message); - - uint16_t getBootSequence(void) { return bootSequence; } - void setBootSequence(uint16_t b) { bootSequence = b; writeData(); } - - const framing::Uuid& getUuid() const { return uuid; } - void setUuid(const framing::Uuid& id) { uuid = id; writeData(); } - - static types::Variant::Map toMap(const framing::FieldTable& from); - - class DeletedObject { - public: - typedef boost::shared_ptr shared_ptr; - DeletedObject(ManagementObject::shared_ptr, bool v1, bool v2); - ~DeletedObject() {}; - const std::string getKey() const { - // used to batch up objects of the same class type - return std::string(packageName + std::string(":") + className); - } - - private: - friend class ManagementAgent; - - std::string packageName; - std::string className; - std::string objectId; - - std::string encodedV1Config; // qmfv1 properties - std::string encodedV1Inst; // qmfv1 statistics - qpid::types::Variant::Map encodedV2; - }; - - typedef std::vector DeletedObjectList; - -private: - // Storage for tracking remote management agents, attached via the client - // management agent API. - // - struct RemoteAgent : public Manageable - { - ManagementAgent& agent; - uint32_t brokerBank; - uint32_t agentBank; - std::string routingKey; - ObjectId connectionRef; - qmf::org::apache::qpid::broker::Agent::shared_ptr mgmtObject; - RemoteAgent(ManagementAgent& _agent) : agent(_agent) {} - ManagementObject::shared_ptr GetManagementObject (void) const { return mgmtObject; } - - virtual ~RemoteAgent (); - void mapEncode(qpid::types::Variant::Map& _map) const; - void mapDecode(const qpid::types::Variant::Map& _map); - }; - - typedef std::map > RemoteAgentMap; - - // Storage for known schema classes: - // - // SchemaClassKey -- Key elements for map lookups - // SchemaClassKeyComp -- Comparison class for SchemaClassKey - // SchemaClass -- Non-key elements for classes - // - struct SchemaClassKey - { - std::string name; - uint8_t hash[16]; - - void mapEncode(qpid::types::Variant::Map& _map) const; - void mapDecode(const qpid::types::Variant::Map& _map); - void encode(framing::Buffer& buffer) const; - void decode(framing::Buffer& buffer); - uint32_t encodedBufSize() const; - }; - - 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 - { - uint8_t kind; - ManagementObject::writeSchemaCall_t writeSchemaCall; - std::string data; - uint32_t pendingSequence; - - SchemaClass(uint8_t _kind=0, uint32_t seq=0) : - kind(_kind), writeSchemaCall(0), pendingSequence(seq) {} - SchemaClass(uint8_t _kind, ManagementObject::writeSchemaCall_t call) : - kind(_kind), writeSchemaCall(call), pendingSequence(0) {} - bool hasSchema () { return (writeSchemaCall != 0) || !data.empty(); } - void appendSchema (framing::Buffer& buf); - - void mapEncode(qpid::types::Variant::Map& _map) const; - void mapDecode(const qpid::types::Variant::Map& _map); - }; - - typedef std::map ClassMap; - typedef std::map PackageMap; - - RemoteAgentMap remoteAgents; - PackageMap packages; - - // - // Protected by objectLock - // - ManagementObjectMap managementObjects; - - // - // Protected by addLock - // - ManagementObjectVector newManagementObjects; - - framing::Uuid uuid; - - // - // Lock ordering: userLock -> addLock -> objectLock - // - sys::Mutex userLock; - sys::Mutex addLock; - sys::Mutex objectLock; - - qpid::broker::Exchange::shared_ptr mExchange; - qpid::broker::Exchange::shared_ptr dExchange; - qpid::broker::Exchange::shared_ptr v2Topic; - qpid::broker::Exchange::shared_ptr v2Direct; - std::string dataDir; - bool publish; - uint16_t interval; - qpid::broker::Broker* broker; - qpid::sys::Timer* timer; - qpid::broker::ProtocolRegistry* protocols; - uint16_t bootSequence; - uint32_t nextObjectId; - uint32_t brokerBank; - uint32_t nextRemoteBank; - uint32_t nextRequestSequence; - bool clientWasAdded; - const qpid::sys::AbsTime startTime; - bool suppressed; - - typedef std::pair MethodName; - typedef std::map DisallowedMethods; - DisallowedMethods disallowed; - bool disallowAllV1Methods; - - // Agent name and address - qpid::types::Variant::Map attrMap; - std::string name_address; - std::string vendorNameKey; // "." --> "_" - std::string productNameKey; // "." --> "_" - std::string instanceNameKey; // "." --> "_" - - // supported management protocol - bool qmf1Support; - bool qmf2Support; - - // Maximum # of objects allowed in a single V2 response - // message. - uint32_t maxReplyObjs; - - // list of objects that have been deleted, but have yet to be published - // one final time. - // Indexed by a string composed of the object's package and class name. - // Protected by objectLock. - typedef std::map PendingDeletedObjsMap; - PendingDeletedObjsMap pendingDeletedObjs; - - // Pollable queue to serialize event messages - typedef std::pair, - broker::Message> ExchangeAndMessage; - typedef sys::PollableQueue EventQueue; - - // - // Memory statistics object - // - qmf::org::apache::qpid::broker::Memory::shared_ptr memstat; - - void writeData (); - void periodicProcessing (void); - void deleteObjectNow(const ObjectId& oid); - void encodeHeader (framing::Buffer& buf, uint8_t opcode, uint32_t seq = 0); - bool checkHeader (framing::Buffer& buf, uint8_t *opcode, uint32_t *seq); - EventQueue::Batch::const_iterator sendEvents(const EventQueue::Batch& batch); - void sendBuffer(framing::Buffer& buf, - qpid::broker::Exchange::shared_ptr exchange, - const std::string& routingKey); - void sendBuffer(framing::Buffer& buf, - 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& content_type, - qpid::broker::Exchange::shared_ptr exchange, - const std::string& routingKey, - uint64_t ttl_msec = 0); - void sendBuffer(const std::string& data, - const std::string& cid, - const qpid::types::Variant::Map& headers, - const std::string& content_type, - const std::string& exchange, - const std::string& routingKey, - uint64_t ttl_msec = 0); - void moveNewObjects(); - bool moveDeletedObjects(); - - bool authorizeAgentMessage(qpid::broker::Message& msg); - void dispatchAgentCommand(qpid::broker::Message& msg, bool viaLocal=false); - - PackageMap::iterator findOrAddPackageLH(std::string name); - void addClassLH(uint8_t kind, - PackageMap::iterator pIter, - const std::string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall); - void encodePackageIndication (framing::Buffer& buf, - PackageMap::iterator pIter); - void encodeClassIndication (framing::Buffer& buf, - const std::string packageName, - const struct SchemaClassKey key, - uint8_t kind); - bool bankInUse (uint32_t bank); - uint32_t allocateNewBank (); - uint32_t assignBankLH (uint32_t requestedPrefix); - void deleteOrphanedAgentsLH(); - void sendCommandComplete(const std::string& replyToKey, uint32_t sequence, - uint32_t code = 0, const std::string& text = "OK"); - void sendException(const std::string& rte, const std::string& rtk, const std::string& cid, const std::string& text, uint32_t code=1, bool viaLocal=false); - void handleBrokerRequest (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handlePackageQuery (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handlePackageInd (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleClassQuery (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleClassInd (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleSchemaRequest (framing::Buffer& inBuffer, const std::string& replyToEx, const std::string& replyToKey, uint32_t sequence); - void handleSchemaResponse (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleAttachRequest (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence, const ObjectId& objectId); - void handleGetQuery (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence, const std::string& userId); - void handleMethodRequest (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence, const std::string& userId); - void handleGetQuery (const std::string& body, const std::string& replyToEx, const std::string& replyToKey, const std::string& cid, const std::string& userId, bool viaLocal); - void handleMethodRequest (const std::string& body, const std::string& replyToEx, const std::string& replyToKey, const std::string& cid, const std::string& userId, bool viaLocal); - void handleLocateRequest (const std::string& body, const std::string& replyToEx, const std::string &replyToKey, const std::string& cid); - - - size_t validateSchema(framing::Buffer&, uint8_t kind); - size_t validateTableSchema(framing::Buffer&); - size_t validateEventSchema(framing::Buffer&); - ManagementObjectMap::iterator numericFind(const ObjectId& oid); - - std::string summarizeAgents(); - void debugSnapshot(const char* title); - std::auto_ptr sendQueue; -}; - -void setManagementExecutionContext(const broker::Connection&); -void resetManagementExecutionContext(); -const broker::Connection* getCurrentPublisher(); -}} - -#endif /*!_ManagementAgent_*/ diff --git a/qpid/cpp/src/qpid/management/ManagementDirectExchange.cpp b/qpid/cpp/src/qpid/management/ManagementDirectExchange.cpp deleted file mode 100644 index 8ede6940b0..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementDirectExchange.cpp +++ /dev/null @@ -1,65 +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/ManagementDirectExchange.h" -#include "qpid/log/Statement.h" -#include - -using namespace qpid::management; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -ManagementDirectExchange::ManagementDirectExchange(const std::string& _name, Manageable* _parent, Broker* b) : - Exchange (_name, _parent, b), - DirectExchange(_name, _parent, b), - managementAgent(0) {} -ManagementDirectExchange::ManagementDirectExchange(const std::string& _name, - bool _durable, - const FieldTable& _args, - Manageable* _parent, Broker* b) : - Exchange (_name, _durable, false, _args, _parent, b), - DirectExchange(_name, _durable, false, _args, _parent, b), - managementAgent(0) {} - -void ManagementDirectExchange::route(Deliverable& msg) -{ - bool routeIt = true; - - if (managementAgent) - routeIt = managementAgent->dispatchCommand(msg, msg.getMessage().getRoutingKey(), 0/*args - TODO*/, false, qmfVersion); - - if (routeIt) - DirectExchange::route(msg); -} - -void ManagementDirectExchange::setManagmentAgent(ManagementAgent* agent, int qv) -{ - managementAgent = agent; - qmfVersion = qv; - assert(qmfVersion == 2); // QMFv1 doesn't use a specialized direct exchange -} - - -ManagementDirectExchange::~ManagementDirectExchange() {} - -const std::string ManagementDirectExchange::typeName("management-direct"); - diff --git a/qpid/cpp/src/qpid/management/ManagementDirectExchange.h b/qpid/cpp/src/qpid/management/ManagementDirectExchange.h deleted file mode 100644 index 582354d723..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementDirectExchange.h +++ /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. - * - */ -#ifndef _ManagementDirectExchange_ -#define _ManagementDirectExchange_ - -#include "qpid/broker/DirectExchange.h" -#include "qpid/management/ManagementAgent.h" - -namespace qpid { -namespace broker { - -class ManagementDirectExchange : public virtual DirectExchange -{ - private: - management::ManagementAgent* managementAgent; - int qmfVersion; - - public: - static const std::string typeName; - - ManagementDirectExchange(const std::string& name, Manageable* _parent = 0, Broker* broker = 0); - ManagementDirectExchange(const std::string& _name, bool _durable, - const qpid::framing::FieldTable& _args, - Manageable* _parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - virtual void route(Deliverable& msg); - - void setManagmentAgent(management::ManagementAgent* agent, int qmfVersion); - - virtual ~ManagementDirectExchange(); -}; - - -} -} - -#endif diff --git a/qpid/cpp/src/qpid/management/ManagementEvent.h b/qpid/cpp/src/qpid/management/ManagementEvent.h deleted file mode 100644 index e80175096f..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementEvent.h +++ /dev/null @@ -1,53 +0,0 @@ -#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 - -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.cpp b/qpid/cpp/src/qpid/management/ManagementObject.cpp deleted file mode 100644 index f18f575ff8..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementObject.cpp +++ /dev/null @@ -1,413 +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/framing/FieldTable.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" -#include "qpid/log/Statement.h" -#include - -#include - -using namespace std; -using namespace qpid; -using namespace qpid::management; - -void AgentAttachment::setBanks(uint32_t broker, uint32_t bank) -{ - first = - ((uint64_t) (broker & 0x000fffff)) << 28 | - ((uint64_t) (bank & 0x0fffffff)); -} - -// Deprecated -ObjectId::ObjectId(uint8_t flags, uint16_t seq, uint32_t broker, uint64_t object) - : agent(0), agentEpoch(seq) -{ - first = - ((uint64_t) (flags & 0x0f)) << 60 | - ((uint64_t) (seq & 0x0fff)) << 48 | - ((uint64_t) (broker & 0x000fffff)) << 28; - second = object; -} - - -ObjectId::ObjectId(uint8_t flags, uint16_t seq, uint32_t broker) - : agent(0), second(0), agentEpoch(seq) -{ - first = - ((uint64_t) (flags & 0x0f)) << 60 | - ((uint64_t) (seq & 0x0fff)) << 48 | - ((uint64_t) (broker & 0x000fffff)) << 28; -} - -ObjectId::ObjectId(AgentAttachment* _agent, uint8_t flags, uint16_t seq) - : agent(_agent), second(0), agentEpoch(seq) -{ - - first = - ((uint64_t) (flags & 0x0f)) << 60 | - ((uint64_t) (seq & 0x0fff)) << 48; -} - - -ObjectId::ObjectId(istream& in) : agent(0) -{ - string text; - in >> text; - fromString(text); -} - -ObjectId::ObjectId(const string& text) : agent(0) -{ - fromString(text); -} - -void ObjectId::fromString(const string& text) -{ -#define FIELDS 5 -#if defined (_WIN32) && !defined (atoll) -# define atoll(X) _atoi64(X) -#endif - - // format: - // V1: ---- - // V2: Not used - - string copy(text.c_str()); - char* cText; - char* field[FIELDS]; - bool atFieldStart = true; - int idx = 0; - - cText = const_cast(copy.c_str()); - for (char* cursor = cText; *cursor; cursor++) { - if (atFieldStart) { - if (idx >= FIELDS) - throw Exception("Invalid ObjectId format"); - field[idx++] = cursor; - atFieldStart = false; - } else { - if (*cursor == '-') { - *cursor = '\0'; - atFieldStart = true; - } - } - } - - if (idx != FIELDS) - throw Exception("Invalid ObjectId format"); - - agentEpoch = atoll(field[1]); - - first = (atoll(field[0]) << 60) + - (atoll(field[1]) << 48) + - (atoll(field[2]) << 28); - - agentName = string(field[3]); - second = atoll(field[4]); -} - - -bool ObjectId::operator==(const ObjectId &other) const -{ - return v2Key == other.v2Key; -} - -bool ObjectId::operator<(const ObjectId &other) const -{ - return v2Key < other.v2Key; -} - -bool ObjectId::equalV1(const ObjectId &other) const -{ - uint64_t otherFirst = agent == 0 ? other.first : other.first & 0xffff000000000000LL; - return first == otherFirst && second == other.second; -} - -// encode as V1-format binary -void ObjectId::encode(string& buffer) const -{ - const uint32_t len = 16; - char _data[len]; - qpid::framing::Buffer body(_data, len); - - if (agent == 0) - body.putLongLong(first); - else - body.putLongLong(first | agent->first); - body.putLongLong(second); - - body.reset(); - body.getRawData(buffer, len); -} - -// decode as V1-format binary -void ObjectId::decode(const string& buffer) -{ - const uint32_t len = 16; - char _data[len]; - qpid::framing::Buffer body(_data, len); - - body.checkAvailable(buffer.length()); - body.putRawData(buffer); - body.reset(); - first = body.getLongLong(); - second = body.getLongLong(); - v2Key = boost::lexical_cast(second); -} - -// generate the V2 key from the index fields defined -// in the schema. -void ObjectId::setV2Key(const ManagementObject& object) -{ - stringstream oname; - oname << object.getPackageName() << ":" << object.getClassName() << ":" << object.getKey(); - v2Key = oname.str(); -} - - -// encode as V2-format map -void ObjectId::mapEncode(types::Variant::Map& map) const -{ - map["_object_name"] = v2Key; - if (!agentName.empty()) - map["_agent_name"] = agentName; - if (agentEpoch) - map["_agent_epoch"] = agentEpoch; -} - -// decode as v2-format map -void ObjectId::mapDecode(const types::Variant::Map& map) -{ - types::Variant::Map::const_iterator i; - - if ((i = map.find("_object_name")) != map.end()) - v2Key = i->second.asString(); - else - throw Exception("Required _object_name field missing."); - - if ((i = map.find("_agent_name")) != map.end()) - agentName = i->second.asString(); - - if ((i = map.find("_agent_epoch")) != map.end()) - agentEpoch = i->second.asInt64(); -} - - -ObjectId::operator types::Variant::Map() const -{ - types::Variant::Map m; - mapEncode(m); - return m; -} - - - -namespace qpid { -namespace management { - -ostream& operator<<(ostream& out, const ObjectId& i) -{ - uint64_t virtFirst = i.first; - if (i.agent) - virtFirst |= i.agent->getFirst(); - - out << ((virtFirst & 0xF000000000000000LL) >> 60) << - "-" << ((virtFirst & 0x0FFF000000000000LL) >> 48) << - "-" << ((virtFirst & 0x0000FFFFF0000000LL) >> 28) << - "-" << i.agentName << - "-" << i.second << - "(" << i.v2Key << ")"; - return out; -} - -}} - -// Called with lock held -Manageable* ManagementObject::ManageablePtr::get() const { - if (ptr == 0) - throw framing::ResourceDeletedException("managed object deleted"); - return ptr; -} - -void ManagementObject::ManageablePtr::reset() { - Mutex::ScopedLock l(lock); - ptr = 0; -} - -uint32_t ManagementObject::ManageablePtr::ManagementMethod( - uint32_t methodId, Args& args, std::string& text) -{ - Mutex::ScopedLock l(lock); - return get()->ManagementMethod(methodId, args, text); -} - -bool ManagementObject::ManageablePtr:: AuthorizeMethod( - uint32_t methodId, Args& args, const std::string& userId) -{ - Mutex::ScopedLock l(lock); - return get()->AuthorizeMethod(methodId, args, userId); -} - -ManagementObject::ManagementObject(Manageable* _core) : - createTime(qpid::sys::Duration::FromEpoch()), - destroyTime(0), updateTime(createTime), configChanged(true), - instChanged(true), deleted(false), - manageable(_core), flags(0), forcePublish(false) {} - -void ManagementObject::setUpdateTime() -{ - updateTime = sys::Duration::FromEpoch(); -} - -void ManagementObject::resourceDestroy() -{ - QPID_LOG(trace, "Management object marked deleted: " << getObjectId().getV2Key()); - destroyTime = sys::Duration::FromEpoch(); - deleted = true; - manageable.reset(); -} - -int ManagementObject::maxThreads = 1; -int ManagementObject::nextThreadIndex = 0; - -void ManagementObject::writeTimestamps (string& buf) const -{ - char _data[4000]; - qpid::framing::Buffer body(_data, 4000); - - body.putShortString (getPackageName ()); - body.putShortString (getClassName ()); - body.putBin128 (getMd5Sum ()); - body.putLongLong (updateTime); - body.putLongLong (createTime); - body.putLongLong (destroyTime); - - uint32_t len = body.getPosition(); - body.reset(); - body.getRawData(buf, len); - - string oid; - objectId.encode(oid); - buf += oid; -} - -void ManagementObject::readTimestamps (const string& buf) -{ - char _data[4000]; - qpid::framing::Buffer body(_data, 4000); - string unused; - uint8_t unusedUuid[16]; - - body.checkAvailable(buf.length()); - body.putRawData(buf); - body.reset(); - - body.getShortString(unused); - body.getShortString(unused); - body.getBin128(unusedUuid); - updateTime = body.getLongLong(); - createTime = body.getLongLong(); - destroyTime = body.getLongLong(); -} - -uint32_t ManagementObject::writeTimestampsSize() const -{ - return 1 + getPackageName().length() + // str8 - 1 + getClassName().length() + // str8 - 16 + // bin128 - 8 + // uint64 - 8 + // uint64 - 8 + // uint64 - objectId.encodedSize(); // objectId -} - - -void ManagementObject::writeTimestamps (types::Variant::Map& map) const -{ - // types::Variant::Map oid, sid; - - // sid["_package_name"] = getPackageName(); - // sid["_class_name"] = getClassName(); - // sid["_hash"] = qpid::types::Uuid(getMd5Sum()); - // map["_schema_id"] = sid; - - // objectId.mapEncode(oid); - // map["_object_id"] = oid; - - map["_update_ts"] = updateTime; - map["_create_ts"] = createTime; - map["_delete_ts"] = destroyTime; -} - -void ManagementObject::readTimestamps (const types::Variant::Map& map) -{ - types::Variant::Map::const_iterator i; - - if ((i = map.find("_update_ts")) != map.end()) - updateTime = i->second.asUint64(); - if ((i = map.find("_create_ts")) != map.end()) - createTime = i->second.asUint64(); - if ((i = map.find("_delete_ts")) != map.end()) - destroyTime = i->second.asUint64(); -} - - -void ManagementObject::setReference(ObjectId) {} - -int ManagementObject::getThreadIndex() { - static QPID_TSS int thisIndex = -1; - if (thisIndex == -1) { - Mutex::ScopedLock mutex(accessLock); - thisIndex = nextThreadIndex; - if (nextThreadIndex < maxThreads - 1) - nextThreadIndex++; - } - return thisIndex; -} - - -// void ManagementObject::mapEncode(types::Variant::Map& map, -// bool includeProperties, -// bool includeStatistics) -// { -// types::Variant::Map values; - -// writeTimestamps(map); - -// mapEncodeValues(values, includeProperties, includeStatistics); -// map["_values"] = values; -// } - -// void ManagementObject::mapDecode(const types::Variant::Map& map) -// { -// types::Variant::Map::const_iterator i; - -// readTimestamps(map); - -// if ((i = map.find("_values")) != map.end()) -// mapDecodeValues(i->second.asMap()); -// } diff --git a/qpid/cpp/src/qpid/management/ManagementObject.h b/qpid/cpp/src/qpid/management/ManagementObject.h deleted file mode 100644 index a299f1ef4a..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementObject.h +++ /dev/null @@ -1,256 +0,0 @@ -#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/Args.h" -#include "qpid/management/Mutex.h" -#include "qpid/types/Variant.h" -#include -#include - -#include - -namespace qpid { -namespace management { - -class ObjectId; -class ManagementObject; -class Manageable; - - -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: - // Thread safe wrapper for Manageable* with atomic calls and destroy(). - class ManageablePtr { - Manageable* ptr; - mutable Mutex lock; - Manageable* get() const; - ManageablePtr(const ManageablePtr&); // not copyable - ManageablePtr& operator=(const ManageablePtr&); // not copyable - - public: - ManageablePtr(Manageable* m) : ptr(m) {} - - uint32_t ManagementMethod(uint32_t methodId, Args& args, std::string& text); - bool AuthorizeMethod(uint32_t methodId, Args& args, const std::string& userId); - void reset(); - }; - - uint64_t createTime; - uint64_t destroyTime; - uint64_t updateTime; - ObjectId objectId; - mutable bool configChanged; - mutable bool instChanged; - bool deleted; - ManageablePtr manageable; - 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: - typedef boost::shared_ptr shared_ptr; - - 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); -}; - -typedef std::map ManagementObjectMap; -typedef std::vector ManagementObjectVector; - -}} - - - -#endif /*!_ManagementObject_*/ diff --git a/qpid/cpp/src/qpid/management/ManagementTopicExchange.cpp b/qpid/cpp/src/qpid/management/ManagementTopicExchange.cpp deleted file mode 100644 index 0241d5a404..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementTopicExchange.cpp +++ /dev/null @@ -1,73 +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/ManagementTopicExchange.h" -#include "qpid/log/Statement.h" - -using namespace qpid::management; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -ManagementTopicExchange::ManagementTopicExchange(const std::string& _name, Manageable* _parent, Broker* b) : - Exchange (_name, _parent, b), - TopicExchange(_name, _parent, b), - managementAgent(0) {} -ManagementTopicExchange::ManagementTopicExchange(const std::string& _name, - bool _durable, - const FieldTable& _args, - Manageable* _parent, Broker* b) : - Exchange (_name, _durable, false, _args, _parent, b), - TopicExchange(_name, _durable, false, _args, _parent, b), - managementAgent(0) {} - -void ManagementTopicExchange::route(Deliverable& msg) -{ - bool routeIt = true; - - // Intercept management agent commands - if (managementAgent) - routeIt = managementAgent->dispatchCommand(msg, msg.getMessage().getRoutingKey(), 0/*args - TODO*/, true, qmfVersion); - - if (routeIt) - TopicExchange::route(msg); -} - -bool ManagementTopicExchange::bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args) -{ - if (qmfVersion == 1) - managementAgent->clientAdded(routingKey); - return TopicExchange::bind(queue, routingKey, args); -} - -void ManagementTopicExchange::setManagmentAgent(ManagementAgent* agent, int qv) -{ - managementAgent = agent; - qmfVersion = qv; -} - - -ManagementTopicExchange::~ManagementTopicExchange() {} - -const std::string ManagementTopicExchange::typeName("management-topic"); - diff --git a/qpid/cpp/src/qpid/management/ManagementTopicExchange.h b/qpid/cpp/src/qpid/management/ManagementTopicExchange.h deleted file mode 100644 index f5192a0936..0000000000 --- a/qpid/cpp/src/qpid/management/ManagementTopicExchange.h +++ /dev/null @@ -1,61 +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. - * - */ -#ifndef _ManagementTopicExchange_ -#define _ManagementTopicExchange_ - -#include "qpid/broker/TopicExchange.h" -#include "qpid/management/ManagementAgent.h" - -namespace qpid { -namespace broker { - -class ManagementTopicExchange : public virtual TopicExchange -{ - private: - management::ManagementAgent* managementAgent; - int qmfVersion; - - public: - static const std::string typeName; - - ManagementTopicExchange(const std::string& name, Manageable* _parent = 0, Broker* broker = 0); - ManagementTopicExchange(const std::string& _name, bool _durable, - const qpid::framing::FieldTable& _args, - Manageable* _parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - virtual void route(Deliverable& msg); - - virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - void setManagmentAgent(management::ManagementAgent* agent, int qmfVersion); - - virtual ~ManagementTopicExchange(); -}; - - -} -} - -#endif diff --git a/qpid/cpp/src/qpid/management/Mutex.cpp b/qpid/cpp/src/qpid/management/Mutex.cpp deleted file mode 100644 index f05abb01dc..0000000000 --- a/qpid/cpp/src/qpid/management/Mutex.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * 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/management/Mutex.h" -#include "qpid/sys/Mutex.h" - -using namespace std; -using namespace qpid::management; - -Mutex::Mutex() : impl(new sys::Mutex()) {} -Mutex::~Mutex() { delete impl; } -void Mutex::lock() { impl->lock(); } -void Mutex::unlock() { impl->unlock(); } - diff --git a/qpid/cpp/src/qpid/management/Mutex.h b/qpid/cpp/src/qpid/management/Mutex.h deleted file mode 100644 index 67ae04bae9..0000000000 --- a/qpid/cpp/src/qpid/management/Mutex.h +++ /dev/null @@ -1,67 +0,0 @@ -#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 ScopedLockTemplate { - public: - ScopedLockTemplate(L& l) : mutex(l) { mutex.lock(); } - ~ScopedLockTemplate() { mutex.unlock(); } - private: - L& mutex; - }; - - template class ScopedUnlockTemplate { - public: - ScopedUnlockTemplate(L& l) : mutex(l) { mutex.unlock(); } - ~ScopedUnlockTemplate() { mutex.lock(); } - private: - L& mutex; - }; - - class Mutex { - public: - typedef ScopedLockTemplate ScopedLock; - typedef ScopedUnlockTemplate 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/memory.h b/qpid/cpp/src/qpid/memory.h deleted file mode 100644 index 99d7a71e7b..0000000000 --- a/qpid/cpp/src/qpid/memory.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef QPID_AUTO_PTR_H -#define QPID_AUTO_PTR_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 -namespace qpid { -/** Convenient template for creating auto_ptr in-place in an argument list. */ -template -std::auto_ptr make_auto_ptr(T* ptr) { return std::auto_ptr(ptr); } - -} // namespace qpid - - - -#endif /*!QPID_AUTO_PTR_H*/ diff --git a/qpid/cpp/src/qpid/messaging/Address.cpp b/qpid/cpp/src/qpid/messaging/Address.cpp deleted file mode 100644 index 6fbaeef661..0000000000 --- a/qpid/cpp/src/qpid/messaging/Address.cpp +++ /dev/null @@ -1,111 +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/messaging/Address.h" -#include "qpid/messaging/AddressImpl.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/framing/Uuid.h" -#include -#include - -namespace qpid { -namespace messaging { - -using namespace qpid::types; - -namespace { -const std::string SUBJECT_DIVIDER = "/"; -const std::string OPTIONS_DIVIDER = ";"; -const std::string SPACE = " "; -const std::string TYPE = "type"; -} -Address::Address() : impl(new AddressImpl()) {} -Address::Address(const std::string& address) : impl(new AddressImpl()) -{ - AddressParser parser(address); - parser.parse(*this); -} -Address::Address(const std::string& name, const std::string& subject, const Variant::Map& options, - const std::string& type) - : impl(new AddressImpl(name, subject, options)) { setType(type); } -Address::Address(const Address& a) : - impl(new AddressImpl(a.impl->name, a.impl->subject, a.impl->options)) { impl->temporary = a.impl->temporary; } -Address::~Address() { delete impl; } - -Address& Address::operator=(const Address& a) { *impl = *a.impl; return *this; } - - -std::string Address::str() const -{ - std::stringstream out; - out << impl->name; - if (!impl->subject.empty()) out << SUBJECT_DIVIDER << impl->subject; - if (!impl->options.empty()) out << OPTIONS_DIVIDER << impl->options; - return out.str(); -} -Address::operator bool() const { return !impl->name.empty(); } -bool Address::operator !() const { return impl->name.empty(); } - -const std::string& Address::getName() const { return impl->name; } -void Address::setName(const std::string& name) { impl->name = name; } -const std::string& Address::getSubject() const { return impl->subject; } -void Address::setSubject(const std::string& subject) { impl->subject = subject; } -const Variant::Map& Address::getOptions() const { return impl->options; } -Variant::Map& Address::getOptions() { return impl->options; } -void Address::setOptions(const Variant::Map& options) { impl->options = options; } - - -namespace{ -const Variant EMPTY_VARIANT; -const std::string EMPTY_STRING; -const std::string NODE_PROPERTIES="node"; -} - -const Variant& find(const Variant::Map& map, const std::string& key) -{ - Variant::Map::const_iterator i = map.find(key); - if (i == map.end()) return EMPTY_VARIANT; - else return i->second; -} - -std::string Address::getType() const -{ - const Variant& props = find(impl->options, NODE_PROPERTIES); - if (props.getType() == VAR_MAP) { - const Variant& type = find(props.asMap(), TYPE); - if (!type.isVoid()) return type.asString(); - } - return EMPTY_STRING; -} - -void Address::setType(const std::string& type) -{ - Variant& props = impl->options[NODE_PROPERTIES]; - if (props.isVoid()) props = Variant::Map(); - props.asMap()[TYPE] = type; -} - -std::ostream& operator<<(std::ostream& out, const Address& address) -{ - out << address.str(); - return out; -} - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/AddressImpl.h b/qpid/cpp/src/qpid/messaging/AddressImpl.h deleted file mode 100644 index 8d34bd73c4..0000000000 --- a/qpid/cpp/src/qpid/messaging/AddressImpl.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_MESSAGING_ADDRESSIMPL_H -#define QPID_MESSAGING_ADDRESSIMPL_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/messaging/Address.h" -#include "qpid/types/Variant.h" -namespace qpid { -namespace messaging { - -class AddressImpl -{ - public: - std::string name; - std::string subject; - qpid::types::Variant::Map options; - bool temporary; - - AddressImpl() : temporary(false) {} - AddressImpl(const std::string& n, const std::string& s, const qpid::types::Variant::Map& o) : - name(n), subject(s), options(o), temporary(false) {} - static void setTemporary(Address& a, bool value) { a.impl->temporary = value; } - static bool isTemporary(const Address& a) { return a.impl->temporary; } -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_ADDRESSIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/AddressParser.cpp b/qpid/cpp/src/qpid/messaging/AddressParser.cpp deleted file mode 100644 index 882deba463..0000000000 --- a/qpid/cpp/src/qpid/messaging/AddressParser.cpp +++ /dev/null @@ -1,271 +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 "AddressParser.h" -#include "AddressImpl.h" -#include "qpid/framing/Uuid.h" -#include - -namespace qpid { -namespace messaging { - -using namespace qpid::types; - -AddressParser::AddressParser(const std::string& s) : input(s), current(0) {} - -bool AddressParser::error(const std::string& message) -{ - throw MalformedAddress((boost::format("%1%, character %2% of %3%") % message % current % input).str()); -} - -bool AddressParser::parse(Address& address) -{ - std::string name; - if (readName(name)) { - if (name.find('#') == 0) { - name = qpid::framing::Uuid(true).str() + name; - AddressImpl::setTemporary(address, true); - } - address.setName(name); - if (readChar('/')) { - std::string subject; - readSubject(subject); - address.setSubject(subject); - } - if (readChar(';')) { - Variant options = Variant::Map(); - if (readMap(options)) { - address.setOptions(options.asMap()); - } - } - //skip trailing whitespace - while (!eos() && iswhitespace()) ++current; - return eos() || error("Unexpected chars in address: " + input.substr(current)); - } else { - return input.empty() || error("Expected name"); - } -} - -bool AddressParser::parseMap(Variant::Map& map) -{ - if (readChar('{')) { - readMapEntries(map); - return readChar('}') || error("Unmatched '{'!"); - } else { - return false; - } -} - -bool AddressParser::parseList(Variant::List& list) -{ - if (readChar('[')) { - readListItems(list); - return readChar(']') || error("Unmatched '['!"); - } else { - return false; - } -} - - -bool AddressParser::readList(Variant& value) -{ - if (readChar('[')) { - value = Variant::List(); - readListItems(value.asList()); - return readChar(']') || error("Unmatched '['!"); - } else { - return false; - } -} - -void AddressParser::readListItems(Variant::List& list) -{ - Variant item; - while (readValueIfExists(item)) { - list.push_back(item); - if (!readChar(',')) break; - } -} - -bool AddressParser::readMap(Variant& value) -{ - if (readChar('{')) { - value = Variant::Map(); - readMapEntries(value.asMap()); - return readChar('}') || error("Unmatched '{'!"); - } else { - return false; - } -} - -void AddressParser::readMapEntries(Variant::Map& map) -{ - while (readKeyValuePair(map) && readChar(',')) {} -} - -bool AddressParser::readKeyValuePair(Variant::Map& map) -{ - std::string key; - Variant value; - if (readKey(key)) { - if (readChar(':') && readValue(value)) { - map[key] = value; - return true; - } else { - return error("Bad key-value pair, expected ':'"); - } - } else { - return false; - } -} - -bool AddressParser::readKey(std::string& key) -{ - return readWord(key) || readQuotedString(key); -} - -bool AddressParser::readValue(Variant& value) -{ - return readValueIfExists(value) || error("Expected value"); -} - -bool AddressParser::readValueIfExists(Variant& value) -{ - return readSimpleValue(value) || readQuotedValue(value) || - readMap(value) || readList(value); -} - -bool AddressParser::readString(std::string& value, char delimiter) -{ - if (readChar(delimiter)) { - std::string::size_type start = current; - while (!eos()) { - if (input.at(current) == delimiter) { - if (current > start) { - value = input.substr(start, current - start); - } else { - value = ""; - } - ++current; - return true; - } else { - ++current; - } - } - return error("Unmatched delimiter"); - } else { - return false; - } -} - -bool AddressParser::readName(std::string& name) -{ - return readQuotedString(name) || readWord(name, "/;"); -} - -bool AddressParser::readSubject(std::string& subject) -{ - return readQuotedString(subject) || readWord(subject, ";"); -} - -bool AddressParser::readQuotedString(std::string& s) -{ - return readString(s, '"') || readString(s, '\''); -} - -bool AddressParser::readQuotedValue(Variant& value) -{ - std::string s; - if (readQuotedString(s)) { - value = s; - value.setEncoding("utf8"); - return true; - } else { - return false; - } -} - -bool AddressParser::readSimpleValue(Variant& value) -{ - std::string s; - if (readWord(s)) { - value.parse(s); - if (value.getType() == VAR_STRING) value.setEncoding("utf8"); - return true; - } else { - return false; - } -} - -bool AddressParser::readWord(std::string& value, const std::string& delims) -{ - //skip leading whitespace - while (!eos() && iswhitespace()) ++current; - - //read any number of non-whitespace, non-reserved chars into value - std::string::size_type start = current; - while (!eos() && !iswhitespace() && !in(delims)) ++current; - - if (current > start) { - value = input.substr(start, current - start); - return true; - } else { - return false; - } -} - -bool AddressParser::readChar(char c) -{ - while (!eos()) { - if (iswhitespace()) { - ++current; - } else if (input.at(current) == c) { - ++current; - return true; - } else { - return false; - } - } - return false; -} - -bool AddressParser::iswhitespace() -{ - return ::isspace(input.at(current)); -} - -bool AddressParser::isreserved() -{ - return in(RESERVED); -} - -bool AddressParser::in(const std::string& chars) -{ - return chars.find(input.at(current)) != std::string::npos; -} - -bool AddressParser::eos() -{ - return current >= input.size(); -} - -const std::string AddressParser::RESERVED = "\'\"{}[],:/"; - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/AddressParser.h b/qpid/cpp/src/qpid/messaging/AddressParser.h deleted file mode 100644 index 5e429e1ca9..0000000000 --- a/qpid/cpp/src/qpid/messaging/AddressParser.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef QPID_MESSAGING_ADDRESSPARSER_H -#define QPID_MESSAGING_ADDRESSPARSER_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/messaging/ImportExport.h" -#include "qpid/messaging/Address.h" - -namespace qpid { -namespace messaging { - -class AddressParser -{ - public: - QPID_MESSAGING_EXTERN AddressParser(const std::string&); - bool parse(Address& address); - QPID_MESSAGING_EXTERN bool parseMap(qpid::types::Variant::Map& map); - QPID_MESSAGING_EXTERN bool parseList(qpid::types::Variant::List& list); - private: - const std::string& input; - std::string::size_type current; - static const std::string RESERVED; - - bool readChar(char c); - bool readQuotedString(std::string& s); - bool readQuotedValue(qpid::types::Variant& value); - bool readString(std::string& value, char delimiter); - bool readWord(std::string& word, const std::string& delims = RESERVED); - bool readSimpleValue(qpid::types::Variant& word); - bool readKey(std::string& key); - bool readValue(qpid::types::Variant& value); - bool readValueIfExists(qpid::types::Variant& value); - bool readKeyValuePair(qpid::types::Variant::Map& map); - bool readMap(qpid::types::Variant& value); - bool readList(qpid::types::Variant& value); - bool readName(std::string& name); - bool readSubject(std::string& subject); - bool error(const std::string& message); - bool eos(); - bool iswhitespace(); - bool in(const std::string& delims); - bool isreserved(); - void readListItems(qpid::types::Variant::List& list); - void readMapEntries(qpid::types::Variant::Map& map); -}; - -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_ADDRESSPARSER_H*/ diff --git a/qpid/cpp/src/qpid/messaging/Connection.cpp b/qpid/cpp/src/qpid/messaging/Connection.cpp deleted file mode 100644 index c40d32cbc1..0000000000 --- a/qpid/cpp/src/qpid/messaging/Connection.cpp +++ /dev/null @@ -1,111 +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/messaging/Connection.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/messaging/ConnectionImpl.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/SessionImpl.h" -#include "qpid/messaging/PrivateImplRef.h" -#include "qpid/messaging/ProtocolRegistry.h" -#include "qpid/client/amqp0_10/ConnectionImpl.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace messaging { - -// Explicitly instantiate Handle superclass -template class Handle; - -using namespace qpid::types; - -typedef PrivateImplRef PI; - -Connection::Connection(ConnectionImpl* impl) { PI::ctor(*this, impl); } -Connection::Connection(const Connection& c) : Handle() { PI::copy(*this, c); } -Connection& Connection::operator=(const Connection& c) { return PI::assign(*this, c); } -Connection::~Connection() { PI::dtor(*this); } - -Connection::Connection(const std::string& url, const std::string& o) -{ - Variant::Map options; - AddressParser parser(o); - if (o.empty() || parser.parseMap(options)) { - PI::ctor(*this, ProtocolRegistry::create(url, options)); - } else { - throw InvalidOptionString("Invalid option string: " + o); - } -} -Connection::Connection(const std::string& url, const Variant::Map& options) -{ - PI::ctor(*this, ProtocolRegistry::create(url, options)); -} - -Connection::Connection() -{ - Variant::Map options; - std::string url = "127.0.0.1:5672"; - PI::ctor(*this, ProtocolRegistry::create(url, options)); -} - -void Connection::open() -{ - while (true) { - try { - impl->open(); - return; - } catch (const ProtocolVersionError& e) { - PI::set(*this, ProtocolRegistry::next(PI::get(impl).get())); - QPID_LOG(info, e.what() << ", trying alternative protocol version..."); - } - } -} -bool Connection::isOpen() { return impl->isOpen(); } -bool Connection::isOpen() const { return impl->isOpen(); } -void Connection::close() { impl->close(); } -Session Connection::createSession(const std::string& name) { return impl->newSession(false, name); } -Session Connection::createTransactionalSession(const std::string& name) -{ - return impl->newSession(true, name); -} -Session Connection::getSession(const std::string& name) const { return impl->getSession(name); } -void Connection::setOption(const std::string& name, const Variant& value) -{ - impl->setOption(name, value); -} -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 deleted file mode 100644 index 05d835b282..0000000000 --- a/qpid/cpp/src/qpid/messaging/ConnectionImpl.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_MESSAGING_CONNECTIONIMPL_H -#define QPID_MESSAGING_CONNECTIONIMPL_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 -#include -#include "qpid/RefCounted.h" - -namespace qpid { - -namespace types { -class Variant; -} - -namespace messaging { - -class ProtocolRegistry; -class Session; - -class ConnectionImpl : public virtual qpid::RefCounted -{ - public: - virtual ~ConnectionImpl() {} - virtual void open() = 0; - virtual bool isOpen() const = 0; - virtual void close() = 0; - virtual Session newSession(bool transactional, const std::string& name) = 0; - 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: - friend class ProtocolRegistry; - boost::function next; -}; - -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_CONNECTIONIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp b/qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp deleted file mode 100644 index d956e9a1b1..0000000000 --- a/qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp +++ /dev/null @@ -1,135 +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/messaging/ConnectionOptions.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/types/Variant.h" -#include "qpid/log/Statement.h" -#include -#include - -namespace qpid { -namespace messaging { - -namespace { -double FOREVER(std::numeric_limits::max()); - -double timeValue(const qpid::types::Variant& value) { - if (types::isIntegerType(value.getType())) - return double(value.asInt64()); - return value.asDouble(); -} - -void merge(const std::string& value, std::vector& list) { - if (std::find(list.begin(), list.end(), value) == list.end()) - list.push_back(value); -} - -void merge(const qpid::types::Variant::List& from, std::vector& to) -{ - for (qpid::types::Variant::List::const_iterator i = from.begin(); i != from.end(); ++i) - merge(i->asString(), to); -} - -} - -ConnectionOptions::ConnectionOptions(const std::map& options) - : replaceUrls(false), reconnect(false), timeout(FOREVER), limit(-1), minReconnectInterval(0.001), maxReconnectInterval(2), - retries(0), reconnectOnLimitExceeded(true), nestAnnotations(false), setToOnSend(false) -{ - // By default we want the sasl service name to be "amqp" for 1.0 - // this will be overridden by a parsed "sasl-service" option - service = "amqp"; - - for (qpid::types::Variant::Map::const_iterator i = options.begin(); i != options.end(); ++i) { - set(i->first, i->second); - } -} - -void ConnectionOptions::set(const std::string& name, const qpid::types::Variant& value) -{ - if (name == "reconnect") { - reconnect = value; - } else if (name == "reconnect-timeout" || name == "reconnect_timeout") { - timeout = timeValue(value); - } else if (name == "reconnect-limit" || name == "reconnect_limit") { - limit = value; - } else if (name == "reconnect-interval" || name == "reconnect_interval") { - maxReconnectInterval = minReconnectInterval = timeValue(value); - } else if (name == "reconnect-interval-min" || name == "reconnect_interval_min") { - minReconnectInterval = timeValue(value); - } else if (name == "reconnect-interval-max" || name == "reconnect_interval_max") { - maxReconnectInterval = timeValue(value); - } else if (name == "reconnect-urls-replace" || name == "reconnect_urls_replace") { - replaceUrls = value.asBool(); - } else if (name == "reconnect-urls" || name == "reconnect_urls") { - if (replaceUrls) urls.clear(); - if (value.getType() == qpid::types::VAR_LIST) { - merge(value.asList(), urls); - } else { - merge(value.asString(), urls); - } - } else if (name == "username") { - username = value.asString(); - } else if (name == "password") { - password = value.asString(); - } else if (name == "sasl-mechanism" || name == "sasl_mechanism" || - name == "sasl-mechanisms" || name == "sasl_mechanisms") { - mechanism = value.asString(); - } else if (name == "sasl-service" || name == "sasl_service") { - service = value.asString(); - } else if (name == "sasl-min-ssf" || name == "sasl_min_ssf") { - minSsf = value; - } else if (name == "sasl-max-ssf" || name == "sasl_max_ssf") { - maxSsf = value; - } else if (name == "heartbeat") { - heartbeat = value; - } else if (name == "tcp-nodelay" || name == "tcp_nodelay") { - tcpNoDelay = value; - } else if (name == "locale") { - locale = value.asString(); - } else if (name == "max-channels" || name == "max_channels") { - maxChannels = value; - } else if (name == "max-frame-size" || name == "max_frame_size") { - maxFrameSize = value; - } else if (name == "bounds") { - bounds = value; - } else if (name == "transport") { - protocol = value.asString(); - } else if (name == "ssl-cert-name" || name == "ssl_cert_name") { - sslCertName = value.asString(); - } else if (name == "ssl-ignore-hostname-verification-failure" || name == "ssl_ignore_hostname_verification_failure") { - sslIgnoreHostnameVerificationFailure = value; - } else if (name == "x-reconnect-on-limit-exceeded" || name == "x_reconnect_on_limit_exceeded") { - reconnectOnLimitExceeded = value; - } else if (name == "container-id" || name == "container_id") { - identifier = value.asString(); - } else if (name == "nest-annotations" || name == "nest_annotations") { - nestAnnotations = value; - } else if (name == "set-to-on-send" || name == "set_to_on_send") { - setToOnSend = value; - } else if (name == "properties" || name == "client-properties" || name == "client_properties") { - properties = value.asMap(); - } else { - throw qpid::messaging::MessagingException(QPID_MSG("Invalid option: " << name << " not recognised")); - } -} - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/ConnectionOptions.h b/qpid/cpp/src/qpid/messaging/ConnectionOptions.h deleted file mode 100644 index c8c8798b7b..0000000000 --- a/qpid/cpp/src/qpid/messaging/ConnectionOptions.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QPID_MESSAGING_CONNECTIONOPTIONS_H -#define QPID_MESSAGING_CONNECTIONOPTIONS_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/messaging/ImportExport.h" - -#include "qpid/client/ConnectionSettings.h" -#include -#include - -namespace qpid { -namespace types { -class Variant; -} -namespace messaging { - -struct ConnectionOptions : qpid::client::ConnectionSettings -{ - std::vector urls; - bool replaceUrls; - bool reconnect; - double timeout; - int32_t limit; - double minReconnectInterval; - double maxReconnectInterval; - int32_t retries; - bool reconnectOnLimitExceeded; - std::string identifier; - bool nestAnnotations; - bool setToOnSend; - std::map properties; - - QPID_MESSAGING_EXTERN ConnectionOptions(const std::map&); - QPID_MESSAGING_EXTERN void set(const std::string& name, const qpid::types::Variant& value); -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_CONNECTIONOPTIONS_H*/ diff --git a/qpid/cpp/src/qpid/messaging/Duration.cpp b/qpid/cpp/src/qpid/messaging/Duration.cpp deleted file mode 100644 index a23e9f5bcb..0000000000 --- a/qpid/cpp/src/qpid/messaging/Duration.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Duration.h" -#include - -namespace qpid { -namespace messaging { - -Duration::Duration(uint64_t ms) : milliseconds(ms) {} -uint64_t Duration::getMilliseconds() const { return milliseconds; } - -Duration operator*(const Duration& duration, uint64_t multiplier) -{ - return Duration(duration.getMilliseconds() * multiplier); -} - -Duration operator*(uint64_t multiplier, const Duration& duration) -{ - return Duration(duration.getMilliseconds() * multiplier); -} - -bool operator==(const Duration& a, const Duration& b) -{ - return a.getMilliseconds() == b.getMilliseconds(); -} - -bool operator!=(const Duration& a, const Duration& b) -{ - return a.getMilliseconds() != b.getMilliseconds(); -} - -const Duration Duration::FOREVER(std::numeric_limits::max()); -const Duration Duration::IMMEDIATE(0); -const Duration Duration::SECOND(1000); -const Duration Duration::MINUTE(SECOND * 60); - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/FailoverUpdates.cpp b/qpid/cpp/src/qpid/messaging/FailoverUpdates.cpp deleted file mode 100644 index 4f2fcf2e82..0000000000 --- a/qpid/cpp/src/qpid/messaging/FailoverUpdates.cpp +++ /dev/null @@ -1,85 +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/messaging/FailoverUpdates.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Session.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" -#include "qpid/Url.h" -#include "qpid/framing/Uuid.h" -#include - -namespace qpid { -namespace messaging { -using framing::Uuid; - -struct FailoverUpdatesImpl : qpid::sys::Runnable -{ - Connection connection; - Session session; - Receiver receiver; - qpid::sys::Thread thread; - - FailoverUpdatesImpl(Connection& c) : connection(c) - { - session = connection.createSession("failover-updates."+Uuid(true).str()); - receiver = session.createReceiver("amq.failover"); - thread = qpid::sys::Thread(*this); - } - - ~FailoverUpdatesImpl() { - try { - session.close(); - } catch(...) {} // Squash exceptions in a destructor. - thread.join(); - } - - void run() - { - try { - Message message; - while (receiver.fetch(message)) { - connection.setOption("reconnect-urls", message.getProperties()["amq.failover"]); - QPID_LOG(debug, "Set reconnect-urls to " << message.getProperties()["amq.failover"]); - session.acknowledge(); - } - } - catch (const ClosedException&) {} - catch (const qpid::TransportFailure& e) { - QPID_LOG(warning, "Failover updates stopped on loss of connection. " << e.what()); - } - catch (const std::exception& e) { - QPID_LOG(warning, "Failover updates stopped due to exception: " << e.what()); - } - } -}; - -FailoverUpdates::FailoverUpdates(Connection& connection) : impl(new FailoverUpdatesImpl(connection)) {} -FailoverUpdates::~FailoverUpdates() { if (impl) { delete impl; } } -FailoverUpdates::FailoverUpdates(const FailoverUpdates&) : impl(0) {} -FailoverUpdates& FailoverUpdates::operator=(const FailoverUpdates&) { return *this; } - - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/Logger.cpp b/qpid/cpp/src/qpid/messaging/Logger.cpp deleted file mode 100644 index c259cb4c1b..0000000000 --- a/qpid/cpp/src/qpid/messaging/Logger.cpp +++ /dev/null @@ -1,200 +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/messaging/Logger.h" - -#include "qpid/log/Logger.h" -#include "qpid/log/OstreamOutput.h" -#include "qpid/messaging/exceptions.h" - -#include -#include -#include - -using std::string; -using std::vector; - -namespace qpid { -namespace messaging { - -// Proxy class to call the users output class/routine -class ProxyOutput : public qpid::log::Logger::Output { - LoggerOutput& output; - - void log(const qpid::log::Statement& s, const string& message) { - output.log(qpid::messaging::Level(s.level), s.category==qpid::log::external_application, s.file, s.line, s.function, message); - } - -public: - ProxyOutput(LoggerOutput& o) : - output(o) - {} -}; - -LoggerOutput::~LoggerOutput() -{ -} - -inline qpid::log::Logger& logger() { - static qpid::log::Logger& theLogger=qpid::log::Logger::instance(); - return theLogger; -} - -namespace { - std::string loggerUsage; - qpid::log::Selector loggerSelector; -} - -std::string Logger::usage() -{ - return loggerUsage; -} - -void Logger::configure(int argc, const char* argv[], const string& pre) -try -{ - bool logToStdout = false; - bool logToStderr = false; - string logFile; - std::vector selectors; - std::vector deselectors; - bool time = false; - bool level = false; - bool thread = false; - bool source = false; - bool function = false; - bool hiresTs = false; - - selectors.push_back("notice+"); // Set this for the usage message default - - string prefix = pre.empty() ? pre : pre+"-"; - qpid::Options myOptions; - myOptions.addOptions() - ((prefix+"log-enable").c_str(), optValue(selectors, "RULE"), - ("Enables logging for selected levels and components. " - "RULE is in the form 'LEVEL[+-][:PATTERN]'\n" - "LEVEL is one of: \n\t "+qpid::log::getLevels()+"\n" - "PATTERN is a logging category name, or a namespace-qualified " - "function name or name fragment. " - "Logging category names are: \n\t "+qpid::log::getCategories()+"\n" - "The category \"Application\" contains all messages logged by the application.\n" - "For example:\n" - "\t'--log-enable warning+'\n" - "logs all warning, error and critical messages.\n" - "\t'--log-enable trace+:Application --log-enable notice+'\n" - "logs all application messages, but only notice or higher for the qpid library messages\n" - "\t'--log-enable debug:framing'\n" - "logs debug messages from all functions with 'framing' in the namespace or function name.\n" - "This option can be used multiple times").c_str()) - ((prefix+"log-disable").c_str(), optValue(deselectors, "RULE"), - ("Disables logging for selected levels and components. " - "RULE is in the form 'LEVEL[+-][:PATTERN]'\n" - "LEVEL is one of: \n\t "+qpid::log::getLevels()+"\n" - "PATTERN is a logging category name, or a namespace-qualified " - "function name or name fragment. " - "Logging category names are: \n\t "+qpid::log::getCategories()+"\n" - "For example:\n" - "\t'--log-disable warning-'\n" - "disables logging all warning, notice, info, debug, and trace messages.\n" - "\t'--log-disable trace:Application'\n" - "disables all application trace messages.\n" - "\t'--log-disable debug-:qmf::'\n" - "disables logging debug and trace messages from all functions with 'qmf::' in the namespace.\n" - "This option can be used multiple times").c_str()) - ((prefix+"log-time").c_str(), optValue(time, "yes|no"), "Include time in log messages") - ((prefix+"log-level").c_str(), optValue(level,"yes|no"), "Include severity level in log messages") - ((prefix+"log-source").c_str(), optValue(source,"yes|no"), "Include source file:line in log messages") - ((prefix+"log-thread").c_str(), optValue(thread,"yes|no"), "Include thread ID in log messages") - ((prefix+"log-function").c_str(), optValue(function,"yes|no"), "Include function signature in log messages") - ((prefix+"log-hires-timestamp").c_str(), optValue(hiresTs,"yes|no"), "Use hi-resolution timestamps in log messages") - ((prefix+"log-to-stderr").c_str(), optValue(logToStderr, "yes|no"), "Send logging output to stderr") - ((prefix+"log-to-stdout").c_str(), optValue(logToStdout, "yes|no"), "Send logging output to stdout") - ((prefix+"log-to-file").c_str(), optValue(logFile, "FILE"), "Send log output to FILE.") - ; - - std::ostringstream loggerSStream; - myOptions.print(loggerSStream); - - loggerUsage=loggerSStream.str(); - - selectors.clear(); // Clear to give passed in options precedence - - // Parse the command line not failing for unrecognised options - myOptions.parse(argc, argv, std::string(), true); - - // If no passed in enable or disable log specification then go back to default - if (selectors.empty() && deselectors.empty()) - selectors.push_back("notice+"); - // Set the logger options according to what we just parsed - qpid::log::Options logOptions; - logOptions.selectors = selectors; - logOptions.deselectors = deselectors; - logOptions.time = time; - logOptions.level = level; - logOptions.category = false; - logOptions.thread = thread; - logOptions.source = source; - logOptions.function = function; - logOptions.hiresTs = hiresTs; - - loggerSelector = qpid::log::Selector(logOptions); - logger().clear(); // Need to clear before configuring as it will have been initialised statically already - logger().format(logOptions); - logger().select(loggerSelector); - - // Have to set up the standard output sinks manually - if (logToStderr) - logger().output(std::auto_ptr - (new qpid::log::OstreamOutput(std::clog))); - if (logToStdout) - logger().output(std::auto_ptr - (new qpid::log::OstreamOutput(std::cout))); - - if (logFile.length() > 0) - logger().output(std::auto_ptr - (new qpid::log::OstreamOutput(logFile))); -} -catch (std::exception& e) -{ - throw MessagingException(e.what()); -} - -void Logger::setOutput(LoggerOutput& o) -{ - logger().output(std::auto_ptr(new ProxyOutput(o))); -} - -void Logger::log(Level level, const char* file, int line, const char* function, const string& message) -{ - if (loggerSelector.isEnabled(qpid::log::Level(level), function, qpid::log::unspecified)) { - qpid::log::Statement s = { - true, - file, - line, - function, - qpid::log::Level(level), - qpid::log::external_application, - }; - logger().log(s, message); - } -} - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/Message.cpp b/qpid/cpp/src/qpid/messaging/Message.cpp deleted file mode 100644 index 376e1cc5f6..0000000000 --- a/qpid/cpp/src/qpid/messaging/Message.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/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/amqp_0_10/Codecs.h" -#include -#include - -namespace qpid { -namespace messaging { - -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; } - -Message& Message::operator=(const Message& m) { *impl = *m.impl; return *this; } - -void Message::setReplyTo(const Address& d) { impl->setReplyTo(d); } -const Address& Message::getReplyTo() const { return impl->getReplyTo(); } - -void Message::setSubject(const std::string& s) { impl->setSubject(s); } -const std::string& Message::getSubject() const { return impl->getSubject(); } - -void Message::setContentType(const std::string& s) { impl->setContentType(s); } -const std::string& Message::getContentType() const { return impl->getContentType(); } - -void Message::setMessageId(const std::string& id) { impl->setMessageId(id); } -const std::string& Message::getMessageId() const { return impl->getMessageId(); } - -void Message::setUserId(const std::string& id) { impl->setUserId(id); } -const std::string& Message::getUserId() const { return impl->getUserId(); } - -void Message::setCorrelationId(const std::string& id) { impl->setCorrelationId(id); } -const std::string& Message::getCorrelationId() const { return impl->getCorrelationId(); } - -uint8_t Message::getPriority() const { return impl->getPriority(); } -void Message::setPriority(uint8_t priority) { impl->setPriority(priority); } - -void Message::setTtl(Duration ttl) { impl->setTtl(ttl.getMilliseconds()); } -Duration Message::getTtl() const { return Duration(impl->getTtl()); } - -void Message::setDurable(bool durable) { impl->setDurable(durable); } -bool Message::getDurable() const { return impl->isDurable(); } - -bool Message::getRedelivered() const { return impl->isRedelivered(); } -void Message::setRedelivered(bool redelivered) { impl->setRedelivered(redelivered); } - -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) { this->setContentBytes(c); } -void Message::setContent(const char* chars, size_t count) { - impl->getContent().reset(); - impl->setBytes(chars, count); -} -std::string Message::getContent() const { return impl->getBytes(); } - -void Message::setContentBytes(const std::string& c) { - impl->getContent().reset(); - 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(); -} - -size_t Message::getContentSize() const -{ - return impl->getBytes().size(); -} - -EncodingException::EncodingException(const std::string& msg) : qpid::types::Exception(msg) {} - -const std::string BAD_ENCODING("Unsupported encoding: %1% (only %2% is supported at present)."); - -template struct MessageCodec -{ - static bool checkEncoding(const std::string& requested) - { - if (requested.size()) { - if (requested == C::contentType) return true; - else throw EncodingException((boost::format(BAD_ENCODING) % requested % C::contentType).str()); - } else { - return false; - } - } - - /* - * Currently only support a single encoding type for both list and - * map, based on AMQP 0-10, though wider support is anticipated in the - * future. This method simply checks that the desired encoding (if one - * is specified, either through the message-content or through an - * override) is indeed supported. - */ - static void checkEncoding(const Message& message, const std::string& requested) - { - checkEncoding(requested) || checkEncoding(message.getContentType()); - } - - static void decode(const Message& message, typename C::ObjectType& object, const std::string& encoding) - { - checkEncoding(message, encoding); - try { - C::decode(message.getContent(), object); - } catch (const qpid::Exception &ex) { - throw EncodingException(ex.what()); - } - } - - static void encode(const typename C::ObjectType& map, Message& message, const std::string& encoding) - { - checkEncoding(message, encoding); - std::string content; - C::encode(map, content); - message.setContentType(C::contentType); - message.setContent(content); - } -}; - -void decode(const Message& message, Variant::Map& map, const std::string& encoding) -{ - MessageCodec::decode(message, map, encoding); -} -void decode(const Message& message, Variant::List& list, const std::string& encoding) -{ - MessageCodec::decode(message, list, encoding); -} -void encode(const Variant::Map& map, Message& message, const std::string& encoding) -{ - MessageCodec::encode(map, message, encoding); -} -void encode(const Variant::List& list, Message& message, const std::string& encoding) -{ - MessageCodec::encode(list, message, encoding); -} - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/MessageImpl.cpp b/qpid/cpp/src/qpid/messaging/MessageImpl.cpp deleted file mode 100644 index 620e48ec2e..0000000000 --- a/qpid/cpp/src/qpid/messaging/MessageImpl.cpp +++ /dev/null @@ -1,253 +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 "MessageImpl.h" -#include "qpid/messaging/Message.h" - -namespace qpid { -namespace messaging { - -namespace { -const std::string EMPTY_STRING = ""; -} - -using namespace qpid::types; - -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) : - 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(); - internalId = 0; -} - -void MessageImpl::setReplyTo(const Address& d) -{ - replyTo = d; - updated(); -} -const Address& MessageImpl::getReplyTo() const -{ - if (!replyTo && encoded) encoded->getReplyTo(replyTo); - return replyTo; -} - -void MessageImpl::setSubject(const std::string& s) -{ - subject = s; - updated(); -} -const std::string& MessageImpl::getSubject() const -{ - if (!subject.size() && encoded) encoded->getSubject(subject); - return subject; -} - -void MessageImpl::setContentType(const std::string& s) -{ - contentType = s; - updated(); -} -const std::string& MessageImpl::getContentType() const -{ - if (!contentType.size() && encoded) encoded->getContentType(contentType); - return contentType; -} - -void MessageImpl::setMessageId(const std::string& s) -{ - messageId = s; - updated(); -} -const std::string& MessageImpl::getMessageId() const -{ - if (!messageId.size() && encoded) encoded->getMessageId(messageId); - return messageId; -} -void MessageImpl::setUserId(const std::string& s) -{ - userId = s; - updated(); -} -const std::string& MessageImpl::getUserId() const -{ - if (!userId.size() && encoded) encoded->getUserId(userId); - return userId; -} -void MessageImpl::setCorrelationId(const std::string& s) -{ - correlationId = s; - updated(); -} -const std::string& MessageImpl::getCorrelationId() const -{ - if (!correlationId.size() && encoded) encoded->getCorrelationId(correlationId); - return correlationId; -} -void MessageImpl::setPriority(uint8_t p) -{ - priority = p; -} -uint8_t MessageImpl::getPriority() const -{ - return priority; -} -void MessageImpl::setTtl(uint64_t t) -{ - ttl = t; -} -uint64_t MessageImpl::getTtl() const -{ - return ttl; -} -void MessageImpl::setDurable(bool d) -{ - durable = d; -} -bool MessageImpl::isDurable() const -{ - return durable; -} -void MessageImpl::setRedelivered(bool b) -{ - redelivered = b; -} -bool MessageImpl::isRedelivered() const -{ - return redelivered; -} - -const Variant::Map& MessageImpl::getHeaders() const -{ - if (!headers.size() && encoded) encoded->populate(headers); - return headers; -} -Variant::Map& MessageImpl::getHeaders() { - if (!headers.size() && encoded) encoded->populate(headers); - updated(); - return headers; -} -void MessageImpl::setHeader(const std::string& key, const qpid::types::Variant& val) -{ - headers[key] = val; updated(); -} - -//should these methods be on MessageContent? -void MessageImpl::setBytes(const std::string& c) -{ - bytes = c; - updated(); -} -void MessageImpl::setBytes(const char* chars, size_t count) -{ - bytes.assign(chars, count); - updated(); -} -const std::string& MessageImpl::getBytes() const -{ - if (encoded && !contentDecoded) { - encoded->getBody(bytes, content); - contentDecoded = true; - } - if (bytes.empty() && content.getType() == VAR_STRING) return content.getString(); - else return bytes; -} -std::string& MessageImpl::getBytes() -{ - updated();//have to assume body may be edited, invalidating our message - if (bytes.empty() && content.getType() == VAR_STRING) 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; } -qpid::framing::SequenceNumber MessageImpl::getInternalId() { return internalId; } - -void MessageImpl::updated() -{ - - if (!replyTo && encoded) encoded->getReplyTo(replyTo); - if (!subject.size() && encoded) encoded->getSubject(subject); - if (!contentType.size() && encoded) encoded->getContentType(contentType); - if (!messageId.size() && encoded) encoded->getMessageId(messageId); - if (!userId.size() && encoded) encoded->getUserId(userId); - if (!correlationId.size() && encoded) encoded->getCorrelationId(correlationId); - if (!headers.size() && encoded) encoded->populate(headers); - if (encoded && !contentDecoded) { - encoded->getBody(bytes, content); - contentDecoded = true; - } - - encoded.reset(); -} - -MessageImpl& MessageImplAccess::get(Message& msg) -{ - return *msg.impl; -} -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 deleted file mode 100644 index 647972de16..0000000000 --- a/qpid/cpp/src/qpid/messaging/MessageImpl.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef QPID_MESSAGING_MESSAGEIMPL_H -#define QPID_MESSAGING_MESSAGEIMPL_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/messaging/ImportExport.h" - -#include "qpid/messaging/Address.h" -#include "qpid/types/Variant.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/messaging/amqp/EncodedMessage.h" -#include -#include - -namespace qpid { -namespace messaging { - -class MessageImpl -{ - private: - mutable Address replyTo; - mutable std::string subject; - mutable std::string contentType; - mutable std::string messageId; - mutable std::string userId; - mutable std::string correlationId; - uint8_t priority; - uint64_t ttl; - bool durable; - bool redelivered; - mutable qpid::types::Variant::Map headers; - - mutable std::string bytes; - mutable qpid::types::Variant content; - mutable bool contentDecoded; - boost::shared_ptr encoded; - - qpid::framing::SequenceNumber internalId; - - void updated(); - public: - MessageImpl(const std::string& c); - MessageImpl(const char* chars, size_t count); - - void clear(); - void setReplyTo(const Address& d); - QPID_MESSAGING_EXTERN const Address& getReplyTo() const; - - void setSubject(const std::string& s); - QPID_MESSAGING_EXTERN const std::string& getSubject() const; - - void setContentType(const std::string& s); - QPID_MESSAGING_EXTERN const std::string& getContentType() const; - - void setMessageId(const std::string&); - QPID_MESSAGING_EXTERN const std::string& getMessageId() const; - void setUserId(const std::string& ); - QPID_MESSAGING_EXTERN const std::string& getUserId() const; - void setCorrelationId(const std::string& ); - QPID_MESSAGING_EXTERN const std::string& getCorrelationId() const; - void setPriority(uint8_t); - QPID_MESSAGING_EXTERN uint8_t getPriority() const; - void setTtl(uint64_t); - QPID_MESSAGING_EXTERN uint64_t getTtl() const; - void setDurable(bool); - QPID_MESSAGING_EXTERN bool isDurable() const; - void setRedelivered(bool); - QPID_MESSAGING_EXTERN bool isRedelivered() 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); - QPID_MESSAGING_EXTERN const std::string& getBytes() const; - std::string& getBytes(); - qpid::types::Variant& getContent(); - QPID_MESSAGING_EXTERN const qpid::types::Variant& getContent() const; - - QPID_MESSAGING_EXTERN void setInternalId(qpid::framing::SequenceNumber id); - QPID_MESSAGING_EXTERN qpid::framing::SequenceNumber getInternalId(); - void setEncoded(boost::shared_ptr e) { encoded = e; } - boost::shared_ptr getEncoded() const { return encoded; } -}; - -class Message; - -/** - * Provides access to the internal MessageImpl for a message which is - * useful when accessing any message state not exposed directly - * through the public API. - */ -struct MessageImplAccess -{ - QPID_MESSAGING_EXTERN static MessageImpl& get(Message&); - QPID_MESSAGING_EXTERN static const MessageImpl& get(const Message&); -}; - -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_MESSAGEIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/Message_io.cpp b/qpid/cpp/src/qpid/messaging/Message_io.cpp deleted file mode 100644 index b6bc43a4e6..0000000000 --- a/qpid/cpp/src/qpid/messaging/Message_io.cpp +++ /dev/null @@ -1,45 +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/messaging/Message_io.h" -#include - -namespace qpid { -namespace messaging { - -using namespace std; -ostream& operator<<(ostream& o, const Message& message) { - o << "Message(properties=" << message.getProperties(); - if (!message.getSubject().empty()) { - o << ", subject='" << message.getSubject() << "'"; - } - if (!message.getContentObject().isVoid()) { - o << ", content='"; - if (message.getContentType() == "amqp/map") { - o << message.getContentObject().asMap(); - } else { - o << message.getContentObject(); - } - } - o << "')"; - return o; -} - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/PrivateImplRef.h b/qpid/cpp/src/qpid/messaging/PrivateImplRef.h deleted file mode 100644 index a60f4eeadf..0000000000 --- a/qpid/cpp/src/qpid/messaging/PrivateImplRef.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef QPID_MESSAGING_PRIVATEIMPL_H -#define QPID_MESSAGING_PRIVATEIMPL_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/messaging/ImportExport.h" -#include -#include "qpid/RefCounted.h" - -namespace qpid { -namespace messaging { - -/** - * Helper class to implement a class with a private, reference counted - * implementation and reference semantics. - * - * Such classes are used in the public API to hide implementation, they - * should. Example of use: - * - * === Foo.h - * - * template PrivateImplRef; - * class FooImpl; - * - * Foo : public Handle { - * public: - * Foo(FooImpl* = 0); - * Foo(const Foo&); - * ~Foo(); - * Foo& operator=(const Foo&); - * - * int fooDo(); // and other Foo functions... - * - * private: - * typedef FooImpl Impl; - * Impl* impl; - * friend class PrivateImplRef; - * - * === Foo.cpp - * - * typedef PrivateImplRef PI; - * Foo::Foo(FooImpl* p) { PI::ctor(*this, p); } - * Foo::Foo(const Foo& c) : Handle() { PI::copy(*this, c); } - * Foo::~Foo() { PI::dtor(*this); } - * Foo& Foo::operator=(const Foo& c) { return PI::assign(*this, c); } - * - * int foo::fooDo() { return impl->fooDo(); } - * - */ -template class PrivateImplRef { - public: - typedef typename T::Impl Impl; - typedef boost::intrusive_ptr intrusive_ptr; - - /** Get the implementation pointer from a handle */ - static intrusive_ptr get(const T& t) { return intrusive_ptr(t.impl); } - - /** Set the implementation pointer in a handle */ - static void set(T& t, const intrusive_ptr& p) { - if (t.impl == p) return; - if (t.impl) intrusive_ptr_release(t.impl); - t.impl = p.get(); - if (t.impl) intrusive_ptr_add_ref(t.impl); - } - - // Helper functions to implement the ctor, dtor, copy, assign - static void ctor(T& t, Impl* p) { t.impl = p; if (p) intrusive_ptr_add_ref(p); } - static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); } - static void dtor(T& t) { if(t.impl) intrusive_ptr_release(t.impl); } - static T& assign(T& t, const T& x) { set(t, get(x)); return t;} -}; - -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_PRIVATEIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/ProtocolRegistry.cpp b/qpid/cpp/src/qpid/messaging/ProtocolRegistry.cpp deleted file mode 100644 index ba55149048..0000000000 --- a/qpid/cpp/src/qpid/messaging/ProtocolRegistry.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "ProtocolRegistry.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/amqp0_10/ConnectionImpl.h" -#include "qpid/client/LoadPlugins.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Mutex.h" -#include "qpid/Options.h" -#include "qpid/StringUtils.h" -#include "config.h" -#include -#include -#include - -using qpid::types::Variant; - -namespace qpid { -namespace messaging { -namespace { -struct ProtocolOptions : qpid::Options -{ - std::string protocolDefaults; - - ProtocolOptions() : qpid::Options("Protocol Settings") - { - addOptions() - ("protocol-defaults", optValue(protocolDefaults, "PROTOCOLS"), "Protocols to use when none are specified"); - } -}; -const std::string SEPARATOR(", "); -const std::string EMPTY; -std::string join(const std::vector& in, const std::string& base=EMPTY, const std::string& separator = SEPARATOR) -{ - std::stringstream out; - if (!base.empty()) out << base; - for (std::vector::const_iterator i = in.begin(); i != in.end(); ++i) { - if (i != in.begin()) out << separator; - out << *i; - } - return out.str(); -} - -typedef std::map Factories; -typedef std::vector Shutdowns; - -ConnectionImpl* create_0_10(const std::string& url, const qpid::types::Variant::Map& options) -{ - return new qpid::client::amqp0_10::ConnectionImpl(url, options); -} - -class Registry -{ - public: - Registry() - { - factories["amqp0-10"] = &create_0_10; - shutdowns.push_back(&qpid::client::shutdown); - CommonOptions common("", "", QPIDC_CONF_FILE); - ProtocolOptions options; - try { - common.parse(0, 0, common.clientConfig, true); - options.parse (0, 0, common.clientConfig, true); - } catch (const std::exception& e) { - throw qpid::types::Exception(QPID_MSG("Failed to parse options while initialising Protocol Registry: " << e.what())); - } - QPID_LOG(debug, "Protocol defaults: " << options.protocolDefaults); - if (!options.protocolDefaults.empty()) { - split(versions, options.protocolDefaults, ", "); - } - } - ProtocolRegistry::Factory* find(const std::string& name) const - { - Factories::const_iterator i = factories.find(name); - if (i == factories.end()) { - std::stringstream error; - error << "Unsupported protocol: " << name; - error << " (valid values are " << getNames() << ")"; - throw MessagingException(error.str()); - } else { - return i->second; - } - } - void add(const std::string& name, ProtocolRegistry::Factory* factory, ProtocolRegistry::Shutdown* shutdown) - { - factories[name] = factory; - shutdowns.push_back(shutdown); - } - std::string getNames() const - { - std::stringstream names; - for (Factories::const_iterator i = factories.begin(); i != factories.end(); ++i) { - if (i != factories.begin()) names << ", "; - names << i->first; - } - return names.str(); - } - void collectNames(std::vector& names) const - { - for (std::vector< std::string >::const_iterator i = versions.begin(); i != versions.end(); ++i) { - Factories::const_iterator j = factories.find(*i); - if (j == factories.end()) { - QPID_LOG(notice, "Unsupported protocol specified in defaults " << *i); - } else { - names.push_back(*i); - } - } - if (names.empty()) { - if (!versions.empty()) { - QPID_LOG(warning, "Protocol defaults specified are not valid (" << join(versions) << ") falling back to " << getNames()); - } - for (Factories::const_iterator i = factories.begin(); i != factories.end(); ++i) { - names.push_back(i->first); - } - } - } - void shutdown() { - sys::Mutex::ScopedLock l(shutdownLock); - while (!shutdowns.empty()) { - shutdowns.back()(); - shutdowns.pop_back(); - } - } - private: - Factories factories; - Shutdowns shutdowns; - sys::Mutex shutdownLock; - std::vector versions; -}; - -Registry& theRegistry() -{ - static Registry factories; - return factories; -} - -bool extract(const std::string& key, Variant& value, const Variant::Map& in, Variant::Map& out) -{ - bool matched = false; - for (Variant::Map::const_iterator i = in.begin(); i != in.end(); ++i) { - if (i->first == key) { - value = i->second; - matched = true; - } else { - out.insert(*i); - } - } - return matched; -} -} - -ConnectionImpl* ProtocolRegistry::create(const std::string& url, const Variant::Map& options) -{ - qpid::client::theModuleLoader();//ensure modules are loaded - Variant name; - Variant::Map stripped; - std::vector versions; - if (extract("protocol", name, options, stripped)) { - split(versions, name.asString(), ", "); - } else { - theRegistry().collectNames(versions); - } - bool debugOn; - QPID_LOG_TEST(debug, debugOn); - if (debugOn) { - QPID_LOG(debug, "Trying versions " << join(versions)); - } - return createInternal(versions, url, stripped, join(versions, "No suitable protocol version supported by peer, tried ")); -} - -ConnectionImpl* ProtocolRegistry::createInternal(const std::vector& requested, const std::string& url, const Variant::Map& options, const std::string& error) -{ - std::vector::const_iterator i = requested.begin(); - if (i == requested.end()) - throw MessagingException(error); - std::string name = *i; - ConnectionImpl* result = theRegistry().find(name)(url, options); - result->next = boost::bind(&ProtocolRegistry::createInternal, std::vector(++i, requested.end()), url, options, error); - return result; - } - -ConnectionImpl* ProtocolRegistry::next(ConnectionImpl* last) -{ - if (last->next) { - return last->next(); - } - throw MessagingException("No suitable protocol version supported by peer"); -} - -void ProtocolRegistry::add(const std::string& name, Factory* factory, Shutdown* shutdown) -{ - theRegistry().add(name, factory, shutdown); -} - -void ProtocolRegistry::shutdown() { - theRegistry().shutdown(); -} - - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/ProtocolRegistry.h b/qpid/cpp/src/qpid/messaging/ProtocolRegistry.h deleted file mode 100644 index e5d8e918f7..0000000000 --- a/qpid/cpp/src/qpid/messaging/ProtocolRegistry.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_MESSAGING_PROTOCOLREGISTRY_H -#define QPID_MESSAGING_PROTOCOLREGISTRY_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/messaging/ImportExport.h" -#include "qpid/types/Variant.h" -#include - -namespace qpid { -namespace messaging { -class ConnectionImpl; -/** - * Registry for different implementations of the messaging API e.g AMQP 1.0 - */ -class ProtocolRegistry -{ - public: - typedef ConnectionImpl* Factory(const std::string& url, const qpid::types::Variant::Map& options); - typedef void Shutdown(); - - static ConnectionImpl* create(const std::string& url, const qpid::types::Variant::Map& options); - static ConnectionImpl* next(ConnectionImpl*); - QPID_MESSAGING_EXTERN static void add(const std::string& name, Factory*, Shutdown*); - QPID_MESSAGING_EXTERN static void shutdown(); - private: - static ConnectionImpl* createInternal(const std::vector& versions, const std::string& url, const qpid::types::Variant::Map& options, const std::string& error); -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_PROTOCOLREGISTRY_H*/ diff --git a/qpid/cpp/src/qpid/messaging/Receiver.cpp b/qpid/cpp/src/qpid/messaging/Receiver.cpp deleted file mode 100644 index a2c6b4cade..0000000000 --- a/qpid/cpp/src/qpid/messaging/Receiver.cpp +++ /dev/null @@ -1,62 +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/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" - -namespace qpid { -namespace messaging { - -// Explicitly instantiate Handle superclass -template class Handle; - -typedef PrivateImplRef PI; - -Receiver::Receiver(ReceiverImpl* impl) { PI::ctor(*this, impl); } -Receiver::Receiver(const Receiver& s) : Handle() { PI::copy(*this, s); } -Receiver::~Receiver() { PI::dtor(*this); } -Receiver& Receiver::operator=(const Receiver& s) { return PI::assign(*this, s); } -bool Receiver::get(Message& message, Duration timeout) -{ - MessageImplAccess::get(message).clear(); - return impl->get(message, timeout); -} -Message Receiver::get(Duration timeout) { return impl->get(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(); } -uint32_t Receiver::getAvailable() { return impl->getAvailable(); } -uint32_t Receiver::getUnsettled() { return impl->getUnsettled(); } -void Receiver::close() { impl->close(); } -const std::string& Receiver::getName() const { return impl->getName(); } -Session Receiver::getSession() const { return impl->getSession(); } -bool Receiver::isClosed() const { return impl->isClosed(); } -Address Receiver::getAddress() const { return impl->getAddress(); } -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/ReceiverImpl.h b/qpid/cpp/src/qpid/messaging/ReceiverImpl.h deleted file mode 100644 index 59ccc3214e..0000000000 --- a/qpid/cpp/src/qpid/messaging/ReceiverImpl.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef QPID_MESSAGING_RECEIVERIMPL_H -#define QPID_MESSAGING_RECEIVERIMPL_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/RefCounted.h" -#include "qpid/sys/IntegerTypes.h" - -namespace qpid { -namespace messaging { - -class Address; -class Duration; -class Message; -class MessageListener; -class Session; - -class ReceiverImpl : public virtual qpid::RefCounted -{ - public: - virtual ~ReceiverImpl() {} - virtual bool get(Message& message, Duration timeout) = 0; - virtual Message get(Duration timeout) = 0; - virtual bool fetch(Message& message, Duration timeout) = 0; - virtual Message fetch(Duration timeout) = 0; - virtual void setCapacity(uint32_t) = 0; - virtual uint32_t getCapacity() = 0; - virtual uint32_t getAvailable() = 0; - virtual uint32_t getUnsettled() = 0; - virtual void close() = 0; - virtual const std::string& getName() const = 0; - virtual Session getSession() const = 0; - virtual bool isClosed() const = 0; - virtual Address getAddress() const = 0; -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_RECEIVERIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/Sender.cpp b/qpid/cpp/src/qpid/messaging/Sender.cpp deleted file mode 100644 index a26f2544c8..0000000000 --- a/qpid/cpp/src/qpid/messaging/Sender.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/SenderImpl.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/PrivateImplRef.h" - -namespace qpid { -namespace messaging { - -// Explicitly instantiate Handle superclass -template class Handle; - -typedef PrivateImplRef PI; - -Sender::Sender(SenderImpl* impl) { PI::ctor(*this, impl); } -Sender::Sender(const Sender& s) : qpid::messaging::Handle() { PI::copy(*this, s); } -Sender::~Sender() { PI::dtor(*this); } -Sender& Sender::operator=(const Sender& s) { return PI::assign(*this, s); } -void Sender::send(const Message& message, bool sync) { impl->send(message, sync); } -void Sender::close() { impl->close(); } -void Sender::setCapacity(uint32_t c) { impl->setCapacity(c); } -uint32_t Sender::getCapacity() { return impl->getCapacity(); } -uint32_t Sender::getUnsettled() { return impl->getUnsettled(); } -uint32_t Sender::getAvailable() { return getCapacity() - getUnsettled(); } -const std::string& Sender::getName() const { return impl->getName(); } -Session Sender::getSession() const { return impl->getSession(); } -Address Sender::getAddress() const { return impl->getAddress(); } -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/SenderImpl.h b/qpid/cpp/src/qpid/messaging/SenderImpl.h deleted file mode 100644 index 91fd9b1536..0000000000 --- a/qpid/cpp/src/qpid/messaging/SenderImpl.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_MESSAGING_SENDERIMPL_H -#define QPID_MESSAGING_SENDERIMPL_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/RefCounted.h" -#include "qpid/sys/IntegerTypes.h" - -namespace qpid { -namespace messaging { - -class Address; -class Message; -class Session; - -class SenderImpl : public virtual qpid::RefCounted -{ - public: - virtual ~SenderImpl() {} - virtual void send(const Message& message, bool sync) = 0; - virtual void close() = 0; - virtual void setCapacity(uint32_t) = 0; - virtual uint32_t getCapacity() = 0; - virtual uint32_t getUnsettled() = 0; - virtual const std::string& getName() const = 0; - virtual Session getSession() const = 0; - virtual Address getAddress() const = 0; - private: -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_SENDERIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/Session.cpp b/qpid/cpp/src/qpid/messaging/Session.cpp deleted file mode 100644 index fd0519705d..0000000000 --- a/qpid/cpp/src/qpid/messaging/Session.cpp +++ /dev/null @@ -1,113 +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/messaging/Session.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/SessionImpl.h" -#include "qpid/messaging/PrivateImplRef.h" - -namespace qpid { -namespace messaging { - -// Explicitly instantiate Handle superclass -template class Handle; - -typedef PrivateImplRef PI; - -Session::Session(SessionImpl* impl) { PI::ctor(*this, impl); } -Session::Session(const Session& s) : Handle() { PI::copy(*this, s); } -Session::~Session() { PI::dtor(*this); } -Session& Session::operator=(const Session& s) { return PI::assign(*this, s); } -void Session::commit() { impl->commit(); } -void Session::rollback() { impl->rollback(); } -void Session::acknowledge(bool sync) { impl->acknowledge(sync); } -void Session::acknowledge(Message& m, bool s) { impl->acknowledge(m, false); sync(s); } -void Session::acknowledgeUpTo(Message& m, bool s) { impl->acknowledge(m, true); sync(s); } -void Session::reject(Message& m) { impl->reject(m); } -void Session::release(Message& m) { impl->release(m); } -void Session::close() { impl->close(); } - -Sender Session::createSender(const Address& address) -{ - return impl->createSender(address); -} -Receiver Session::createReceiver(const Address& address) -{ - return impl->createReceiver(address); -} - -Sender Session::createSender(const std::string& address) -{ - return impl->createSender(Address(address)); -} -Receiver Session::createReceiver(const std::string& address) -{ - return impl->createReceiver(Address(address)); -} - -void Session::sync(bool block) -{ - impl->sync(block); -} - -bool Session::nextReceiver(Receiver& receiver, Duration timeout) -{ - return impl->nextReceiver(receiver, timeout); -} - - -Receiver Session::nextReceiver(Duration timeout) -{ - return impl->nextReceiver(timeout); -} - -uint32_t Session::getReceivable() { return impl->getReceivable(); } -uint32_t Session::getUnsettledAcks() { return impl->getUnsettledAcks(); } - -Sender Session::getSender(const std::string& name) const -{ - return impl->getSender(name); -} -Receiver Session::getReceiver(const std::string& name) const -{ - return impl->getReceiver(name); -} - -Connection Session::getConnection() const -{ - return impl->getConnection(); -} - -void Session::checkError() { impl->checkError(); } -bool Session::hasError() -{ - try { - checkError(); - return false; - } catch (const std::exception&) { - return true; - } -} - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/messaging/SessionImpl.h b/qpid/cpp/src/qpid/messaging/SessionImpl.h deleted file mode 100644 index 60ae615253..0000000000 --- a/qpid/cpp/src/qpid/messaging/SessionImpl.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef QPID_MESSAGING_SESSIONIMPL_H -#define QPID_MESSAGING_SESSIONIMPL_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/RefCounted.h" -#include -#include "qpid/messaging/Duration.h" - -namespace qpid { -namespace messaging { - -class Address; -class Connection; -class Message; -class Sender; -class Receiver; - -class SessionImpl : public virtual qpid::RefCounted -{ - public: - virtual ~SessionImpl() {} - virtual void commit() = 0; - virtual void rollback() = 0; - virtual void acknowledge(bool sync) = 0; - virtual void acknowledge(Message&, bool cumulative) = 0; - virtual void reject(Message&) = 0; - virtual void release(Message&) = 0; - virtual void close() = 0; - virtual void sync(bool block) = 0; - virtual Sender createSender(const Address& address) = 0; - virtual Receiver createReceiver(const Address& address) = 0; - virtual bool nextReceiver(Receiver& receiver, Duration timeout) = 0; - virtual Receiver nextReceiver(Duration timeout) = 0; - virtual uint32_t getReceivable() = 0; - virtual uint32_t getUnsettledAcks() = 0; - virtual Sender getSender(const std::string& name) const = 0; - virtual Receiver getReceiver(const std::string& name) const = 0; - virtual Connection getConnection() const = 0; - virtual void checkError() = 0; - private: -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_SESSIONIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp deleted file mode 100644 index 96466dcfba..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp +++ /dev/null @@ -1,788 +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 "PnData.h" -#include "qpid/messaging/amqp/AddressHelper.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/AddressImpl.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/types/encodings.h" -#include "qpid/log/Statement.h" -#include -#include -#include -#include -#include -extern "C" { -#include -} - - -namespace qpid { -namespace messaging { -namespace amqp { - -using qpid::types::Variant; - -namespace { -//policy types -const std::string CREATE("create"); -const std::string ASSERT("assert"); -const std::string DELETE("delete"); - -//policy values -const std::string ALWAYS("always"); -const std::string NEVER("never"); -const std::string RECEIVER("receiver"); -const std::string SENDER("sender"); - -const std::string NODE("node"); -const std::string LINK("link"); -const std::string CAPABILITIES("capabilities"); -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"); -const std::string QUEUE("queue"); -const std::string DURABLE("durable"); -const std::string NAME("name"); -const std::string RELIABILITY("reliability"); -const std::string SELECTOR("selector"); -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"); -const std::string COPY("copy"); - -const std::string SUPPORTED_DIST_MODES("supported-dist-modes"); -const std::string AUTO_DELETE("auto-delete"); -const std::string LIFETIME_POLICY("lifetime-policy"); -const std::string DELETE_ON_CLOSE("delete-on-close"); -const std::string DELETE_IF_UNUSED("delete-if-unused"); -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 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::string NULL_ADDRESS(""); - -const std::vector RECEIVER_MODES = boost::assign::list_of(ALWAYS) (RECEIVER); -const std::vector SENDER_MODES = boost::assign::list_of(ALWAYS) (SENDER); - -class Verifier -{ - public: - Verifier(); - void verify(const Address& address) const; - private: - Variant::Map defined; - void verify(const Variant::Map& allowed, const Variant::Map& actual) const; -}; -const Verifier verifier; - -pn_bytes_t convert(const std::string& s) -{ - pn_bytes_t result; - result.start = const_cast(s.data()); - result.size = s.size(); - return result; -} - -std::string convert(pn_bytes_t in) -{ - return std::string(in.start, in.size); -} - -bool hasWildcards(const std::string& key) -{ - return key.find('*') != std::string::npos || key.find('#') != std::string::npos; -} - -uint64_t getFilterDescriptor(const std::string& key) -{ - return hasWildcards(key) ? qpid::amqp::filters::LEGACY_TOPIC_FILTER_CODE : qpid::amqp::filters::LEGACY_DIRECT_FILTER_CODE; -} - -bool test(const Variant::Map& options, const std::string& name) -{ - Variant::Map::const_iterator j = options.find(name); - if (j == options.end()) { - return false; - } else { - return j->second; - } -} - -template 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 getOption(const Variant::Map& options, const std::string& name, std::string& variable) -{ - Variant::Map::const_iterator j = options.find(name); - if (j == options.end()) { - return false; - } else { - variable = j->second.asString(); - return true; - } -} - -bool getOption(const Variant::Map& options, const std::string& name, Variant::Map& variable) -{ - Variant::Map::const_iterator j = options.find(name); - if (j == options.end()) { - return false; - } else { - variable = j->second.asMap(); - return true; - } -} - -bool getOption(const Variant::Map& options, const std::string& name, Variant::List& variable) -{ - Variant::Map::const_iterator j = options.find(name); - if (j == options.end()) { - return false; - } else { - variable = j->second.asList(); - return true; - } -} - -bool getAddressOption(const Address& address, const std::string& name, std::string& variable) -{ - return getOption(address.getOptions(), name, variable); -} - -bool getAddressOption(const Address& address, const std::string& name, Variant::Map& variable) -{ - return getOption(address.getOptions(), name, variable); -} - -bool in(const std::string& value, const std::vector& choices) -{ - for (std::vector::const_iterator i = choices.begin(); i != choices.end(); ++i) { - if (value == *i) return true; - } - return false; -} -void add(Variant::Map& target, const Variant::Map& source) -{ - for (Variant::Map::const_iterator i = source.begin(); i != source.end(); ++i) { - target[i->first] = i->second; - } -} -void flatten(Variant::Map& base, const std::string& nested) -{ - Variant::Map::iterator i = base.find(nested); - if (i != base.end()) { - add(base, i->second.asMap()); - 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; - } -} - -const uint32_t DEFAULT_DURABLE_TIMEOUT(2*60);//2 minutes -const uint32_t DEFAULT_TIMEOUT(0); -} - -AddressHelper::AddressHelper(const Address& address) : - isTemporary(AddressImpl::isTemporary(address)), - name(address.getName()), - type(address.getType()), - durableNode(false), - durableLink(false), - timeout(0), - browse(false) -{ - verifier.verify(address); - getAddressOption(address, CREATE, createPolicy); - getAddressOption(address, DELETE, deletePolicy); - getAddressOption(address, ASSERT, assertPolicy); - - getAddressOption(address, NODE, node); - getAddressOption(address, LINK, link); - getOption(node, PROPERTIES, properties); - getOption(node, CAPABILITIES, capabilities); - getOption(link, RELIABILITY, reliability); - durableNode = test(node, DURABLE); - durableLink = test(link, DURABLE); - timeout = get(link, TIMEOUT, durableLink && reliability != AT_LEAST_ONCE ? DEFAULT_DURABLE_TIMEOUT : DEFAULT_TIMEOUT); - std::string mode; - if (getAddressOption(address, MODE, mode)) { - if (mode == BROWSE) { - browse = true; - } else if (mode != CONSUME) { - throw qpid::messaging::AddressError("Invalid value for mode; must be 'browse' or 'consume'."); - } - } - - if (!deletePolicy.empty()) { - throw qpid::messaging::AddressError("Delete policies not supported over AMQP 1.0."); - } - if (node.find(X_BINDINGS) != node.end()) { - throw qpid::messaging::AddressError("Node scoped x-bindings element not supported over AMQP 1.0."); - } - if (link.find(X_BINDINGS) != link.end()) { - throw qpid::messaging::AddressError("Link scoped x-bindings element not supported over AMQP 1.0."); - } - if (link.find(X_SUBSCRIBE) != link.end()) { - throw qpid::messaging::AddressError("Link scoped x-subscribe element not supported over AMQP 1.0."); - } - if (link.find(X_DECLARE) != link.end()) { - throw qpid::messaging::AddressError("Link scoped x-declare element not supported over AMQP 1.0."); - } - //massage x-declare into properties - 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); - } - //for temp queues, if neither lifetime-policy nor autodelete are specified, assume delete-on-close - if (isTemporary && properties.find(LIFETIME_POLICY) == properties.end() && properties.find(AUTO_DELETE) == properties.end()) { - properties[LIFETIME_POLICY] = DELETE_ON_CLOSE; - } - - if (properties.size() && !(isTemporary || !createPolicy.empty() || !assertPolicy.empty())) { - QPID_LOG(warning, "Properties will be ignored! " << address); - } - - qpid::types::Variant::Map::const_iterator selector = link.find(SELECTOR); - if (selector != link.end()) { - addFilter(SELECTOR, qpid::amqp::filters::SELECTOR_FILTER_CODE, selector->second); - } - if (!address.getSubject().empty()) { - addFilter(SUBJECT_FILTER, getFilterDescriptor(address.getSubject()), address.getSubject()); - } - qpid::types::Variant::Map::const_iterator filter = link.find(FILTER); - if (filter != link.end()) { - if (filter->second.getType() == qpid::types::VAR_MAP) { - addFilter(filter->second.asMap()); - } else if (filter->second.getType() == qpid::types::VAR_LIST) { - addFilters(filter->second.asList()); - } else { - throw qpid::messaging::AddressError("Filter must be a map or a list of maps, each containing name, descriptor and value."); - } - } -} - -void AddressHelper::addFilters(const qpid::types::Variant::List& f) -{ - for (qpid::types::Variant::List::const_iterator i = f.begin(); i != f.end(); ++i) { - addFilter(i->asMap()); - } -} - -void AddressHelper::addFilter(const qpid::types::Variant::Map& f) -{ - qpid::types::Variant::Map::const_iterator name = f.find(NAME); - qpid::types::Variant::Map::const_iterator descriptor = f.find(DESCRIPTOR); - qpid::types::Variant::Map::const_iterator value = f.find(VALUE); - //all fields are required at present (may relax this at a later stage): - if (name == f.end()) { - throw qpid::messaging::AddressError("Filter entry must specify name"); - } - if (descriptor == f.end()) { - throw qpid::messaging::AddressError("Filter entry must specify descriptor"); - } - if (value == f.end()) { - throw qpid::messaging::AddressError("Filter entry must specify value"); - } - try { - addFilter(name->second.asString(), descriptor->second.asUint64(), value->second); - } catch (const qpid::types::InvalidConversion&) { - addFilter(name->second.asString(), descriptor->second.asString(), value->second); - } - -} - -AddressHelper::Filter::Filter() : descriptorCode(0), confirmed(false) {} -AddressHelper::Filter::Filter(const std::string& n, uint64_t d, const qpid::types::Variant& v) : name(n), descriptorCode(d), value(v), confirmed(false) {} -AddressHelper::Filter::Filter(const std::string& n, const std::string& d, const qpid::types::Variant& v) : name(n), descriptorSymbol(d), descriptorCode(0), value(v), confirmed(false) {} - -void AddressHelper::addFilter(const std::string& name, uint64_t descriptor, const qpid::types::Variant& value) -{ - filters.push_back(Filter(name, descriptor, value)); -} -void AddressHelper::addFilter(const std::string& name, const std::string& descriptor, const qpid::types::Variant& value) -{ - filters.push_back(Filter(name, descriptor, value)); -} - -namespace { -bool checkLifetimePolicy(const std::string& requested, const std::string& actual) -{ - if (actual == qpid::amqp::lifetime_policy::DELETE_ON_CLOSE_SYMBOL && requested == DELETE_ON_CLOSE) return true; - else if (actual == qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_SYMBOL && requested == DELETE_IF_UNUSED) return true; - else if (actual == qpid::amqp::lifetime_policy::DELETE_ON_NO_MESSAGES_SYMBOL && requested == DELETE_IF_EMPTY) return true; - else if (actual == qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_SYMBOL && requested == DELETE_IF_UNUSED_AND_EMPTY) return true; - else return actual == requested; -} -bool checkLifetimePolicy(const std::string& requested, uint64_t actual) -{ - if (actual == qpid::amqp::lifetime_policy::DELETE_ON_CLOSE_CODE) - return checkLifetimePolicy(requested, qpid::amqp::lifetime_policy::DELETE_ON_CLOSE_SYMBOL); - else if (actual == qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_CODE) - return checkLifetimePolicy(requested, qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_SYMBOL); - else if (actual == qpid::amqp::lifetime_policy::DELETE_ON_NO_MESSAGES_CODE) - return checkLifetimePolicy(requested, qpid::amqp::lifetime_policy::DELETE_ON_NO_MESSAGES_SYMBOL); - else if (actual == qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_CODE) - return checkLifetimePolicy(requested, qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_SYMBOL); - else - return false; -} -bool checkLifetimePolicy(const std::string& requested, pn_data_t* actual) -{ - bool result(false); - if (pn_data_is_described(actual)) { - pn_data_enter(actual); - pn_data_next(actual); - if (pn_data_type(actual) == PN_ULONG) { - result = checkLifetimePolicy(requested, pn_data_get_ulong(actual)); - } else if (pn_data_type(actual) == PN_SYMBOL) { - result = checkLifetimePolicy(requested, convert(pn_data_get_symbol(actual))); - } - pn_data_exit(actual); - } - return result; -} -} -void AddressHelper::checkAssertion(pn_terminus_t* terminus, CheckMode mode) -{ - if (assertEnabled(mode)) { - QPID_LOG(debug, "checking capabilities: " << capabilities); - //ensure all desired capabilities have been offered - std::set desired; - for (Variant::List::const_iterator i = capabilities.begin(); i != capabilities.end(); ++i) { - if (*i != CREATE_ON_DEMAND) desired.insert(i->asString()); - } - pn_data_t* data = pn_terminus_capabilities(terminus); - 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()) { - std::stringstream missing; - missing << "Desired capabilities not met: "; - bool first(true); - for (std::set::const_iterator i = desired.begin(); i != desired.end(); ++i) { - if (first) first = false; - else missing << ", "; - missing << *i; - } - throw qpid::messaging::AssertionFailed(missing.str()); - } - - //ensure all desired filters are in use - data = pn_terminus_filter(terminus); - if (pn_data_next(data)) { - size_t count = pn_data_get_map(data); - pn_data_enter(data); - for (size_t i = 0; i < count && pn_data_next(data); ++i) { - //skip key: - if (!pn_data_next(data)) break; - //expecting described value: - if (pn_data_is_described(data)) { - pn_data_enter(data); - pn_data_next(data); - if (pn_data_type(data) == PN_ULONG) { - confirmFilter(pn_data_get_ulong(data)); - } else if (pn_data_type(data) == PN_SYMBOL) { - confirmFilter(convert(pn_data_get_symbol(data))); - } - pn_data_exit(data); - } - } - pn_data_exit(data); - } - std::stringstream missing; - missing << "Desired filters not in use: "; - bool first(true); - for (std::vector::iterator i = filters.begin(); i != filters.end(); ++i) { - if (!i->confirmed) { - if (first) first = false; - else missing << ", "; - missing << i->name << "("; - if (i->descriptorSymbol.empty()) missing << "0x" << std::hex << i->descriptorCode; - else missing << i->descriptorSymbol; - missing << ")"; - } - } - if (!first) throw qpid::messaging::AssertionFailed(missing.str()); - - //assert on properties (Note: this violates the AMQP 1.0 - //specification - as does the create option - by sending - //node-properties even if the dynamic option is not - //set. However this can be avoided by not specifying any node - //properties when asserting) - if (!type.empty() || durableNode || !properties.empty()) { - bool isAutoDeleted = false; - qpid::types::Variant::Map requested = properties; - if (!type.empty()) requested[SUPPORTED_DIST_MODES] = type == TOPIC ? COPY : MOVE; - if (durableNode) requested[DURABLE] = true; - - data = pn_terminus_properties(terminus); - if (pn_data_next(data)) { - size_t count = pn_data_get_map(data); - pn_data_enter(data); - for (size_t i = 0; i < count && pn_data_next(data); ++i) { - std::string key = convert(pn_data_get_symbol(data)); - pn_data_next(data); - qpid::types::Variant::Map::const_iterator j = requested.find(key); - qpid::types::Variant v; - if (key == LIFETIME_POLICY) { - isAutoDeleted = true; - if (j != requested.end() && checkLifetimePolicy(j->second.asString(), data)) { - requested.erase(j->first); - } - } else if (key == AUTO_DELETE) { - PnData(data).get(v); - isAutoDeleted = v.asBool(); - } else if (j != requested.end() && (PnData(data).get(v) && v.asString() == j->second.asString())) { - requested.erase(j->first); - } - } - pn_data_exit(data); - qpid::types::Variant::Map::iterator i = requested.find(AUTO_DELETE); - if (i != requested.end() && i->second.asBool() == isAutoDeleted) { - requested.erase(i); - } - if (!requested.empty()) { - std::stringstream missing; - missing << "Requested node properties not met: " << requested; - throw qpid::messaging::AssertionFailed(missing.str()); - } - } - } - } -} - -void AddressHelper::confirmFilter(const std::string& descriptor) -{ - for (std::vector::iterator i = filters.begin(); i != filters.end(); ++i) { - if (descriptor == i->descriptorSymbol) i->confirmed = true; - } -} - -void AddressHelper::confirmFilter(uint64_t descriptor) -{ - for (std::vector::iterator i = filters.begin(); i != filters.end(); ++i) { - if (descriptor == i->descriptorCode) i->confirmed = true; - } -} - -bool AddressHelper::createEnabled(CheckMode mode) const -{ - return enabled(createPolicy, mode); -} - -bool AddressHelper::assertEnabled(CheckMode mode) const -{ - return enabled(assertPolicy, mode); -} - -bool AddressHelper::enabled(const std::string& policy, CheckMode mode) const -{ - bool result = false; - switch (mode) { - case FOR_RECEIVER: - result = in(policy, RECEIVER_MODES); - break; - case FOR_SENDER: - result = in(policy, SENDER_MODES); - break; - } - return result; -} - -bool AddressHelper::isNameNull() const -{ - return name == NULL_ADDRESS; -} - -bool AddressHelper::isUnreliable() const -{ - return reliability == AT_MOST_ONCE || reliability == UNRELIABLE || - (reliability.empty() && browse); // A browser defaults to unreliable. -} - -const qpid::types::Variant::Map& AddressHelper::getNodeProperties() const -{ - return node; -} -const qpid::types::Variant::Map& AddressHelper::getLinkProperties() const -{ - return link; -} - -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_dynamic(terminus, true); - setNodeProperties(terminus); - } else if (name != NULL_ADDRESS) { - pn_terminus_set_address(terminus, name.c_str()); - if (createEnabled(mode)) { - //application expects name of node to be as specified - setNodeProperties(terminus); - createOnDemand = true; - } else if (assertEnabled(mode)) { - setNodeProperties(terminus); - } - } - - setCapabilities(terminus, createOnDemand); - if (durableLink) { - pn_terminus_set_durability(terminus, PN_DELIVERIES); - } - 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); - for (std::vector::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); - } - PnData(filter).put(i->value); - pn_data_exit(filter); - } - pn_data_exit(filter); - } - } - if (isUnreliable()) { - pn_link_set_snd_settle_mode(link, PN_SND_SETTLED); - } else if (!reliability.empty()) { - if (reliability == EXACTLY_ONCE ) { - QPID_LOG(warning, "Unsupported reliability mode: " << reliability); - } else if (reliability != AT_LEAST_ONCE ) { - QPID_LOG(warning, "Unrecognised reliability mode: " << reliability); - } - pn_link_set_snd_settle_mode(link, PN_SND_UNSETTLED); - } -} - -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 (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) -{ - AddressHelper helper(address); - const qpid::types::Variant::Map& linkProps = helper.getLinkProperties(); - qpid::types::Variant::Map::const_iterator i = linkProps.find(NAME); - if (i != linkProps.end()) { - return i->second.asString(); - } else { - std::stringstream name; - name << address.getName() << "_" << qpid::types::Uuid(true); - return name.str(); - } -} -namespace { -std::string toLifetimePolicy(const std::string& value) -{ - if (value == DELETE_ON_CLOSE) return qpid::amqp::lifetime_policy::DELETE_ON_CLOSE_SYMBOL; - else if (value == DELETE_IF_UNUSED) return qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_SYMBOL; - else if (value == DELETE_IF_EMPTY) return qpid::amqp::lifetime_policy::DELETE_ON_NO_MESSAGES_SYMBOL; - else if (value == DELETE_IF_UNUSED_AND_EMPTY) return qpid::amqp::lifetime_policy::DELETE_ON_NO_LINKS_OR_MESSAGES_SYMBOL; - else return value;//asume value is itself the symbolic descriptor -} -void putLifetimePolicy(pn_data_t* data, const std::string& value) -{ - pn_data_put_described(data); - pn_data_enter(data); - pn_data_put_symbol(data, convert(value)); - pn_data_put_list(data); - pn_data_exit(data); -} -} -void AddressHelper::setNodeProperties(pn_terminus_t* terminus) -{ - if (properties.size() || type.size() || durableNode) { - pn_data_t* data = pn_terminus_properties(terminus); - pn_data_put_map(data); - pn_data_enter(data); - if (type.size()) { - pn_data_put_symbol(data, convert(SUPPORTED_DIST_MODES)); - pn_data_put_string(data, convert(type == TOPIC ? COPY : MOVE)); - } - if (durableNode) { - pn_data_put_symbol(data, convert(DURABLE)); - pn_data_put_bool(data, true); - } - for (qpid::types::Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - if (i->first == LIFETIME_POLICY) { - pn_data_put_symbol(data, convert(i->first)); - putLifetimePolicy(data, toLifetimePolicy(i->second.asString())); - } else { - pn_data_put_symbol(data, convert(i->first)); - PnData(data).put(i->second); - } - } - pn_data_exit(data); - } -} - -Verifier::Verifier() -{ - defined[CREATE] = true; - defined[ASSERT] = true; - defined[DELETE] = true; - defined[MODE] = true; - Variant::Map node; - node[TYPE] = true; - node[DURABLE] = true; - node[PROPERTIES] = true; - node[CAPABILITIES] = true; - node[X_DECLARE] = true; - node[X_BINDINGS] = true; - defined[NODE] = node; - Variant::Map link; - 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; - link[SELECTOR] = true; - link[FILTER] = true; - defined[LINK] = link; -} -void Verifier::verify(const Address& address) const -{ - verify(defined, address.getOptions()); -} - -void Verifier::verify(const Variant::Map& allowed, const Variant::Map& actual) const -{ - for (Variant::Map::const_iterator i = actual.begin(); i != actual.end(); ++i) { - Variant::Map::const_iterator option = allowed.find(i->first); - if (option == allowed.end()) { - throw AddressError((boost::format("Unrecognised option: %1%") % i->first).str()); - } else if (option->second.getType() == qpid::types::VAR_MAP) { - verify(option->second.asMap(), i->second.asMap()); - } - } -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h deleted file mode 100644 index 381f37ac88..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_ADDRESSHELPER_H -#define QPID_MESSAGING_AMQP_ADDRESSHELPER_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/types/Variant.h" -#include - -struct pn_link_t; -struct pn_terminus_t; - -namespace qpid { -namespace messaging { -class Address; -namespace amqp { -class AddressHelper -{ - public: - enum CheckMode {FOR_RECEIVER, FOR_SENDER}; - - AddressHelper(const Address& address); - void configure(pn_link_t* link, pn_terminus_t* terminus, CheckMode mode); - void checkAssertion(pn_terminus_t* terminus, CheckMode mode); - - bool isNameNull() const; - 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: - struct Filter - { - std::string name; - std::string descriptorSymbol; - uint64_t descriptorCode; - qpid::types::Variant value; - bool confirmed; - - Filter(); - Filter(const std::string& name, uint64_t descriptor, const qpid::types::Variant& value); - Filter(const std::string& name, const std::string& descriptor, const qpid::types::Variant& value); - }; - - bool isTemporary; - std::string createPolicy; - std::string assertPolicy; - std::string deletePolicy; - qpid::types::Variant::Map node; - qpid::types::Variant::Map link; - qpid::types::Variant::Map properties; - 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 filters; - - bool enabled(const std::string& policy, CheckMode mode) const; - bool createEnabled(CheckMode mode) const; - bool assertEnabled(CheckMode mode) const; - void setCapabilities(pn_terminus_t* terminus, bool create); - void setNodeProperties(pn_terminus_t* terminus); - void addFilter(const qpid::types::Variant::Map&); - void addFilter(const std::string& name, uint64_t descriptor, const qpid::types::Variant& value); - void addFilter(const std::string& name, const std::string& descriptor, const qpid::types::Variant& value); - 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 - -#endif /*!QPID_MESSAGING_AMQP_ADDRESSHELPER_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp deleted file mode 100644 index bb0d32e333..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp +++ /dev/null @@ -1,1323 +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 "ConnectionContext.h" -#include "DriverImpl.h" -#include "PnData.h" -#include "ReceiverContext.h" -#include "Sasl.h" -#include "SenderContext.h" -#include "SessionContext.h" -#include "Transaction.h" -#include "Transport.h" -#include "util.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/amqp/Encoder.h" -#include "qpid/amqp/Descriptor.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/AddressImpl.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/urlAdd.h" -#include "config.h" -#include -#include -#include -extern "C" { -#include -} - -namespace qpid { -namespace messaging { -namespace amqp { -using types::Variant; - -namespace { - -void do_trace(pn_transport_t* transport, const char* message) -{ - ConnectionContext* c = reinterpret_cast(pn_transport_get_context(transport)); - if (c) c->trace(message); -} - -void set_tracer(pn_transport_t* transport, void* context) -{ - pn_transport_set_context(transport, context); - pn_transport_set_tracer(transport, &do_trace); -} - -#ifdef USE_PROTON_TRANSPORT_CONDITION -std::string get_error(pn_connection_t* connection, pn_transport_t* transport) -{ - std::stringstream text; - pn_error_t* cerror = pn_connection_error(connection); - if (cerror) text << "connection error " << pn_error_text(cerror) << " [" << cerror << "]"; - pn_condition_t* tcondition = pn_transport_condition(transport); - if (pn_condition_is_set(tcondition)) text << get_error_string(tcondition, "transport error", ": "); - return text.str(); -} -#else -std::string get_error(pn_connection_t* connection, pn_transport_t* transport) -{ - std::stringstream text; - pn_error_t* cerror = pn_connection_error(connection); - if (cerror) text << "connection error " << pn_error_text(cerror) << " [" << cerror << "]"; - pn_error_t* terror = pn_transport_error(transport); - if (terror) text << "transport error " << pn_error_text(terror) << " [" << terror << "]"; - return text.str(); -} -#endif - -class ConnectionTickerTask : public qpid::sys::TimerTask -{ - qpid::sys::Timer& timer; - ConnectionContext& connection; - public: - ConnectionTickerTask(const qpid::sys::Duration& interval, qpid::sys::Timer& t, ConnectionContext& c) : - TimerTask(interval, "ConnectionTicker"), - timer(t), - connection(c) - {} - - void fire() { - QPID_LOG(debug, "ConnectionTickerTask fired"); - // Setup next firing - setupNextFire(); - timer.add(this); - - // Send Ticker - connection.activateOutput(); - } -}; -} - -void ConnectionContext::trace(const char* message) const -{ - QPID_LOG_CAT(trace, protocol, "[" << identifier << "]: " << message); -} - -ConnectionContext::ConnectionContext(const std::string& url, const qpid::types::Variant::Map& o) - : qpid::messaging::ConnectionOptions(o), - fullUrl(url, 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), - codecAdapter(*this), - notifyOnWrite(false) -{ - // Concatenate all known URLs into a single URL, get rid of duplicate addresses. - sys::urlAddStrings(fullUrl, urls.begin(), urls.end(), protocol.empty() ? - qpid::Address::TCP : protocol); - if (identifier.empty()) { - identifier = qpid::types::Uuid(true).str(); - } - configureConnection(); -} - -ConnectionContext::~ConnectionContext() -{ - if (ticker) ticker->cancel(); - close(); - sessions.clear(); - pn_connection_free(connection); - pn_transport_free(engine); -} - -bool ConnectionContext::isOpen() const -{ - sys::Monitor::ScopedLock l(lock); - return state == CONNECTED && pn_connection_state(connection) & (PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE); -} - -void ConnectionContext::sync(boost::shared_ptr ssn) -{ - sys::Monitor::ScopedLock l(lock); - syncLH(ssn, l); -} - -void ConnectionContext::syncLH(boost::shared_ptr ssn, sys::Monitor::ScopedLock&) { - while (!ssn->settled()) { - QPID_LOG(debug, "Waiting for sends to settle on sync()"); - wait(ssn);//wait until message has been confirmed - wakeupDriver(); - } - checkClosed(ssn); -} - -void ConnectionContext::endSession(boost::shared_ptr ssn) -{ - sys::Monitor::ScopedLock l(lock); - if (pn_session_state(ssn->session) & PN_REMOTE_ACTIVE) { - //explicitly release messages that have yet to be fetched - for (SessionContext::ReceiverMap::iterator i = ssn->receivers.begin(); i != ssn->receivers.end(); ++i) { - drain_and_release_messages(ssn, i->second); - } - syncLH(ssn, l); - } - - if (pn_session_state(ssn->session) & PN_REMOTE_ACTIVE) { - pn_session_close(ssn->session); - } - sessions.erase(ssn->getName()); - - wakeupDriver(); -} - -void ConnectionContext::close() -{ - sys::Monitor::ScopedLock l(lock); - if (state != CONNECTED) return; - if (!(pn_connection_state(connection) & PN_LOCAL_CLOSED)) { - for (SessionMap::iterator i = sessions.begin(); i != sessions.end(); ++i) { - syncLH(i->second, l); - if (!(pn_session_state(i->second->session) & PN_LOCAL_CLOSED)) { - pn_session_close(i->second->session); - } - } - pn_connection_close(connection); - wakeupDriver(); - //wait for close to be confirmed by peer? - while (!(pn_connection_state(connection) & PN_REMOTE_CLOSED)) { - if (state == DISCONNECTED) { - QPID_LOG(warning, "Disconnected before close received from peer."); - break; - } - lock.wait(); - } - sessions.clear(); - } - if (state != DISCONNECTED) { - transport->close(); - while (state != DISCONNECTED) { - lock.wait(); - } - } - if (ticker) { - ticker->cancel(); - ticker = boost::intrusive_ptr(); - } -} - -bool ConnectionContext::fetch(boost::shared_ptr ssn, boost::shared_ptr lnk, qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - /** - * For fetch() on a receiver with zero capacity, need to reissue the - * credit on reconnect, so track the fetches in progress. - */ - qpid::sys::AtomicCount::ScopedIncrement track(lnk->fetching); - { - sys::Monitor::ScopedLock l(lock); - checkClosed(ssn, lnk); - if (!lnk->capacity) { - pn_link_flow(lnk->receiver, 1); - wakeupDriver(); - } - } - if (get(ssn, lnk, message, timeout)) { - return true; - } else { - { - sys::Monitor::ScopedLock l(lock); - pn_link_drain(lnk->receiver, 0); - wakeupDriver(); - while (pn_link_draining(lnk->receiver) && !pn_link_queued(lnk->receiver)) { - QPID_LOG(debug, "Waiting for message or for credit to be drained: credit=" << pn_link_credit(lnk->receiver) << ", queued=" << pn_link_queued(lnk->receiver)); - wait(ssn, lnk); - } - if (lnk->capacity && pn_link_queued(lnk->receiver) == 0) { - pn_link_flow(lnk->receiver, lnk->capacity); - } - } - if (get(ssn, lnk, message, qpid::messaging::Duration::IMMEDIATE)) { - return true; - } else { - return false; - } - } -} - -qpid::sys::AbsTime convert(qpid::messaging::Duration timeout) -{ - qpid::sys::AbsTime until; - uint64_t ms = timeout.getMilliseconds(); - if (ms < (uint64_t) (qpid::sys::TIME_INFINITE/qpid::sys::TIME_MSEC)) { - return qpid::sys::AbsTime(qpid::sys::now(), ms * qpid::sys::TIME_MSEC); - } else { - return qpid::sys::FAR_FUTURE; - } -} - -bool ConnectionContext::get(boost::shared_ptr ssn, boost::shared_ptr lnk, qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - qpid::sys::AbsTime until(convert(timeout)); - while (true) { - sys::Monitor::ScopedLock l(lock); - checkClosed(ssn, lnk); - pn_delivery_t* current = pn_link_current((pn_link_t*) lnk->receiver); - QPID_LOG(debug, "In ConnectionContext::get(), current=" << current); - if (current && !pn_delivery_partial(current)) { - qpid::messaging::MessageImpl& impl = MessageImplAccess::get(message); - boost::shared_ptr 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); - QPID_LOG(debug, "Received message of " << encoded->getSize() << " bytes: "); - encoded->init(impl); - impl.setEncoded(encoded); - impl.setInternalId(ssn->record(current)); - if (lnk->capacity) { - pn_link_flow(lnk->receiver, 1); - if (lnk->wakeupToIssueCredit()) { - wakeupDriver(); - } else { - haveOutput = true; - } - } - // Automatically ack messages if we are in a transaction. - if (ssn->transaction) - acknowledgeLH(ssn, &message, false, l); - return true; - } else if (until > qpid::sys::now()) { - waitUntil(ssn, lnk, until); - } else { - return false; - } - } - return false; -} - -boost::shared_ptr ConnectionContext::nextReceiver(boost::shared_ptr ssn, qpid::messaging::Duration timeout) -{ - qpid::sys::AbsTime until(convert(timeout)); - while (true) { - sys::Monitor::ScopedLock l(lock); - checkClosed(ssn); - boost::shared_ptr r = ssn->nextReceiver(); - if (r) { - return r; - } else if (until > qpid::sys::now()) { - waitUntil(ssn, until); - } else { - return boost::shared_ptr(); - } - } -} - -void ConnectionContext::acknowledge(boost::shared_ptr ssn, qpid::messaging::Message* message, bool cumulative) { - sys::Monitor::ScopedLock l(lock); - acknowledgeLH(ssn, message, cumulative, l); -} - -void ConnectionContext::acknowledgeLH(boost::shared_ptr ssn, qpid::messaging::Message* message, bool cumulative, sys::Monitor::ScopedLock&) -{ - checkClosed(ssn); - if (message) { - ssn->acknowledge(MessageImplAccess::get(*message).getInternalId(), cumulative); - } else { - ssn->acknowledge(); - } - wakeupDriver(); -} - -void ConnectionContext::nack(boost::shared_ptr ssn, qpid::messaging::Message& message, bool reject) -{ - sys::Monitor::ScopedLock l(lock); - checkClosed(ssn); - ssn->nack(MessageImplAccess::get(message).getInternalId(), reject); - wakeupDriver(); -} - -void ConnectionContext::detach(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - sys::Monitor::ScopedLock 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); - } - ssn->removeSender(lnk->getName()); -} - -void ConnectionContext::drain_and_release_messages(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - pn_link_drain(lnk->receiver, 0); - wakeupDriver(); - //Not all implementations handle drain correctly, so limit the - //time spent waiting for it - qpid::sys::AbsTime until(qpid::sys::now(), qpid::sys::TIME_SEC*2); - while (pn_link_credit(lnk->receiver) > pn_link_queued(lnk->receiver) && until > qpid::sys::now()) { - QPID_LOG(debug, "Waiting for credit to be drained: credit=" << pn_link_credit(lnk->receiver) << ", queued=" << pn_link_queued(lnk->receiver)); - waitUntil(ssn, lnk, until); - } - //release as yet unfetched messages: - for (pn_delivery_t* d = pn_link_current(lnk->receiver); d; d = pn_link_current(lnk->receiver)) { - pn_link_advance(lnk->receiver); - pn_delivery_update(d, PN_RELEASED); - pn_delivery_settle(d); - } -} - -void ConnectionContext::detach(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - sys::Monitor::ScopedLock l(lock); - drain_and_release_messages(ssn, lnk); - if (pn_link_state(lnk->receiver) & PN_LOCAL_ACTIVE) { - lnk->close(); - } - wakeupDriver(); - while (pn_link_state(lnk->receiver) & PN_REMOTE_ACTIVE) { - wait(ssn); - } - ssn->removeReceiver(lnk->getName()); -} - -void ConnectionContext::attach(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - lnk->configure(); - attach(ssn, lnk->sender); - checkClosed(ssn, lnk); - lnk->verify(); - QPID_LOG(debug, "Attach succeeded to " << lnk->getTarget()); -} - -void ConnectionContext::attach(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - lnk->configure(); - attach(ssn, lnk->receiver, lnk->capacity); - checkClosed(ssn, lnk); - lnk->verify(); - QPID_LOG(debug, "Attach succeeded from " << lnk->getSource()); -} - -void ConnectionContext::attach(boost::shared_ptr ssn, pn_link_t* link, int credit) -{ - 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(ssn); - } -} - -boost::shared_ptr ConnectionContext::createSender(boost::shared_ptr session, const qpid::messaging::Address& address) -{ - sys::Monitor::ScopedLock l(lock); - boost::shared_ptr sender = session->createSender(address, setToOnSend); - try { - attach(session, sender); - return sender; - } catch (...) { - session->removeSender(sender->getName()); - throw; - } - -} -boost::shared_ptr ConnectionContext::createReceiver(boost::shared_ptr session, const qpid::messaging::Address& address) -{ - sys::Monitor::ScopedLock l(lock); - boost::shared_ptr receiver = session->createReceiver(address); - try { - attach(session, receiver); - return receiver; - } catch (...) { - session->removeReceiver(receiver->getName()); - throw; - } -} -boost::shared_ptr ConnectionContext::getSender(boost::shared_ptr session, const std::string& name) const -{ - sys::Monitor::ScopedLock l(lock); - return session->getSender(name); -} - -boost::shared_ptr ConnectionContext::getReceiver(boost::shared_ptr session, const std::string& name) const -{ - sys::Monitor::ScopedLock l(lock); - return session->getReceiver(name); -} - -void ConnectionContext::send( - boost::shared_ptr ssn, - boost::shared_ptr snd, - const qpid::messaging::Message& message, - bool sync, - SenderContext::Delivery** delivery) -{ - sys::Monitor::ScopedLock l(lock); - sendLH(ssn, snd, message, sync, delivery, l); -} - -void ConnectionContext::sendLH( - boost::shared_ptr ssn, - boost::shared_ptr snd, - const qpid::messaging::Message& message, - bool sync, - SenderContext::Delivery** delivery, - sys::Monitor::ScopedLock&) -{ - checkClosed(ssn); - while (pn_transport_pending(engine) > 65536) { - QPID_LOG(debug, "Have " << pn_transport_pending(engine) << " bytes of output pending; waiting for this to be written..."); - notifyOnWrite = true; - wakeupDriver(); - wait(ssn, snd); - notifyOnWrite = false; - } - while (!snd->send(message, delivery)) { - QPID_LOG(debug, "Waiting for capacity..."); - wait(ssn, snd);//wait for capacity - } - wakeupDriver(); - if (sync && *delivery) { - while (!(*delivery)->delivered()) { - QPID_LOG(debug, "Waiting for confirmation..."); - wait(ssn, snd);//wait until message has been confirmed - } - if ((*delivery)->rejected()) { - throw MessageRejected("Message was rejected by peer"); - } - - } -} - -void ConnectionContext::setCapacity(boost::shared_ptr sender, uint32_t capacity) -{ - sys::Monitor::ScopedLock l(lock); - sender->setCapacity(capacity); -} -uint32_t ConnectionContext::getCapacity(boost::shared_ptr sender) -{ - sys::Monitor::ScopedLock l(lock); - return sender->getCapacity(); -} -uint32_t ConnectionContext::getUnsettled(boost::shared_ptr sender) -{ - sys::Monitor::ScopedLock l(lock); - return sender->getUnsettled(); -} - -void ConnectionContext::setCapacity(boost::shared_ptr receiver, uint32_t capacity) -{ - sys::Monitor::ScopedLock l(lock); - receiver->setCapacity(capacity); - pn_link_flow((pn_link_t*) receiver->receiver, receiver->getCapacity()); - wakeupDriver(); -} -uint32_t ConnectionContext::getCapacity(boost::shared_ptr receiver) -{ - sys::Monitor::ScopedLock l(lock); - return receiver->getCapacity(); -} -uint32_t ConnectionContext::getAvailable(boost::shared_ptr receiver) -{ - sys::Monitor::ScopedLock l(lock); - return receiver->getAvailable(); -} -uint32_t ConnectionContext::getUnsettled(boost::shared_ptr receiver) -{ - sys::Monitor::ScopedLock l(lock); - return receiver->getUnsettled(); -} - -void ConnectionContext::activateOutput() -{ - sys::Monitor::ScopedLock l(lock); - if (state == CONNECTED) wakeupDriver(); -} -/** - * Expects lock to be held by caller - */ -void ConnectionContext::wakeupDriver() -{ - switch (state) { - case CONNECTED: - haveOutput = true; - transport->activateOutput(); - QPID_LOG(debug, "wakeupDriver()"); - break; - case DISCONNECTED: - case CONNECTING: - QPID_LOG(error, "wakeupDriver() called while not connected"); - break; - } -} - -namespace { -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_connection_free(connection); - pn_transport_free(engine); - - engine = pn_transport(); - connection = pn_connection(); - configureConnection(); - - for (SessionMap::iterator i = sessions.begin(); i != sessions.end(); ++i) { - i->second->reset(connection); - } -} - -bool ConnectionContext::check() { - if (checkDisconnected()) { - if (ConnectionOptions::reconnect) { - QPID_LOG(notice, "Auto-reconnecting to " << fullUrl); - autoconnect(); - QPID_LOG(notice, "Auto-reconnected to " << currentUrl); - } else { - throw qpid::messaging::TransportFailure("Disconnected (reconnect disabled)"); - } - return true; - } - return false; -} - -bool ConnectionContext::checkDisconnected() { - if (state == DISCONNECTED) { - reset(); - } else { - if ((pn_connection_state(connection) & REQUIRES_CLOSE) == REQUIRES_CLOSE) { - std::string text = get_error_string(pn_connection_remote_condition(connection), "Connection closed by peer"); - pn_connection_close(connection); - throw qpid::messaging::ConnectionError(text); - } - } - return state == DISCONNECTED; -} - -void ConnectionContext::wait() -{ - if (check()) return; // Reconnected, may need to re-test condition. - lock.wait(); - check(); -} -void ConnectionContext::waitUntil(qpid::sys::AbsTime until) -{ - lock.wait(until); - check(); -} -void ConnectionContext::wait(boost::shared_ptr ssn) -{ - wait(); - checkClosed(ssn); -} -void ConnectionContext::wait(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - wait(); - checkClosed(ssn, lnk); -} -void ConnectionContext::wait(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - wait(); - checkClosed(ssn, lnk); -} -void ConnectionContext::waitUntil(boost::shared_ptr ssn, qpid::sys::AbsTime until) -{ - waitUntil(until); - checkClosed(ssn); -} -void ConnectionContext::waitUntil(boost::shared_ptr ssn, boost::shared_ptr lnk, qpid::sys::AbsTime until) -{ - waitUntil(until); - checkClosed(ssn, lnk); -} -void ConnectionContext::waitUntil(boost::shared_ptr ssn, boost::shared_ptr lnk, qpid::sys::AbsTime until) -{ - waitUntil(until); - checkClosed(ssn, lnk); -} -void ConnectionContext::checkClosed(boost::shared_ptr ssn) -{ - check(); - ssn->error.raise(); - if ((pn_session_state(ssn->session) & REQUIRES_CLOSE) == REQUIRES_CLOSE) { - std::string text = get_error_string(pn_session_remote_condition(ssn->session), "Session ended by peer"); - pn_session_close(ssn->session); - throw qpid::messaging::SessionError(text); - } else if ((pn_session_state(ssn->session) & IS_CLOSED) == IS_CLOSED) { - throw qpid::messaging::SessionClosed(); - } -} - -bool ConnectionContext::isClosed(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - try { - checkClosed(ssn, lnk->receiver); - return false; - } catch (const LinkError&) { - return true; - } -} -void ConnectionContext::checkClosed(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - checkClosed(ssn, lnk->receiver); -} -void ConnectionContext::checkClosed(boost::shared_ptr ssn, boost::shared_ptr lnk) -{ - checkClosed(ssn, lnk->sender); -} -void ConnectionContext::checkClosed(boost::shared_ptr ssn, pn_link_t* lnk) -{ - checkClosed(ssn); - if ((pn_link_state(lnk) & REQUIRES_CLOSE) == REQUIRES_CLOSE) { - pn_condition_t* error = pn_link_remote_condition(lnk); - std::string text = get_error_string(error, "Link detached by peer"); - pn_link_close(lnk); - std::string name = pn_condition_get_name(error); - if (name == qpid::amqp::error_conditions::NOT_FOUND) { - throw qpid::messaging::NotFound(text); - } else if (name == qpid::amqp::error_conditions::UNAUTHORIZED_ACCESS) { - throw qpid::messaging::UnauthorizedAccess(text); - } else { - throw qpid::messaging::LinkError(text); - } - } else if ((pn_link_state(lnk) & IS_CLOSED) == IS_CLOSED) { - throw qpid::messaging::LinkError("Link is not attached"); - } -} - -void ConnectionContext::restartSession(boost::shared_ptr s) -{ - if (s->error) return; - 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); - if (i->second->capacity) { - attach(s, i->second->receiver, i->second->capacity); - } else { - attach(s, i->second->receiver, (uint32_t) i->second->fetching); - } - i->second->verify(); - QPID_LOG(debug, id << " receiver " << i->first << " reattached"); - } - wakeupDriver(); -} - -boost::shared_ptr ConnectionContext::newSession(bool transactional, const std::string& n) -{ - boost::shared_ptr session; - std::string name = n.empty() ? qpid::framing::Uuid(true).str() : n; - { - sys::Monitor::ScopedLock l(lock); - SessionMap::const_iterator i = sessions.find(name); - if (i == sessions.end()) { - session = boost::shared_ptr(new SessionContext(connection)); - session->setName(name); - pn_session_open(session->session); - wakeupDriver(); - sessions[name] = session; // Add it now so it will be restarted if we reconnect in wait() - while (pn_session_state(session->session) & PN_REMOTE_UNINIT) { - wait(); - } - } else { - throw qpid::messaging::KeyError(std::string("Session already exists: ") + name); - } - - } - if (transactional) { // Outside of lock - startTxSession(session); - } - return session; -} - -boost::shared_ptr ConnectionContext::getSession(const std::string& name) const -{ - SessionMap::const_iterator i = sessions.find(name); - if (i == sessions.end()) { - throw qpid::messaging::KeyError(std::string("No such session") + name); - } else { - return i->second; - } -} - -void ConnectionContext::setOption(const std::string& name, const qpid::types::Variant& value) -{ - set(name, value); -} - -std::string ConnectionContext::getAuthenticatedUsername() -{ - return sasl.get() ? sasl->getAuthenticatedUsername() : std::string(); -} - -std::size_t ConnectionContext::decodePlain(const char* buffer, std::size_t size) -{ - sys::Monitor::ScopedLock l(lock); - QPID_LOG(trace, id << " decode(" << size << ")"); - if (readHeader) { - size_t decoded = readProtocolHeader(buffer, size); - if (decoded < size) { - decoded += decode(buffer + decoded, size - decoded); - } - return decoded; - } - - //TODO: Fix pn_engine_input() to take const buffer - ssize_t n = pn_transport_input(engine, const_cast(buffer), size); - if (n > 0 || n == PN_EOS) { - // PN_EOS either means we received a Close (which also means we've - // consumed all the input), OR some Very Bad Thing happened and this - // connection is toast. - if (n == PN_EOS) - { - std::string error; - if (checkTransportError(error)) { - // "He's dead, Jim." - QPID_LOG_CAT(error, network, id << " connection failed: " << error); - transport->abort(); - return 0; - } else { - n = size; // assume all consumed - } - } - QPID_LOG_CAT(debug, network, id << " decoded " << n << " bytes from " << size) - // QPID-6698: don't use wallclock here, use monotonic clock - int64_t now = qpid::sys::Duration(qpid::sys::ZERO, qpid::sys::AbsTime::now()); - pn_transport_tick(engine, now / int64_t(qpid::sys::TIME_MSEC)); - lock.notifyAll(); - return n; - } else if (n == PN_ERR) { - std::string error; - checkTransportError(error); - QPID_LOG_CAT(error, network, id << " connection error: " << error); - transport->abort(); - return 0; - } else { - return 0; - } - -} -std::size_t ConnectionContext::encodePlain(char* buffer, std::size_t size) -{ - sys::Monitor::ScopedLock l(lock); - QPID_LOG(trace, id << " encode(" << size << ")"); - if (writeHeader) { - size_t encoded = writeProtocolHeader(buffer, size); - if (encoded < size) { - encoded += encode(buffer + encoded, size - encoded); - } - return encoded; - } - - ssize_t n = pn_transport_output(engine, buffer, size); - if (n > 0) { - QPID_LOG_CAT(debug, network, id << " encoded " << n << " bytes from " << size) - haveOutput = true; - if (notifyOnWrite) lock.notifyAll(); - if (ticker) ticker->restart(); - return n; - } else if (n == PN_ERR) { - std::string error; - checkTransportError(error); - QPID_LOG_CAT(error, network, id << " connection error: " << error); - transport->abort(); - return 0; - } else if (n == PN_EOS) { - haveOutput = false; - // Normal close, or error? - std::string error; - if (checkTransportError(error)) { - QPID_LOG_CAT(error, network, id << " connection failed: " << error); - transport->abort(); - } - return 0; - } else { - haveOutput = false; - return 0; - } -} -bool ConnectionContext::canEncodePlain() -{ - sys::Monitor::ScopedLock l(lock); - - // QPID-6698: don't use wallclock here, use monotonic clock - int64_t now = qpid::sys::Duration(qpid::sys::ZERO, qpid::sys::AbsTime::now()); - pn_transport_tick(engine, now / int64_t(qpid::sys::TIME_MSEC)); - return (haveOutput || pn_transport_pending(engine)) && state == CONNECTED; -} -void ConnectionContext::closed() -{ - sys::Monitor::ScopedLock l(lock); - state = DISCONNECTED; - lock.notifyAll(); -} -void ConnectionContext::opened() -{ - sys::Monitor::ScopedLock l(lock); - state = CONNECTED; - lock.notifyAll(); -} -bool ConnectionContext::isClosed() const -{ - return !isOpen(); -} -namespace { -qpid::framing::ProtocolVersion AMQP_1_0_PLAIN(1,0,qpid::framing::ProtocolVersion::AMQP); -} - -std::string ConnectionContext::getError() -{ - return get_error(connection, engine); -} - -framing::ProtocolVersion ConnectionContext::getVersion() const -{ - return AMQP_1_0_PLAIN; -} - -std::size_t ConnectionContext::readProtocolHeader(const char* buffer, std::size_t size) -{ - framing::ProtocolInitiation pi(getVersion()); - if (size >= pi.encodedSize()) { - readHeader = false; - qpid::framing::Buffer out(const_cast(buffer), size); - pi.decode(out); - QPID_LOG_CAT(debug, protocol, id << " read protocol header: " << pi); - return pi.encodedSize(); - } else { - return 0; - } -} -std::size_t ConnectionContext::writeProtocolHeader(char* buffer, std::size_t size) -{ - framing::ProtocolInitiation pi(getVersion()); - if (size >= pi.encodedSize()) { - QPID_LOG_CAT(debug, protocol, id << " writing protocol header: " << pi); - writeHeader = false; - qpid::framing::Buffer out(buffer, size); - pi.encode(out); - return pi.encodedSize(); - } else { - QPID_LOG_CAT(debug, protocol, id << " insufficient buffer for protocol header: " << size) - return 0; - } -} -bool ConnectionContext::useSasl() -{ - return !(mechanism == "none" || mechanism == "NONE" || mechanism == "None"); -} - -qpid::sys::Codec& ConnectionContext::getCodec() -{ - return *this; -} - -const qpid::messaging::ConnectionOptions* ConnectionContext::getOptions() -{ - return this; -} - -std::size_t ConnectionContext::decode(const char* buffer, std::size_t size) -{ - sys::Monitor::ScopedLock l(lock); - size_t decoded = 0; - try { - if (sasl.get() && !sasl->authenticated()) { - decoded = sasl->decode(buffer, size); - if (!sasl->authenticated()) return decoded; - } - if (decoded < size) { - if (sasl.get() && sasl->getSecurityLayer()) decoded += sasl->getSecurityLayer()->decode(buffer+decoded, size-decoded); - else decoded += decodePlain(buffer+decoded, size-decoded); - } - } catch (const AuthenticationFailure&) { - transport->close(); - } - return decoded; -} -std::size_t ConnectionContext::encode(char* buffer, std::size_t size) -{ - sys::Monitor::ScopedLock l(lock); - size_t encoded = 0; - try { - if (sasl.get() && sasl->canEncode()) { - encoded += sasl->encode(buffer, size); - if (!sasl->authenticated()) return encoded; - } - if (encoded < size) { - if (sasl.get() && sasl->getSecurityLayer()) encoded += sasl->getSecurityLayer()->encode(buffer+encoded, size-encoded); - else encoded += encodePlain(buffer+encoded, size-encoded); - } - } catch (const AuthenticationFailure&) { - transport->close(); - } - return encoded; -} -bool ConnectionContext::canEncode() -{ - sys::Monitor::ScopedLock l(lock); - if (sasl.get()) { - try { - if (sasl->canEncode()) return true; - else if (!sasl->authenticated()) return false; - else if (sasl->getSecurityLayer()) return sasl->getSecurityLayer()->canEncode(); - } catch (const AuthenticationFailure&) { - transport->close(); - return false; - } - } - return canEncodePlain(); -} - -namespace { -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); -} -void ConnectionContext::setProperties() -{ - PnData data(pn_connection_properties(connection)); - pn_data_put_map(data.data); - pn_data_enter(data.data); - data.putSymbol(CLIENT_PROCESS_NAME); - data.putSymbol(sys::SystemInfo::getProcessName()); - data.putSymbol(CLIENT_PID); - data.put(int32_t(sys::SystemInfo::getProcessId())); - data.putSymbol(CLIENT_PPID); - data.put(int32_t(sys::SystemInfo::getParentProcessId())); - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) - { - data.putSymbol(i->first); - data.put(i->second); - } - pn_data_exit(data.data); -} - -const qpid::sys::SecuritySettings* ConnectionContext::getTransportSecuritySettings() -{ - return transport ? transport->getSecuritySettings() : 0; -} - -void ConnectionContext::open() -{ - sys::Monitor::ScopedLock l(lock); - if (state != DISCONNECTED) throw qpid::messaging::ConnectionError("Connection was already opened!"); - if (!driver) driver = DriverImpl::getDefault(); - QPID_LOG(info, "Starting connection to " << fullUrl); - autoconnect(); -} - - -namespace { -double FOREVER(std::numeric_limits::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 throwConnectFail(const Url& url, const std::string& msg) { - throw qpid::messaging::TransportFailure( - Msg() << "Connect failed to " << url << ": " << msg); -} - -void ConnectionContext::autoconnect() -{ - qpid::sys::AbsTime started(qpid::sys::now()); - for (double i = minReconnectInterval; !tryConnectUrl(fullUrl); i = std::min(i*2, maxReconnectInterval)) { - if (!ConnectionOptions::reconnect) throwConnectFail(fullUrl, "Reconnect disabled"); - if (limit >= 0 && retries++ >= limit) throwConnectFail(fullUrl, "Exceeded retries"); - if (expired(started, timeout)) throwConnectFail(fullUrl, "Exceeded timeout"); - QPID_LOG(debug, "Connection retry in " << i*1000*1000 << " microseconds to" - << fullUrl); - qpid::sys::usleep(int64_t(i*1000*1000)); // Sleep in microseconds. - } - retries = 0; -} - -void ConnectionContext::reconnect(const Url& url) { - QPID_LOG(notice, "Reconnecting to " << url); - sys::Monitor::ScopedLock l(lock); - if (state != DISCONNECTED) throw qpid::messaging::ConnectionError("Connection was already opened!"); - if (!driver) driver = DriverImpl::getDefault(); - reset(); - if (!tryConnectUrl(url)) throwConnectFail(url, "Failed to reconnect"); - QPID_LOG(notice, "Reconnected to " << currentUrl); -} - -void ConnectionContext::reconnect(const std::string& url) { reconnect(Url(url)); } - -void ConnectionContext::reconnect() { reconnect(fullUrl); } - -void ConnectionContext::waitNoReconnect() { - if (!checkDisconnected()) { - lock.wait(); - checkDisconnected(); - } -} - -// Try to connect to a URL, i.e. try to connect to each of its addresses in turn -// till one succeeds or they all fail. -// @return true if we connect successfully -bool ConnectionContext::tryConnectUrl(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) { - QPID_LOG(info, "Connecting to " << *i); - if (tryConnectAddr(*i) && tryOpenAddr(*i)) { - QPID_LOG(info, "Connected to " << *i); - return true; - } - } - return false; -} - -// Try to open an AMQP protocol connection on an address, after we have already -// established a transport connect (see tryConnectAddr below) -// @return true if the AMQP connection is succesfully opened. -bool ConnectionContext::tryOpenAddr(const qpid::Address& addr) { - currentUrl = Url(addr); - if (sasl.get()) { - wakeupDriver(); - while (!sasl->authenticated() && state != DISCONNECTED) { - QPID_LOG(debug, id << " Waiting to be authenticated..."); - waitNoReconnect(); - } - if (state == DISCONNECTED) return false; - QPID_LOG(debug, id << " Authenticated"); - } - - QPID_LOG(debug, id << " Opening..."); - pn_connection_open(connection); - wakeupDriver(); //want to write - while ((pn_connection_state(connection) & PN_REMOTE_UNINIT) && - state != DISCONNECTED) - waitNoReconnect(); - if (state == DISCONNECTED) return false; - if (!(pn_connection_state(connection) & PN_REMOTE_ACTIVE)) { - throw qpid::messaging::ConnectionError("Failed to open connection"); - } - - // Connection open - check for idle timeout from the remote and start a - // periodic tick to monitor for idle connections - pn_timestamp_t remote = pn_transport_get_remote_idle_timeout(engine); - pn_timestamp_t local = pn_transport_get_idle_timeout(engine); - uint64_t shortest = ((remote && local) - ? std::min(remote, local) - : (remote) ? remote : local); - if (shortest) { - // send an idle frame at least twice before timeout - shortest = (shortest + 1)/2; - qpid::sys::Duration d(shortest * qpid::sys::TIME_MSEC); - ticker = boost::intrusive_ptr(new ConnectionTickerTask(d, driver->getTimer(), *this)); - driver->getTimer().add(ticker); - QPID_LOG(debug, id << " AMQP 1.0 idle-timeout set:" - << " local=" << pn_transport_get_idle_timeout(engine) - << " remote=" << pn_transport_get_remote_idle_timeout(engine)); - } - - QPID_LOG(debug, id << " Opened"); - - return restartSessions(); -} - -std::string ConnectionContext::getUrl() const -{ - sys::Monitor::ScopedLock l(lock); - return (state == CONNECTED) ? currentUrl.str() : std::string(); -} - -// Try to establish a transport connect to an individual address (typically a -// TCP host:port) -// @return true if we succeed in connecting. -bool ConnectionContext::tryConnectAddr(const qpid::Address& address) -{ - transport = driver->getTransport(address.protocol, *this); - id = boost::lexical_cast(address); - if (useSasl()) { - sasl = std::auto_ptr(new Sasl(id, *this, address.host)); - } - state = CONNECTING; - try { - QPID_LOG(debug, id << " Connecting ..."); - transport->connect(address.host, boost::lexical_cast(address.port)); - 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; - break; - } - } - } catch (const std::exception& e) { - QPID_LOG(info, id << " Error while connecting: " << e.what()); - state = DISCONNECTED; - } - transport = boost::shared_ptr(); - 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; - } -} - -void ConnectionContext::initSecurityLayer(qpid::sys::SecurityLayer& s) -{ - s.init(&codecAdapter); -} - -ConnectionContext::CodecAdapter::CodecAdapter(ConnectionContext& c) : context(c) {} -std::size_t ConnectionContext::CodecAdapter::decode(const char* buffer, std::size_t size) -{ - return context.decodePlain(buffer, size); -} -std::size_t ConnectionContext::CodecAdapter::encode(char* buffer, std::size_t size) -{ - return context.encodePlain(buffer, size); -} -bool ConnectionContext::CodecAdapter::canEncode() -{ - return context.canEncodePlain(); -} - -void ConnectionContext::startTxSession(boost::shared_ptr session) { - try { - QPID_LOG(debug, id << " attaching transaction for " << session->getName()); - boost::shared_ptr tx(new Transaction(session->session)); - session->transaction = tx; - { - sys::Monitor::ScopedLock l(lock); - attach(session, boost::shared_ptr(tx)); - } - tx->declare(boost::bind(&ConnectionContext::send, this, _1, _2, _3, _4, _5), session); - } catch (const Exception& e) { - throw TransactionError(Msg() << "Cannot start transaction: " << e.what()); - } -} - -void ConnectionContext::discharge(boost::shared_ptr session, bool fail) { - { - sys::Monitor::ScopedLock l(lock); - checkClosed(session); - if (!session->transaction) - throw TransactionError("No Transaction"); - Transaction::SendFunction sendFn = boost::bind( - &ConnectionContext::sendLH, this, _1, _2, _3, _4, _5, boost::ref(l)); - syncLH(session, boost::ref(l)); // Sync to make sure all tx transfers have been received. - session->transaction->discharge(sendFn, session, fail); - session->transaction->declare(sendFn, session); - } -} - -void ConnectionContext::commit(boost::shared_ptr session) { - discharge(session, false); -} - -void ConnectionContext::rollback(boost::shared_ptr session) { - discharge(session, true); -} - - -// setup the transport and connection objects: -void ConnectionContext::configureConnection() -{ - pn_connection_set_container(connection, identifier.c_str()); - setProperties(); - if (heartbeat) { - // fail an idle connection at 2 x heartbeat (in msecs) - pn_transport_set_idle_timeout(engine, heartbeat*2*1000); - } - - bool enableTrace(false); - QPID_LOG_TEST_CAT(trace, protocol, enableTrace); - if (enableTrace) { - pn_transport_trace(engine, PN_TRACE_FRM); - set_tracer(engine, this); - } - - int err = pn_transport_bind(engine, connection); - if (err) - QPID_LOG(error, id << " Error binding connection and transport: " << err); -} - - -// check for failures of the transport: -bool ConnectionContext::checkTransportError(std::string& text) -{ - std::stringstream info; - -#ifdef USE_PROTON_TRANSPORT_CONDITION - pn_condition_t* tcondition = pn_transport_condition(engine); - if (pn_condition_is_set(tcondition)) - info << get_error_string(tcondition, "transport error", ": "); -#else - pn_error_t* terror = pn_transport_error(engine); - if (terror) info << "transport error " << pn_error_text(terror) << " [" << terror << "]"; -#endif - - text = info.str(); - return !text.empty(); -} -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h deleted file mode 100644 index ba3220c0ab..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h +++ /dev/null @@ -1,233 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_CONNECTIONCONTEXT_H -#define QPID_MESSAGING_AMQP_CONNECTIONCONTEXT_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 -#include -#include -#include -#include -#include -#include "qpid/Url.h" -#include "qpid/messaging/ConnectionOptions.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/Monitor.h" -#include "qpid/types/Variant.h" -#include "qpid/messaging/amqp/TransportContext.h" -#include "SenderContext.h" - -struct pn_connection_t; -struct pn_link_t; -struct pn_session_t; -struct pn_transport_t; - - -namespace qpid { -namespace framing { -class ProtocolVersion; -} -namespace sys { -class SecurityLayer; -struct SecuritySettings; -class TimerTask; -} -namespace messaging { -class Duration; -class Message; -namespace amqp { - -class DriverImpl; -class ReceiverContext; -class Sasl; -class SessionContext; -class Transport; - -/** - * - */ -class ConnectionContext : public qpid::sys::ConnectionCodec, public qpid::messaging::ConnectionOptions, public TransportContext -{ - public: - ConnectionContext(const std::string& url, const qpid::types::Variant::Map& options); - ~ConnectionContext(); - void open(); - bool isOpen() const; - void close(); - boost::shared_ptr newSession(bool transactional, const std::string& name); - boost::shared_ptr getSession(const std::string& name) const; - void endSession(boost::shared_ptr); - boost::shared_ptr createSender(boost::shared_ptr, const qpid::messaging::Address& address); - boost::shared_ptr createReceiver(boost::shared_ptr, const qpid::messaging::Address& address); - boost::shared_ptr getSender(boost::shared_ptr, const std::string& name) const; - boost::shared_ptr getReceiver(boost::shared_ptr, const std::string& name) const; - - void detach(boost::shared_ptr, boost::shared_ptr); - void detach(boost::shared_ptr, boost::shared_ptr); - void drain_and_release_messages(boost::shared_ptr, boost::shared_ptr); - bool isClosed(boost::shared_ptr, boost::shared_ptr); - - // Link operations - void send(boost::shared_ptr, boost::shared_ptr ctxt, - const qpid::messaging::Message& message, bool sync, - SenderContext::Delivery** delivery); - - bool fetch(boost::shared_ptr ssn, boost::shared_ptr lnk, qpid::messaging::Message& message, qpid::messaging::Duration timeout); - bool get(boost::shared_ptr ssn, boost::shared_ptr lnk, qpid::messaging::Message& message, qpid::messaging::Duration timeout); - - // Session operations - void acknowledge(boost::shared_ptr ssn, qpid::messaging::Message* message, bool cumulative); - void commit(boost::shared_ptr ssn); - void rollback(boost::shared_ptr ssn); - - void nack(boost::shared_ptr ssn, qpid::messaging::Message& message, bool reject); - void sync(boost::shared_ptr ssn); - boost::shared_ptr nextReceiver(boost::shared_ptr ssn, qpid::messaging::Duration timeout); - - void setOption(const std::string& name, const qpid::types::Variant& value); - std::string getAuthenticatedUsername(); - - // Link operations - void setCapacity(boost::shared_ptr, uint32_t); - uint32_t getCapacity(boost::shared_ptr); - uint32_t getUnsettled(boost::shared_ptr); - void setCapacity(boost::shared_ptr, uint32_t); - uint32_t getCapacity(boost::shared_ptr); - uint32_t getAvailable(boost::shared_ptr); - uint32_t getUnsettled(boost::shared_ptr); - - - void activateOutput(); - qpid::sys::Codec& getCodec(); - const qpid::messaging::ConnectionOptions* getOptions(); - //ConnectionCodec interface: - std::size_t decode(const char* buffer, std::size_t size); - std::size_t encode(char* buffer, std::size_t size); - bool canEncode(); - void closed(); - bool isClosed() const; - 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(); - void initSecurityLayer(qpid::sys::SecurityLayer&); - void trace(const char*) const; - - private: - typedef std::map > SessionMap; - class CodecAdapter : public qpid::sys::Codec - { - public: - CodecAdapter(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& context; - }; - - Url fullUrl; // Combined URL of all known addresses. - Url currentUrl; // URL of currently connected address. - - boost::shared_ptr driver; - boost::shared_ptr transport; - - pn_transport_t* engine; - pn_connection_t* connection; - SessionMap sessions; - mutable qpid::sys::Monitor lock; - bool writeHeader; - bool readHeader; - bool haveOutput; - std::string id; - enum { - DISCONNECTED, - CONNECTING, - CONNECTED - } state; - std::auto_ptr sasl; - CodecAdapter codecAdapter; - bool notifyOnWrite; - boost::intrusive_ptr ticker; - - bool check(); - bool checkDisconnected(); - void waitNoReconnect(); - - // NOTE: All wait*() functions must be called in a loop that checks for the - // waited condition with the lock held. - void wait(); - void waitUntil(qpid::sys::AbsTime until); - void wait(boost::shared_ptr); - void waitUntil(boost::shared_ptr, qpid::sys::AbsTime until); - void wait(boost::shared_ptr, boost::shared_ptr); - void wait(boost::shared_ptr, boost::shared_ptr); - void waitUntil(boost::shared_ptr, boost::shared_ptr, qpid::sys::AbsTime until); - void waitUntil(boost::shared_ptr, boost::shared_ptr, qpid::sys::AbsTime until); - - void checkClosed(boost::shared_ptr); - void checkClosed(boost::shared_ptr, boost::shared_ptr); - void checkClosed(boost::shared_ptr, boost::shared_ptr); - void checkClosed(boost::shared_ptr, pn_link_t*); - - void wakeupDriver(); - void attach(boost::shared_ptr, pn_link_t*, int credit=0); - void attach(boost::shared_ptr, boost::shared_ptr); - void attach(boost::shared_ptr, boost::shared_ptr); - void autoconnect(); - bool tryConnectUrl(const qpid::Url& url); - bool tryOpenAddr(const qpid::Address& address); - bool tryConnectAddr(const qpid::Address& address); - void reconnect(const Url& url); - void reset(); - bool restartSessions(); - void restartSession(boost::shared_ptr); - - 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); - std::string getError(); - bool useSasl(); - void setProperties(); - - void configureConnection(); - bool checkTransportError(std::string&); - - void discharge(boost::shared_ptr, bool fail); - void startTxSession(boost::shared_ptr); - - void syncLH(boost::shared_ptr ssn, sys::Monitor::ScopedLock&); - void sendLH(boost::shared_ptr, boost::shared_ptr ctxt, - const qpid::messaging::Message& message, bool sync, - SenderContext::Delivery** delivery, sys::Monitor::ScopedLock&); - void acknowledgeLH(boost::shared_ptr ssn, qpid::messaging::Message* message, bool cumulative, sys::Monitor::ScopedLock&); -}; - -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_CONNECTIONCONTEXT_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp b/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp deleted file mode 100644 index e34e0a5874..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp +++ /dev/null @@ -1,108 +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 "ConnectionHandle.h" -#include "ConnectionContext.h" -#include "SessionHandle.h" -#include "DriverImpl.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/ProtocolRegistry.h" - -namespace qpid { -namespace messaging { -namespace amqp { -// Static constructor which registers this implementation in the ProtocolRegistry -namespace { -ConnectionImpl* create(const std::string& u, const qpid::types::Variant::Map& o) -{ - try { - return new ConnectionHandle(u, o); - } catch (const types::Exception& ) { - throw; - } catch (const qpid::Exception& e) { - throw messaging::ConnectionError( e.what() ); - } -} - -void shutdown() { - DriverImpl::getDefault()->stop(); -} - -struct StaticInit -{ - StaticInit() - { - ProtocolRegistry::add("amqp1.0", &create, &shutdown); - }; -} init; -} - -ConnectionHandle::ConnectionHandle(const std::string& url, const qpid::types::Variant::Map& options) : connection(new ConnectionContext(url, options)) {} -ConnectionHandle::ConnectionHandle(boost::shared_ptr c) : connection(c) {} - -void ConnectionHandle::open() -{ - connection->open(); -} - -bool ConnectionHandle::isOpen() const -{ - return connection->isOpen(); -} - -void ConnectionHandle::close() -{ - connection->close(); -} - -Session ConnectionHandle::newSession(bool transactional, const std::string& name) -{ - return qpid::messaging::Session(new SessionHandle(connection, connection->newSession(transactional, name))); -} - -Session ConnectionHandle::getSession(const std::string& name) const -{ - return qpid::messaging::Session(new SessionHandle(connection, connection->getSession(name))); -} - -void ConnectionHandle::setOption(const std::string& name, const qpid::types::Variant& value) -{ - connection->setOption(name, value); -} - -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 deleted file mode 100644 index 0238313f93..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_CONNECTIONHANDLE_H -#define QPID_MESSAGING_AMQP_CONNECTIONHANDLE_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 -#include "qpid/messaging/ConnectionImpl.h" -#include "qpid/types/Variant.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -class ConnectionContext; -/** - * Handles are directly referenced by applications; Contexts are - * referenced by Handles. This allows a graph structure that - * remains intact as long as the application references any part - * of it, but that can be automatically reclaimed if the whole - * graph becomes unreferenced. - */ -class ConnectionHandle : public qpid::messaging::ConnectionImpl -{ - public: - ConnectionHandle(const std::string& url, const qpid::types::Variant::Map& options); - ConnectionHandle(boost::shared_ptr); - void open(); - bool isOpen() const; - void close(); - Session newSession(bool transactional, const std::string& name); - 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 connection; -}; - -}}} // namespace qpid::messaging::amqp_1.0 - -#endif /*!QPID_MESSAGING_AMQP_CONNECTIONHANDLE_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/DriverImpl.cpp b/qpid/cpp/src/qpid/messaging/amqp/DriverImpl.cpp deleted file mode 100644 index 67b2ae2f6f..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/DriverImpl.cpp +++ /dev/null @@ -1,78 +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 "DriverImpl.h" -#include "Transport.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Timer.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -DriverImpl::DriverImpl() : poller(new qpid::sys::Poller), timer(new qpid::sys::Timer) -{ - start(); -} -DriverImpl::~DriverImpl() -{ - stop(); -} - -void DriverImpl::start() -{ - thread = qpid::sys::Thread(*poller); - QPID_LOG(debug, "Driver started"); -} - -void DriverImpl::stop() -{ - QPID_LOG(debug, "Driver stopped"); - if (!poller->hasShutdown()) { - poller->shutdown(); - thread.join(); - timer->stop(); - } -} - -boost::shared_ptr DriverImpl::getTransport(const std::string& protocol, TransportContext& connection) -{ - boost::shared_ptr t(Transport::create(protocol, connection, poller)); - if (!t) throw qpid::messaging::ConnectionError("No such transport: " + protocol); - return t; -} - - -qpid::sys::Mutex DriverImpl::defaultLock; -boost::weak_ptr DriverImpl::theDefault; -boost::shared_ptr DriverImpl::getDefault() -{ - qpid::sys::Mutex::ScopedLock l(defaultLock); - boost::shared_ptr p = theDefault.lock(); - if (!p) { - p = boost::shared_ptr(new DriverImpl); - theDefault = p; - } - return p; -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/DriverImpl.h b/qpid/cpp/src/qpid/messaging/amqp/DriverImpl.h deleted file mode 100644 index 36cb196343..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/DriverImpl.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_DRIVERIMPL_H -#define QPID_MESSAGING_AMQP_DRIVERIMPL_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/Thread.h" -#include -#include - -namespace qpid { -namespace sys { -class Poller; -class Timer; -} -namespace messaging { -namespace amqp { -class TransportContext; -class Transport; -/** - * - */ -class DriverImpl -{ - public: - DriverImpl(); - ~DriverImpl(); - - void start(); - void stop(); - - boost::shared_ptr getTransport(const std::string& protocol, TransportContext& connection); - sys::Timer& getTimer() { return *timer; } - - static boost::shared_ptr getDefault(); - private: - boost::shared_ptr poller; - qpid::sys::Thread thread; - std::auto_ptr timer; - - static qpid::sys::Mutex defaultLock; - static boost::weak_ptr theDefault; -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_DRIVERIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp b/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp deleted file mode 100644 index cf60046245..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp +++ /dev/null @@ -1,366 +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/messaging/amqp/EncodedMessage.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/Exception.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 -#include - -namespace qpid { -namespace messaging { -namespace amqp { -using namespace qpid::amqp; - -EncodedMessage::EncodedMessage(size_t s) : size(s), data(size ? new char[size] : 0), nestAnnotations(false) -{ - init(); -} - -EncodedMessage::EncodedMessage() : size(0), data(0), nestAnnotations(false) -{ - init(); -} - -EncodedMessage::EncodedMessage(const EncodedMessage& other) : size(other.size), data(size ? new char[size] : 0), nestAnnotations(false) -{ - init(); -} - -void EncodedMessage::init() -{ - //init all CharSequence members - deliveryAnnotations.init(); - messageAnnotations.init(); - userId.init(); - to.init(); - subject.init(); - replyTo.init(); - contentType.init(); - contentEncoding.init(); - groupId.init(); - replyToGroupId.init(); - applicationProperties.init(); - body.init(); - footer.init(); -} - -EncodedMessage::~EncodedMessage() -{ - delete[] data; -} - -size_t EncodedMessage::getSize() const -{ - return size; -} -void EncodedMessage::trim(size_t t) -{ - size = t; -} -void EncodedMessage::resize(size_t s) -{ - delete[] data; - size = s; - data = new char[size]; -} - -char* EncodedMessage::getData() -{ - return data; -} -const char* EncodedMessage::getData() const -{ - return data; -} - -void EncodedMessage::init(qpid::messaging::MessageImpl& impl) -{ - try { - //initial scan of raw data - qpid::amqp::Decoder decoder(data, size); - InitialScan reader(*this, impl); - decoder.read(reader); - bareMessage = reader.getBareMessage(); - if (bareMessage.data && !bareMessage.size) { - bareMessage.size = (data + size) - bareMessage.data; - } - } catch (const qpid::Exception& e) { - throw FetchError(e.what()); - } -} -void EncodedMessage::setNestAnnotationsOption(bool b) { nestAnnotations = b; } - -namespace { -using qpid::types::Variant; -void merge(qpid::types::Variant::Map& map, const qpid::types::Variant::Map& additions) -{ - for (Variant::Map::const_iterator i = additions.begin(); i != additions.end(); ++i) - { - if (map.find(i->first) == map.end()) { - map[i->first] = i->second; - } else { - QPID_LOG(info, "Annotation " << i->first << " hidden by application property of the same name (consider using nest_annotations option?)"); - } - } -} -} - -void EncodedMessage::populate(qpid::types::Variant::Map& map) const -{ - try { - //decode application properties - if (applicationProperties) { - qpid::amqp::Decoder decoder(applicationProperties.data, applicationProperties.size); - decoder.readMap(map); - } - //add in 'x-amqp-' prefixed values - if (!!firstAcquirer) { - map["x-amqp-first-acquirer"] = firstAcquirer.get(); - } - if (!!deliveryCount) { - map["x-amqp-delivery-count"] = deliveryCount.get(); - } - if (to) { - map["x-amqp-to"] = to.str(); - } - if (contentEncoding) { - map["x-amqp-content-encoding"] = contentEncoding.str(); - } - if (!!absoluteExpiryTime) { - map["x-amqp-absolute-expiry-time"] = absoluteExpiryTime.get(); - } - if (!!creationTime) { - map["x-amqp-creation-time"] = creationTime.get(); - } - if (groupId) { - map["x-amqp-group-id"] = groupId.str(); - } - if (!!groupSequence) { - map["x-amqp-group-sequence"] = groupSequence.get(); - } - if (replyToGroupId) { - map["x-amqp-reply-to-group-id"] = replyToGroupId.str(); - } - //add in any annotations - if (deliveryAnnotations) { - qpid::amqp::Decoder decoder(deliveryAnnotations.data, deliveryAnnotations.size); - if (nestAnnotations) { - map["x-amqp-delivery-annotations"] = decoder.readMap(); - } else { - merge(map, decoder.readMap()); - } - } - if (messageAnnotations) { - qpid::amqp::Decoder decoder(messageAnnotations.data, messageAnnotations.size); - if (nestAnnotations) { - map["x-amqp-message-annotations"] = decoder.readMap(); - } else { - merge(map, decoder.readMap()); - } - } - } catch (const qpid::Exception& e) { - throw FetchError(e.what()); - } -} -qpid::amqp::CharSequence EncodedMessage::getBareMessage() const -{ - return bareMessage; -} - -void EncodedMessage::getReplyTo(qpid::messaging::Address& a) const -{ - std::string rt = replyTo.str(); - std::string::size_type i = rt.find('/'); - if (i != std::string::npos && i > 0 && rt.find('/', i+1) == std::string::npos) { - //handle / special case - a.setName(rt.substr(0, i)); - a.setSubject(rt.substr(i+1)); - } else { - a.setName(rt); - } -} -void EncodedMessage::getSubject(std::string& s) const -{ - s.assign(subject.data, subject.size); -} -void EncodedMessage::getContentType(std::string& s) const -{ - s.assign(contentType.data, contentType.size); -} -void EncodedMessage::getUserId(std::string& s) const -{ - s.assign(userId.data, userId.size); -} -void EncodedMessage::getMessageId(std::string& s) const -{ - messageId.assign(s); -} -void EncodedMessage::getCorrelationId(std::string& s) const -{ - correlationId.assign(s); -} -void EncodedMessage::getBody(std::string& raw, qpid::types::Variant& c) const -{ - try { - 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::types::Variant v = qpid::types::Variant::Map(); - qpid::amqp::DataBuilder builder(v); - 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); - } - } - } catch (const qpid::Exception& e) { - throw FetchError(e.what()); - } -} - -qpid::amqp::CharSequence EncodedMessage::getBody() const -{ - return body; -} - -bool EncodedMessage::hasHeaderChanged(const qpid::messaging::MessageImpl& msg) const -{ - if (!durable) { - if (msg.isDurable()) return true; - } else { - if (durable.get() != msg.isDurable()) return true; - } - - if (!priority) { - if (msg.getPriority() != 4) return true; - } else { - if (priority.get() != msg.getPriority()) return true; - } - - if (msg.getTtl() && (!ttl || msg.getTtl() != ttl.get())) { - return true; - } - - //first-acquirer can't be changed via Message interface as yet - - if (msg.isRedelivered() && (!deliveryCount || deliveryCount.get() == 0)) { - return true; - } - - return false; -} - - - -EncodedMessage::InitialScan::InitialScan(EncodedMessage& e, qpid::messaging::MessageImpl& m) : em(e), mi(m) -{ - //set up defaults as needed: - mi.setPriority(4); -} -//header: -void EncodedMessage::InitialScan::onDurable(bool b) { mi.setDurable(b); em.durable = b; } -void EncodedMessage::InitialScan::onPriority(uint8_t i) { mi.setPriority(i); em.priority = i; } -void EncodedMessage::InitialScan::onTtl(uint32_t i) { mi.setTtl(i); em.ttl = i; } -void EncodedMessage::InitialScan::onFirstAcquirer(bool b) { em.firstAcquirer = b; } -void EncodedMessage::InitialScan::onDeliveryCount(uint32_t i) -{ - mi.setRedelivered(i); - em.deliveryCount = i; -} - -//properties: -void EncodedMessage::InitialScan::onMessageId(uint64_t v) { em.messageId.set(v); } -void EncodedMessage::InitialScan::onMessageId(const qpid::amqp::CharSequence& v, qpid::types::VariantType t) { em.messageId.set(v, t); } -void EncodedMessage::InitialScan::onUserId(const qpid::amqp::CharSequence& v) { em.userId = v; } -void EncodedMessage::InitialScan::onTo(const qpid::amqp::CharSequence& v) { em.to = v; } -void EncodedMessage::InitialScan::onSubject(const qpid::amqp::CharSequence& v) { em.subject = v; } -void EncodedMessage::InitialScan::onReplyTo(const qpid::amqp::CharSequence& v) { em.replyTo = v;} -void EncodedMessage::InitialScan::onCorrelationId(uint64_t v) { em.correlationId.set(v); } -void EncodedMessage::InitialScan::onCorrelationId(const qpid::amqp::CharSequence& v, qpid::types::VariantType t) { em.correlationId.set(v, t); } -void EncodedMessage::InitialScan::onContentType(const qpid::amqp::CharSequence& v) { em.contentType = v; } -void EncodedMessage::InitialScan::onContentEncoding(const qpid::amqp::CharSequence& v) { em.contentEncoding = v; } -void EncodedMessage::InitialScan::onAbsoluteExpiryTime(int64_t i) { em.absoluteExpiryTime = i; } -void EncodedMessage::InitialScan::onCreationTime(int64_t i) { em.creationTime = i; } -void EncodedMessage::InitialScan::onGroupId(const qpid::amqp::CharSequence& v) { em.groupId = 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, 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) -{ - em.body = v; - em.bodyType = qpid::amqp::typecodes::LIST_NAME; -} -void EncodedMessage::InitialScan::onAmqpValue(const qpid::amqp::CharSequence& v, const std::string& type, const qpid::amqp::Descriptor*) -{ - 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, const qpid::amqp::Descriptor*) -{ - 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 deleted file mode 100644 index 241118386c..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.h +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_ENCODEDMESSAGE_H -#define QPID_MESSAGING_AMQP_ENCODEDMESSAGE_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/messaging/ImportExport.h" - -#include "qpid/amqp/CharSequence.h" -#include "qpid/amqp/MessageId.h" -#include "qpid/amqp/MessageReader.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/types/Variant.h" -#include - -namespace qpid { -namespace amqp { -struct Descriptor; -} -namespace messaging { -class Address; -class MessageImpl; -namespace amqp { - -/** - * Used to 'lazy-decode' an AMQP 1.0 message. - * - * There are four categories of data item: - * - * (i) simple, fixed width primitives - priority, ttl, durability, - * delivery count - for which lazy-decoding doesn't buy much. These - * are decoded unconditionally on an initial scan of the message. - * - * (ii) standard variable length string properties - subject, - * message-id, user-id etc - which require conversion to a std::string - * for returning to the application. By delaying the conversion of - * these to a std::string we can avoid allocation & copying until it - * is actually required. The initial scan of the message merely - * records the position of these strings within the raw message data. - * - * (iii) custom, application defined headers. These form a map, and - * again, delaying the creation of that map until it is actually - * required can be advantageous. The initial scan of the message merely - * records the position of this section within the raw message data. - * - * (iv) the body content. This may be retreived as a std::string, or - * as a char*. Avoiding conversion to the string until it is required - * is advantageous. The initial scan of the message merely records the - * position of this section within the raw message data. - * - * At present the Message class only explicitly exposes some of the - * standard property and headers defined by AMQP 1.0. The remainder - * will have to be accessed through the message 'headers' map, using - * the 'x-amqp-' prefix. - */ -class EncodedMessage -{ - public: - QPID_MESSAGING_EXTERN EncodedMessage(); - QPID_MESSAGING_EXTERN EncodedMessage(size_t); - QPID_MESSAGING_EXTERN EncodedMessage(const EncodedMessage&); - QPID_MESSAGING_EXTERN ~EncodedMessage(); - - - 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 populate(qpid::types::Variant::Map&) 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; - QPID_MESSAGING_EXTERN bool hasHeaderChanged(const qpid::messaging::MessageImpl&) const; - private: - size_t size; - char* data; - bool nestAnnotations; - - class InitialScan : public qpid::amqp::MessageReader - { - public: - InitialScan(EncodedMessage& e, qpid::messaging::MessageImpl& m); - //header: - void onDurable(bool b); - void onPriority(uint8_t i); - void onTtl(uint32_t i); - void onFirstAcquirer(bool b); - void onDeliveryCount(uint32_t i); - //properties: - void onMessageId(uint64_t); - void onMessageId(const qpid::amqp::CharSequence&, qpid::types::VariantType); - void onUserId(const qpid::amqp::CharSequence& v); - void onTo(const qpid::amqp::CharSequence& v); - void onSubject(const qpid::amqp::CharSequence& v); - void onReplyTo(const qpid::amqp::CharSequence& v); - void onCorrelationId(uint64_t); - void onCorrelationId(const qpid::amqp::CharSequence&, qpid::types::VariantType); - void onContentType(const qpid::amqp::CharSequence& v); - void onContentEncoding(const qpid::amqp::CharSequence& v); - void onAbsoluteExpiryTime(int64_t i); - void onCreationTime(int64_t); - void onGroupId(const qpid::amqp::CharSequence&); - void onGroupSequence(uint32_t); - void onReplyToGroupId(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, const qpid::amqp::Descriptor*); - void onAmqpValue(const qpid::types::Variant&, const qpid::amqp::Descriptor*); - - void onFooter(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&); - private: - EncodedMessage& em; - qpid::messaging::MessageImpl& mi; - }; - //header: - boost::optional durable; - boost::optional priority; - boost::optional ttl; - boost::optional firstAcquirer; - boost::optional deliveryCount; - //annotations: - qpid::amqp::CharSequence deliveryAnnotations; - qpid::amqp::CharSequence messageAnnotations; - - qpid::amqp::CharSequence bareMessage;//properties, application-properties and content - //properties: - qpid::amqp::MessageId messageId; - qpid::amqp::CharSequence userId; - qpid::amqp::CharSequence to; - qpid::amqp::CharSequence subject; - qpid::amqp::CharSequence replyTo; - qpid::amqp::MessageId correlationId; - qpid::amqp::CharSequence contentType; - qpid::amqp::CharSequence contentEncoding; - boost::optional absoluteExpiryTime; - boost::optional creationTime; - qpid::amqp::CharSequence groupId; - boost::optional groupSequence; - 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; - - void init(); - //not implemented: - EncodedMessage& operator=(const EncodedMessage&); -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_ENCODEDMESSAGE_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/PnData.cpp b/qpid/cpp/src/qpid/messaging/amqp/PnData.cpp deleted file mode 100644 index 3309d1a683..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/PnData.cpp +++ /dev/null @@ -1,246 +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 "PnData.h" -#include "qpid/types/encodings.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -using types::Variant; -using namespace types::encodings; - -// TODO aconway 2014-11-20: PnData duplicates functionality of qpid::amqp::Encoder,Decoder. -// Collapse them all into a single proton-based codec. - -void PnData::put(const Variant::Map& map) -{ - pn_data_put_map(data); - pn_data_enter(data); - for (Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) { - pn_data_put_string(data, bytes(i->first)); - put(i->second); - } - pn_data_exit(data); -} - -void PnData::put(const Variant::List& list) -{ - pn_data_put_list(data); - pn_data_enter(data); - for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { - put(*i); - } - pn_data_exit(data); -} - -void PnData::put(const Variant& value) -{ - // Open data descriptors associated with the value. - const Variant::List& descriptors = value.getDescriptors(); - for (Variant::List::const_iterator i = descriptors.begin(); i != descriptors.end(); ++i) { - pn_data_put_described(data); - pn_data_enter(data); - if (i->getType() == types::VAR_STRING) - pn_data_put_symbol(data, bytes(i->asString())); - else - pn_data_put_ulong(data, i->asUint64()); - } - - // Put the variant value - switch (value.getType()) { - case qpid::types::VAR_VOID: - pn_data_put_null(data); - break; - case qpid::types::VAR_BOOL: - pn_data_put_bool(data, value.asBool()); - break; - case qpid::types::VAR_UINT64: - pn_data_put_ulong(data, value.asUint64()); - break; - case qpid::types::VAR_INT64: - pn_data_put_long(data, value.asInt64()); - break; - case qpid::types::VAR_DOUBLE: - pn_data_put_double(data, value.asDouble()); - break; - case qpid::types::VAR_STRING: - if (value.getEncoding() == ASCII) - pn_data_put_symbol(data, bytes(value.asString())); - else if (value.getEncoding() == BINARY) - pn_data_put_binary(data, bytes(value.asString())); - else - pn_data_put_string(data, bytes(value.asString())); - break; - case qpid::types::VAR_MAP: - put(value.asMap()); - break; - case qpid::types::VAR_LIST: - put(value.asList()); - break; - default: - break; - } - - // Close any descriptors. - for (Variant::List::const_iterator i = descriptors.begin(); i != descriptors.end(); ++i) - pn_data_exit(data); -} - -bool PnData::get(qpid::types::Variant& value) -{ - return get(pn_data_type(data), value); -} - -void PnData::getList(qpid::types::Variant::List& value) -{ - size_t count = pn_data_get_list(data); - pn_data_enter(data); - for (size_t i = 0; i < count && pn_data_next(data); ++i) { - qpid::types::Variant e; - if (get(e)) value.push_back(e); - } - pn_data_exit(data); -} - -void PnData::getMap(qpid::types::Variant::Map& value) -{ - size_t count = pn_data_get_list(data); - pn_data_enter(data); - for (size_t i = 0; i < (count/2) && pn_data_next(data); ++i) { - std::string key = string(pn_data_get_symbol(data)); - pn_data_next(data); - qpid::types::Variant e; - if (get(e)) value[key]= e; - } - pn_data_exit(data); -} - -void PnData::getArray(qpid::types::Variant::List& value) -{ - size_t count = pn_data_get_array(data); - pn_type_t type = pn_data_get_array_type(data); - pn_data_enter(data); - for (size_t i = 0; i < count && pn_data_next(data); ++i) { - qpid::types::Variant e; - if (get(type, e)) value.push_back(e); - } - pn_data_exit(data); -} - -bool PnData::get(pn_type_t type, qpid::types::Variant& value) -{ - switch (type) { - case PN_NULL: - if (value.getType() != qpid::types::VAR_VOID) value = qpid::types::Variant(); - return true; - case PN_BOOL: - value = pn_data_get_bool(data); - return true; - case PN_UBYTE: - value = pn_data_get_ubyte(data); - return true; - case PN_BYTE: - value = pn_data_get_byte(data); - return true; - case PN_USHORT: - value = pn_data_get_ushort(data); - return true; - case PN_SHORT: - value = pn_data_get_short(data); - return true; - case PN_UINT: - value = pn_data_get_uint(data); - return true; - case PN_INT: - value = pn_data_get_int(data); - return true; - case PN_CHAR: - value = pn_data_get_char(data); - return true; - case PN_ULONG: - value = pn_data_get_ulong(data); - return true; - case PN_LONG: - value = pn_data_get_long(data); - return true; - case PN_TIMESTAMP: - value = pn_data_get_timestamp(data); - return true; - case PN_FLOAT: - value = pn_data_get_float(data); - return true; - case PN_DOUBLE: - value = pn_data_get_double(data); - return true; - case PN_UUID: - value = qpid::types::Uuid(pn_data_get_uuid(data).bytes); - return true; - case PN_BINARY: - value = string(pn_data_get_binary(data)); - value.setEncoding(qpid::types::encodings::BINARY); - return true; - case PN_STRING: - value = string(pn_data_get_string(data)); - value.setEncoding(qpid::types::encodings::UTF8); - return true; - case PN_SYMBOL: - value = string(pn_data_get_string(data)); - value.setEncoding(qpid::types::encodings::ASCII); - return true; - case PN_LIST: - value = qpid::types::Variant::List(); - getList(value.asList()); - return true; - break; - case PN_MAP: - value = qpid::types::Variant::Map(); - getMap(value.asMap()); - return true; - case PN_ARRAY: - value = qpid::types::Variant::List(); - getArray(value.asList()); - return true; - case PN_DESCRIBED: - // TODO aconway 2014-11-20: get described values. - case PN_DECIMAL32: - case PN_DECIMAL64: - case PN_DECIMAL128: - default: - return false; - } -} - -pn_bytes_t PnData::bytes(const std::string& s) -{ - pn_bytes_t result; - result.start = const_cast(s.data()); - result.size = s.size(); - return result; -} - -std::string PnData::string(const pn_bytes_t& in) -{ - return std::string(in.start, in.size); -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/PnData.h b/qpid/cpp/src/qpid/messaging/amqp/PnData.h deleted file mode 100644 index b0119f88fd..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/PnData.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_PNDATA_H -#define QPID_MESSAGING_AMQP_PNDATA_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/types/Variant.h" -extern "C" { -#include -} - -namespace qpid { -namespace messaging { -namespace amqp { - -/** - * Helper class to put/get messaging types to/from pn_data_t. - */ -class PnData -{ - public: - pn_data_t* data; - - PnData(pn_data_t* d) : data(d) {} - - void put(const types::Variant& value); - void put(const types::Variant::Map& map); - void put(const types::Variant::List& list); - void put(int32_t n) { pn_data_put_int(data, n); } - void putSymbol(const std::string& symbol) { pn_data_put_symbol(data, bytes(symbol)); } - - bool get(pn_type_t type, types::Variant& value); - bool get(types::Variant& value); - void getList(types::Variant::List& value); - void getMap(types::Variant::Map& value); - void getArray(types::Variant::List& value); - - static pn_bytes_t bytes(const std::string&); - static std::string string(const pn_bytes_t&); -}; -}}} // namespace messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_PNDATA_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp deleted file mode 100644 index 427a6336e9..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp +++ /dev/null @@ -1,140 +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/messaging/amqp/ReceiverContext.h" -#include "qpid/messaging/AddressImpl.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/Message.h" -#include "qpid/log/Statement.h" -extern "C" { -#include -} - -namespace qpid { -namespace messaging { -namespace amqp { -//TODO: proper conversion to wide string for address -ReceiverContext::ReceiverContext(pn_session_t* session, const std::string& n, const qpid::messaging::Address& a) - : name(n), - address(a), - helper(address), - receiver(pn_receiver(session, name.c_str())), - capacity(0), used(0) {} - -ReceiverContext::~ReceiverContext() -{ - if (receiver) pn_link_free(receiver); -} - -void ReceiverContext::setCapacity(uint32_t c) -{ - if (c != capacity) { - //stop - capacity = c; - //reissue credit - } -} - -uint32_t ReceiverContext::getCapacity() -{ - return capacity; -} - -uint32_t ReceiverContext::getAvailable() -{ - return pn_link_queued(receiver); -} - -uint32_t ReceiverContext::getUnsettled() -{ - assert(pn_link_unsettled(receiver) >= pn_link_queued(receiver)); - return pn_link_unsettled(receiver) - pn_link_queued(receiver); -} - -void ReceiverContext::close() -{ - if (receiver) pn_link_close(receiver); -} - -const std::string& ReceiverContext::getName() const -{ - return name; -} - -const std::string& ReceiverContext::getSource() const -{ - return address.getName(); -} -void ReceiverContext::verify() -{ - pn_terminus_t* source = pn_link_remote_source(receiver); - if (!helper.isNameNull() && !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() -{ - if (receiver) configure(pn_link_source(receiver)); -} -void ReceiverContext::configure(pn_terminus_t* source) -{ - 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 -{ - return address; -} - -void ReceiverContext::reset(pn_session_t* session) -{ - receiver = session ? pn_receiver(session, name.c_str()) : 0; - if (receiver) configure(); -} - -bool ReceiverContext::hasCurrent() -{ - return receiver && pn_link_current(receiver); -} - -bool ReceiverContext::wakeupToIssueCredit() -{ - if (++used >= (capacity/2)) { - used = 0; - return true; - } else { - return false; - } -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h deleted file mode 100644 index dd1352aecb..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_RECEIVERCONTEXT_H -#define QPID_MESSAGING_AMQP_RECEIVERCONTEXT_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/messaging/Address.h" -#include "qpid/messaging/amqp/AddressHelper.h" -#include -#include "qpid/sys/AtomicCount.h" -#include "qpid/sys/IntegerTypes.h" - -struct pn_link_t; -struct pn_session_t; -struct pn_terminus_t; - -namespace qpid { -namespace messaging { - -class Duration; -class Message; - -namespace amqp { - -/** - * - */ -class ReceiverContext -{ - public: - ReceiverContext(pn_session_t* session, const std::string& name, const qpid::messaging::Address& source); - virtual ~ReceiverContext(); - void reset(pn_session_t* session); - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getAvailable(); - uint32_t getUnsettled(); - void attach(); - void close(); - const std::string& getName() const; - const std::string& getSource() const; - void configure(); - void verify(); - Address getAddress() const; - bool hasCurrent(); - private: - friend class ConnectionContext; - const std::string name; - Address address; - AddressHelper helper; - pn_link_t* receiver; - uint32_t capacity; - uint32_t used; - qpid::sys::AtomicCount fetching; - void configure(pn_terminus_t*); - bool wakeupToIssueCredit(); -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_RECEIVERCONTEXT_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp b/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp deleted file mode 100644 index bd7082079c..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp +++ /dev/null @@ -1,111 +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 "ReceiverHandle.h" -#include "ConnectionContext.h" -#include "SessionContext.h" -#include "SessionHandle.h" -#include "ReceiverContext.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Session.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -ReceiverHandle::ReceiverHandle(boost::shared_ptr c, - boost::shared_ptr s, - boost::shared_ptr r -) : connection(c), session(s), receiver(r) {} - - -bool ReceiverHandle::get(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - return connection->get(session, receiver, message, timeout); -} - -qpid::messaging::Message ReceiverHandle::get(qpid::messaging::Duration timeout) -{ - qpid::messaging::Message result; - if (!get(result, timeout)) throw qpid::messaging::NoMessageAvailable(); - return result; -} - -bool ReceiverHandle::fetch(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - return connection->fetch(session, receiver, message, timeout); -} - -qpid::messaging::Message ReceiverHandle::fetch(qpid::messaging::Duration timeout) -{ - qpid::messaging::Message result; - if (!fetch(result, timeout)) throw qpid::messaging::NoMessageAvailable(); - return result; -} - -void ReceiverHandle::setCapacity(uint32_t capacity) -{ - connection->setCapacity(receiver, capacity); -} - -uint32_t ReceiverHandle::getCapacity() -{ - return connection->getCapacity(receiver); -} - -uint32_t ReceiverHandle::getAvailable() -{ - return connection->getAvailable(receiver); -} - -uint32_t ReceiverHandle::getUnsettled() -{ - return connection->getUnsettled(receiver); -} - -void ReceiverHandle::close() -{ - connection->detach(session, receiver); -} - -const std::string& ReceiverHandle::getName() const -{ - return receiver->getName(); -} - -qpid::messaging::Session ReceiverHandle::getSession() const -{ - //create new SessionHandle instance; i.e. create new handle that shares the same context - return qpid::messaging::Session(new SessionHandle(connection, session)); -} - -bool ReceiverHandle::isClosed() const -{ - return connection->isClosed(session, receiver); -} - -Address ReceiverHandle::getAddress() const -{ - return receiver->getAddress(); -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.h b/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.h deleted file mode 100644 index 08a95fb585..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_RECEIVERHANDLE_H -#define QPID_MESSAGING_AMQP_RECEIVERHANDLE_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 -#include "qpid/messaging/ReceiverImpl.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -class ConnectionContext; -class SessionContext; -class ReceiverContext; -/** - * - */ -class ReceiverHandle : public qpid::messaging::ReceiverImpl -{ - public: - ReceiverHandle(boost::shared_ptr, - boost::shared_ptr, - boost::shared_ptr - ); - bool get(Message& message, qpid::messaging::Duration timeout); - qpid::messaging::Message get(qpid::messaging::Duration timeout); - bool fetch(Message& message, qpid::messaging::Duration timeout); - qpid::messaging::Message fetch(qpid::messaging::Duration timeout); - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getAvailable(); - uint32_t getUnsettled(); - void close(); - const std::string& getName() const; - qpid::messaging::Session getSession() const; - bool isClosed() const; - Address getAddress() const; - private: - boost::shared_ptr connection; - boost::shared_ptr session; - boost::shared_ptr receiver; -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_RECEIVERHANDLE_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp b/qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp deleted file mode 100644 index e1c15c2c22..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp +++ /dev/null @@ -1,186 +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 "ConnectionContext.h" -#include "qpid/messaging/amqp/Sasl.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/log/Statement.h" -#include "qpid/Sasl.h" -#include "qpid/SaslFactory.h" -#include "qpid/StringUtils.h" -#include - -namespace qpid { -namespace messaging { -namespace amqp { - -Sasl::Sasl(const std::string& id, ConnectionContext& c, const std::string& hostname_) - : qpid::amqp::SaslClient(id), context(c), - sasl(qpid::SaslFactory::getInstance().create(c.username, c.password, c.service, hostname_, c.minSsf, c.maxSsf, false)), - hostname(hostname_), readHeader(true), writeHeader(true), haveOutput(false), state(NONE) {} - -Sasl::~Sasl() {} -std::size_t Sasl::decode(const char* buffer, std::size_t size) -{ - size_t decoded = 0; - if (readHeader) { - decoded += readProtocolHeader(buffer, size); - readHeader = !decoded; - } - if (state == NONE && decoded < size) { - decoded += read(buffer + decoded, size - decoded); - } - QPID_LOG(trace, id << " Sasl::decode(" << size << "): " << decoded); - return decoded; -} - -std::size_t Sasl::encode(char* buffer, std::size_t size) -{ - size_t encoded = 0; - if (writeHeader) { - encoded += writeProtocolHeader(buffer, size); - writeHeader = !encoded; - } - if (encoded < size) { - encoded += write(buffer + encoded, size - encoded); - } - haveOutput = (encoded == size); - QPID_LOG(trace, id << " Sasl::encode(" << size << "): " << encoded); - return encoded; -} - -bool Sasl::canEncode() -{ - QPID_LOG(trace, id << " Sasl::canEncode(): " << writeHeader << " || " << haveOutput); - return writeHeader || haveOutput; -} - -void Sasl::mechanisms(const std::string& offered) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-MECHANISMS(" << offered << ")"); - std::string response; - - std::string mechanisms; - if (context.mechanism.size()) { - std::vector allowed = split(context.mechanism, " "); - std::vector supported = split(offered, " "); - std::stringstream intersection; - for (std::vector::const_iterator i = allowed.begin(); i != allowed.end(); ++i) { - if (std::find(supported.begin(), supported.end(), *i) != supported.end()) { - intersection << *i << " "; - } - } - mechanisms = intersection.str(); - } else { - mechanisms = offered; - } - - try { - if (sasl->start(mechanisms, response, context.getTransportSecuritySettings())) { - init(sasl->getMechanism(), &response, hostname.size() ? &hostname : 0); - } else { - init(sasl->getMechanism(), 0, hostname.size() ? &hostname : 0); - } - haveOutput = true; - context.activateOutput(); - } catch (const std::exception& e) { - failed(e.what()); - } -} -void Sasl::challenge(const std::string& challenge) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-CHALLENGE(" << challenge.size() << " bytes)"); - try { - std::string r = sasl->step(challenge); - response(&r); - haveOutput = true; - context.activateOutput(); - } catch (const std::exception& e) { - failed(e.what()); - } -} -namespace { -const std::string EMPTY; -} -void Sasl::challenge() -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-CHALLENGE(null)"); - try { - std::string r = sasl->step(EMPTY); - response(&r); - } catch (const std::exception& e) { - failed(e.what()); - } -} -void Sasl::outcome(uint8_t result, const std::string& extra) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-OUTCOME(" << result << ", " << extra << ")"); - outcome(result); -} -void Sasl::outcome(uint8_t result) -{ - QPID_LOG_CAT(debug, protocol, id << " Received SASL-OUTCOME(" << result << ")"); - if (result) state = FAILED; - else state = SUCCEEDED; - - securityLayer = sasl->getSecurityLayer(context.maxFrameSize); - if (securityLayer.get()) { - context.initSecurityLayer(*securityLayer); - } - context.activateOutput(); -} - -bool Sasl::stopReading() -{ - return state != NONE; -} - -qpid::sys::Codec* Sasl::getSecurityLayer() -{ - return securityLayer.get(); -} - -namespace { -const std::string DEFAULT_ERROR("Authentication failed"); -} - -bool Sasl::authenticated() -{ - switch (state) { - case SUCCEEDED: return true; - case FAILED: throw qpid::messaging::AuthenticationFailure(error.size() ? error : DEFAULT_ERROR); - case NONE: default: return false; - } -} - -void Sasl::failed(const std::string& text) -{ - QPID_LOG_CAT(info, client, id << " Failure during authentication: " << text); - error = text; - state = FAILED; -} - -std::string Sasl::getAuthenticatedUsername() -{ - return sasl->getUserId(); -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/Sasl.h b/qpid/cpp/src/qpid/messaging/amqp/Sasl.h deleted file mode 100644 index a836e2e465..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/Sasl.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_SASL_H -#define QPID_MESSAGING_AMQP_SASL_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/Codec.h" -#include "qpid/amqp/SaslClient.h" -#include - -namespace qpid { -class Sasl; -namespace sys { -class SecurityLayer; -} -namespace messaging { -struct ConnectionOptions; -namespace amqp { -class ConnectionContext; - -/** - * - */ -class Sasl : public qpid::sys::Codec, qpid::amqp::SaslClient -{ - public: - Sasl(const std::string& id, ConnectionContext& context, const std::string& hostname); - ~Sasl(); - std::size_t decode(const char* buffer, std::size_t size); - std::size_t encode(char* buffer, std::size_t size); - bool canEncode(); - - bool authenticated(); - qpid::sys::Codec* getSecurityLayer(); - std::string getAuthenticatedUsername(); - private: - ConnectionContext& context; - std::auto_ptr sasl; - std::string hostname; - bool readHeader; - bool writeHeader; - bool haveOutput; - enum { - NONE, FAILED, SUCCEEDED - } state; - std::auto_ptr securityLayer; - std::string error; - - void mechanisms(const std::string&); - void challenge(const std::string&); - void challenge(); //null != empty string - void outcome(uint8_t result, const std::string&); - void outcome(uint8_t result); - void failed(const std::string&); - protected: - bool stopReading(); -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_SASL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp deleted file mode 100644 index fe8b4d33b7..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp +++ /dev/null @@ -1,643 +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 "SenderContext.h" -#include "Transaction.h" -#include "EncodedMessage.h" -#include "PnData.h" -#include "util.h" -#include "qpid/messaging/AddressImpl.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/Exception.h" -#include "qpid/amqp/descriptors.h" -#include "qpid/amqp/MapHandler.h" -#include "qpid/amqp/MessageEncoder.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/log/Statement.h" -#include "config.h" -extern "C" { -#include -} -#include -#include - -namespace qpid { -namespace messaging { -namespace amqp { - -//TODO: proper conversion to wide string for address -SenderContext::SenderContext(pn_session_t* session, const std::string& n, - const qpid::messaging::Address& a, - bool setToOnSend_, - const CoordinatorPtr& coord) - : sender(pn_sender(session, n.c_str())), - name(n), - address(a), - helper(address), - nextId(0), capacity(50), unreliable(helper.isUnreliable()), - setToOnSend(setToOnSend_), - transaction(coord) -{} - -SenderContext::~SenderContext() -{ - if (sender) pn_link_free(sender); -} - -void SenderContext::close() -{ - if (sender) pn_link_close(sender); -} - -void SenderContext::setCapacity(uint32_t c) -{ - if (c < deliveries.size()) throw qpid::messaging::SenderError("Desired capacity is less than unsettled message count!"); - capacity = c; -} - -uint32_t SenderContext::getCapacity() -{ - return capacity; -} - -uint32_t SenderContext::getUnsettled() -{ - return processUnsettled(true/*always allow retrieval of unsettled count, even if link has failed*/); -} - -const std::string& SenderContext::getName() const -{ - return name; -} - -const std::string& SenderContext::getTarget() const -{ - return address.getName(); -} - -bool SenderContext::send(const qpid::messaging::Message& message, SenderContext::Delivery** out) -{ - 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)) { - types::Variant state; - if (transaction) - state = transaction->getSendState(); - if (unreliable) { - Delivery delivery(nextId++); - delivery.encode(MessageImplAccess::get(message), address, setToOnSend); - delivery.send(sender, unreliable, state); - *out = 0; - return true; - } else { - deliveries.push_back(Delivery(nextId++)); - try { - Delivery& delivery = deliveries.back(); - delivery.encode(MessageImplAccess::get(message), address, setToOnSend); - delivery.send(sender, unreliable, state); - *out = &delivery; - return true; - } catch (const std::exception& e) { - deliveries.pop_back(); - --nextId; - throw SendError(e.what()); - } - } - } else { - return false; - } -} - -void SenderContext::check() -{ - if (pn_link_state(sender) & PN_REMOTE_CLOSED && !(pn_link_state(sender) & PN_LOCAL_CLOSED)) { - std::string text = get_error_string(pn_link_remote_condition(sender), "Link detached by peer"); - pn_link_close(sender); - throw qpid::messaging::LinkError(text); - } -} - -uint32_t SenderContext::processUnsettled(bool silent) -{ - if (!silent) { - check(); - } - //remove messages from front of deque once peer has confirmed receipt - while (!deliveries.empty() && deliveries.front().delivered() && !(pn_link_state(sender) & PN_REMOTE_CLOSED)) { - deliveries.front().settle(); - deliveries.pop_front(); - } - return deliveries.size(); -} -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 -{ - public: - HeaderAdapter(const qpid::messaging::MessageImpl& impl) : msg(impl), headers(msg.getHeaders()) {} - virtual bool isDurable() const - { - return msg.isDurable(); - } - virtual uint8_t getPriority() const - { - return msg.getPriority(); - } - virtual bool hasTtl() const - { - return msg.getTtl(); - } - virtual uint32_t getTtl() const - { - return msg.getTtl(); - } - virtual bool isFirstAcquirer() const - { - qpid::types::Variant::Map::const_iterator i = headers.find(X_AMQP_FIRST_ACQUIRER); - if (i != headers.end()) { - return i->second; - } else { - return false; - } - } - virtual uint32_t getDeliveryCount() const - { - qpid::types::Variant::Map::const_iterator i = headers.find(X_AMQP_DELIVERY_COUNT); - if (i != headers.end()) { - return i->second; - } else { - return msg.isRedelivered() ? 1 : 0; - } - } - private: - const qpid::messaging::MessageImpl& msg; - const qpid::types::Variant::Map& headers; -}; -const std::string EMPTY; -const std::string FORWARD_SLASH("/"); -const std::string X_AMQP_TO("x-amqp-to"); -const std::string X_AMQP_CONTENT_ENCODING("x-amqp-content-encoding"); -const std::string X_AMQP_CREATION_TIME("x-amqp-creation-time"); -const std::string X_AMQP_ABSOLUTE_EXPIRY_TIME("x-amqp-absolute-expiry-time"); -const std::string X_AMQP_GROUP_ID("x-amqp-group-id"); -const std::string X_AMQP_GROUP_SEQUENCE("x-amqp-group-sequence"); -const std::string X_AMQP_REPLY_TO_GROUP_ID("x-amqp-reply-to-group-id"); -const std::string X_AMQP_MESSAGE_ANNOTATIONS("x-amqp-message-annotations"); -const std::string X_AMQP_DELIVERY_ANNOTATIONS("x-amqp-delivery-annotations"); - -class PropertiesAdapter : public qpid::amqp::MessageEncoder::Properties -{ - public: - PropertiesAdapter(const qpid::messaging::MessageImpl& impl, const std::string& s, const std::string& t) : msg(impl), headers(msg.getHeaders()), subject(s), to(t) {} - bool hasMessageId() const - { - return getMessageId().size(); - } - std::string getMessageId() const - { - return msg.getMessageId(); - } - - bool hasUserId() const - { - return getUserId().size(); - } - - std::string getUserId() const - { - return msg.getUserId(); - } - - bool hasTo() const - { - return hasHeader(X_AMQP_TO) || !to.empty(); - } - - std::string getTo() const - { - qpid::types::Variant::Map::const_iterator i = headers.find(X_AMQP_TO); - if (i == headers.end()) return to; - else return i->second; - } - - bool hasSubject() const - { - return subject.size() || getSubject().size(); - } - - std::string getSubject() const - { - return subject.size() ? subject : msg.getSubject(); - } - - bool hasReplyTo() const - { - return msg.getReplyTo(); - } - - std::string getReplyTo() const - { - Address a = msg.getReplyTo(); - if (a.getSubject().size()) { - return a.getName() + FORWARD_SLASH + a.getSubject(); - } else { - return a.getName(); - } - } - - bool hasCorrelationId() const - { - return getCorrelationId().size(); - } - - std::string getCorrelationId() const - { - return msg.getCorrelationId(); - } - - bool hasContentType() const - { - return getContentType().size(); - } - - std::string getContentType() const - { - return msg.getContentType(); - } - - bool hasContentEncoding() const - { - return hasHeader(X_AMQP_CONTENT_ENCODING); - } - - std::string getContentEncoding() const - { - return headers.find(X_AMQP_CONTENT_ENCODING)->second; - } - - bool hasAbsoluteExpiryTime() const - { - return hasHeader(X_AMQP_ABSOLUTE_EXPIRY_TIME); - } - - int64_t getAbsoluteExpiryTime() const - { - return headers.find(X_AMQP_ABSOLUTE_EXPIRY_TIME)->second; - } - - bool hasCreationTime() const - { - return hasHeader(X_AMQP_CREATION_TIME); - } - - int64_t getCreationTime() const - { - return headers.find(X_AMQP_CREATION_TIME)->second; - } - - bool hasGroupId() const - { - return hasHeader(X_AMQP_GROUP_ID); - } - - std::string getGroupId() const - { - return headers.find(X_AMQP_GROUP_ID)->second; - } - - bool hasGroupSequence() const - { - return hasHeader(X_AMQP_GROUP_SEQUENCE); - } - - uint32_t getGroupSequence() const - { - return headers.find(X_AMQP_GROUP_SEQUENCE)->second; - } - - bool hasReplyToGroupId() const - { - return hasHeader(X_AMQP_REPLY_TO_GROUP_ID); - } - - std::string getReplyToGroupId() const - { - return headers.find(X_AMQP_REPLY_TO_GROUP_ID)->second; - } - private: - const qpid::messaging::MessageImpl& msg; - const qpid::types::Variant::Map& headers; - const std::string subject; - const std::string to; - - bool hasHeader(const std::string& key) const - { - return headers.find(key) != headers.end(); - } -}; - -bool startsWith(const std::string& input, const std::string& pattern) -{ - if (input.size() < pattern.size()) return false; - for (std::string::const_iterator b = pattern.begin(), a = input.begin(); b != pattern.end(); ++b, ++a) { - if (*a != *b) return false; - } - return true; -} -class ApplicationPropertiesAdapter : public qpid::amqp::MessageEncoder::ApplicationProperties -{ - public: - ApplicationPropertiesAdapter(const qpid::types::Variant::Map& h) : headers(h) {} - void handle(qpid::amqp::MapHandler& h) const - { - 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) || i->first == X_AMQP_0_10_APP_ID) { - qpid::amqp::CharSequence key(convert(i->first)); - switch (i->second.getType()) { - case qpid::types::VAR_VOID: - h.handleVoid(key); - break; - case qpid::types::VAR_BOOL: - h.handleBool(key, i->second); - break; - case qpid::types::VAR_UINT8: - h.handleUint8(key, i->second); - break; - case qpid::types::VAR_UINT16: - h.handleUint16(key, i->second); - break; - case qpid::types::VAR_UINT32: - h.handleUint32(key, i->second); - break; - case qpid::types::VAR_UINT64: - h.handleUint64(key, i->second); - break; - case qpid::types::VAR_INT8: - h.handleInt8(key, i->second); - break; - case qpid::types::VAR_INT16: - h.handleInt16(key, i->second); - break; - case qpid::types::VAR_INT32: - h.handleInt32(key, i->second); - break; - case qpid::types::VAR_INT64: - h.handleInt64(key, i->second); - break; - case qpid::types::VAR_FLOAT: - h.handleFloat(key, i->second); - break; - case qpid::types::VAR_DOUBLE: - h.handleDouble(key, i->second); - break; - case qpid::types::VAR_STRING: - h.handleString(key, convert(i->second), convert(i->second.getEncoding())); - break; - case qpid::types::VAR_UUID: - QPID_LOG(warning, "Skipping UUID in application properties; not yet handled correctly."); - break; - case qpid::types::VAR_MAP: - case qpid::types::VAR_LIST: - QPID_LOG(warning, "Skipping nested list and map; not allowed in application properties."); - break; - } - } - } - } - private: - const qpid::types::Variant::Map& headers; - - static qpid::amqp::CharSequence convert(const std::string& in) - { - qpid::amqp::CharSequence out; - out.data = in.data(); - out.size = in.size(); - return out; - } -}; - -bool changedSubject(const qpid::messaging::MessageImpl& msg, const qpid::messaging::Address& address) -{ - return address.getSubject().size() && address.getSubject() != msg.getSubject(); -} - -} - -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, bool setToField) -{ - try { - boost::shared_ptr original = msg.getEncoded(); - - if (original && !changedSubject(msg, address)) { //still have the content as received, send at least the bare message unaltered - //do we need to alter the header? are durable, priority, ttl, first-acquirer, delivery-count different from what was received? - if (original->hasHeaderChanged(msg)) { - //since as yet have no annotations, just write the revised header then the rest of the message as received - encoded.resize(16/*max header size*/ + original->getBareMessage().size); - qpid::amqp::MessageEncoder encoder(encoded.getData(), encoded.getSize()); - HeaderAdapter header(msg); - encoder.writeHeader(header); - ::memcpy(encoded.getData() + encoder.getPosition(), original->getBareMessage().data, original->getBareMessage().size); - } else { - //since as yet have no annotations, if the header hasn't - //changed and we still have the original bare message, can - //send the entire content as is - encoded.resize(original->getSize()); - ::memcpy(encoded.getData(), original->getData(), original->getSize()); - } - } else { - HeaderAdapter header(msg); - PropertiesAdapter properties(msg, address.getSubject(), setToField ? address.getName() : EMPTY); - ApplicationPropertiesAdapter applicationProperties(msg.getHeaders()); - //compute size: - 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: - encoder.writeHeader(header); - //write delivery-annotations, write message-annotations (none yet supported) - //write properties - encoder.writeProperties(properties); - //write application-properties - encoder.writeApplicationProperties(applicationProperties); - //write body - 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()); - } - //write footer (no annotations yet supported) - } - } catch (const qpid::Exception& e) { - throw SendError(e.what()); - } -} - -void SenderContext::Delivery::send(pn_link_t* sender, bool unreliable, const types::Variant& state) -{ - pn_delivery_tag_t tag; - tag.size = sizeof(id); -#ifdef NO_PROTON_DELIVERY_TAG_T - tag.start = reinterpret_cast(&id); -#else - tag.bytes = reinterpret_cast(&id); -#endif - token = pn_delivery(sender, tag); - if (!state.isVoid()) { // Add transaction state - PnData data(pn_disposition_data(pn_delivery_local(token))); - data.put(state); - pn_delivery_update(token, qpid::amqp::transaction::TRANSACTIONAL_STATE_CODE); - } - 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 (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"); - } else if (!accepted()) { - QPID_LOG(info, "delivery " << id << " was not accepted by peer"); - } - return true; - } else { - return false; - } -} -bool SenderContext::Delivery::accepted() -{ - return pn_delivery_remote_state(token) == PN_ACCEPTED; -} -bool SenderContext::Delivery::rejected() -{ - return pn_delivery_remote_state(token) == PN_REJECTED; -} - -std::string SenderContext::Delivery::error() -{ - pn_condition_t *condition = pn_disposition_condition(pn_delivery_remote(token)); - return (condition && pn_condition_is_set(condition)) ? - Msg() << get_error_string(condition, std::string(), std::string()) : - std::string(); -} - -void SenderContext::Delivery::settle() -{ - pn_delivery_settle(token); -} -void SenderContext::verify() -{ - pn_terminus_t* target = pn_link_remote_target(sender); - if (!helper.isNameNull() && !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() -{ - if (sender) configure(pn_link_target(sender)); -} - -void SenderContext::configure(pn_terminus_t* target) -{ - 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(false) == 0; -} - -bool SenderContext::closed() -{ - return pn_link_state(sender) & PN_LOCAL_CLOSED; -} - -Address SenderContext::getAddress() const -{ - return address; -} - - -void SenderContext::reset(pn_session_t* session) -{ - sender = session ? pn_sender(session, name.c_str()) : 0; - if (sender) 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 deleted file mode 100644 index 467a8e0d3d..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_SENDERCONTEXT_H -#define QPID_MESSAGING_AMQP_SENDERCONTEXT_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 -#include -#include -#include -#include "qpid/sys/IntegerTypes.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/amqp/AddressHelper.h" -#include "qpid/messaging/amqp/EncodedMessage.h" - -struct pn_delivery_t; -struct pn_link_t; -struct pn_session_t; -struct pn_terminus_t; - -namespace qpid { -namespace messaging { - -class Message; -class MessageImpl; - -namespace amqp { - -class Transaction; - - -class SenderContext -{ - public: - class Delivery - { - public: - Delivery(int32_t id); - void encode(const qpid::messaging::MessageImpl& message, const qpid::messaging::Address&, bool setToField); - void send(pn_link_t*, bool unreliable, const types::Variant& state=types::Variant()); - bool delivered(); - bool accepted(); - bool rejected(); - void settle(); - void reset(); - bool sent() const; - pn_delivery_t* getToken() const { return token; } - std::string error(); - private: - int32_t id; - pn_delivery_t* token; - EncodedMessage encoded; - bool presettled; - }; - - typedef boost::shared_ptr CoordinatorPtr; - - SenderContext(pn_session_t* session, const std::string& name, - const qpid::messaging::Address& target, - bool setToOnSend, - const CoordinatorPtr& transaction = CoordinatorPtr()); - virtual ~SenderContext(); - - virtual void reset(pn_session_t* session); - virtual void close(); - virtual void setCapacity(uint32_t); - virtual uint32_t getCapacity(); - virtual uint32_t getUnsettled(); - virtual const std::string& getName() const; - virtual const std::string& getTarget() const; - virtual bool send(const qpid::messaging::Message& message, Delivery**); - virtual void configure(); - virtual void verify(); - virtual void check(); - virtual bool settled(); - virtual bool closed(); - virtual Address getAddress() const; - - protected: - pn_link_t* sender; - - private: - friend class ConnectionContext; - typedef std::deque Deliveries; - - const std::string name; - qpid::messaging::Address address; - AddressHelper helper; - int32_t nextId; - Deliveries deliveries; - uint32_t capacity; - bool unreliable; - bool setToOnSend; - boost::shared_ptr transaction; - - uint32_t processUnsettled(bool silent); - void configure(pn_terminus_t*); - void resend(); -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_SENDERCONTEXT_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp b/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp deleted file mode 100644 index 98f2d34e7d..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp +++ /dev/null @@ -1,81 +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 "SenderHandle.h" -#include "ConnectionContext.h" -#include "SessionContext.h" -#include "SessionHandle.h" -#include "SenderContext.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Session.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -SenderHandle::SenderHandle(boost::shared_ptr c, - boost::shared_ptr s, - boost::shared_ptr sndr -) : connection(c), session(s), sender(sndr) {} - -void SenderHandle::send(const Message& message, bool sync) -{ - SenderContext::Delivery* d = 0; - connection->send(session, sender, message, sync, &d); -} - -void SenderHandle::close() -{ - connection->detach(session, sender); -} - -void SenderHandle::setCapacity(uint32_t capacity) -{ - connection->setCapacity(sender, capacity); -} - -uint32_t SenderHandle::getCapacity() -{ - return connection->getCapacity(sender); -} - -uint32_t SenderHandle::getUnsettled() -{ - return connection->getUnsettled(sender); -} - -const std::string& SenderHandle::getName() const -{ - return sender->getName(); -} - -qpid::messaging::Session SenderHandle::getSession() const -{ - return qpid::messaging::Session(new SessionHandle(connection, session)); -} - -Address SenderHandle::getAddress() const -{ - return sender->getAddress(); -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.h b/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.h deleted file mode 100644 index fab158c1ef..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_SENDERHANDLE_H -#define QPID_MESSAGING_AMQP_SENDERHANDLE_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 -#include "qpid/messaging/SenderImpl.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -class ConnectionContext; -class SessionContext; -class SenderContext; -/** - * - */ -class SenderHandle : public qpid::messaging::SenderImpl -{ - public: - SenderHandle(boost::shared_ptr connection, - boost::shared_ptr session, - boost::shared_ptr sender - ); - void send(const Message& message, bool sync); - void close(); - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getUnsettled(); - const std::string& getName() const; - Session getSession() const; - Address getAddress() const; - private: - boost::shared_ptr connection; - boost::shared_ptr session; - boost::shared_ptr sender; -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_SENDERHANDLE_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp deleted file mode 100644 index 92bdea7dbc..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp +++ /dev/null @@ -1,258 +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 "SessionContext.h" -#include "SenderContext.h" -#include "ReceiverContext.h" -#include "Transaction.h" -#include "PnData.h" -#include -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/amqp/descriptors.h" - -extern "C" { -#include -} - -namespace qpid { -namespace messaging { -namespace amqp { - -SessionContext::SessionContext(pn_connection_t* connection) : session(pn_session(connection)) {} - -SessionContext::~SessionContext() -{ - // Clear all pointers to senders and receivers before we free the session. - senders.clear(); - receivers.clear(); - transaction.reset(); // Transaction is a sender. - if (!error && session) - pn_session_free(session); -} - -boost::shared_ptr SessionContext::createSender(const qpid::messaging::Address& address, bool setToOnSend) -{ - error.raise(); - std::string name = AddressHelper::getLinkName(address); - if (senders.find(name) != senders.end()) - throw LinkError("Link name must be unique within the scope of the connection"); - boost::shared_ptr s( - new SenderContext(session, name, address, setToOnSend, transaction)); - senders[name] = s; - return s; -} - -boost::shared_ptr SessionContext::createReceiver(const qpid::messaging::Address& address) -{ - error.raise(); - std::string name = AddressHelper::getLinkName(address); - if (receivers.find(name) != receivers.end()) throw LinkError("Link name must be unique within the scope of the connection"); - boost::shared_ptr r(new ReceiverContext(session, name, address)); - receivers[name] = r; - return r; -} - -boost::shared_ptr SessionContext::getSender(const std::string& name) const -{ - error.raise(); - SenderMap::const_iterator i = senders.find(name); - if (i == senders.end()) { - throw qpid::messaging::KeyError(std::string("No such sender") + name); - } else { - return i->second; - } -} - -boost::shared_ptr SessionContext::getReceiver(const std::string& name) const -{ - error.raise(); - ReceiverMap::const_iterator i = receivers.find(name); - if (i == receivers.end()) { - throw qpid::messaging::KeyError(std::string("No such receiver") + name); - } else { - return i->second; - } -} - -void SessionContext::removeReceiver(const std::string& n) -{ - error.raise(); - receivers.erase(n); -} - -void SessionContext::removeSender(const std::string& n) -{ - error.raise(); - senders.erase(n); -} - -boost::shared_ptr SessionContext::nextReceiver() -{ - error.raise(); - for (SessionContext::ReceiverMap::iterator i = receivers.begin(); i != receivers.end(); ++i) { - if (i->second->hasCurrent()) { - return i->second; - } - } - - return boost::shared_ptr(); -} - -uint32_t SessionContext::getReceivable() -{ - error.raise(); - return 0;//TODO -} - -uint32_t SessionContext::getUnsettledAcks() -{ - error.raise(); - return 0;//TODO -} - -qpid::framing::SequenceNumber SessionContext::record(pn_delivery_t* delivery) -{ - error.raise(); - qpid::framing::SequenceNumber id = next++; - if (!pn_delivery_settled(delivery)) { - unacked[id] = delivery; - QPID_LOG(debug, "Recorded delivery " << id << " -> " << delivery); - pn_link_advance(pn_delivery_link(delivery)); - } else { - pn_delivery_settle(delivery); // Automatically advances the link. - } - return id; -} - -void SessionContext::acknowledge(DeliveryMap::iterator begin, DeliveryMap::iterator end) -{ - error.raise(); - for (DeliveryMap::iterator i = begin; i != end; ++i) { - types::Variant txState; - if (transaction) { - QPID_LOG(trace, "Setting disposition for transactional delivery " - << i->first << " -> " << i->second); - transaction->acknowledge(i->second); - } else { - QPID_LOG(trace, "Setting disposition for delivery " << i->first << " -> " << i->second); - pn_delivery_update(i->second, PN_ACCEPTED); - pn_delivery_settle(i->second); //TODO: different settlement modes? - } - } - unacked.erase(begin, end); -} - -void SessionContext::acknowledge() -{ - error.raise(); - QPID_LOG(debug, "acknowledging all " << unacked.size() << " messages"); - acknowledge(unacked.begin(), unacked.end()); -} - -void SessionContext::acknowledge(const qpid::framing::SequenceNumber& id, bool cumulative) -{ - error.raise(); - QPID_LOG(debug, "acknowledging selected messages, id=" << id << ", cumulative=" << cumulative); - DeliveryMap::iterator i = unacked.find(id); - if (i != unacked.end()) { - DeliveryMap::iterator start = cumulative ? unacked.begin() : i; - acknowledge(start, ++i); - } else { - QPID_LOG(debug, "selective acknowledgement failed; message not found for id " << id); - } -} - -void SessionContext::nack(const qpid::framing::SequenceNumber& id, bool reject) -{ - error.raise(); - DeliveryMap::iterator i = unacked.find(id); - if (i != unacked.end()) { - if (reject) { - QPID_LOG(debug, "rejecting message with id=" << id); - pn_delivery_update(i->second, PN_REJECTED); - } else { - QPID_LOG(debug, "releasing message with id=" << id); - pn_delivery_update(i->second, PN_MODIFIED); - pn_disposition_set_failed(pn_delivery_local(i->second), true); - } - pn_delivery_settle(i->second); - unacked.erase(i); - } -} - -bool SessionContext::settled() -{ - error.raise(); - bool result = true; - - for (SenderMap::iterator i = senders.begin(); i != senders.end(); ++i) { - try { - if (!i->second->closed() && !i->second->settled()) result = false; - } catch (const std::exception&) { - senders.erase(i); - throw; - } - } - 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) -{ - unacked.clear(); - if (transaction) { - if (transaction->isCommitting()) - error = new TransactionUnknown("Transaction outcome unknown: transport failure"); - else - error = new TransactionAborted("Transaction aborted: transport failure"); - resetSession(0); - senders.clear(); - receivers.clear(); - transaction.reset(); - return; - } - resetSession(pn_session(connection)); - -} - -void SessionContext::resetSession(pn_session_t* session_) { - session = session_; - if (transaction) transaction->reset(session); - 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 deleted file mode 100644 index 67b3c1e401..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_SESSIONCONTEXT_H -#define QPID_MESSAGING_AMQP_SESSIONCONTEXT_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 -#include -#include -#include "qpid/sys/IntegerTypes.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/sys/ExceptionHolder.h" - -struct pn_connection_t; -struct pn_session_t; -struct pn_delivery_t; - -namespace qpid { -namespace messaging { - -class Address; -class Duration; - -namespace amqp { - -class ConnectionContext; -class SenderContext; -class ReceiverContext; -class Transaction; - -/** - * - */ -class SessionContext -{ - public: - SessionContext(pn_connection_t*); - ~SessionContext(); - void reset(pn_connection_t*); - boost::shared_ptr createSender(const qpid::messaging::Address& address, bool setToOnSend); - boost::shared_ptr createReceiver(const qpid::messaging::Address& address); - boost::shared_ptr getSender(const std::string& name) const; - boost::shared_ptr getReceiver(const std::string& name) const; - void removeReceiver(const std::string&); - void removeSender(const std::string&); - boost::shared_ptr nextReceiver(); - uint32_t getReceivable(); - uint32_t getUnsettledAcks(); - bool settled(); - void setName(const std::string&); - std::string getName() const; - - void nack(const qpid::framing::SequenceNumber& id, bool reject); - - private: - friend class ConnectionContext; - typedef std::map > SenderMap; - typedef std::map > ReceiverMap; - typedef std::map DeliveryMap; - - pn_session_t* session; - SenderMap senders; - boost::shared_ptr transaction; - ReceiverMap receivers; - DeliveryMap unacked; - qpid::framing::SequenceNumber next; - std::string name; - sys::ExceptionHolder error; - - qpid::framing::SequenceNumber record(pn_delivery_t*); - void acknowledge(); - void acknowledge(const qpid::framing::SequenceNumber& id, bool cummulative); - void acknowledge(DeliveryMap::iterator begin, DeliveryMap::iterator end); - void resetSession(pn_session_t*); -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_SESSIONCONTEXT_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp b/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp deleted file mode 100644 index 6b90d69c7f..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp +++ /dev/null @@ -1,147 +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 "SessionHandle.h" -#include "ConnectionContext.h" -#include "ConnectionHandle.h" -#include "ReceiverContext.h" -#include "ReceiverHandle.h" -#include "SenderContext.h" -#include "SenderHandle.h" -#include "SessionContext.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Session.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -SessionHandle::SessionHandle(boost::shared_ptr c, boost::shared_ptr s) : connection(c), session(s) {} - -void SessionHandle::commit() -{ - connection->commit(session); -} - -void SessionHandle::rollback() -{ - connection->rollback(session); -} - -void SessionHandle::acknowledge(bool /*sync*/) -{ - connection->acknowledge(session, 0, false); -} - -void SessionHandle::acknowledge(qpid::messaging::Message& msg, bool cumulative) -{ - connection->acknowledge(session, &msg, cumulative); -} - -void SessionHandle::reject(qpid::messaging::Message& msg) -{ - connection->nack(session, msg, true); -} - -void SessionHandle::release(qpid::messaging::Message& msg) -{ - connection->nack(session, msg, false); -} - -void SessionHandle::close() -{ - connection->endSession(session); -} - -void SessionHandle::sync(bool block) -{ - if (block) { - connection->sync(session); - } -} - -qpid::messaging::Sender SessionHandle::createSender(const qpid::messaging::Address& address) -{ - boost::shared_ptr sender = connection->createSender(session, address); - return qpid::messaging::Sender(new SenderHandle(connection, session, sender)); -} - -qpid::messaging::Receiver SessionHandle::createReceiver(const qpid::messaging::Address& address) -{ - boost::shared_ptr receiver = connection->createReceiver(session, address); - return qpid::messaging::Receiver(new ReceiverHandle(connection, session, receiver)); -} - -bool SessionHandle::nextReceiver(Receiver& receiver, Duration timeout) -{ - boost::shared_ptr r = connection->nextReceiver(session, timeout); - if (r) { - //TODO: cache handles in this case to avoid frequent allocation - receiver = qpid::messaging::Receiver(new ReceiverHandle(connection, session, r)); - return true; - } else { - return false; - } -} - -qpid::messaging::Receiver SessionHandle::nextReceiver(Duration timeout) -{ - qpid::messaging::Receiver r; - if (nextReceiver(r, timeout)) return r; - else throw qpid::messaging::NoMessageAvailable(); -} - -uint32_t SessionHandle::getReceivable() -{ - return session->getReceivable(); -} - -uint32_t SessionHandle::getUnsettledAcks() -{ - return session->getUnsettledAcks(); -} - -Sender SessionHandle::getSender(const std::string& name) const -{ - return qpid::messaging::Sender(new SenderHandle(connection, session, connection->getSender(session, name))); -} - -Receiver SessionHandle::getReceiver(const std::string& name) const -{ - return qpid::messaging::Receiver(new ReceiverHandle(connection, session, connection->getReceiver(session, name))); -} - -Connection SessionHandle::getConnection() const -{ - return qpid::messaging::Connection(new ConnectionHandle(connection)); -} - -void SessionHandle::checkError() -{ - -} - - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.h b/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.h deleted file mode 100644 index 5e843aaacc..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_SESSIONIMPL_H -#define QPID_MESSAGING_AMQP_SESSIONIMPL_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 -#include "qpid/messaging/SessionImpl.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -class ConnectionContext; -class SessionContext; -/** - * - */ -class SessionHandle : public qpid::messaging::SessionImpl -{ - public: - SessionHandle(boost::shared_ptr, boost::shared_ptr); - void commit(); - void rollback(); - void acknowledge(bool sync); - void acknowledge(Message&, bool); - void reject(Message&); - void release(Message&); - void close(); - void sync(bool block); - qpid::messaging::Sender createSender(const Address& address); - qpid::messaging::Receiver createReceiver(const Address& address); - bool nextReceiver(Receiver& receiver, Duration timeout); - qpid::messaging::Receiver nextReceiver(Duration timeout); - uint32_t getReceivable(); - uint32_t getUnsettledAcks(); - qpid::messaging::Sender getSender(const std::string& name) const; - qpid::messaging::Receiver getReceiver(const std::string& name) const; - qpid::messaging::Connection getConnection() const; - void checkError(); - private: - boost::shared_ptr connection; - boost::shared_ptr session; -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_SESSIONIMPL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp b/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp deleted file mode 100644 index e8ef2d587b..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp +++ /dev/null @@ -1,186 +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 "SslTransport.h" -#include "TransportContext.h" -#include "qpid/messaging/ConnectionOptions.h" -#include "qpid/sys/ssl/SslSocket.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/Poller.h" -#include "qpid/client/ssl.h" -#include "qpid/log/Statement.h" -#include -#include - -using namespace qpid::sys; -using namespace qpid::sys::ssl; - -namespace qpid { -namespace messaging { -namespace amqp { - -// Static constructor which registers connector here -namespace { -Transport* create(TransportContext& c, Poller::shared_ptr p) -{ - qpid::client::initialiseSSL(); - return new SslTransport(c, p); -} - -struct StaticInit -{ - StaticInit() - { - Transport::add("ssl", &create); - }; - - ~StaticInit() - { - qpid::client::shutdownSSL(); - } -} init; -} - - -SslTransport::SslTransport(TransportContext& c, boost::shared_ptr p) : context(c), connector(0), aio(0), poller(p) -{ - const ConnectionOptions* options = context.getOptions(); - options->configureSocket(socket); - if (options->sslCertName != "") { - QPID_LOG(debug, "ssl-cert-name = " << options->sslCertName); - socket.setCertName(options->sslCertName); - } - if (options->sslIgnoreHostnameVerificationFailure) { - socket.ignoreHostnameVerificationFailure(); - } -} - -void SslTransport::connect(const std::string& host, const std::string& port) -{ - assert(!connector); - assert(!aio); - connector = AsynchConnector::create( - socket, - host, port, - boost::bind(&SslTransport::connected, this, _1), - boost::bind(&SslTransport::failed, this, _3)); - - connector->start(poller); -} - -void SslTransport::failed(const std::string& msg) -{ - QPID_LOG(debug, "Failed to connect: " << msg); - socket.close(); - context.closed(); -} - -void SslTransport::connected(const Socket&) -{ - context.opened(); - aio = AsynchIO::create(socket, - boost::bind(&SslTransport::read, this, _1, _2), - boost::bind(&SslTransport::eof, this, _1), - boost::bind(&SslTransport::disconnected, this, _1), - boost::bind(&SslTransport::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&SslTransport::write, this, _1)); - aio->createBuffers(std::numeric_limits::max());//note: AMQP 1.0 _can_ handle large frame sizes - id = boost::str(boost::format("[%1%]") % socket.getFullAddress()); - aio->start(poller); -} - -void SslTransport::read(AsynchIO&, AsynchIO::BufferBase* buffer) -{ - int32_t decoded = context.getCodec().decode(buffer->bytes+buffer->dataStart, buffer->dataCount); - if (decoded < buffer->dataCount) { - // Adjust buffer for used bytes and then "unread them" - buffer->dataStart += decoded; - buffer->dataCount -= decoded; - aio->unread(buffer); - } else { - // Give whole buffer back to aio subsystem - aio->queueReadBuffer(buffer); - } -} - -void SslTransport::write(AsynchIO&) -{ - if (context.getCodec().canEncode()) { - AsynchIO::BufferBase* buffer = aio->getQueuedBuffer(); - if (buffer) { - size_t encoded = context.getCodec().encode(buffer->bytes, buffer->byteCount); - - buffer->dataStart = 0; - buffer->dataCount = encoded; - aio->queueWrite(buffer); - } - } - -} - -void SslTransport::close() -{ - QPID_LOG(debug, id << " SslTransport closing..."); - if (aio) - aio->queueWriteClose(); -} - -void SslTransport::eof(AsynchIO&) -{ - close(); -} - -void SslTransport::disconnected(AsynchIO&) -{ - close(); - socketClosed(*aio, socket); -} - -void SslTransport::socketClosed(AsynchIO&, const Socket&) -{ - if (aio) - aio->queueForDeletion(); - context.closed(); - QPID_LOG(debug, id << " Socket closed"); -} - -void SslTransport::abort() -{ - if (aio) { - // Established connection - aio->requestCallback(boost::bind(&SslTransport::eof, this, _1)); - } -} - -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 deleted file mode 100644 index 2972be4fac..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_SSLTRANSPORT_H -#define QPID_MESSAGING_AMQP_SSLTRANSPORT_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/messaging/amqp/Transport.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/ssl/SslSocket.h" -#include - -namespace qpid { -namespace sys { -class ConnectionCodec; -class Poller; -class AsynchConnector; -class AsynchIO; -class AsynchIOBufferBase; -} - -namespace messaging { -namespace amqp { -class TransportContext; - -class SslTransport : public Transport -{ - public: - SslTransport(TransportContext&, boost::shared_ptr p); - - void connect(const std::string& host, const std::string& port); - - void activateOutput(); - void abort(); - void connectionEstablished() {}; - void close(); - const qpid::sys::SecuritySettings* getSecuritySettings(); - - private: - qpid::sys::ssl::SslSocket socket; - TransportContext& context; - qpid::sys::AsynchConnector* connector; - qpid::sys::AsynchIO* aio; - boost::shared_ptr poller; - bool closed; - std::string id; - qpid::sys::SecuritySettings securitySettings; - - void connected(const qpid::sys::Socket&); - void failed(const std::string& msg); - void read(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); - void write(qpid::sys::AsynchIO&); - void eof(qpid::sys::AsynchIO&); - void disconnected(qpid::sys::AsynchIO&); - void socketClosed(qpid::sys::AsynchIO&, const qpid::sys::Socket&); - - friend class DriverImpl; -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_SSLTRANSPORT_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp b/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp deleted file mode 100644 index a919e974d6..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp +++ /dev/null @@ -1,185 +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 "TcpTransport.h" -#include "ConnectionContext.h" -#include "qpid/messaging/ConnectionOptions.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/Poller.h" -#include "qpid/log/Statement.h" -#include -#include - -using namespace qpid::sys; - -namespace qpid { -namespace messaging { -namespace amqp { -// Static constructor which registers connector here -namespace { -Transport* create(TransportContext& c, Poller::shared_ptr p) -{ - return new TcpTransport(c, p); -} - -struct StaticInit -{ - StaticInit() - { - Transport::add("tcp", &create); - }; -} init; -} - -TcpTransport::TcpTransport(TransportContext& c, boost::shared_ptr p) : socket(createSocket()), context(c), connector(0), aio(0), poller(p), closed(false) {} - -void TcpTransport::connect(const std::string& host, const std::string& port) -{ - assert(!connector); - assert(!aio); - context.getOptions()->configureSocket(*socket); - connector = AsynchConnector::create( - *socket, - host, port, - boost::bind(&TcpTransport::connected, this, _1), - boost::bind(&TcpTransport::failed, this, _3)); - - connector->start(poller); -} - -void TcpTransport::failed(const std::string& msg) -{ - QPID_LOG(debug, "Failed to connect: " << msg); - closed = true; - connector = 0; - socket->close(); - context.closed(); -} - -void TcpTransport::connected(const Socket&) -{ - context.opened(); - connector = 0; - aio = AsynchIO::create(*socket, - boost::bind(&TcpTransport::read, this, _1, _2), - boost::bind(&TcpTransport::eof, this, _1), - boost::bind(&TcpTransport::disconnected, this, _1), - boost::bind(&TcpTransport::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&TcpTransport::write, this, _1)); - aio->createBuffers(std::numeric_limits::max());//note: AMQP 1.0 _can_ handle large frame sizes - id = boost::str(boost::format("[%1%]") % socket->getFullAddress()); - aio->start(poller); -} - -void TcpTransport::read(AsynchIO&, AsynchIO::BufferBase* buffer) -{ - int32_t decoded = context.getCodec().decode(buffer->bytes+buffer->dataStart, buffer->dataCount); - if (decoded < buffer->dataCount) { - // Adjust buffer for used bytes and then "unread them" - buffer->dataStart += decoded; - buffer->dataCount -= decoded; - aio->unread(buffer); - } else { - // Give whole buffer back to aio subsystem - aio->queueReadBuffer(buffer); - } -} - -void TcpTransport::write(AsynchIO&) -{ - if (context.getCodec().canEncode()) { - AsynchIO::BufferBase* buffer = aio->getQueuedBuffer(); - if (buffer) { - size_t encoded = context.getCodec().encode(buffer->bytes, buffer->byteCount); - - buffer->dataStart = 0; - buffer->dataCount = encoded; - aio->queueWrite(buffer); - } - } - -} - -void TcpTransport::close() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!closed) { - QPID_LOG(debug, id << " TcpTransport closing..."); - if (aio) - aio->queueWriteClose(); - } -} - -void TcpTransport::eof(AsynchIO&) -{ - close(); -} - -void TcpTransport::disconnected(AsynchIO&) -{ - close(); - socketClosed(*aio, *socket); -} - -void TcpTransport::socketClosed(AsynchIO&, const Socket&) -{ - bool notify(false); - { - qpid::sys::Mutex::ScopedLock l(lock); - if (!closed) { - closed = true; - if (aio) - aio->queueForDeletion(); - QPID_LOG(debug, id << " Socket closed"); - notify = true; - } //else has already been closed - } - if (notify) context.closed(); -} - -void TcpTransport::abort() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!closed) { - if (aio) { - // Established connection - aio->requestCallback(boost::bind(&TcpTransport::eof, this, _1)); - } else if (connector) { - // We're still connecting - connector->stop(); - failed("Connection timedout"); - } - } -} - -void TcpTransport::activateOutput() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!closed && 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 deleted file mode 100644 index 3e59ec97b2..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_TCPTRANSPORT_H -#define QPID_MESSAGING_AMQP_TCPTRANSPORT_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/messaging/amqp/Transport.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Socket.h" -#include -#include - -namespace qpid { -namespace sys { -class ConnectionCodec; -class AsynchConnector; -class AsynchIO; -struct AsynchIOBufferBase; -class Poller; -} -namespace messaging { -namespace amqp { -class TransportContext; - -class TcpTransport : public Transport -{ - public: - TcpTransport(TransportContext&, boost::shared_ptr); - - void connect(const std::string& host, const std::string& port); - - void activateOutput(); - void abort(); - void connectionEstablished() {}; - void close(); - const qpid::sys::SecuritySettings* getSecuritySettings(); - - protected: - boost::scoped_ptr socket; - TransportContext& context; - qpid::sys::AsynchConnector* connector; - qpid::sys::AsynchIO* aio; - boost::shared_ptr poller; - std::string id; - - virtual ~TcpTransport() {} - virtual void connected(const qpid::sys::Socket&); - void failed(const std::string& msg); - void read(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); - void write(qpid::sys::AsynchIO&); - void eof(qpid::sys::AsynchIO&); - void disconnected(qpid::sys::AsynchIO&); - void socketClosed(qpid::sys::AsynchIO&, const qpid::sys::Socket&); - - private: - bool closed; - qpid::sys::Mutex lock; -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_TCPTRANSPORT_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/Transaction.cpp b/qpid/cpp/src/qpid/messaging/amqp/Transaction.cpp deleted file mode 100644 index 754b00d802..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/Transaction.cpp +++ /dev/null @@ -1,155 +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 "Transaction.h" -#include "SessionContext.h" -#include "ConnectionContext.h" -#include "PnData.h" -#include -#include -#include -#include -#include -#include "qpid/messaging/Message.h" - -namespace qpid { -namespace messaging { -namespace amqp { - -using namespace types; -using types::Exception; - -namespace { -const std::string LOCAL_TRANSACTIONS("amqp:local-transactions"); -const std::string TX_COORDINATOR("tx-transaction"); -const std::string ADDRESS("tx-transaction;{link:{reliability:at-least-once}}"); -} - -Transaction::Transaction(pn_session_t* session) : - SenderContext(session, TX_COORDINATOR, Address(ADDRESS), false), committing(false) -{} - -void Transaction::clear() { - id.clear(); - sendState.reset(); - acceptState.reset(); -} - -void Transaction::configure() { - SenderContext::configure(); - pn_terminus_t* target = pn_link_target(sender); - pn_terminus_set_type(target, PN_COORDINATOR); - PnData(pn_terminus_capabilities(target)).putSymbol(LOCAL_TRANSACTIONS); -} - -void Transaction::verify() {} - -const std::string& Transaction::getTarget() const { return getName(); } - -void Transaction::declare(SendFunction send, const SessionPtr& session) { - committing = false; - error.raise(); - clear(); - Variant declare = Variant::described(qpid::amqp::transaction::DECLARE_CODE, Variant::List()); - SenderContext::Delivery* delivery = 0; - send(session, shared_from_this(), Message(declare), true, &delivery); - setId(*delivery); -} - -void Transaction::discharge(SendFunction send, const SessionPtr& session, bool fail) { - error.raise(); - committing = !fail; - try { - // Send a discharge message to the remote coordinator. - Variant::List dischargeList; - dischargeList.push_back(Variant(id)); - dischargeList.push_back(Variant(fail)); - Variant discharge(dischargeList); - discharge.setDescriptor(qpid::amqp::transaction::DISCHARGE_CODE); - SenderContext::Delivery* delivery = 0; - send(session, shared_from_this(), Message(discharge), true, &delivery); - if (!delivery->accepted()) - throw TransactionAborted(delivery->error()); - committing = false; - } - catch(const TransactionError&) { - throw; - } - catch(const Exception& e) { - committing = false; - throw TransactionAborted(e.what()); - } -} - -// Set the transaction ID from the delivery returned by the remote coordinator. -void Transaction::setId(const SenderContext::Delivery& delivery) -{ - if (delivery.getToken() && - pn_delivery_remote_state(delivery.getToken()) == qpid::amqp::transaction::DECLARED_CODE) - { - pn_data_t* data = pn_disposition_data(pn_delivery_remote(delivery.getToken())); - if (data && pn_data_next(data)) { - size_t count = pn_data_get_list(data); - if (count > 0) { - pn_data_enter(data); - pn_data_next(data); - setId(PnData::string(pn_data_get_binary(data))); - pn_data_exit(data); - return; - } - } - } - throw TransactionError("No transaction ID returned by remote coordinator."); -} - -void Transaction::setId(const std::string& id_) { - id = id_; - if (id.empty()) { - clear(); - } - else { - // NOTE: The send and accept states are NOT described, the descriptor - // is added in pn_delivery_update. - Variant::List list; - list.push_back(Variant(id, "binary")); - sendState = Variant(list); - - Variant accepted = Variant::described(qpid::amqp::message::ACCEPTED_CODE, Variant::List()); - list.push_back(accepted); - acceptState = Variant(list); - } -} - -types::Variant Transaction::getSendState() const { - error.raise(); - return sendState; -} - -void Transaction::acknowledge(pn_delivery_t* delivery) -{ - error.raise(); - PnData data(pn_disposition_data(pn_delivery_local(delivery))); - data.put(acceptState); - pn_delivery_update(delivery, qpid::amqp::transaction::TRANSACTIONAL_STATE_CODE); - pn_delivery_settle(delivery); -} - - - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/Transaction.h b/qpid/cpp/src/qpid/messaging/amqp/Transaction.h deleted file mode 100644 index 35492c9bb3..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/Transaction.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef COORDINATORCONTEXT_H -#define COORDINATORCONTEXT_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 "SenderContext.h" -#include -#include "qpid/sys/ExceptionHolder.h" -#include -#include - -struct pn_session_t; - -namespace qpid { -namespace messaging { -namespace amqp { - -class SessionContext; -class ConnectionContext; - -/** - * Track the current transaction for a session. - * - * Implements SenderContext, to send transaction command messages to remote coordinator. - */ -class Transaction : public SenderContext, public boost::enable_shared_from_this { - public: - typedef boost::shared_ptr SessionPtr; - - typedef boost::function ssn, - boost::shared_ptr snd, - const qpid::messaging::Message& message, - bool sync, - SenderContext::Delivery** delivery)> SendFunction; - - Transaction(pn_session_t*); - - sys::ExceptionHolder error; - - /** Declare a transaction using connection and session to send to remote co-ordinator. */ - void declare(SendFunction, const SessionPtr& session); - - /** Discharge a transaction using connection and session to send to remote co-ordinator. - *@param fail: true means rollback, false means commit. - */ - void discharge(SendFunction, const SessionPtr& session, bool fail); - - /** Update a delivery with a transactional accept state. */ - void acknowledge(pn_delivery_t* delivery); - - /** Get delivery state to attach to transfers sent in a transaction. */ - types::Variant getSendState() const; - - /** Override SenderContext::getTarget with a more readable value */ - const std::string& getTarget() const; - - bool isCommitting() const { return committing; } - - protected: - // SenderContext overrides - void configure(); - void verify(); - - private: - std::string id; - types::Variant sendState; - types::Variant acceptState; - bool committing; - - - void clear(); - void setId(const SenderContext::Delivery& delivery); - void setId(const std::string& id); -}; - -}}} - -#endif diff --git a/qpid/cpp/src/qpid/messaging/amqp/Transport.cpp b/qpid/cpp/src/qpid/messaging/amqp/Transport.cpp deleted file mode 100644 index 21f51046b1..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/Transport.cpp +++ /dev/null @@ -1,50 +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/messaging/amqp/Transport.h" -#include "qpid/messaging/amqp/TransportContext.h" -#include -#include - -namespace qpid { -namespace messaging { -namespace amqp { -namespace { -typedef std::map Registry; - -Registry& theRegistry() -{ - static Registry factories; - return factories; -} -} - -Transport* Transport::create(const std::string& name, TransportContext& context, boost::shared_ptr poller) -{ - Registry::const_iterator i = theRegistry().find(name); - if (i != theRegistry().end()) return (i->second)(context, poller); - else return 0; -} -void Transport::add(const std::string& name, Factory* factory) -{ - theRegistry()[name] = factory; -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/Transport.h b/qpid/cpp/src/qpid/messaging/amqp/Transport.h deleted file mode 100644 index 6ec99ab58f..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/Transport.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_TRANSPORT_H -#define QPID_MESSAGING_AMQP_TRANSPORT_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/sys/OutputControl.h" -#include - -namespace qpid { -namespace sys { -class Poller; -struct SecuritySettings; -} -namespace messaging { -namespace amqp { -class TransportContext; - -class Transport : public qpid::sys::OutputControl -{ - public: - virtual ~Transport() {} - virtual void connect(const std::string& host, const std::string& port) = 0; - virtual void close() = 0; - virtual void abort() = 0; - virtual const qpid::sys::SecuritySettings* getSecuritySettings() = 0; - - typedef Transport* Factory(TransportContext&, boost::shared_ptr); - QPID_COMMON_EXTERN static Transport* create(const std::string& name, TransportContext&, boost::shared_ptr); - QPID_COMMON_EXTERN static void add(const std::string& name, Factory* factory); -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_TRANSPORT_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/TransportContext.h b/qpid/cpp/src/qpid/messaging/amqp/TransportContext.h deleted file mode 100644 index df9add3e0b..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/TransportContext.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_TRANSPORTCONTEXT_H -#define QPID_MESSAGING_AMQP_TRANSPORTCONTEXT_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 { -class Codec; -} -namespace messaging { -struct ConnectionOptions; - -namespace amqp { - -/** - * Interface to be supplied by 'users' of Transport interface, in - * order to provide codec and handle callbaskc for opening and closing - * of connection. - */ -class TransportContext -{ - public: - virtual ~TransportContext() {} - virtual qpid::sys::Codec& getCodec() = 0; - virtual const qpid::messaging::ConnectionOptions* getOptions() = 0; - virtual void closed() = 0; - virtual void opened() = 0; - private: -}; -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_TRANSPORTCONTEXT_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/util.cpp b/qpid/cpp/src/qpid/messaging/amqp/util.cpp deleted file mode 100644 index 870a89e364..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/util.cpp +++ /dev/null @@ -1,43 +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 "util.h" -#include - -namespace qpid { -namespace messaging { -namespace amqp { - -std::string get_error_string(pn_condition_t* error, const std::string& general, const std::string& delim) -{ - std::string name; - std::stringstream text; - if (pn_condition_is_set(error)) { - name = pn_condition_get_name(error); - text << general << delim << name; - const char* desc = pn_condition_get_description(error); - if (desc) text << ": " << desc; - } else { - text << general; - } - return text.str(); -} - -}}} // namespace qpid::messaging::amqp diff --git a/qpid/cpp/src/qpid/messaging/amqp/util.h b/qpid/cpp/src/qpid/messaging/amqp/util.h deleted file mode 100644 index d10ef406dc..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/util.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef QPID_MESSAGING_AMQP_UTIL_H -#define QPID_MESSAGING_AMQP_UTIL_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 -extern "C" { -#include -} -namespace qpid { -namespace messaging { -namespace amqp { - -std::string get_error_string(pn_condition_t* error, const std::string& general, const std::string& delim = std::string(" with ")); - -}}} // namespace qpid::messaging::amqp - -#endif /*!QPID_MESSAGING_AMQP_UTIL_H*/ diff --git a/qpid/cpp/src/qpid/messaging/amqp/windows/SslTransport.cpp b/qpid/cpp/src/qpid/messaging/amqp/windows/SslTransport.cpp deleted file mode 100644 index 5dbc13175f..0000000000 --- a/qpid/cpp/src/qpid/messaging/amqp/windows/SslTransport.cpp +++ /dev/null @@ -1,136 +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/messaging/amqp/TcpTransport.h" -#include "qpid/messaging/amqp/TransportContext.h" -#include "qpid/messaging/ConnectionOptions.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/Poller.h" -#include "qpid/log/Statement.h" -#include -#include - -#include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/util.h" -#include "qpid/sys/windows/SslAsynchIO.h" -#include "qpid/sys/windows/SslCredential.h" - -using namespace qpid::sys; - -namespace qpid { -namespace messaging { -namespace amqp { - -class SslTransport : public TcpTransport -{ - public: - SslTransport(TransportContext&, boost::shared_ptr p); - - void connect(const std::string& host, const std::string& port); - void negotiationDone(SECURITY_STATUS status); - const qpid::sys::SecuritySettings* getSecuritySettings(); - - private: - std::string brokerHost; - qpid::sys::windows::SslCredential sslCredential; - bool certLoaded; - qpid::sys::SecuritySettings securitySettings; - - void connected(const qpid::sys::Socket&); -}; - -// Static constructor which registers connector here -namespace { -Transport* create(TransportContext& c, Poller::shared_ptr p) -{ - return new SslTransport(c, p); -} - -struct StaticInit -{ - StaticInit() - { - Transport::add("ssl", &create); - }; -} init; -} - - -void SslTransport::negotiationDone(SECURITY_STATUS status) -{ - if (status == SEC_E_OK) { - connector = 0; - context.opened(); - id = boost::str(boost::format("[%1%]") % socket->getFullAddress()); - } else { - if (status == SEC_E_INCOMPLETE_CREDENTIALS && !certLoaded) { - // Server requested a client cert but we supplied none for the following reason: - failed(QPID_MSG(sslCredential.error())); - } - else - failed(QPID_MSG(qpid::sys::strError(status))); - } -} - -SslTransport::SslTransport(TransportContext& c, boost::shared_ptr p) : TcpTransport(c, p) -{ - const ConnectionOptions* options = context.getOptions(); - if (options->sslIgnoreHostnameVerificationFailure) { - sslCredential.ignoreHostnameVerificationFailure(); - } - const std::string& name = (options->sslCertName != "") ? - options->sslCertName : qpid::sys::ssl::SslOptions::global.certName; - certLoaded = sslCredential.load(name); - QPID_LOG(debug, "SslTransport created"); -} - -void SslTransport::connect(const std::string& host, const std::string& port) -{ - brokerHost = host; - TcpTransport::connect(host, port); -} - -void SslTransport::connected(const Socket& s) -{ - aio = new qpid::sys::windows::ClientSslAsynchIO(brokerHost, - s, - sslCredential.handle(), - boost::bind(&SslTransport::read, this, _1, _2), - boost::bind(&SslTransport::eof, this, _1), - boost::bind(&SslTransport::disconnected, this, _1), - boost::bind(&SslTransport::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&SslTransport::write, this, _1), - boost::bind(&SslTransport::negotiationDone, this, _1)); - - aio->createBuffers(std::numeric_limits::max());//note: AMQP 1.0 _can_ handle large frame sizes - aio->start(poller); -} - -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/exceptions.cpp b/qpid/cpp/src/qpid/messaging/exceptions.cpp deleted file mode 100644 index af8ab22251..0000000000 --- a/qpid/cpp/src/qpid/messaging/exceptions.cpp +++ /dev/null @@ -1,65 +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/messaging/exceptions.h" - -namespace qpid { -namespace messaging { - -MessagingException::MessagingException(const std::string& msg) : qpid::types::Exception(msg) {} -MessagingException::~MessagingException() throw() {} - -InvalidOptionString::InvalidOptionString(const std::string& msg) : MessagingException(msg) {} -KeyError::KeyError(const std::string& msg) : MessagingException(msg) {} - - -LinkError::LinkError(const std::string& msg) : MessagingException(msg) {} - -AddressError::AddressError(const std::string& msg) : LinkError(msg) {} -ResolutionError::ResolutionError(const std::string& msg) : AddressError(msg) {} -MalformedAddress::MalformedAddress(const std::string& msg) : AddressError(msg) {} -AssertionFailed::AssertionFailed(const std::string& msg) : ResolutionError(msg) {} -NotFound::NotFound(const std::string& msg) : ResolutionError(msg) {} - -ReceiverError::ReceiverError(const std::string& msg) : LinkError(msg) {} -FetchError::FetchError(const std::string& msg) : ReceiverError(msg) {} -NoMessageAvailable::NoMessageAvailable() : FetchError("No message to fetch") {} - -SenderError::SenderError(const std::string& msg) : LinkError(msg) {} -SendError::SendError(const std::string& msg) : SenderError(msg) {} -MessageRejected::MessageRejected(const std::string& msg) : SendError(msg) {} -TargetCapacityExceeded::TargetCapacityExceeded(const std::string& msg) : SendError(msg) {} -OutOfCapacity::OutOfCapacity(const std::string& msg) : SendError(msg) {} - -SessionError::SessionError(const std::string& msg) : MessagingException(msg) {} -SessionClosed::SessionClosed() : SessionError("Session Closed") {} - -TransactionError::TransactionError(const std::string& msg) : SessionError(msg) {} -TransactionAborted::TransactionAborted(const std::string& msg) : TransactionError(msg) {} -TransactionUnknown::TransactionUnknown(const std::string& msg) : TransactionError(msg) {} -UnauthorizedAccess::UnauthorizedAccess(const std::string& msg) : SessionError(msg) {} - -ConnectionError::ConnectionError(const std::string& msg) : MessagingException(msg) {} -ProtocolVersionError::ProtocolVersionError(const std::string& msg) : ConnectionError(msg) {} -AuthenticationFailure::AuthenticationFailure(const std::string& msg) : ConnectionError(msg) {} - -TransportFailure::TransportFailure(const std::string& msg) : MessagingException(msg) {} - -}} // namespace qpid::messaging diff --git a/qpid/cpp/src/qpid/pointer_to_other.h b/qpid/cpp/src/qpid/pointer_to_other.h deleted file mode 100644 index a99dc89658..0000000000 --- a/qpid/cpp/src/qpid/pointer_to_other.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_POINTERTOOTHER_H -#define QPID_POINTERTOOTHER_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 { - -// Defines the same pointer type (raw or smart) to another pointee type - -template -struct pointer_to_other; - -template class Sp> -struct pointer_to_other< Sp, U > - { - typedef Sp type; - }; - -template class Sp> -struct pointer_to_other< Sp, U > - { - typedef Sp type; - }; - -template class Sp> -struct pointer_to_other< Sp, U > - { - typedef Sp type; - }; - -template -struct pointer_to_other< T*, U > -{ - typedef U* type; -}; - -} // namespace qpid - - - -#endif /*!QPID_POINTERTOOTHER_H*/ diff --git a/qpid/cpp/src/qpid/ptr_map.h b/qpid/cpp/src/qpid/ptr_map.h deleted file mode 100644 index 6ffcd48e89..0000000000 --- a/qpid/cpp/src/qpid/ptr_map.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QPID_PTR_MAP -#define QPID_PTR_MAP - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 -#include -#include -#include - -namespace qpid { - -/** @file - * Workaround for API change between boost 1.33 and 1.34. - * - * To be portable across these versions, code using boost::ptr_map - * iterators should use ptr_map_ptr(i) to get the pointer from - * boost::ptr_map::iterator i. - * - * @see http://www.boost.org/libs/ptr_container/doc/ptr_container.html#upgrading-from-boost-v-1-33 - */ - - -typedef boost::is_same::iterator::value_type, int> IsOldPtrMap; - -template -typename boost::enable_if::type -ptr_map_ptr(const Iter& i) { return &*i; } - -template -typename boost::disable_if::type - >::type -ptr_map_ptr(const Iter& i) { return i->second; } - -} // namespace qpid - -#endif /*!QPID_PTR_MAP*/ diff --git a/qpid/cpp/src/qpid/store/CMakeLists.txt b/qpid/cpp/src/qpid/store/CMakeLists.txt deleted file mode 100644 index ec1fa16e7b..0000000000 --- a/qpid/cpp/src/qpid/store/CMakeLists.txt +++ /dev/null @@ -1,116 +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. -# - -project(qpidc_store) - -#set (CMAKE_VERBOSE_MAKEFILE ON) # for debugging - -include_directories( ${Boost_INCLUDE_DIR} ) - -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -include_directories( ${CMAKE_HOME_DIRECTORY}/include ) - -set (store_SOURCES - MessageStorePlugin.cpp - ) -add_library (store MODULE ${store_SOURCES}) -target_link_libraries (store qpidbroker qpidcommon) -if (CMAKE_COMPILER_IS_GNUCXX) - set (GCC_CATCH_UNDEFINED "-Wl,--no-undefined") - # gcc on SunOS uses native linker whose "-z defs" is too fussy - if (CMAKE_SYSTEM_NAME STREQUAL SunOS) - set (GCC_CATCH_UNDEFINED "") - endif (CMAKE_SYSTEM_NAME STREQUAL SunOS) - - set_target_properties (store PROPERTIES - PREFIX "" - LINK_FLAGS "${GCC_CATCH_UNDEFINED}") -endif (CMAKE_COMPILER_IS_GNUCXX) - -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (MSVC) - add_definitions( - /D "NOMINMAX" - /D "WIN32_LEAN_AND_MEAN" - ) - endif (MSVC) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -set_target_properties (store PROPERTIES - VERSION ${qpidc_version}) -install (TARGETS store # RUNTIME - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - -# Build the MS SQL Storage Provider plugin -set (mssql_default ON) -if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) - set(mssql_default OFF) -endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) -option(BUILD_MSSQL "Build MS SQL Store provider plugin" ${mssql_default}) -if (BUILD_MSSQL) - add_library (mssql_store MODULE - ms-sql/MsSqlProvider.cpp - ms-sql/AmqpTransaction.cpp - ms-sql/BindingRecordset.cpp - ms-sql/BlobAdapter.cpp - ms-sql/BlobEncoder.cpp - ms-sql/BlobRecordset.cpp - ms-sql/DatabaseConnection.cpp - ms-sql/MessageMapRecordset.cpp - ms-sql/MessageRecordset.cpp - ms-sql/Recordset.cpp - ms-sql/SqlTransaction.cpp - ms-sql/State.cpp - ms-sql/TplRecordset.cpp - ms-sql/VariantHelper.cpp) - target_link_libraries (mssql_store qpidbroker qpidcommon) - install (TARGETS mssql_store # RUNTIME - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) -endif (BUILD_MSSQL) - -# Build the MS SQL-CLFS Storage Provider plugin -set (msclfs_default ON) -if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) - set(msclfs_default OFF) -endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) -option(BUILD_MSCLFS "Build MS hybrid SQL-CLFS Store provider plugin" ${msclfs_default}) -if (BUILD_MSCLFS) - add_library (msclfs_store MODULE - ms-clfs/MsSqlClfsProvider.cpp - ms-clfs/Log.cpp - ms-clfs/MessageLog.cpp - ms-clfs/Messages.cpp - ms-clfs/Transaction.cpp - ms-clfs/TransactionLog.cpp - ms-sql/BindingRecordset.cpp - ms-sql/BlobAdapter.cpp - ms-sql/BlobEncoder.cpp - ms-sql/BlobRecordset.cpp - ms-sql/DatabaseConnection.cpp - ms-sql/Recordset.cpp - ms-sql/State.cpp - ms-sql/VariantHelper.cpp) - include_directories(ms-sql) - target_link_libraries (msclfs_store qpidbroker qpidcommon clfsw32.lib) - install (TARGETS msclfs_store # RUNTIME - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) -endif (BUILD_MSCLFS) diff --git a/qpid/cpp/src/qpid/store/MessageStorePlugin.cpp b/qpid/cpp/src/qpid/store/MessageStorePlugin.cpp deleted file mode 100644 index b876bd6b6d..0000000000 --- a/qpid/cpp/src/qpid/store/MessageStorePlugin.cpp +++ /dev/null @@ -1,463 +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 "MessageStorePlugin.h" -#include "StorageProvider.h" -#include "StoreException.h" -#include "qpid/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/DataDir.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace store { - -/* - * The MessageStore pointer given to the Broker points to static storage. - * Thus, it cannot be deleted, especially by the broker. To prevent deletion, - * this no-op deleter is used with the boost::shared_ptr. When the last - * shared_ptr is destroyed, the deleter is called rather than delete(). - */ -namespace { - class NoopDeleter { - public: - NoopDeleter() {} - void operator()(qpid::broker::MessageStore * /*p*/) {} - }; -} - -static MessageStorePlugin static_instance_registers_plugin; - - -MessageStorePlugin::StoreOptions::StoreOptions(const std::string& name) : - qpid::Options(name) -{ - addOptions() - ("storage-provider", qpid::optValue(providerName, "PROVIDER"), - "Name of the storage provider to use.") - ; -} - - -void -MessageStorePlugin::earlyInitialize (qpid::Plugin::Target& target) -{ - qpid::broker::Broker* b = - dynamic_cast(&target); - if (0 == b) - return; // Only listen to Broker targets - - broker = b; - - // See if there are any storage provider plugins ready. If not, we can't - // do a message store. - qpid::Plugin::earlyInitAll(*this); - - if (providers.empty()) { - QPID_LOG(warning, - "Message store plugin: No storage providers available."); - provider = providers.end(); - return; - } - if (!options.providerName.empty()) { - // If specific one was chosen, locate it in loaded set of providers. - provider = providers.find(options.providerName); - if (provider == providers.end()) - throw Exception("Message store plugin: storage provider '" + - options.providerName + - "' does not exist."); - } - else { - // No specific provider chosen; if there's only one, use it. Else - // report the need to pick one. - if (providers.size() > 1) { - provider = providers.end(); - throw Exception("Message store plugin: multiple provider plugins " - "loaded; must either load only one or select one " - "using --storage-provider"); - } - provider = providers.begin(); - } - - provider->second->activate(*this); - NoopDeleter d; - boost::shared_ptr sp(this, d); - broker->setStore(sp); - target.addFinalizer(boost::bind(&MessageStorePlugin::finalizeMe, this)); -} - -void -MessageStorePlugin::initialize(qpid::Plugin::Target& target) -{ - qpid::broker::Broker* broker = - dynamic_cast(&target); - if (0 == broker) - return; // Only listen to Broker targets - - // Pass along the initialize step to the provider that's activated. - if (provider != providers.end()) { - provider->second->initialize(*this); - } - // qpid::Plugin::initializeAll(*this); -} - -void -MessageStorePlugin::finalizeMe() -{ - finalize(); // Call finalizers on any Provider plugins -} - -void -MessageStorePlugin::providerAvailable(const std::string name, - StorageProvider *be) -{ - ProviderMap::value_type newSp(name, be); - std::pair inserted = providers.insert(newSp); - if (inserted.second == false) - QPID_LOG(warning, "Storage provider " << name << " duplicate; ignored."); -} - - -/** - * Record the existence of a durable queue - */ -void -MessageStorePlugin::create(broker::PersistableQueue& queue, - const framing::FieldTable& args) -{ - if (queue.getName().size() == 0) - { - QPID_LOG(error, - "Cannot create store for empty (null) queue name - " - "ignoring and attempting to continue."); - return; - } - if (queue.getPersistenceId()) { - THROW_STORE_EXCEPTION("Queue already created: " + queue.getName()); - } - provider->second->create(queue, args); -} - -/** - * Destroy a durable queue - */ -void -MessageStorePlugin::destroy(broker::PersistableQueue& queue) -{ - provider->second->destroy(queue); -} - -/** - * Record the existence of a durable exchange - */ -void -MessageStorePlugin::create(const broker::PersistableExchange& exchange, - const framing::FieldTable& args) -{ - if (exchange.getPersistenceId()) { - THROW_STORE_EXCEPTION("Exchange already created: " + exchange.getName()); - } - provider->second->create(exchange, args); -} - -/** - * Destroy a durable exchange - */ -void -MessageStorePlugin::destroy(const broker::PersistableExchange& exchange) -{ - provider->second->destroy(exchange); -} - -/** - * Record a binding - */ -void -MessageStorePlugin::bind(const broker::PersistableExchange& exchange, - const broker::PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args) -{ - provider->second->bind(exchange, queue, key, args); -} - -/** - * Forget a binding - */ -void -MessageStorePlugin::unbind(const broker::PersistableExchange& exchange, - const broker::PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args) -{ - provider->second->unbind(exchange, queue, key, args); -} - -/** - * Record generic durable configuration - */ -void -MessageStorePlugin::create(const broker::PersistableConfig& config) -{ - if (config.getPersistenceId()) { - THROW_STORE_EXCEPTION("Config item already created: " + - config.getName()); - } - provider->second->create(config); -} - -/** - * Destroy generic durable configuration - */ -void -MessageStorePlugin::destroy(const broker::PersistableConfig& config) -{ - provider->second->destroy(config); -} - -/** - * Stores a message before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). - */ -void -MessageStorePlugin::stage(const boost::intrusive_ptr& msg) -{ - if (msg->getPersistenceId() == 0) { - provider->second->stage(msg); - } -} - -/** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ -void -MessageStorePlugin::destroy(broker::PersistableMessage& msg) -{ - if (msg.getPersistenceId()) - provider->second->destroy(msg); -} - -/** - * Appends content to a previously staged message - */ -void -MessageStorePlugin::appendContent - (const boost::intrusive_ptr& msg, - const std::string& data) -{ - if (msg->getPersistenceId()) - provider->second->appendContent(msg, data); - else - THROW_STORE_EXCEPTION("Cannot append content. Message not known to store!"); -} - -/** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ -void -MessageStorePlugin::loadContent(const broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length) -{ - if (msg->getPersistenceId()) - provider->second->loadContent(queue, msg, data, offset, length); - else - THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!"); -} - -/** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - */ -void -MessageStorePlugin::enqueue(broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const broker::PersistableQueue& queue) -{ - if (queue.getPersistenceId() == 0) { - THROW_STORE_EXCEPTION("Queue not created: " + queue.getName()); - } - provider->second->enqueue(ctxt, msg, queue); -} - -/** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - */ -void -MessageStorePlugin::dequeue(broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const broker::PersistableQueue& queue) -{ - provider->second->dequeue(ctxt, msg, queue); -} - -/** - * Flushes all async messages to disk for the specified queue - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - */ -void -MessageStorePlugin::flush(const broker::PersistableQueue& queue) -{ - provider->second->flush(queue); -} - -/** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk. - */ -uint32_t -MessageStorePlugin::outstandingQueueAIO(const broker::PersistableQueue& queue) -{ - return provider->second->outstandingQueueAIO(queue); -} - -std::auto_ptr -MessageStorePlugin::begin() -{ - return provider->second->begin(); -} - -std::auto_ptr -MessageStorePlugin::begin(const std::string& xid) -{ - return provider->second->begin(xid); -} - -void -MessageStorePlugin::prepare(broker::TPCTransactionContext& ctxt) -{ - provider->second->prepare(ctxt); -} - -void -MessageStorePlugin::commit(broker::TransactionContext& ctxt) -{ - provider->second->commit(ctxt); -} - -void -MessageStorePlugin::abort(broker::TransactionContext& ctxt) -{ - provider->second->abort(ctxt); -} - -void -MessageStorePlugin::collectPreparedXids(std::set& xids) -{ - provider->second->collectPreparedXids(xids); -} - -/** - * Request recovery of queue and message state; inherited from Recoverable - */ -void -MessageStorePlugin::recover(broker::RecoveryManager& recoverer) -{ - ExchangeMap exchanges; - QueueMap queues; - MessageMap messages; - MessageQueueMap messageQueueMap; - std::vector xids; - PreparedTransactionMap dtxMap; - - provider->second->recoverConfigs(recoverer); - provider->second->recoverExchanges(recoverer, exchanges); - provider->second->recoverQueues(recoverer, queues); - provider->second->recoverBindings(recoverer, exchanges, queues); - // Important to recover messages before transactions in the SQL-CLFS - // case. If this becomes a problem, it may be possible to resolve it. - // If in doubt please raise a jira and notify Steve Huston - // . - provider->second->recoverMessages(recoverer, messages, messageQueueMap); - provider->second->recoverTransactions(recoverer, dtxMap); - // Enqueue msgs where needed. - for (MessageQueueMap::const_iterator i = messageQueueMap.begin(); - i != messageQueueMap.end(); - ++i) { - // Locate the message corresponding to the current message Id - MessageMap::const_iterator iMsg = messages.find(i->first); - if (iMsg == messages.end()) { - std::ostringstream oss; - oss << "No matching message trying to re-enqueue message " - << i->first; - THROW_STORE_EXCEPTION(oss.str()); - } - broker::RecoverableMessage::shared_ptr msg = iMsg->second; - // Now for each queue referenced in the queue map, locate it - // and re-enqueue the message. - for (std::vector::const_iterator j = i->second.begin(); - j != i->second.end(); - ++j) { - // Locate the queue corresponding to the current queue Id - QueueMap::const_iterator iQ = queues.find(j->queueId); - if (iQ == queues.end()) { - std::ostringstream oss; - oss << "No matching queue trying to re-enqueue message " - << " on queue Id " << j->queueId; - THROW_STORE_EXCEPTION(oss.str()); - } - // Messages involved in prepared transactions have their status - // updated accordingly. First, though, restore a message that - // is expected to be on a queue, including non-transacted - // messages and those pending dequeue in a dtx. - if (j->tplStatus != QueueEntry::ADDING) - iQ->second->recover(msg); - switch(j->tplStatus) { - case QueueEntry::ADDING: - dtxMap[j->xid]->enqueue(iQ->second, msg); - break; - case QueueEntry::REMOVING: - dtxMap[j->xid]->dequeue(iQ->second, msg); - break; - default: - break; - } - } - } -} - -}} // namespace qpid::store diff --git a/qpid/cpp/src/qpid/store/MessageStorePlugin.h b/qpid/cpp/src/qpid/store/MessageStorePlugin.h deleted file mode 100644 index 5290fc16db..0000000000 --- a/qpid/cpp/src/qpid/store/MessageStorePlugin.h +++ /dev/null @@ -1,280 +0,0 @@ -#ifndef QPID_STORE_MESSAGESTOREPLUGIN_H -#define QPID_STORE_MESSAGESTOREPLUGIN_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/Plugin.h" -#include "qpid/Options.h" -#include "qpid/broker/MessageStore.h" -//#include "qpid/management/Manageable.h" - -#include - -using namespace qpid; - -namespace qpid { - -namespace broker { -class Broker; -class PersistableExchange; -class PersistableMessage; -class PersistableQueue; -} - -namespace store { - -class StorageProvider; - -/** - * @class MessageStorePlugin - * - * MessageStorePlugin is the front end of the persistent message store - * plugin. It is responsible for coordinating recovery, initialization, - * transactions (both local and distributed), flow-to-disk loading and - * unloading and persisting broker state (queues, bindings etc.). - * Actual storage operations are carried out by a message store storage - * provider that implements the qpid::store::StorageProvider interface. - */ -class MessageStorePlugin : - public qpid::Plugin, - public qpid::broker::MessageStore, // Frontend classes - public qpid::Plugin::Target // Provider target - // @TODO Need a mgmt story for this. Maybe allow r/o access to provider store info? public qpid::management::Manageable -{ - public: - MessageStorePlugin() : broker(0) {} - - /** - * @name Methods inherited from qpid::Plugin - */ - //@{ - virtual Options* getOptions() { return &options; } - virtual void earlyInitialize (Plugin::Target& target); - virtual void initialize(Plugin::Target& target); - //@} - - /// Finalizer; calls Target::finalize() to run finalizers on - /// StorageProviders. - void finalizeMe(); - - /** - * Called by StorageProvider instances during the earlyInitialize sequence. - * Each StorageProvider must supply a unique name by which it is known and a - * pointer to itself. - */ - virtual void providerAvailable(const std::string name, StorageProvider *be); - - /** - * @name Methods inherited from qpid::broker::MessageStore - */ - - /** - * Record the existence of a durable queue - */ - virtual void create(broker::PersistableQueue& queue, - const framing::FieldTable& args); - /** - * Destroy a durable queue - */ - virtual void destroy(broker::PersistableQueue& queue); - - /** - * Record the existence of a durable exchange - */ - virtual void create(const broker::PersistableExchange& exchange, - const framing::FieldTable& args); - /** - * Destroy a durable exchange - */ - virtual void destroy(const broker::PersistableExchange& exchange); - - /** - * Record a binding - */ - virtual void bind(const broker::PersistableExchange& exchange, - const broker::PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - - /** - * Forget a binding - */ - virtual void unbind(const broker::PersistableExchange& exchange, - const broker::PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - - /** - * Record generic durable configuration - */ - virtual void create(const broker::PersistableConfig& config); - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const broker::PersistableConfig& config); - - /** - * Stores a message before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr& msg); - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(broker::PersistableMessage& msg); - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr& msg, - const std::string& data); - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const broker::PersistableQueue& queue); - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const broker::PersistableQueue& queue); - - /** - * Flushes all async messages to disk for the specified queue - * - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const broker::PersistableQueue& queue); - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const broker::PersistableQueue& queue); - //@} - - /** - * @name Methods inherited from qpid::broker::TransactionalStore - */ - //@{ - std::auto_ptr begin(); - - std::auto_ptr begin(const std::string& xid); - - void prepare(broker::TPCTransactionContext& ctxt); - - void commit(broker::TransactionContext& ctxt); - - void abort(broker::TransactionContext& ctxt); - - void collectPreparedXids(std::set& xids); - //@} - - /** - * Request recovery of queue and message state; inherited from Recoverable - */ - virtual void recover(broker::RecoveryManager& recoverer); - - // inline management::Manageable::status_t ManagementMethod (uint32_t, management::Args&, std::string&) - // { return management::Manageable::STATUS_OK; } - - // So storage provider can get the broker info. - broker::Broker *getBroker() { return broker; } - - protected: - - struct StoreOptions : public qpid::Options { - StoreOptions(const std::string& name="Store Options"); - std::string providerName; - }; - StoreOptions options; - - typedef std::map ProviderMap; - ProviderMap providers; - ProviderMap::const_iterator provider; - - broker::Broker *broker; - -}; // class MessageStoreImpl - -}} // namespace qpid::store - -#endif /* QPID_SERIALIZER_H */ diff --git a/qpid/cpp/src/qpid/store/StorageProvider.h b/qpid/cpp/src/qpid/store/StorageProvider.h deleted file mode 100644 index de12ffb869..0000000000 --- a/qpid/cpp/src/qpid/store/StorageProvider.h +++ /dev/null @@ -1,329 +0,0 @@ -#ifndef QPID_STORE_STORAGEPROVIDER_H -#define QPID_STORE_STORAGEPROVIDER_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 -#include -#include -#include "qpid/Exception.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/broker/MessageStore.h" - -using qpid::broker::PersistableConfig; -using qpid::broker::PersistableExchange; -using qpid::broker::PersistableMessage; -using qpid::broker::PersistableQueue; - -namespace qpid { -namespace store { - -typedef std::map - ExchangeMap; -typedef std::map - QueueMap; -typedef std::map - MessageMap; -// Msg Id -> vector of queue entries where message is queued -struct QueueEntry { - enum TplStatus { NONE = 0, ADDING = 1, REMOVING = 2 }; - uint64_t queueId; - TplStatus tplStatus; - std::string xid; - - QueueEntry(uint64_t id, TplStatus tpl = NONE, const std::string& x = "") - : queueId(id), tplStatus(tpl), xid(x) {} - - bool operator==(const QueueEntry& rhs) const { - if (queueId != rhs.queueId) return false; - if (tplStatus == NONE && rhs.tplStatus == NONE) return true; - return xid == rhs.xid; - } -}; -typedef std::map > MessageQueueMap; -typedef std::map - PreparedTransactionMap; - -class MessageStorePlugin; - -/** - * @class StorageProvider - * - * StorageProvider defines the interface for the storage provider plugin to the - * Qpid broker persistence store plugin. - * - * @TODO Should StorageProvider also inherit from MessageStore? If so, then - * maybe remove Recoverable from MessageStore's inheritance and move it - * to MessageStorePlugin? In any event, somehow the discardInit() feature - * needs to get added here. - */ -class StorageProvider : public qpid::Plugin, public qpid::broker::MessageStore -{ -public: - - class Exception : public qpid::Exception - { - public: - virtual ~Exception() throw() {} - virtual const char *what() const throw() = 0; - }; - - /** - * @name Methods inherited from qpid::Plugin - */ - //@{ - /** - * Return a pointer to the provider's options. The options will be - * updated during option parsing by the host program; therefore, the - * referenced Options object must remain valid past this function's return. - * - * @return An options group or 0 for no options. Default returns 0. - * Plugin retains ownership of return value. - */ - virtual qpid::Options* getOptions() = 0; - - /** - * Initialize Plugin functionality on a Target, called before - * initializing the target. - * - * StorageProviders should respond only to Targets of class - * qpid::store::MessageStorePlugin and ignore all others. - * - * When called, the provider should invoke the method - * qpid::store::MessageStorePlugin::providerAvailable() to alert the - * message store of StorageProvider's availability. - * - * Called before the target itself is initialized. - */ - virtual void earlyInitialize (Plugin::Target& target) = 0; - - /** - * Initialize StorageProvider functionality. Called after initializing - * the target. - * - * StorageProviders should respond only to Targets of class - * qpid::store::MessageStorePlugin and ignore all others. - * - * Called after the target is fully initialized. - */ - virtual void initialize(Plugin::Target& target) = 0; - //@} - - /** - * Receive notification that this provider is the one that will actively - * handle storage for the target. If the provider is to be used, this - * method will be called after earlyInitialize() and before any - * recovery operations (recovery, in turn, precedes call to initialize()). - * Thus, it is wise to not actually do any database ops from within - * earlyInitialize() - they can wait until activate() is called because - * at that point it is certain the database will be needed. - */ - virtual void activate(MessageStorePlugin &store) = 0; - - /** - * @name Methods inherited from qpid::broker::MessageStore - */ - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const qpid::framing::FieldTable& args) = 0; - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue) = 0; - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args) = 0; - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange) = 0; - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) = 0; - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) = 0; - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config) = 0; - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config) = 0; - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr& msg) = 0; - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg) = 0; - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr& msg, - const std::string& data) = 0; - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length) = 0; - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) = 0; - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) = 0; - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const qpid::broker::PersistableQueue& queue) = 0; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) = 0; - //@} - - /** - * @TODO This should probably not be here - it's only here because - * MessageStore inherits from Recoverable... maybe move that derivation. - * - * As it is now, we don't use this. Separate recover methods are - * declared below for individual types, which also set up maps of - * messages, queues, transactions for the main store plugin to handle - * properly. - * - * Request recovery of queue and message state. - */ - virtual void recover(qpid::broker::RecoveryManager& /*recoverer*/) {} - - /** - * @name Methods that do the recovery of the various objects that - * were saved. - */ - //@{ - - /** - * Recover bindings. - */ - virtual void recoverConfigs(qpid::broker::RecoveryManager& recoverer) = 0; - virtual void recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap) = 0; - virtual void recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap) = 0; - virtual void recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap) = 0; - virtual void recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap) = 0; - virtual void recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap) = 0; - //@} -}; - -}} // namespace qpid::store - -#endif /* QPID_STORE_STORAGEPROVIDER_H */ diff --git a/qpid/cpp/src/qpid/store/StoreException.h b/qpid/cpp/src/qpid/store/StoreException.h deleted file mode 100644 index 1dc7f670ec..0000000000 --- a/qpid/cpp/src/qpid/store/StoreException.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef QPID_STORE_STOREEXCEPTION_H -#define QPID_STORE_STOREEXCEPTION_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 -#include -#include "StorageProvider.h" - -namespace qpid { -namespace store { - -class StoreException : public std::exception -{ - std::string text; -public: - StoreException(const std::string& _text) : text(_text) {} - StoreException(const std::string& _text, - const StorageProvider::Exception& cause) - : text(_text + ": " + cause.what()) {} - virtual ~StoreException() throw() {} - virtual const char* what() const throw() { return text.c_str(); } -}; - -#define THROW_STORE_EXCEPTION(MESSAGE) throw qpid::store::StoreException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__)) -#define THROW_STORE_EXCEPTION_2(MESSAGE, EXCEPTION) throw qpid::store::StoreException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__), EXCEPTION) - -}} // namespace qpid::store - -#endif /* QPID_STORE_STOREEXCEPTION_H */ diff --git a/qpid/cpp/src/qpid/store/ms-clfs/Log.cpp b/qpid/cpp/src/qpid/store/ms-clfs/Log.cpp deleted file mode 100644 index e6cb10c133..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/Log.cpp +++ /dev/null @@ -1,182 +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 -#include -#include -#include -#include -#include -#include -#include - -#include "Log.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -Log::~Log() -{ - if (marshal != 0) - ::DeleteLogMarshallingArea(marshal); - ::CloseHandle(handle); -} - -void -Log::open(const std::string& path, const TuningParameters& params) -{ - this->containerSize = static_cast(params.containerSize); - logPath = path; - std::string logSpec = "log:" + path; - size_t specLength = logSpec.length(); - std::auto_ptr wLogSpec(new wchar_t[specLength + 1]); - size_t converted; - mbstowcs_s(&converted, - wLogSpec.get(), specLength+1, - logSpec.c_str(), specLength); - handle = ::CreateLogFile(wLogSpec.get(), - GENERIC_WRITE | GENERIC_READ, - 0, - 0, - OPEN_ALWAYS, - 0); - QPID_WINDOWS_CHECK_NOT(handle, INVALID_HANDLE_VALUE); - CLFS_INFORMATION info; - ULONG infoSize = sizeof(info); - BOOL ok = ::GetLogFileInformation(handle, &info, &infoSize); - QPID_WINDOWS_CHECK_NOT(ok, 0); - ok = ::RegisterManageableLogClient(handle, 0); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - // Set up policies for how many containers to initially create and how - // large each container should be. Also, auto-grow the log when container - // space runs out. - CLFS_MGMT_POLICY logPolicy; - logPolicy.Version = CLFS_MGMT_POLICY_VERSION; - logPolicy.LengthInBytes = sizeof(logPolicy); - logPolicy.PolicyFlags = 0; - - // If this is the first time this log is opened, give an opportunity to - // initialize its content. - bool needInitialize(false); - if (info.TotalContainers == 0) { - // New log; set the configured container size and create the - // initial set of containers. - logPolicy.PolicyType = ClfsMgmtPolicyNewContainerSize; - logPolicy.PolicyParameters.NewContainerSize.SizeInBytes = containerSize; - ok = ::InstallLogPolicy(handle, &logPolicy); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - ULONGLONG desired(params.containers), actual(0); - ok = ::SetLogFileSizeWithPolicy(handle, &desired, &actual); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - needInitialize = true; - } - // Ensure that the log is extended as needed and will shrink when 50% - // becomes unused. - logPolicy.PolicyType = ClfsMgmtPolicyAutoGrow; - logPolicy.PolicyParameters.AutoGrow.Enabled = 1; - ok = ::InstallLogPolicy(handle, &logPolicy); - QPID_WINDOWS_CHECK_NOT(ok, 0); - logPolicy.PolicyType = ClfsMgmtPolicyAutoShrink; - logPolicy.PolicyParameters.AutoShrink.Percentage = params.shrinkPct; - ok = ::InstallLogPolicy(handle, &logPolicy); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - // Need a marshaling area - ok = ::CreateLogMarshallingArea(handle, - NULL, NULL, NULL, // Alloc, free, context - marshallingBufferSize(), - params.maxWriteBuffers, - 1, // Max read buffers - &marshal); - QPID_WINDOWS_CHECK_NOT(ok, 0); - if (needInitialize) - initialize(); -} - -uint32_t -Log::marshallingBufferSize() -{ - // Default implementation returns the minimum marshalling buffer size; - // derived ones should come up with a more fitting value. - // - // Find the directory name part of the log specification, including the - // trailing '\'. - size_t dirMarker = logPath.rfind('\\'); - if (dirMarker == std::string::npos) - dirMarker = logPath.rfind('/'); - DWORD bytesPerSector; - DWORD dontCare; - ::GetDiskFreeSpace(logPath.substr(0, dirMarker).c_str(), - &dontCare, - &bytesPerSector, - &dontCare, - &dontCare); - return bytesPerSector; -} - -CLFS_LSN -Log::write(void* entry, uint32_t length, CLFS_LSN* prev) -{ - CLFS_WRITE_ENTRY desc; - desc.Buffer = entry; - desc.ByteLength = length; - CLFS_LSN lsn; - BOOL ok = ::ReserveAndAppendLog(marshal, - &desc, 1, // Buffer descriptor - 0, prev, // Undo-Next, Prev - 0, 0, // Reservation - CLFS_FLAG_FORCE_FLUSH, - &lsn, - 0); - QPID_WINDOWS_CHECK_NOT(ok, 0); - return lsn; -} - -// Get the current base LSN of the log. -CLFS_LSN -Log::getBase() -{ - CLFS_INFORMATION info; - ULONG infoSize = sizeof(info); - BOOL ok = ::GetLogFileInformation(handle, &info, &infoSize); - QPID_WINDOWS_CHECK_NOT(ok, 0); - return info.BaseLsn; -} - -void -Log::moveTail(const CLFS_LSN& oldest) -{ - BOOL ok = ::AdvanceLogBase(marshal, - const_cast(&oldest), - 0, NULL); - // If multiple threads are manipulating things they may get out of - // order when moving the tail; if someone already moved it further - // than this, it's ok - ignore it. - if (ok || ::GetLastError() == ERROR_LOG_START_OF_LOG) - return; - QPID_WINDOWS_CHECK_NOT(ok, 0); -} - -}}} // namespace qpid::store::ms_clfs diff --git a/qpid/cpp/src/qpid/store/ms-clfs/Log.h b/qpid/cpp/src/qpid/store/ms-clfs/Log.h deleted file mode 100644 index 2f7eb6cada..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/Log.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_LOG_H -#define QPID_STORE_MSCLFS_LOG_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 -#include -#include -#include - -namespace qpid { -namespace store { -namespace ms_clfs { - -/** - * @class Log - * - * Represents a CLFS-housed log. - */ -class Log { - -protected: - HANDLE handle; - ULONGLONG containerSize; - std::string logPath; - PVOID marshal; - - // Give subclasses a chance to initialize a new log. Called after a new - // log is created, initial set of containers is added, and marshalling - // area is allocated. - virtual void initialize() {} - -public: - struct TuningParameters { - size_t containerSize; - unsigned short containers; - unsigned short shrinkPct; - uint32_t maxWriteBuffers; - }; - - Log() : handle(INVALID_HANDLE_VALUE), containerSize(0), marshal(0) {} - virtual ~Log(); - - void open(const std::string& path, const TuningParameters& params); - - virtual uint32_t marshallingBufferSize(); - - CLFS_LSN write(void* entry, uint32_t length, CLFS_LSN* prev = 0); - - // Get the current base LSN of the log. - CLFS_LSN getBase(); - - // Move the log tail to the indicated LSN. - void moveTail(const CLFS_LSN& oldest); -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_LOG_H */ diff --git a/qpid/cpp/src/qpid/store/ms-clfs/Lsn.h b/qpid/cpp/src/qpid/store/ms-clfs/Lsn.h deleted file mode 100644 index 7f46c1f266..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/Lsn.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_LSN_H -#define QPID_STORE_MSCLFS_LSN_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 - -namespace { - // Make it easy to assign LSNs - inline CLFS_LSN idToLsn(const uint64_t val) - { CLFS_LSN lsn; lsn.Internal = val; return lsn; } - - inline uint64_t lsnToId(const CLFS_LSN& lsn) - { uint64_t val = lsn.Internal; return val; } -} - -#endif /* QPID_STORE_MSCLFS_LSN_H */ diff --git a/qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp b/qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp deleted file mode 100644 index 5ff24e7d33..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp +++ /dev/null @@ -1,1102 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// From ms-sql... -#include "BlobAdapter.h" -#include "BlobRecordset.h" -#include "BindingRecordset.h" -#include "DatabaseConnection.h" -#include "Exception.h" -#include "State.h" -#include "VariantHelper.h" -using qpid::store::ms_sql::BlobAdapter; -using qpid::store::ms_sql::BlobRecordset; -using qpid::store::ms_sql::BindingRecordset; -using qpid::store::ms_sql::DatabaseConnection; -using qpid::store::ms_sql::ADOException; -using qpid::store::ms_sql::State; -using qpid::store::ms_sql::VariantHelper; - -#include "Log.h" -#include "Messages.h" -#include "Transaction.h" -#include "TransactionLog.h" - -// Bring in ADO 2.8 (yes, I know it says "15", but that's it...) -#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ - no_namespace rename("EOF", "EndOfFile") -#include -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; - -// Table names -const std::string TblBinding("tblBinding"); -const std::string TblConfig("tblConfig"); -const std::string TblExchange("tblExchange"); -const std::string TblQueue("tblQueue"); - -} - -namespace qpid { -namespace store { -namespace ms_clfs { - -/** - * @class MSSqlClfsProvider - * - * Implements a qpid::store::StorageProvider that uses a hybrid Microsoft - * SQL Server and Windows CLFS approach as the backend data store for Qpid. - */ -class MSSqlClfsProvider : public qpid::store::StorageProvider -{ -protected: - void finalizeMe(); - - void dump(); - -public: - MSSqlClfsProvider(); - ~MSSqlClfsProvider(); - - virtual qpid::Options* getOptions() { return &options; } - - virtual void earlyInitialize (Plugin::Target& target); - virtual void initialize(Plugin::Target& target); - - /** - * Receive notification that this provider is the one that will actively - * handle provider storage for the target. If the provider is to be used, - * this method will be called after earlyInitialize() and before any - * recovery operations (recovery, in turn, precedes call to initialize()). - */ - virtual void activate(MessageStorePlugin &store); - - /** - * @name Methods inherited from qpid::broker::MessageStore - */ - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const qpid::framing::FieldTable& args); - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue); - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args); - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange); - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config); - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config); - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr& msg); - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg); - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr& msg, - const std::string& data); - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue); - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue); - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: this is a no-op for this provider. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const PersistableQueue& queue) {}; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) - {return 0;} - //@} - - /** - * @name Methods inherited from qpid::broker::TransactionalStore - */ - //@{ - virtual std::auto_ptr begin(); - virtual std::auto_ptr begin(const std::string& xid); - virtual void prepare(qpid::broker::TPCTransactionContext& txn); - virtual void commit(qpid::broker::TransactionContext& txn); - virtual void abort(qpid::broker::TransactionContext& txn); - virtual void collectPreparedXids(std::set& xids); - //@} - - virtual void recoverConfigs(qpid::broker::RecoveryManager& recoverer); - virtual void recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap); - virtual void recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap); - virtual void recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap); - virtual void recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap); - virtual void recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap); - -private: - struct ProviderOptions : public qpid::Options - { - std::string connectString; - std::string catalogName; - std::string storeDir; - size_t containerSize; - unsigned short initialContainers; - uint32_t maxWriteBuffers; - - ProviderOptions(const std::string &name) - : qpid::Options(name), - catalogName("QpidStore"), - containerSize(1024 * 1024), - initialContainers(2), - maxWriteBuffers(10) - { - const enum { NAMELEN = MAX_COMPUTERNAME_LENGTH + 1 }; - TCHAR myName[NAMELEN]; - DWORD myNameLen = NAMELEN; - GetComputerName(myName, &myNameLen); - connectString = "Data Source="; - connectString += myName; - connectString += "\\SQLEXPRESS;Integrated Security=SSPI"; - addOptions() - ("connect", - qpid::optValue(connectString, "STRING"), - "Connection string for the database to use. Will prepend " - "Provider=SQLOLEDB;") - ("catalog", - qpid::optValue(catalogName, "DB NAME"), - "Catalog (database) name") - ("store-dir", - qpid::optValue(storeDir, "DIR"), - "Location to store message and transaction data " - "(default uses data-dir if available)") - ("container-size", - qpid::optValue(containerSize, "VALUE"), - "Bytes per container; min 512K. Only used when creating " - "a new log") - ("initial-containers", - qpid::optValue(initialContainers, "VALUE"), - "Number of containers to add if creating a new log") - ("max-write-buffers", - qpid::optValue(maxWriteBuffers, "VALUE"), - "Maximum write buffers outstanding before log is flushed " - "(0 means no limit)") - ; - } - }; - ProviderOptions options; - std::string brokerDataDir; - Messages messages; - // TransactionLog requires itself to have a shared_ptr reference to start. - TransactionLog::shared_ptr transactions; - - // Each thread has a separate connection to the database and also needs - // to manage its COM initialize/finalize individually. This is done by - // keeping a thread-specific State. - boost::thread_specific_ptr dbState; - - State *initState(); - DatabaseConnection *initConnection(void); - void createDb(DatabaseConnection *db, const std::string &name); - void createLogs(); -}; - -static MSSqlClfsProvider static_instance_registers_plugin; - -void -MSSqlClfsProvider::finalizeMe() -{ - dbState.reset(); -} - -MSSqlClfsProvider::MSSqlClfsProvider() - : options("MS SQL/CLFS Provider options") -{ - transactions.reset(new TransactionLog()); -} - -MSSqlClfsProvider::~MSSqlClfsProvider() -{ -} - -void -MSSqlClfsProvider::earlyInitialize(Plugin::Target &target) -{ - MessageStorePlugin *store = dynamic_cast(&target); - if (store) { - // Check the store dir option; if not specified, need to - // grab the broker's data dir. - if (options.storeDir.empty()) { - const DataDir& dir = store->getBroker()->getDataDir(); - if (dir.isEnabled()) { - options.storeDir = dir.getPath(); - } - else { - QPID_LOG(error, - "MSSQL-CLFS: --store-dir required if --no-data-dir specified"); - return; - } - } - - // If CLFS is not available on this system, give up now. - try { - Log::TuningParameters params; - params.containerSize = options.containerSize; - params.containers = options.initialContainers; - params.shrinkPct = 50; - params.maxWriteBuffers = options.maxWriteBuffers; - std::string msgPath = options.storeDir + "\\" + "messages"; - messages.openLog(msgPath, params); - std::string transPath = options.storeDir + "\\" + "transactions"; - transactions->open(transPath, params); - } - catch (std::exception &e) { - QPID_LOG(error, e.what()); - return; - } - - // If the database init fails, report it and don't register; give - // the rest of the broker a chance to run. - // - // Don't try to initConnection() since that will fail if the - // database doesn't exist. Instead, try to open a connection without - // a database name, then search for the database. There's still a - // chance this provider won't be selected for the store too, so be - // be sure to close the database connection before return to avoid - // leaving a connection up that will not be used. - try { - initState(); // This initializes COM - std::auto_ptr db(new DatabaseConnection()); - db->open(options.connectString, ""); - _ConnectionPtr conn(*db); - _RecordsetPtr pCatalogs = NULL; - VariantHelper catalogName(options.catalogName); - pCatalogs = conn->OpenSchema(adSchemaCatalogs, catalogName); - if (pCatalogs->EndOfFile) { - // Database doesn't exist; create it - QPID_LOG(notice, - "MSSQL-CLFS: Creating database " + options.catalogName); - createDb(db.get(), options.catalogName); - } - else { - QPID_LOG(notice, - "MSSQL-CLFS: Database located: " + options.catalogName); - } - if (pCatalogs) { - if (pCatalogs->State == adStateOpen) - pCatalogs->Close(); - pCatalogs = 0; - } - db->close(); - store->providerAvailable("MSSQL-CLFS", this); - } - catch (qpid::Exception &e) { - QPID_LOG(error, e.what()); - return; - } - store->addFinalizer(boost::bind(&MSSqlClfsProvider::finalizeMe, this)); - } -} - -void -MSSqlClfsProvider::initialize(Plugin::Target& target) -{ -} - -void -MSSqlClfsProvider::activate(MessageStorePlugin &store) -{ - QPID_LOG(info, "MS SQL/CLFS Provider is up"); -} - -void -MSSqlClfsProvider::create(PersistableQueue& queue, - const qpid::framing::FieldTable& /*args needed for jrnl*/) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - try { - db->beginTransaction(); - rsQueues.open(db, TblQueue); - rsQueues.add(queue); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating queue " + queue.getName(), e, errs); - } - catch(std::exception& e) { - db->rollbackTransaction(); - THROW_STORE_EXCEPTION(e.what()); - } -} - -/** - * Destroy a durable queue - */ -void -MSSqlClfsProvider::destroy(PersistableQueue& queue) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsQueues.open(db, TblQueue); - rsBindings.open(db, TblBinding); - // Remove bindings first; the queue IDs can't be ripped out from - // under the references in the bindings table. - rsBindings.removeForQueue(queue.getPersistenceId()); - rsQueues.remove(queue); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting queue " + queue.getName(), e, errs); - } - - /* - * Now that the SQL stuff has recorded the queue deletion, expunge - * all record of the queue from the messages set. Any errors logging - * these removals are swallowed because during a recovery the queue - * Id won't be present (the SQL stuff already committed) so any references - * to it in message operations will be removed. - */ - messages.expunge(queue.getPersistenceId()); -} - -/** - * Record the existence of a durable exchange - */ -void -MSSqlClfsProvider::create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - try { - db->beginTransaction(); - rsExchanges.open(db, TblExchange); - rsExchanges.add(exchange); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating exchange " + exchange.getName(), - e, - errs); - } -} - -/** - * Destroy a durable exchange - */ -void -MSSqlClfsProvider::destroy(const PersistableExchange& exchange) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsExchanges.open(db, TblExchange); - rsBindings.open(db, TblBinding); - // Remove bindings first; the exchange IDs can't be ripped out from - // under the references in the bindings table. - rsBindings.removeForExchange(exchange.getPersistenceId()); - rsExchanges.remove(exchange); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting exchange " + exchange.getName(), - e, - errs); - } -} - -/** - * Record a binding - */ -void -MSSqlClfsProvider::bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsBindings.open(db, TblBinding); - rsBindings.add(exchange.getPersistenceId(), - queue.getPersistenceId(), - key, - args); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error binding exchange " + exchange.getName() + - " to queue " + queue.getName(), - e, - errs); - } -} - -/** - * Forget a binding - */ -void -MSSqlClfsProvider::unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsBindings.open(db, TblBinding); - rsBindings.remove(exchange.getPersistenceId(), - queue.getPersistenceId(), - key, - args); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error unbinding exchange " + exchange.getName() + - " from queue " + queue.getName(), - e, - errs); - } -} - -/** - * Record generic durable configuration - */ -void -MSSqlClfsProvider::create(const PersistableConfig& config) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - try { - db->beginTransaction(); - rsConfigs.open(db, TblConfig); - rsConfigs.add(config); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating config " + config.getName(), e, errs); - } -} - -/** - * Destroy generic durable configuration - */ -void -MSSqlClfsProvider::destroy(const PersistableConfig& config) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - try { - db->beginTransaction(); - rsConfigs.open(db, TblConfig); - rsConfigs.remove(config); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting config " + config.getName(), e, errs); - } -} - -/** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ -void -MSSqlClfsProvider::stage(const boost::intrusive_ptr& msg) -{ -#if 0 - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.add(msg); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error staging message", e, errs); - } -#endif -} - -/** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ -void -MSSqlClfsProvider::destroy(PersistableMessage& msg) -{ -#if 0 - DatabaseConnection *db = initConnection(); - BlobRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.remove(msg); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting message", e, errs); - } -#endif -} - -/** - * Appends content to a previously staged message - */ -void -MSSqlClfsProvider::appendContent(const boost::intrusive_ptr& msg, - const std::string& data) -{ -#if 0 - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.append(msg, data); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error appending to message", e, errs); - } -#endif -} - -/** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ -void -MSSqlClfsProvider::loadContent(const qpid::broker::PersistableQueue& /*queue*/, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length) -{ - // Message log keeps all messages in one log, so we don't need the - // queue reference. - messages.loadContent(msg->getPersistenceId(), data, offset, length); -} - -/** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * @param ctxt The transaction context under which this enqueue happens. - * @param msg The message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - */ -void -MSSqlClfsProvider::enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) -{ - Transaction::shared_ptr t; - TransactionContext *ctx = dynamic_cast(ctxt); - if (ctx) - t = ctx->getTransaction(); - else { - TPCTransactionContext *tctx; - tctx = dynamic_cast(ctxt); - if (tctx) - t = tctx->getTransaction(); - } - uint64_t msgId = msg->getPersistenceId(); - if (msgId == 0) { - messages.add(msg); - msgId = msg->getPersistenceId(); - } - messages.enqueue(msgId, queue.getPersistenceId(), t); - msg->enqueueComplete(); -} - -/** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * @param ctxt The transaction context under which this dequeue happens. - * @param msg The message to dequeue - * @param queue The queue from which it is to be dequeued - */ -void -MSSqlClfsProvider::dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) -{ - Transaction::shared_ptr t; - TransactionContext *ctx = dynamic_cast(ctxt); - if (ctx) - t = ctx->getTransaction(); - else { - TPCTransactionContext *tctx; - tctx = dynamic_cast(ctxt); - if (tctx) - t = tctx->getTransaction(); - } - messages.dequeue(msg->getPersistenceId(), queue.getPersistenceId(), t); - msg->dequeueComplete(); -} - -std::auto_ptr -MSSqlClfsProvider::begin() -{ - Transaction::shared_ptr t = transactions->begin(); - std::auto_ptr tc(new TransactionContext(t)); - return tc; -} - -std::auto_ptr -MSSqlClfsProvider::begin(const std::string& xid) -{ - TPCTransaction::shared_ptr t = transactions->begin(xid); - std::auto_ptr tc(new TPCTransactionContext(t)); - return tc; -} - -void -MSSqlClfsProvider::prepare(qpid::broker::TPCTransactionContext& txn) -{ - TPCTransactionContext *ctx = dynamic_cast (&txn); - if (ctx == 0) - throw qpid::broker::InvalidTransactionContextException(); - ctx->getTransaction()->prepare(); -} - -void -MSSqlClfsProvider::commit(qpid::broker::TransactionContext& txn) -{ - Transaction::shared_ptr t; - TransactionContext *ctx = dynamic_cast(&txn); - if (ctx) - t = ctx->getTransaction(); - else { - TPCTransactionContext *tctx; - tctx = dynamic_cast(&txn); - if (tctx == 0) - throw qpid::broker::InvalidTransactionContextException(); - t = tctx->getTransaction(); - } - t->commit(messages); -} - -void -MSSqlClfsProvider::abort(qpid::broker::TransactionContext& txn) -{ - Transaction::shared_ptr t; - TransactionContext *ctx = dynamic_cast(&txn); - if (ctx) - t = ctx->getTransaction(); - else { - TPCTransactionContext *tctx; - tctx = dynamic_cast(&txn); - if (tctx == 0) - throw qpid::broker::InvalidTransactionContextException(); - t = tctx->getTransaction(); - } - t->abort(messages); -} - -void -MSSqlClfsProvider::collectPreparedXids(std::set& xids) -{ - std::map preparedMap; - transactions->collectPreparedXids(preparedMap); - std::map::const_iterator i; - for (i = preparedMap.begin(); i != preparedMap.end(); ++i) { - xids.insert(i->first); - } -} - -// @TODO Much of this recovery code is way too similar... refactor to -// a recover template method on BlobRecordset. - -void -MSSqlClfsProvider::recoverConfigs(qpid::broker::RecoveryManager& recoverer) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - rsConfigs.open(db, TblConfig); - _RecordsetPtr p = (_RecordsetPtr)rsConfigs; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Config instance and reset its ID. - broker::RecoverableConfig::shared_ptr config = - recoverer.recoverConfig(blob); - config->setPersistenceId(id); - p->MoveNext(); - } -} - -void -MSSqlClfsProvider::recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - rsExchanges.open(db, TblExchange); - _RecordsetPtr p = (_RecordsetPtr)rsExchanges; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Exchange instance, reset its ID, and remember the - // ones restored for matching up when recovering bindings. - broker::RecoverableExchange::shared_ptr exchange = - recoverer.recoverExchange(blob); - exchange->setPersistenceId(id); - exchangeMap[id] = exchange; - p->MoveNext(); - } -} - -void -MSSqlClfsProvider::recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - rsQueues.open(db, TblQueue); - _RecordsetPtr p = (_RecordsetPtr)rsQueues; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Queue instance and reset its ID. - broker::RecoverableQueue::shared_ptr queue = - recoverer.recoverQueue(blob); - queue->setPersistenceId(id); - queueMap[id] = queue; - p->MoveNext(); - } -} - -void -MSSqlClfsProvider::recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - rsBindings.open(db, TblBinding); - rsBindings.recover(recoverer, exchangeMap, queueMap); -} - -void -MSSqlClfsProvider::recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap) -{ - // Read the list of valid queue Ids to ensure that no broken msg->queue - // refs get restored. - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - rsQueues.open(db, TblQueue); - _RecordsetPtr p = (_RecordsetPtr)rsQueues; - std::set validQueues; - if (!(p->BOF && p->EndOfFile)) { - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - validQueues.insert(id); - p->MoveNext(); - } - } - std::map transMap; - transactions->recover(transMap); - messages.recover(recoverer, - validQueues, - transMap, - messageMap, - messageQueueMap); -} - -void -MSSqlClfsProvider::recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap) -{ - std::map preparedMap; - transactions->collectPreparedXids(preparedMap); - std::map::const_iterator i; - for (i = preparedMap.begin(); i != preparedMap.end(); ++i) { - std::auto_ptr ctx(new TPCTransactionContext(i->second)); - std::auto_ptr brokerCtx(ctx); - dtxMap[i->first] = recoverer.recoverTransaction(i->first, brokerCtx); - } -} - -////////////// Internal Methods - -State * -MSSqlClfsProvider::initState() -{ - State *state = dbState.get(); // See if thread has initialized - if (!state) { - state = new State; - dbState.reset(state); - } - return state; -} - -DatabaseConnection * -MSSqlClfsProvider::initConnection(void) -{ - State *state = initState(); - if (state->dbConn != 0) - return state->dbConn; // And the DatabaseConnection is set up too - std::auto_ptr db(new DatabaseConnection); - db->open(options.connectString, options.catalogName); - state->dbConn = db.release(); - return state->dbConn; -} - -void -MSSqlClfsProvider::createDb(DatabaseConnection *db, const std::string &name) -{ - const std::string dbCmd = "CREATE DATABASE " + name; - const std::string useCmd = "USE " + name; - const std::string tableCmd = "CREATE TABLE "; - const std::string colSpecs = - " (persistenceId bigint PRIMARY KEY NOT NULL IDENTITY(1,1)," - " fieldTableBlob varbinary(MAX) NOT NULL)"; - const std::string bindingSpecs = - " (exchangeId bigint REFERENCES tblExchange(persistenceId) NOT NULL," - " queueId bigint REFERENCES tblQueue(persistenceId) NOT NULL," - " routingKey varchar(255)," - " fieldTableBlob varbinary(MAX))"; - - _variant_t unused; - _bstr_t dbStr = dbCmd.c_str(); - _ConnectionPtr conn(*db); - try { - conn->Execute(dbStr, &unused, adExecuteNoRecords); - _bstr_t useStr = useCmd.c_str(); - conn->Execute(useStr, &unused, adExecuteNoRecords); - std::string makeTable = tableCmd + TblQueue + colSpecs; - _bstr_t makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblExchange + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblConfig + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblBinding + bindingSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - } - catch(_com_error &e) { - throw ADOException("MSSQL can't create " + name, e, db->getErrors()); - } -} - -void -MSSqlClfsProvider::dump() -{ - // dump all db records to qpid_log - QPID_LOG(notice, "DB Dump: (not dumping anything)"); - // rsQueues.dump(); -} - - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-clfs/MessageLog.cpp b/qpid/cpp/src/qpid/store/ms-clfs/MessageLog.cpp deleted file mode 100644 index 849a0a44e8..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/MessageLog.cpp +++ /dev/null @@ -1,406 +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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include "MessageLog.h" -#include "Lsn.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -namespace { - -// Structures that hold log records. Each has a type field at the start. -enum MessageEntryType { - MessageStartEntry = 1, - MessageChunkEntry = 2, - MessageDeleteEntry = 3, - MessageEnqueueEntry = 4, - MessageDequeueEntry = 5 -}; -static const uint32_t MaxMessageContentLength = 64 * 1024; - -// Message-Start -struct MessageStart { - MessageEntryType type; - // If the complete message encoding doesn't fit, remainder is in - // MessageChunk records to follow. - // headerLength is the size of the message's header in content. It is - // part of the totalLength and the segmentLength. - uint32_t headerLength; - uint32_t totalLength; - uint32_t segmentLength; - char content[MaxMessageContentLength]; - - MessageStart() - : type(MessageStartEntry), - headerLength(0), - totalLength(0), - segmentLength(0) {} -}; -// Message-Chunk -struct MessageChunk { - MessageEntryType type; - uint32_t segmentLength; - char content[MaxMessageContentLength]; - - MessageChunk() : type(MessageChunkEntry), segmentLength(0) {} -}; -// Message-Delete -struct MessageDelete { - MessageEntryType type; - - MessageDelete() : type(MessageDeleteEntry) {} -}; -// Message-Enqueue -struct MessageEnqueue { - MessageEntryType type; - uint64_t queueId; - uint64_t transId; - - MessageEnqueue(uint64_t qId = 0, uint64_t tId = 0) - : type(MessageEnqueueEntry), queueId(qId), transId(tId) {} -}; -// Message-Dequeue -struct MessageDequeue { - MessageEntryType type; - uint64_t queueId; - uint64_t transId; - - MessageDequeue(uint64_t qId = 0, uint64_t tId = 0) - : type(MessageDequeueEntry), queueId(qId), transId(tId) {} -}; - -} // namespace - -void -MessageLog::initialize() -{ - // Write something to occupy the first record, preventing a real message - // from being lsn/id 0. Delete of a non-existant id is easily tossed - // during recovery if no other messages have caused the tail to be moved - // up past this dummy record by then. - deleteMessage(0, 0); -} - -uint32_t -MessageLog::marshallingBufferSize() -{ - size_t biggestNeed = std::max(sizeof(MessageStart), sizeof(MessageEnqueue)); - uint32_t defSize = static_cast(biggestNeed); - uint32_t minSize = Log::marshallingBufferSize(); - if (defSize <= minSize) - return minSize; - // Round up to multiple of minSize - return (defSize + minSize) / minSize * minSize; -} - -uint64_t -MessageLog::add(const boost::intrusive_ptr& msg) -{ - // The message may be too long to fit in one record; if so, write - // Message-Chunk records to contain the rest. If it does all fit in one - // record, though, optimize the encoding by going straight to the - // Message-Start record rather than encoding then copying to the record. - // In all case - MessageStart entry; - uint32_t encodedMessageLength = msg->encodedSize(); - entry.headerLength = msg->encodedHeaderSize(); - entry.totalLength = encodedMessageLength; - CLFS_LSN location, lastChunkLsn; - std::auto_ptr encodeStage; - char *encodeBuff = 0; - bool oneRecord = encodedMessageLength <= MaxMessageContentLength; - if (oneRecord) { - encodeBuff = entry.content; - entry.segmentLength = encodedMessageLength; - } - else { - encodeStage.reset(new char[encodedMessageLength]); - encodeBuff = encodeStage.get(); - entry.segmentLength = MaxMessageContentLength; - } - qpid::framing::Buffer buff(encodeBuff, encodedMessageLength); - msg->encode(buff); - if (!oneRecord) - memcpy_s(entry.content, sizeof(entry.content), - encodeBuff, entry.segmentLength); - uint32_t entryLength = static_cast(sizeof(entry)); - entryLength -= (MaxMessageContentLength - entry.segmentLength); - location = write(&entry, entryLength); - // Write any Message-Chunk records before setting the message's id. - uint32_t sent = entry.segmentLength; - uint32_t remaining = encodedMessageLength - entry.segmentLength; - while (remaining > 0) { - MessageChunk chunk; - chunk.segmentLength = std::max(MaxMessageContentLength, remaining); - memcpy_s(chunk.content, sizeof(chunk.content), - encodeStage.get() + sent, chunk.segmentLength); - entryLength = static_cast(sizeof(chunk)); - entryLength -= (MaxMessageContentLength - chunk.segmentLength); - lastChunkLsn = write(&chunk, entryLength, &location); - sent += chunk.segmentLength; - remaining -= chunk.segmentLength; - } - return lsnToId(location); -} - -void -MessageLog::deleteMessage(uint64_t messageId, uint64_t newFirstId) -{ - MessageDelete deleteEntry; - CLFS_LSN msgLsn = idToLsn(messageId); - write(&deleteEntry, sizeof(deleteEntry), &msgLsn); - if (newFirstId != 0) - moveTail(idToLsn(newFirstId)); -} - -// Load part or all of a message's content from previously stored -// log record(s). -void -MessageLog::loadContent(uint64_t messageId, - std::string& data, - uint64_t offset, - uint32_t length) -{ -} - -void -MessageLog::recordEnqueue (uint64_t messageId, - uint64_t queueId, - uint64_t transactionId) -{ - MessageEnqueue entry(queueId, transactionId); - CLFS_LSN msgLsn = idToLsn(messageId); - write(&entry, sizeof(entry), &msgLsn); -} - -void -MessageLog::recordDequeue (uint64_t messageId, - uint64_t queueId, - uint64_t transactionId) -{ - MessageDequeue entry(queueId, transactionId); - CLFS_LSN msgLsn = idToLsn(messageId); - write(&entry, sizeof(entry), &msgLsn); -} - -void -MessageLog::recover(qpid::broker::RecoveryManager& recoverer, - qpid::store::MessageMap& messageMap, - std::map >& messageOps) -{ - // If context and content needs to be saved while reassembling messages - // split across log records, save the info and reassembly buffer. - struct MessageBlocks { - uint32_t totalLength; - uint32_t soFarLength; - boost::shared_ptr content; - - MessageBlocks() : totalLength(0), soFarLength(0), content((char*)0) {} - }; - std::map reassemblies; - std::map::iterator at; - - QPID_LOG(debug, "Recovering message log"); - - // Note that there may be message refs in the log which are deleted, so - // be sure to only add msgs at message-start record, and ignore those - // that don't have an existing message record. - // Get the base LSN - that's how to say "start reading at the beginning" - CLFS_INFORMATION info; - ULONG infoLength = sizeof (info); - BOOL ok = ::GetLogFileInformation(handle, &info, &infoLength); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - // Pointers for the various record types that can be assigned in the - // reading loop below. - MessageStart *start; - MessageChunk *chunk; - MessageEnqueue *enqueue; - MessageDequeue *dequeue; - - qpid::store::MessageMap::iterator messageMapSpot; - qpid::store::MessageQueueMap::iterator queueMapSpot; - PVOID recordPointer; - ULONG recordLength; - CLFS_RECORD_TYPE recordType = ClfsDataRecord; - CLFS_LSN messageLsn, current, undoNext; - PVOID readContext; - uint64_t msgId; - // Note 'current' in case it's needed below; ReadNextLogRecord returns it - // via a parameter. - current = info.BaseLsn; - ok = ::ReadLogRecord(marshal, - &info.BaseLsn, - ClfsContextForward, - &recordPointer, - &recordLength, - &recordType, - &undoNext, - &messageLsn, - &readContext, - 0); - while (ok) { - // All the record types this class writes have a MessageEntryType in the - // beginning. Based on that, do what's needed. - MessageEntryType *t = - reinterpret_cast(recordPointer); - switch(*t) { - case MessageStartEntry: - start = reinterpret_cast(recordPointer); - msgId = lsnToId(current); - QPID_LOG(debug, "Message Start, id " << msgId); - // If the message content is split across multiple log records, save - // this content off to the side until the remaining record(s) are - // located. - if (start->totalLength == start->segmentLength) { // Whole thing - // Start by recovering the header then see if the rest of - // the content is desired. - qpid::framing::Buffer buff(start->content, start->headerLength); - qpid::broker::RecoverableMessage::shared_ptr m = - recoverer.recoverMessage(buff); - m->setPersistenceId(msgId); - messageMap[msgId] = m; - uint32_t contentLength = - start->totalLength - start->headerLength; - if (m->loadContent(contentLength)) { - qpid::framing::Buffer content(&(start->content[start->headerLength]), - contentLength); - m->decodeContent(content); - } - } - else { - // Save it in a block big enough. - MessageBlocks b; - b.totalLength = start->totalLength; - b.soFarLength = start->segmentLength; - b.content.reset(new char[b.totalLength]); - memcpy_s(b.content.get(), b.totalLength, - start->content, start->segmentLength); - reassemblies[msgId] = b; - } - break; - case MessageChunkEntry: - chunk = reinterpret_cast(recordPointer); - // Remember, all entries chained to MessageStart via previous. - msgId = lsnToId(messageLsn); - QPID_LOG(debug, "Message Chunk for id " << msgId); - at = reassemblies.find(msgId); - if (at == reassemblies.end()) { - QPID_LOG(debug, "Message frag for " << msgId << - " but no start; discarded"); - } - else { - MessageBlocks *b = &(at->second); - if (b->soFarLength + chunk->segmentLength > b->totalLength) - throw std::runtime_error("Invalid message chunk length"); - memcpy_s(b->content.get() + b->soFarLength, - b->totalLength - b->soFarLength, - chunk->content, - chunk->segmentLength); - b->soFarLength += chunk->segmentLength; - if (b->totalLength == b->soFarLength) { - qpid::framing::Buffer buff(b->content.get(), - b->totalLength); - qpid::broker::RecoverableMessage::shared_ptr m = - recoverer.recoverMessage(buff); - m->setPersistenceId(msgId); - messageMap[msgId] = m; - reassemblies.erase(at); - } - } - break; - case MessageDeleteEntry: - msgId = lsnToId(messageLsn); - QPID_LOG(debug, "Message Delete, id " << msgId); - messageMap.erase(msgId); - messageOps.erase(msgId); - break; - case MessageEnqueueEntry: - enqueue = reinterpret_cast(recordPointer); - msgId = lsnToId(messageLsn); - QPID_LOG(debug, "Message " << msgId << " Enqueue on queue " << - enqueue->queueId << ", txn " << enqueue->transId); - if (messageMap.find(msgId) == messageMap.end()) { - QPID_LOG(debug, - "Message " << msgId << " doesn't exist; discarded"); - } - else { - std::vector& ops = messageOps[msgId]; - RecoveredMsgOp op(RECOVERED_ENQUEUE, - enqueue->queueId, - enqueue->transId); - ops.push_back(op); - } - break; - case MessageDequeueEntry: - dequeue = reinterpret_cast(recordPointer); - msgId = lsnToId(messageLsn); - QPID_LOG(debug, "Message " << msgId << " Dequeue from queue " << - dequeue->queueId); - if (messageMap.find(msgId) == messageMap.end()) { - QPID_LOG(debug, - "Message " << msgId << " doesn't exist; discarded"); - } - else { - std::vector& ops = messageOps[msgId]; - RecoveredMsgOp op(RECOVERED_DEQUEUE, - dequeue->queueId, - dequeue->transId); - ops.push_back(op); - } - break; - default: - throw std::runtime_error("Bad message log entry type"); - } - - recordType = ClfsDataRecord; - ok = ::ReadNextLogRecord(readContext, - &recordPointer, - &recordLength, - &recordType, - 0, // No userLsn - &undoNext, - &messageLsn, - ¤t, - 0); - } - DWORD status = ::GetLastError(); - ::TerminateReadLog(readContext); - if (status == ERROR_HANDLE_EOF) { // No more records - QPID_LOG(debug, "Message log recovered"); - return; - } - throw QPID_WINDOWS_ERROR(status); -} - -}}} // namespace qpid::store::ms_clfs diff --git a/qpid/cpp/src/qpid/store/ms-clfs/MessageLog.h b/qpid/cpp/src/qpid/store/ms-clfs/MessageLog.h deleted file mode 100644 index b3705287a6..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/MessageLog.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_MESSAGELOG_H -#define QPID_STORE_MSCLFS_MESSAGELOG_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 -#include -#include -#include -#include - -#include "Log.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -/** - * @class MessageLog - * - * Represents a CLFS-housed message log. - */ -class MessageLog : public Log { - -protected: - // Message log needs to have a no-op first record written in the log - // to ensure that no real message gets an ID 0. - virtual void initialize(); - -public: - // Inherited and reimplemented from Log. Figure the minimum marshalling - // buffer size needed for the records this class writes. - virtual uint32_t marshallingBufferSize(); - - // Add the specified message to the log; Return the persistence Id. - uint64_t add(const boost::intrusive_ptr& msg); - - // Write a Delete entry for messageId. If newFirstId is not 0, it is now - // the earliest valid message in the log, so move the tail up to it. - void deleteMessage(uint64_t messageId, uint64_t newFirstId); - - // Load part or all of a message's content from previously stored - // log record(s). - void loadContent(uint64_t messageId, - std::string& data, - uint64_t offset, - uint32_t length); - - // Enqueue and dequeue operations track messages' transit across - // queues; each operation may be associated with a transaction. If - // the transactionId is 0 the operation is not associated with a - // transaction. - void recordEnqueue (uint64_t messageId, - uint64_t queueId, - uint64_t transactionId); - void recordDequeue (uint64_t messageId, - uint64_t queueId, - uint64_t transactionId); - - // Recover the messages and their queueing records from the log. - // @param recoverer Recovery manager used to recreate broker objects from - // encoded framing buffers recovered from the log. - // @param messageMap This method fills in the map of id -> ptr of - // recovered messages. - // @param messageOps This method fills in the map of msg id -> - // vector of operations involving the message that were - // recovered from the log. It is the caller's - // responsibility to sort the operations out and - // ascertain which operations should be acted on. The - // order of operations in the vector is as they were - // read in order from the log. - typedef enum { RECOVERED_ENQUEUE = 1, RECOVERED_DEQUEUE } RecoveredOpType; - struct RecoveredMsgOp { - RecoveredOpType op; - uint64_t queueId; - uint64_t txnId; - - RecoveredMsgOp(RecoveredOpType o, const uint64_t& q, const uint64_t& t) - : op(o), queueId(q), txnId(t) {} - }; - void recover(qpid::broker::RecoveryManager& recoverer, - qpid::store::MessageMap& messageMap, - std::map >& messageOps); -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_MESSAGELOG_H */ diff --git a/qpid/cpp/src/qpid/store/ms-clfs/Messages.cpp b/qpid/cpp/src/qpid/store/ms-clfs/Messages.cpp deleted file mode 100644 index db5d2ebf4c..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/Messages.cpp +++ /dev/null @@ -1,472 +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 - -#include "Messages.h" -#include "Lsn.h" -#include "qpid/store/StoreException.h" -#include - -namespace qpid { -namespace store { -namespace ms_clfs { - -void -Messages::openLog(const std::string& path, const Log::TuningParameters& params) -{ - log.open (path, params); -} - -void -Messages::add(const boost::intrusive_ptr& msg) -{ - uint64_t id = log.add(msg); - msg->setPersistenceId(id); - std::auto_ptr autom(new MessageInfo); - MessageInfo::shared_ptr m(autom); - std::pair p(id, m); - { - qpid::sys::ScopedWlock l(lock); - messages.insert(p); - // If there's only this one message there, move the tail to it. - // This prevents the log from continually growing when messages - // are added and removed one at a time. - if (messages.size() == 1) { - CLFS_LSN newTail = idToLsn(id); - log.moveTail(newTail); - } - } -} - -void -Messages::enqueue(uint64_t msgId, uint64_t queueId, Transaction::shared_ptr& t) -{ - MessageInfo::shared_ptr p; - { - qpid::sys::ScopedRlock l(lock); - MessageMap::const_iterator i = messages.find(msgId); - if (i == messages.end()) - THROW_STORE_EXCEPTION("Message does not exist"); - p = i->second; - } - MessageInfo::Location loc(queueId, t, MessageInfo::TRANSACTION_ENQUEUE); - { - qpid::sys::ScopedLock l(p->whereLock); - p->where.push_back(loc); - uint64_t transactionId = 0; - if (t.get() != 0) { - transactionId = t->getId(); - t->enroll(msgId); - } - try { - log.recordEnqueue(msgId, queueId, transactionId); - } - catch (...) { - // Undo the record-keeping if the log wasn't written correctly. - if (transactionId != 0) - t->unenroll(msgId); - p->where.pop_back(); - throw; - } - } -} - -void -Messages::dequeue(uint64_t msgId, uint64_t queueId, Transaction::shared_ptr& t) -{ - MessageInfo::shared_ptr p; - { - qpid::sys::ScopedRlock l(lock); - MessageMap::const_iterator i = messages.find(msgId); - if (i == messages.end()) - THROW_STORE_EXCEPTION("Message does not exist"); - p = i->second; - } - { - // Locate the 'where' entry for the specified queue. Once this operation - // is recorded in the log, update the 'where' entry to reflect it. - // Note that an existing entry in 'where' that refers to a transaction - // is not eligible for this operation. - qpid::sys::ScopedLock l(p->whereLock); - std::list::iterator i; - for (i = p->where.begin(); i != p->where.end(); ++i) { - if (i->queueId == queueId && i->transaction.get() == 0) - break; - } - if (i == p->where.end()) - THROW_STORE_EXCEPTION("Message not on queue"); - uint64_t transactionId = 0; - if (t.get() != 0) { - transactionId = t->getId(); - t->enroll(msgId); - } - try { - log.recordDequeue(msgId, queueId, transactionId); - } - catch (...) { - // Undo the record-keeping if the log wasn't written correctly. - if (transactionId != 0) - t->unenroll(msgId); - throw; - } - // Ok, logged successfully. If this is a transactional op, note - // the transaction. If non-transactional, remove the 'where' entry. - if (transactionId != 0) { - i->transaction = t; - i->disposition = MessageInfo::TRANSACTION_DEQUEUE; - } - else { - p->where.erase(i); - // If the message doesn't exist on any other queues, remove it. - if (p->where.empty()) - remove(msgId); - } - } -} - -// Commit a previous provisional enqueue or dequeue of a particular message -// actions under a specified transaction. If this results in the message's -// being removed from all queues, it is deleted. -void -Messages::commit(uint64_t msgId, Transaction::shared_ptr& t) -{ - MessageInfo::shared_ptr p; - { - qpid::sys::ScopedRlock l(lock); - MessageMap::const_iterator i = messages.find(msgId); - if (i == messages.end()) - THROW_STORE_EXCEPTION("Message does not exist"); - p = i->second; - } - { - qpid::sys::ScopedLock l(p->whereLock); - std::list::iterator i; - for (i = p->where.begin(); i != p->where.end(); ++i) { - if (i->transaction != t) - continue; - // Transactional dequeues can now remove the item from the - // where list; enqueues just clear the transaction reference. - if (i->disposition == MessageInfo::TRANSACTION_DEQUEUE) - i = p->where.erase(i); - else - i->transaction.reset(); - } - } - // If committing results in this message having no further enqueue - // references, delete it. If the delete fails, swallow the exception - // and let recovery take care of removing it later. - if (p->where.empty()) { - try { - remove(msgId); - } - catch(...) {} - } -} - -// Abort a previous provisional enqueue or dequeue of a particular message -// actions under a specified transaction. If this results in the message's -// being removed from all queues, it is deleted. -void -Messages::abort(uint64_t msgId, Transaction::shared_ptr& t) -{ - MessageInfo::shared_ptr p; - { - qpid::sys::ScopedRlock l(lock); - MessageMap::const_iterator i = messages.find(msgId); - if (i == messages.end()) - THROW_STORE_EXCEPTION("Message does not exist"); - p = i->second; - } - { - qpid::sys::ScopedLock l(p->whereLock); - std::list::iterator i = p->where.begin(); - while (i != p->where.end()) { - if (i->transaction != t) { - ++i; - continue; - } - // Aborted transactional dequeues result in the message remaining - // enqueued like before the operation; enqueues clear the - // message from the where list - like the enqueue never happened. - if (i->disposition == MessageInfo::TRANSACTION_ENQUEUE) - i = p->where.erase(i); - else { - i->transaction.reset(); - ++i; - } - } - } - // If aborting results in this message having no further enqueue - // references, delete it. If the delete fails, swallow the exception - // and let recovery take care of removing it later. - if (p->where.empty()) { - try { - remove(msgId); - } - catch(...) {} - } -} - -// Load part or all of a message's content from previously stored -// log record(s). -void -Messages::loadContent(uint64_t msgId, - std::string& data, - uint64_t offset, - uint32_t length) -{ - log.loadContent(msgId, data, offset, length); -} - -// Recover the current set of messages and where they're queued from -// the log. -void -Messages::recover(qpid::broker::RecoveryManager& recoverer, - const std::set &validQueues, - const std::map& transMap, - qpid::store::MessageMap& messageMap, - qpid::store::MessageQueueMap& messageQueueMap) -{ - std::map > messageOps; - log.recover(recoverer, messageMap, messageOps); - // Now read through the messageOps replaying the operations with the - // knowledge of which transactions committed, aborted, etc. A transaction - // should not be deleted until there are no messages referencing it so - // a message operation with a transaction id not found in transMap is - // a serious problem. - QPID_LOG(debug, "Beginning CLFS-recovered message operation replay"); - // Keep track of any messages that are recovered from the log but don't - // have any place to be. This can happen, for example, if the broker - // crashes while logging a message deletion. After all the recovery is - // done, delete all the homeless messages. - std::vector homeless; - std::map >::const_iterator msg; - for (msg = messageOps.begin(); msg != messageOps.end(); ++msg) { - uint64_t msgId = msg->first; - const std::vector& ops = msg->second; - QPID_LOG(debug, "Message " << msgId << "; " << ops.size() << " op(s)"); - MessageInfo::shared_ptr m(new MessageInfo); - std::vector& entries = messageQueueMap[msgId]; - std::vector::const_iterator op; - for (op = ops.begin(); op != ops.end(); ++op) { - QueueEntry entry(op->queueId); - MessageInfo::Location loc(op->queueId); - std::string dir = - op->op == MessageLog::RECOVERED_ENQUEUE ? "enqueue" - : "dequeue"; - if (validQueues.find(op->queueId) == validQueues.end()) { - QPID_LOG(info, - "Message " << msgId << dir << " on non-existant queue " - << op->queueId << "; dropped"); - continue; - } - if (op->txnId != 0) { - // Be sure to enroll this message in the transaction even if - // it has committed or aborted. This ensures that the - // transaction isn't removed from the log while finalizing the - // recovery. If it were to be removed and the broker failed - // again before removing this message during normal operation, - // it couldn't be recovered again. - // - // Recall what is being reconstructed; 2 things: - // 1. This class's 'messages' list which keeps track - // of the queues each message is on and the transactions - // each message is enrolled in. For this, aborted - // transactions cause the result of the operation to be - // ignored, but the message does need to be enrolled in - // the transaction to properly maintain the transaction - // references until the message is deleted. - // 2. The StorageProvider's MessageQueueMap, which also - // has an entry for each queue each message is on and - // its TPL status and associated xid. - const Transaction::shared_ptr &t = - transMap.find(op->txnId)->second; - // Prepared transactions cause the operation to be - // provisionally acted on, and the message to be enrolled in - // the transaction for when it commits/aborts. This is - // noted in the QueueEntry for the StorageProvider's map. - if (t->getState() == Transaction::TRANS_PREPARED) { - QPID_LOG(debug, dir << " for queue " << op->queueId << - ", prepared txn " << op->txnId); - TPCTransaction::shared_ptr tpct(boost::dynamic_pointer_cast(t)); - if (tpct.get() == 0) - THROW_STORE_EXCEPTION("Invalid transaction state"); - t->enroll(msgId); - entry.xid = tpct->getXid(); - loc.transaction = t; - if (op->op == MessageLog::RECOVERED_ENQUEUE) { - entry.tplStatus = QueueEntry::ADDING; - loc.disposition = MessageInfo::TRANSACTION_ENQUEUE; - } - else { - entry.tplStatus = QueueEntry::REMOVING; - loc.disposition = MessageInfo::TRANSACTION_DEQUEUE; - } - } - else if (t->getState() != Transaction::TRANS_COMMITTED) { - QPID_LOG(debug, dir << " for queue " << op->queueId << - ", txn " << op->txnId << ", rolling back"); - continue; - } - } - // Here for non-transactional and prepared transactional operations - // to set up the messageQueueMap entries. Note that at this point - // a committed transactional operation looks like a - // non-transactional one as far as the QueueEntry is - // concerned - just do it. If this is an entry enqueuing a - // message, just add it to the entries list. If it's a dequeue - // operation, locate the matching entry for the queue and delete - // it if the current op is non-transactional; if it's a prepared - // transaction then replace the existing entry with the current - // one that notes the message is enqueued but being removed under - // a prepared transaction. - QPID_LOG(debug, dir + " at queue " << entry.queueId); - if (op->op == MessageLog::RECOVERED_ENQUEUE) { - entries.push_back(entry); - m->where.push_back(loc); - } - else { - std::vector::iterator i = entries.begin(); - while (i != entries.end()) { - if (i->queueId == entry.queueId) { - if (entry.tplStatus != QueueEntry::NONE) - *i = entry; - else - entries.erase(i); - break; - } - ++i; - } - std::list::iterator w = m->where.begin(); - while (w != m->where.end()) { - if (w->queueId == loc.queueId) { - if (loc.transaction.get() != 0) { - *w = loc; - ++w; - } - else { - w = m->where.erase(w); - } - } - } - } - } - // Now that all the queue entries have been set correctly, see if - // there are any entries; they may have all been removed during - // recovery. If there are none, add this message to the homeless - // list to be deleted from the log after the recovery is done. - if (m->where.size() == 0) { - homeless.push_back(msgId); - messageMap.erase(msgId); - messageQueueMap.erase(msgId); - } - else { - std::pair p(msgId, m); - messages.insert(p); - } - } - - QPID_LOG(debug, "Message log recovery done."); - // Done! Ok, go back and delete all the homeless messages. - BOOST_FOREACH(uint64_t msg, homeless) { - QPID_LOG(debug, "Deleting homeless message " << msg); - remove(msg); - } -} - -// Expunge is called when a queue is deleted. All references to that -// queue must be expunged from all messages. 'Dequeue' log records are -// written for each queue entry removed, but any errors are swallowed. -// On recovery there's a list of valid queues passed in. The deleted -// queue will not be on that list so if any references to it are -// recovered they'll get weeded out then. -void -Messages::expunge(uint64_t queueId) -{ - std::vector toBeDeleted; // Messages to be deleted later. - - { - // Lock everybody out since all messages are possibly in play. - // There also may be other threads already working on particular - // messages so individual message mutex still must be acquired. - qpid::sys::ScopedWlock l(lock); - MessageMap::iterator m; - for (m = messages.begin(); m != messages.end(); ++m) { - MessageInfo::shared_ptr p = m->second; - { - qpid::sys::ScopedLock ml(p->whereLock); - std::list::iterator i = p->where.begin(); - while (i != p->where.end()) { - if (i->queueId != queueId) { - ++i; - continue; - } - // If this entry is involved in a transaction, unenroll it. - // Then remove the entry. - if (i->transaction.get() != 0) - i->transaction->unenroll(m->first); - i = p->where.erase(i); - try { - log.recordDequeue(m->first, queueId, 0); - } - catch(...) { - } - } - if (p->where.size() == 0) - toBeDeleted.push_back(m->first); - } - } - } - // Swallow any exceptions during this; don't care. Recover it later - // if needed. - try { - BOOST_FOREACH(uint64_t msg, toBeDeleted) - remove(msg); - } - catch(...) { - } -} - -// Remove a specified message from those controlled by this object. -void -Messages::remove(uint64_t messageId) -{ - uint64_t newFirstId = 0; - { - qpid::sys::ScopedWlock l(lock); - messages.erase(messageId); - // May have deleted the first entry; if so the log can release that. - // If this message being deleted results in an empty list of - // messages, move the tail up to this message's LSN. This may - // result in one or more messages being stranded in the log - // until there's more activity. If a restart happens while these - // unneeded log records are there, the presence of the MessageDelete - // entry will cause the message(s) to be ignored anyway. - if (messages.empty()) - newFirstId = messageId; - else if (messages.begin()->first > messageId) - newFirstId = messages.begin()->first; - } - log.deleteMessage(messageId, newFirstId); -} - -}}} // namespace qpid::store::ms_clfs diff --git a/qpid/cpp/src/qpid/store/ms-clfs/Messages.h b/qpid/cpp/src/qpid/store/ms-clfs/Messages.h deleted file mode 100644 index 93cc8bfe62..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/Messages.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_MESSAGES_H -#define QPID_STORE_MSCLFS_MESSAGES_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 -#include -#include -#include -#include -#include -#include - -#include "MessageLog.h" -#include "Transaction.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -class Messages { - - struct MessageInfo { - // How many queues this message is on, whether actually (non-transacted) - // or provisionally (included in a non-yet-committed transaction). - volatile LONG enqueuedCount; - - // Keep a list of transactional operations this message is - // referenced in. When the transaction changes/finalizes these all - // need to be acted on. - typedef enum { TRANSACTION_NONE = 0, - TRANSACTION_ENQUEUE, - TRANSACTION_DEQUEUE } TransType; -#if 0 - std::map > transOps; - qpid::sys::Mutex transOpsLock; -#endif - // Think what I need is a list of "where is this message" - queue id, - // transaction ref, what kind of trans op (enq/deq). Then "remove all - // queue refs" can search through all messages looking for queue ids - // and undo them. Write "remove from queue" record to log. Also need to - // add "remove from queue" to recovery. - struct Location { - uint64_t queueId; - Transaction::shared_ptr transaction; - TransType disposition; - - Location(uint64_t q) - : queueId(q), transaction(), disposition(TRANSACTION_NONE) {} - Location(uint64_t q, Transaction::shared_ptr& t, TransType d) - : queueId(q), transaction(t), disposition(d) {} - }; - qpid::sys::Mutex whereLock; - std::list where; - // The transactions vector just keeps a shared_ptr to each - // Transaction this message was involved in, regardless of the - // disposition or transaction state. Keeping a valid shared_ptr - // prevents the Transaction from being deleted. As long as there - // are any messages that referred to a transaction, that - // transaction's state needs to be known so the message disposition - // can be correctly recovered if needed. - std::vector transactions; - - typedef boost::shared_ptr shared_ptr; - - MessageInfo() : enqueuedCount(0) {} - }; - - qpid::sys::RWlock lock; - typedef std::map MessageMap; - MessageMap messages; - MessageLog log; - - // Remove a specified message from those controlled by this object. - void remove(uint64_t messageId); - -public: - void openLog(const std::string& path, const Log::TuningParameters& params); - - // Add the specified message to the log and list of known messages. - // Upon successful return the message's persistenceId is set. - void add(const boost::intrusive_ptr& msg); - - // Add the specified queue to the message's list of places it is - // enqueued. - void enqueue(uint64_t msgId, uint64_t queueId, Transaction::shared_ptr& t); - - // Remove the specified queue from the message's list of places it is - // enqueued. If there are no other queues holding the message, it is - // deleted. - void dequeue(uint64_t msgId, uint64_t queueId, Transaction::shared_ptr& t); - - // Commit a previous provisional enqueue or dequeue of a particular message - // actions under a specified transaction. If this results in the message's - // being removed from all queues, it is deleted. - void commit(uint64_t msgId, Transaction::shared_ptr& transaction); - - // Abort a previous provisional enqueue or dequeue of a particular message - // actions under a specified transaction. If this results in the message's - // being removed from all queues, it is deleted. - void abort(uint64_t msgId, Transaction::shared_ptr& transaction); - - // Load part or all of a message's content from previously stored - // log record(s). - void loadContent(uint64_t msgId, - std::string& data, - uint64_t offset, - uint32_t length); - - // Expunge is called when a queue is deleted. All references to that - // queue must be expunged from all messages. - void expunge(uint64_t queueId); - - // Recover the current set of messages and where they're queued from - // the log. - void recover(qpid::broker::RecoveryManager& recoverer, - const std::set &validQueues, - const std::map& transMap, - qpid::store::MessageMap& messageMap, - qpid::store::MessageQueueMap& messageQueueMap); -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_MESSAGES_H */ diff --git a/qpid/cpp/src/qpid/store/ms-clfs/Transaction.cpp b/qpid/cpp/src/qpid/store/ms-clfs/Transaction.cpp deleted file mode 100644 index f94fef6f84..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/Transaction.cpp +++ /dev/null @@ -1,83 +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 "Transaction.h" -#include "Messages.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -Transaction::~Transaction() -{ - // Transactions that are recovered then found to be deleted get destroyed - // but need not be logged. - if (state != TRANS_DELETED) - log->deleteTransaction(id); -} - -void -Transaction::enroll(uint64_t msgId) -{ - qpid::sys::ScopedWlock l(enrollLock); - enrolledMessages.push_back(msgId); -} - -void -Transaction::unenroll(uint64_t msgId) -{ - qpid::sys::ScopedWlock l(enrollLock); - for (std::vector::iterator i = enrolledMessages.begin(); - i < enrolledMessages.end(); - ++i) { - if (*i == msgId) { - enrolledMessages.erase(i); - break; - } - } -} - -void -Transaction::abort(Messages& messages) -{ - log->recordAbort(id); - for (size_t i = 0; i < enrolledMessages.size(); ++i) - messages.abort(enrolledMessages[i], shared_from_this()); - state = TRANS_ABORTED; -} - -void -Transaction::commit(Messages& messages) -{ - log->recordCommit(id); - for (size_t i = 0; i < enrolledMessages.size(); ++i) - messages.commit(enrolledMessages[i], shared_from_this()); - state = TRANS_COMMITTED; -} - -void -TPCTransaction::prepare(void) -{ - log->recordPrepare(id); - state = TRANS_PREPARED; -} - -}}} // namespace qpid::store::ms_clfs diff --git a/qpid/cpp/src/qpid/store/ms-clfs/Transaction.h b/qpid/cpp/src/qpid/store/ms-clfs/Transaction.h deleted file mode 100644 index 499b01d503..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/Transaction.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_TRANSACTION_H -#define QPID_STORE_MSCLFS_TRANSACTION_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 -#include -#include -#include -#include -#include - -#include "TransactionLog.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -class Messages; - -/** - * @class Transaction - * - * Class representing an AMQP transaction. This is used around a set of - * enqueue and dequeue operations that occur when the broker is acting - * on a transaction commit/abort from the client. - * This class is what the store uses internally to implement things a - * transaction needs; the broker knows about TransactionContext, which - * holds a pointer to Transaction. - * - * NOTE: All references to Transactions (and TPCTransactions, below) are - * through Boost shared_ptr instances. All messages enrolled in a transaction - * hold a shared_ptr. Thus, a Transaction object will not be deleted until all - * messages holding a reference to it are deleted. This fact is also used - * during recovery to automatically clean up and delete any Transaction without - * messages left referring to it. - */ -class Transaction : public boost::enable_shared_from_this { -private: - // TransactionLog has to create all Transaction instances. - Transaction() {} - -public: - - typedef boost::shared_ptr shared_ptr; - typedef enum { TRANS_OPEN = 1, - TRANS_PREPARED, - TRANS_ABORTED, - TRANS_COMMITTED, - TRANS_DELETED } State; - - virtual ~Transaction(); - - uint64_t getId() { return id; } - State getState() { return state; } - - void enroll(uint64_t msgId); - void unenroll(uint64_t msgId); // For failed ops, not normal end-of-trans - - void abort(Messages& messages); - void commit(Messages& messages); - -protected: - friend class TransactionLog; - Transaction(uint64_t _id, const TransactionLog::shared_ptr& _log) - : id(_id), state(TRANS_OPEN), log(_log) {} - - uint64_t id; - State state; - TransactionLog::shared_ptr log; - std::vector enrolledMessages; - qpid::sys::RWlock enrollLock; -}; - -class TransactionContext : public qpid::broker::TransactionContext { - Transaction::shared_ptr transaction; - -public: - TransactionContext(const Transaction::shared_ptr& _transaction) - : transaction(_transaction) {} - - virtual Transaction::shared_ptr& getTransaction() { return transaction; } -}; - -/** - * @class TPCTransaction - * - * Class representing a Two-Phase-Commit (TPC) AMQP transaction. This is - * used around a set of enqueue and dequeue operations that occur when the - * broker is acting on a transaction prepare/commit/abort from the client. - * This class is what the store uses internally to implement things a - * transaction needs; the broker knows about TPCTransactionContext, which - * holds a pointer to TPCTransaction. - */ -class TPCTransaction : public Transaction { - - friend class TransactionLog; - TPCTransaction(uint64_t _id, - const TransactionLog::shared_ptr& _log, - const std::string& _xid) - : Transaction(_id, _log), xid(_xid) {} - - std::string xid; - -public: - typedef boost::shared_ptr shared_ptr; - - virtual ~TPCTransaction() {} - - void prepare(); - bool isPrepared() const { return state == TRANS_PREPARED; } - - const std::string& getXid(void) const { return xid; } -}; - -class TPCTransactionContext : public qpid::broker::TPCTransactionContext { - TPCTransaction::shared_ptr transaction; - -public: - TPCTransactionContext(const TPCTransaction::shared_ptr& _transaction) - : transaction(_transaction) {} - - virtual TPCTransaction::shared_ptr& getTransaction() { return transaction; } -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_TRANSACTION_H */ diff --git a/qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.cpp b/qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.cpp deleted file mode 100644 index 0ef046d7c8..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.cpp +++ /dev/null @@ -1,428 +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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include "TransactionLog.h" -#include "Transaction.h" -#include "Lsn.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -namespace { - -// Structures that hold log records. Each has a type field at the start. -enum TransactionEntryType { - TransactionStartDtxEntry = 1, - TransactionStartTxEntry = 2, - TransactionPrepareEntry = 3, - TransactionCommitEntry = 4, - TransactionAbortEntry = 5, - TransactionDeleteEntry = 6 -}; -// The only thing that really takes up space in transaction records is the -// xid. Max xid length is in the neighborhood of 600 bytes. Leave some room. -static const uint32_t MaxTransactionContentLength = 1024; - -// Dtx-Start -struct TransactionStartDtx { - TransactionEntryType type; - uint32_t length; - char content[MaxTransactionContentLength]; - - TransactionStartDtx() - : type(TransactionStartDtxEntry), length(0) {} -}; -// Tx-Start -struct TransactionStartTx { - TransactionEntryType type; - - TransactionStartTx() - : type(TransactionStartTxEntry) {} -}; -// Prepare -struct TransactionPrepare { - TransactionEntryType type; - - TransactionPrepare() - : type(TransactionPrepareEntry) {} -}; -// Commit -struct TransactionCommit { - TransactionEntryType type; - - TransactionCommit() - : type(TransactionCommitEntry) {} -}; -// Abort -struct TransactionAbort { - TransactionEntryType type; - - TransactionAbort() - : type(TransactionAbortEntry) {} -}; -// Delete -struct TransactionDelete { - TransactionEntryType type; - - TransactionDelete() - : type(TransactionDeleteEntry) {} -}; - -} // namespace - -void -TransactionLog::initialize() -{ - // Write something to occupy the first record, preventing a real - // transaction from being lsn/id 0. Delete of a non-existant id is easily - // tossed during recovery if no other transactions have caused the tail - // to be moved up past this dummy record by then. - deleteTransaction(0); -} - -uint32_t -TransactionLog::marshallingBufferSize() -{ - size_t biggestNeed = sizeof(TransactionStartDtx); - uint32_t defSize = static_cast(biggestNeed); - uint32_t minSize = Log::marshallingBufferSize(); - if (defSize <= minSize) - return minSize; - // Round up to multiple of minSize - return (defSize + minSize) / minSize * minSize; -} - -// Get a new Transaction -boost::shared_ptr -TransactionLog::begin() -{ - TransactionStartTx entry; - CLFS_LSN location; - uint64_t id; - uint32_t entryLength = static_cast(sizeof(entry)); - location = write(&entry, entryLength); - try { - qpid::sys::ScopedLock l(idsLock); - id = lsnToId(location); - std::auto_ptr t(new Transaction(id, shared_from_this())); - boost::shared_ptr t2(t); - boost::weak_ptr weak_t2(t2); - { - qpid::sys::ScopedLock l(idsLock); - validIds[id] = weak_t2; - } - return t2; - } - catch(...) { - deleteTransaction(id); - throw; - } -} - -// Get a new TPCTransaction -boost::shared_ptr -TransactionLog::begin(const std::string& xid) -{ - TransactionStartDtx entry; - CLFS_LSN location; - uint64_t id; - uint32_t entryLength = static_cast(sizeof(entry)); - entry.length = static_cast(xid.length()); - memcpy_s(entry.content, sizeof(entry.content), - xid.c_str(), xid.length()); - entryLength -= (sizeof(entry.content) - entry.length); - location = write(&entry, entryLength); - try { - id = lsnToId(location); - std::auto_ptr t(new TPCTransaction(id, - shared_from_this(), - xid)); - boost::shared_ptr t2(t); - boost::weak_ptr weak_t2(t2); - { - qpid::sys::ScopedLock l(idsLock); - validIds[id] = weak_t2; - } - return t2; - } - catch(...) { - deleteTransaction(id); - throw; - } -} - -void -TransactionLog::recordPrepare(uint64_t transId) -{ - TransactionPrepare entry; - CLFS_LSN transLsn = idToLsn(transId); - write(&entry, sizeof(entry), &transLsn); -} - -void -TransactionLog::recordCommit(uint64_t transId) -{ - TransactionCommit entry; - CLFS_LSN transLsn = idToLsn(transId); - write(&entry, sizeof(entry), &transLsn); - { - qpid::sys::ScopedLock l(idsLock); - validIds[transId].reset(); - } -} - -void -TransactionLog::recordAbort(uint64_t transId) -{ - TransactionAbort entry; - CLFS_LSN transLsn = idToLsn(transId); - write(&entry, sizeof(entry), &transLsn); - { - qpid::sys::ScopedLock l(idsLock); - validIds[transId].reset(); - } -} - -void -TransactionLog::deleteTransaction(uint64_t transId) -{ - uint64_t newFirstId = 0; - { - qpid::sys::ScopedLock l(idsLock); - validIds.erase(transId); - // May have deleted the first entry; if so the log can release that. - // If this deletion results in an empty list of transactions, - // move the tail up to this transaction's LSN. This may result in - // one or more transactions being stranded in the log until there's - // more activity. If a restart happens while these unneeded log - // records are there, the presence of the TransactionDelete - // entry will cause them to be ignored anyway. - if (validIds.empty()) - newFirstId = transId; - else if (validIds.begin()->first > transId) - newFirstId = validIds.begin()->first; - } - TransactionDelete deleteEntry; - CLFS_LSN transLsn = idToLsn(transId); - write(&deleteEntry, sizeof(deleteEntry), &transLsn); - if (newFirstId != 0) - moveTail(idToLsn(newFirstId)); -} - -void -TransactionLog::collectPreparedXids(std::map& preparedMap) -{ - // Go through all the known transactions; if the transaction is still - // valid (open or prepared) it will have weak_ptr to the Transaction. - // If it can be downcast and has a state of TRANS_PREPARED, add to the map. - qpid::sys::ScopedLock l(idsLock); - std::map >::const_iterator i; - for (i = validIds.begin(); i != validIds.end(); ++i) { - Transaction::shared_ptr t = i->second.lock(); - if (t.get() == 0) - continue; - TPCTransaction::shared_ptr tpct(boost::dynamic_pointer_cast(t)); - if (tpct.get() == 0) - continue; - if (tpct->state == Transaction::TRANS_PREPARED) - preparedMap[tpct->getXid()] = tpct; - } -} - -void -TransactionLog::recover(std::map& transMap) -{ - QPID_LOG(debug, "Recovering transaction log"); - - // Note that there may be transaction refs in the log which are deleted, - // so be sure to only add transactions at Start records, and ignore those - // that don't have an existing message record. - // Get the base LSN - that's how to say "start reading at the beginning" - CLFS_INFORMATION info; - ULONG infoLength = sizeof (info); - BOOL ok = ::GetLogFileInformation(handle, &info, &infoLength); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - // Pointers for the various record types that can be assigned in the - // reading loop below. - TransactionStartDtx *startDtxEntry; - TransactionStartTx *startTxEntry; - - PVOID recordPointer; - ULONG recordLength; - CLFS_RECORD_TYPE recordType = ClfsDataRecord; - CLFS_LSN transLsn, current, undoNext; - PVOID readContext; - uint64_t transId; - // Note 'current' in case it's needed below; ReadNextLogRecord returns it - // via a parameter. - current = info.BaseLsn; - ok = ::ReadLogRecord(marshal, - &info.BaseLsn, - ClfsContextForward, - &recordPointer, - &recordLength, - &recordType, - &undoNext, - &transLsn, - &readContext, - 0); - - std::auto_ptr tPtr; - std::auto_ptr tpcPtr; - while (ok) { - std::string xid; - - // All the record types this class writes have a TransactionEntryType - // in the beginning. Based on that, do what's needed. - TransactionEntryType *t = - reinterpret_cast(recordPointer); - switch(*t) { - case TransactionStartDtxEntry: - startDtxEntry = - reinterpret_cast(recordPointer); - transId = lsnToId(current); - QPID_LOG(debug, "Dtx start, id " << transId); - xid.assign(startDtxEntry->content, startDtxEntry->length); - tpcPtr.reset(new TPCTransaction(transId, shared_from_this(), xid)); - transMap[transId] = boost::shared_ptr(tpcPtr); - break; - case TransactionStartTxEntry: - startTxEntry = - reinterpret_cast(recordPointer); - transId = lsnToId(current); - QPID_LOG(debug, "Tx start, id " << transId); - tPtr.reset(new Transaction(transId, shared_from_this())); - transMap[transId] = boost::shared_ptr(tPtr); - break; - case TransactionPrepareEntry: - transId = lsnToId(transLsn); - QPID_LOG(debug, "Dtx prepare, id " << transId); - if (transMap.find(transId) == transMap.end()) { - QPID_LOG(debug, - "Dtx " << transId << " doesn't exist; discarded"); - } - else { - transMap[transId]->state = Transaction::TRANS_PREPARED; - } - break; - case TransactionCommitEntry: - transId = lsnToId(transLsn); - QPID_LOG(debug, "Txn commit, id " << transId); - if (transMap.find(transId) == transMap.end()) { - QPID_LOG(debug, - "Txn " << transId << " doesn't exist; discarded"); - } - else { - transMap[transId]->state = Transaction::TRANS_COMMITTED; - } - break; - case TransactionAbortEntry: - transId = lsnToId(transLsn); - QPID_LOG(debug, "Txn abort, id " << transId); - if (transMap.find(transId) == transMap.end()) { - QPID_LOG(debug, - "Txn " << transId << " doesn't exist; discarded"); - } - else { - transMap[transId]->state = Transaction::TRANS_ABORTED; - } - break; - case TransactionDeleteEntry: - transId = lsnToId(transLsn); - QPID_LOG(debug, "Txn delete, id " << transId); - if (transMap.find(transId) == transMap.end()) { - QPID_LOG(debug, - "Txn " << transId << " doesn't exist; discarded"); - } - else { - transMap[transId]->state = Transaction::TRANS_DELETED; - transMap.erase(transId); - } - break; - default: - throw std::runtime_error("Bad transaction log entry type"); - } - - recordType = ClfsDataRecord; - ok = ::ReadNextLogRecord(readContext, - &recordPointer, - &recordLength, - &recordType, - 0, // No userLsn - &undoNext, - &transLsn, - ¤t, - 0); - } - DWORD status = ::GetLastError(); - ::TerminateReadLog(readContext); - if (status != ERROR_HANDLE_EOF) // No more records - throw QPID_WINDOWS_ERROR(status); - - QPID_LOG(debug, "Transaction log recovered"); - - // At this point we have a list of all the not-deleted transactions that - // were in existence when the broker last ran. All transactions of both - // Dtx and Tx types that haven't prepared or committed will be aborted. - // This will give the proper background against which to decide each - // message's disposition when recovering messages that were involved in - // transactions. - // In addition to recovering and aborting transactions, rebuild the - // validIds map now that we know which ids are really valid. - std::map::const_iterator i; - for (i = transMap.begin(); i != transMap.end(); ++i) { - switch(i->second->state) { - case Transaction::TRANS_OPEN: - QPID_LOG(debug, "Txn " << i->first << " was open; aborted"); - i->second->state = Transaction::TRANS_ABORTED; - break; - case Transaction::TRANS_ABORTED: - QPID_LOG(debug, "Txn " << i->first << " was aborted"); - break; - case Transaction::TRANS_COMMITTED: - QPID_LOG(debug, "Txn " << i->first << " was committed"); - break; - case Transaction::TRANS_PREPARED: - QPID_LOG(debug, "Txn " << i->first << " was prepared"); - break; - case Transaction::TRANS_DELETED: - QPID_LOG(error, - "Txn " << i->first << " was deleted; shouldn't be here"); - break; - } - boost::weak_ptr weak_txn(i->second); - validIds[i->first] = weak_txn; - } -} - -}}} // namespace qpid::store::ms_clfs diff --git a/qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.h b/qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.h deleted file mode 100644 index 7ca27c229e..0000000000 --- a/qpid/cpp/src/qpid/store/ms-clfs/TransactionLog.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_TRANSACTIONLOG_H -#define QPID_STORE_MSCLFS_TRANSACTIONLOG_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 - -#include -#include - -#include -#include -#include - -#include "Log.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -class Transaction; -class TPCTransaction; - -/** - * @class TransactionLog - * - * Represents a CLFS-housed transaction log. - */ -class TransactionLog : public Log, - public boost::enable_shared_from_this { - - // To know when it's ok to move the log tail the lowest valid Id must - // always be known. Keep track of valid Ids here. These are transactions - // which have not yet been Deleted in the log. They may be new, in progress, - // prepared, committed, or aborted - but not deleted. - // Entries corresponding to not-yet-finalized transactions (i.e., open or - // prepared) also have a weak_ptr so the Transaction can be accessed. - // This is primarily to check its state and get a list of prepared Xids. - std::map > validIds; - qpid::sys::Mutex idsLock; - -protected: - // Transaction log needs to have a no-op first record written in the log - // to ensure that no real transaction gets an ID 0; messages think trans - // id 0 means "no transaction." - virtual void initialize(); - -public: - // Inherited and reimplemented from Log. Figure the minimum marshalling - // buffer size needed for the records this class writes. - virtual uint32_t marshallingBufferSize(); - - typedef boost::shared_ptr shared_ptr; - - // Get a new Transaction - boost::shared_ptr begin(); - - // Get a new TPCTransaction - boost::shared_ptr begin(const std::string& xid); - - void recordPrepare(uint64_t transId); - void recordCommit(uint64_t transId); - void recordAbort(uint64_t transId); - void deleteTransaction(uint64_t transId); - - // Fill @arg preparedMap with Xid->TPCTransaction::shared_ptr for all - // currently prepared transactions. - void collectPreparedXids(std::map >& preparedMap); - - // Recover the transactions and their state from the log. - // Every non-deleted transaction recovered from the log will be - // represented in @arg transMap. The recovering messages can use this - // information to tell if a transaction referred to in an enqueue/dequeue - // operation should be recovered or dropped by examining transaction state. - // - // @param recoverer Recovery manager used to recreate broker objects from - // entries recovered from the log. - // @param transMap This method fills in the map of id -> shared_ptr of - // recovered transactions. - void recover(std::map >& transMap); -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_TRANSACTIONLOG_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.cpp b/qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.cpp deleted file mode 100644 index 095d1bf331..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.cpp +++ /dev/null @@ -1,67 +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 "AmqpTransaction.h" -#include "DatabaseConnection.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -AmqpTransaction::AmqpTransaction(const boost::shared_ptr& _db) - : db(_db), sqlTrans(_db) -{ -} - -AmqpTransaction::~AmqpTransaction() -{ -} - -void -AmqpTransaction::sqlBegin() -{ - sqlTrans.begin(); -} - -void -AmqpTransaction::sqlCommit() -{ - sqlTrans.commit(); -} - -void -AmqpTransaction::sqlAbort() -{ - sqlTrans.abort(); -} - - -AmqpTPCTransaction::AmqpTPCTransaction(const boost::shared_ptr& db, - const std::string& _xid) - : AmqpTransaction(db), prepared(false), xid(_xid) -{ -} - -AmqpTPCTransaction::~AmqpTPCTransaction() -{ -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.h b/qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.h deleted file mode 100644 index 625fab5595..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/AmqpTransaction.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef QPID_STORE_MSSQL_AMQPTRANSACTION_H -#define QPID_STORE_MSSQL_AMQPTRANSACTION_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 -#include -#include - -#include "SqlTransaction.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -class DatabaseConnection; - -/** - * @class AmqpTransaction - * - * Class representing an AMQP transaction. This is used around a set of - * enqueue and dequeue operations that occur when the broker is acting - * on a transaction commit/abort from the client. - */ -class AmqpTransaction : public qpid::broker::TransactionContext { - - boost::shared_ptr db; - SqlTransaction sqlTrans; - -public: - AmqpTransaction(const boost::shared_ptr& _db); - virtual ~AmqpTransaction(); - - DatabaseConnection *dbConn() { return db.get(); } - - void sqlBegin(); - void sqlCommit(); - void sqlAbort(); -}; - -/** - * @class AmqpTPCTransaction - * - * Class representing a Two-Phase-Commit (TPC) AMQP transaction. This is - * used around a set of enqueue and dequeue operations that occur when the - * broker is acting on a transaction prepare/commit/abort from the client. - */ -class AmqpTPCTransaction : public AmqpTransaction, - public qpid::broker::TPCTransactionContext { - bool prepared; - std::string xid; - -public: - AmqpTPCTransaction(const boost::shared_ptr& db, - const std::string& _xid); - virtual ~AmqpTPCTransaction(); - - void setPrepared(void) { prepared = true; } - bool isPrepared(void) const { return prepared; } - - const std::string& getXid(void) const { return xid; } -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_AMQPTRANSACTION_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.cpp b/qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.cpp deleted file mode 100644 index 1dc4370312..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.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 -#include - -#include "BindingRecordset.h" -#include "BlobAdapter.h" -#include "BlobEncoder.h" -#include "VariantHelper.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -void -BindingRecordset::removeFilter(const std::string& filter) -{ - rs->PutFilter (VariantHelper(filter)); - long recs = rs->GetRecordCount(); - if (recs == 0) - return; // Nothing to do - while (recs > 0) { - // Deleting adAffectAll doesn't work as documented; go one by one. - rs->Delete(adAffectCurrent); - if (--recs > 0) - rs->MoveNext(); - } - rs->Update(); -} - -void -BindingRecordset::add(uint64_t exchangeId, - uint64_t queueId, - const std::string& routingKey, - const qpid::framing::FieldTable& args) -{ - VariantHelper routingKeyStr(routingKey); - BlobEncoder blob (args); // Marshall field table to a blob - rs->AddNew(); - rs->Fields->GetItem("exchangeId")->Value = exchangeId; - rs->Fields->GetItem("queueId")->Value = queueId; - rs->Fields->GetItem("routingKey")->Value = routingKeyStr; - rs->Fields->GetItem("fieldTableBlob")->AppendChunk(blob); - rs->Update(); -} - -void -BindingRecordset::remove(uint64_t exchangeId, - uint64_t queueId, - const std::string& routingKey, - const qpid::framing::FieldTable& /*args*/) -{ - // Look up the affected binding. - std::ostringstream filter; - filter << "exchangeId = " << exchangeId - << " AND queueId = " << queueId - << " AND routingKey = '" << routingKey << "'" << std::ends; - removeFilter(filter.str()); -} - -void -BindingRecordset::removeForExchange(uint64_t exchangeId) -{ - // Look up the affected bindings by the exchange ID - std::ostringstream filter; - filter << "exchangeId = " << exchangeId << std::ends; - removeFilter(filter.str()); -} - -void -BindingRecordset::removeForQueue(uint64_t queueId) -{ - // Look up the affected bindings by the queue ID - std::ostringstream filter; - filter << "queueId = " << queueId << std::ends; - removeFilter(filter.str()); -} - -void -BindingRecordset::recover(broker::RecoveryManager& recoverer, - const store::ExchangeMap& exchMap, - const store::QueueMap& queueMap) -{ - if (rs->BOF && rs->EndOfFile) - return; // Nothing to do - rs->MoveFirst(); - Binding b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - while (!rs->EndOfFile) { - long blobSize = rs->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = rs->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - store::ExchangeMap::const_iterator exch = exchMap.find(b.exchangeId); - if (exch == exchMap.end()) { - std::ostringstream msg; - msg << "Error recovering bindings; exchange ID " << b.exchangeId - << " not found in exchange map"; - throw qpid::Exception(msg.str()); - } - broker::RecoverableExchange::shared_ptr exchPtr = exch->second; - store::QueueMap::const_iterator q = queueMap.find(b.queueId); - if (q == queueMap.end()) { - std::ostringstream msg; - msg << "Error recovering bindings; queue ID " << b.queueId - << " not found in queue map"; - throw qpid::Exception(msg.str()); - } - broker::RecoverableQueue::shared_ptr qPtr = q->second; - // The recovery manager wants the queue name, so get it from the - // RecoverableQueue. - std::string key(b.routingKey); - exchPtr->bind(qPtr->getName(), key, blob); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -void -BindingRecordset::dump() -{ - Recordset::dump(); - if (rs->EndOfFile && rs->BOF) // No records - return; - rs->MoveFirst(); - - Binding b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - - while (VARIANT_FALSE == rs->EndOfFile) { - QPID_LOG(notice, "exch Id " << b.exchangeId - << ", q Id " << b.queueId - << ", k: " << b.routingKey); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.h b/qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.h deleted file mode 100644 index 3cb732de75..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/BindingRecordset.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef QPID_STORE_MSSQL_BINDINGRECORDSET_H -#define QPID_STORE_MSSQL_BINDINGRECORDSET_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 -#include "Recordset.h" -#include -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class BindingRecordset - * - * Class for the binding records. - */ -class BindingRecordset : public Recordset { - - class Binding : public CADORecordBinding { - BEGIN_ADO_BINDING(Binding) - ADO_FIXED_LENGTH_ENTRY2(1, adBigInt, exchangeId, FALSE) - ADO_FIXED_LENGTH_ENTRY2(2, adBigInt, queueId, FALSE) - ADO_VARIABLE_LENGTH_ENTRY4(3, adVarChar, routingKey, - sizeof(routingKey), FALSE) - END_ADO_BINDING() - - public: - uint64_t exchangeId; - uint64_t queueId; - char routingKey[256]; - }; - - // Remove all records matching the specified filter/query. - void removeFilter(const std::string& filter); - -public: - // Add a new binding - void add(uint64_t exchangeId, - uint64_t queueId, - const std::string& routingKey, - const qpid::framing::FieldTable& args); - - // Remove a specific binding - void remove(uint64_t exchangeId, - uint64_t queueId, - const std::string& routingKey, - const qpid::framing::FieldTable& args); - - // Remove all bindings for the specified exchange - void removeForExchange(uint64_t exchangeId); - - // Remove all bindings for the specified queue - void removeForQueue(uint64_t queueId); - - // Recover bindings set using exchMap to get from Id to RecoverableExchange. - void recover(qpid::broker::RecoveryManager& recoverer, - const qpid::store::ExchangeMap& exchMap, - const qpid::store::QueueMap& queueMap); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_BINDINGRECORDSET_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.cpp b/qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.cpp deleted file mode 100644 index 1889f34e41..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.cpp +++ /dev/null @@ -1,64 +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 "BlobAdapter.h" -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -void -BlobAdapter::extractBuff() -{ - // To give a valid Buffer back, lock the safearray, obtaining a pointer to - // the actual data. Record the pointer in the Buffer so the destructor - // knows to unlock the safearray. - if (buff.getPointer() == 0) { - char *blob; - SafeArrayAccessData(this->parray, (void **)&blob); - qpid::framing::Buffer lockedBuff(blob, buff.getSize()); - buff = lockedBuff; - } -} - - -BlobAdapter::~BlobAdapter() -{ - // If buff's pointer is set, the safearray is locked, so unlock it - if (buff.getPointer() != 0) - SafeArrayUnaccessData(this->parray); -} - -BlobAdapter::operator qpid::framing::Buffer& () -{ - extractBuff(); - return buff; -} - -BlobAdapter::operator qpid::framing::FieldTable& () -{ - extractBuff(); - fields.decode(buff); - return fields; -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.h b/qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.h deleted file mode 100644 index 1c666392bc..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/BlobAdapter.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_STORE_MSSQL_BLOBADAPTER_H -#define QPID_STORE_MSSQL_BLOBADAPTER_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 -#include -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class BlobAdapter - * - * Adapter for accessing a blob (varbinary SQL field) as a qpid::framing::Buffer - * in an exception-safe way. - */ -class BlobAdapter : public _variant_t { -private: - // This Buffer's pointer indicates whether or not a safearray has - // been locked; if it's 0, no locking was done. - qpid::framing::Buffer buff; - qpid::framing::FieldTable fields; - - void extractBuff(); - -public: - // Initialize with the known length of the data that will come. - // Assigning a _variant_t to this object will set up the array to be - // accessed with the operator Buffer&() - BlobAdapter(long blobSize) : _variant_t(), buff(0, blobSize) {} - ~BlobAdapter(); - BlobAdapter& operator=(_variant_t& var_t_Src) - { _variant_t::operator=(var_t_Src); return *this; } - operator qpid::framing::Buffer& (); - operator qpid::framing::FieldTable& (); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_BLOBADAPTER_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.cpp b/qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.cpp deleted file mode 100644 index 75d3dc2d86..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.cpp +++ /dev/null @@ -1,133 +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 "BlobEncoder.h" -#include -#include -#include -#include -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -template void -BlobEncoder::encode(const ITEM &item) -{ - SAFEARRAYBOUND bound[1] = {0, 0}; - bound[0].cElements = item.encodedSize(); - blob = SafeArrayCreate(VT_UI1, 1, bound); - if (S_OK != SafeArrayLock(blob)) { - SafeArrayDestroy(blob); - blob = 0; - throw qpid::Exception("Error locking blob area for persistable item"); - } - try { - qpid::framing::Buffer buff((char *)blob->pvData, bound[0].cElements); - item.encode(buff); - } - catch(...) { - SafeArrayUnlock(blob); - SafeArrayDestroy(blob); - blob = 0; - throw; - } - this->vt = VT_ARRAY | VT_UI1; - this->parray = blob; - SafeArrayUnlock(blob); -} - -template <> void -BlobEncoder::encode(const boost::intrusive_ptr &item) -{ - // NOTE! If this code changes, verify the recovery code in MessageRecordset - SAFEARRAYBOUND bound[1] = {0, 0}; - bound[0].cElements = item->encodedSize() + sizeof(uint32_t); - blob = SafeArrayCreate(VT_UI1, 1, bound); - if (S_OK != SafeArrayLock(blob)) { - SafeArrayDestroy(blob); - blob = 0; - throw qpid::Exception("Error locking blob area for message"); - } - try { - uint32_t headerSize = item->encodedHeaderSize(); - qpid::framing::Buffer buff((char *)blob->pvData, bound[0].cElements); - buff.putLong(headerSize); - item->encode(buff); - } - catch(...) { - SafeArrayUnlock(blob); - SafeArrayDestroy(blob); - blob = 0; - throw; - } - this->vt = VT_ARRAY | VT_UI1; - this->parray = blob; - SafeArrayUnlock(blob); -} - -template <> void -BlobEncoder::encode(const std::string &item) -{ - SAFEARRAYBOUND bound[1] = {0, 0}; - bound[0].cElements = item.size(); - blob = SafeArrayCreate(VT_UI1, 1, bound); - if (S_OK != SafeArrayLock(blob)) { - SafeArrayDestroy(blob); - blob = 0; - throw qpid::Exception("Error locking blob area for string"); - } - memcpy_s(blob->pvData, item.size(), item.data(), item.size()); - this->vt = VT_ARRAY | VT_UI1; - this->parray = blob; - SafeArrayUnlock(blob); -} - -BlobEncoder::BlobEncoder(const qpid::broker::Persistable &item) : blob(0) -{ - encode(item); -} - -BlobEncoder::BlobEncoder(const boost::intrusive_ptr &msg) : blob(0) -{ - encode(msg); -} - -BlobEncoder::BlobEncoder(const qpid::framing::FieldTable &fields) : blob(0) -{ - encode(fields); -} - -BlobEncoder::BlobEncoder(const std::string &data) : blob(0) -{ - encode(data); -} - -BlobEncoder::~BlobEncoder() -{ - if (blob) - SafeArrayDestroy(blob); - blob = 0; - this->parray = 0; -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.h b/qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.h deleted file mode 100644 index d2b56223c1..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/BlobEncoder.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_STORE_MSSQL_BLOBENCODER_H -#define QPID_STORE_MSSQL_BLOBENCODER_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 -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class BlobEncoder - * - * Encodes a blob (varbinary) field from a qpid::broker::Persistable or a - * qpid::framing::FieldTable (both of which can be encoded to - * qpid::framing::Buffer) so it can be passed to ADO methods for writing - * to the database. - */ -class BlobEncoder : public _variant_t { -private: - SAFEARRAY *blob; - - template void encode(const ITEM &item); - -public: - BlobEncoder(const qpid::broker::Persistable &item); - BlobEncoder(const boost::intrusive_ptr &msg); - BlobEncoder(const qpid::framing::FieldTable &fields); - BlobEncoder(const std::string& data); - ~BlobEncoder(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_BLOBENCODER_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.cpp b/qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.cpp deleted file mode 100644 index ef1757dbad..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include -#include - -#include "BlobRecordset.h" -#include "BlobEncoder.h" -#include "VariantHelper.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -void -BlobRecordset::add(const qpid::broker::Persistable& item) -{ - BlobEncoder blob (item); // Marshall item info to a blob - rs->AddNew(); - rs->Fields->GetItem("fieldTableBlob")->AppendChunk(blob); - rs->Update(); - uint64_t id = rs->Fields->Item["persistenceId"]->Value; - item.setPersistenceId(id); -} - -void -BlobRecordset::remove(uint64_t id) -{ - // Look up the item by its persistenceId - std::ostringstream filter; - filter << "persistenceId = " << id << std::ends; - rs->PutFilter (VariantHelper(filter.str())); - if (!rs->EndOfFile) { - // Delete the record - rs->Delete(adAffectCurrent); - rs->Update(); - } -} - -void -BlobRecordset::remove(const qpid::broker::Persistable& item) -{ - remove(item.getPersistenceId()); -} - -void -BlobRecordset::dump() -{ - Recordset::dump(); -#if 1 - if (rs->EndOfFile && rs->BOF) // No records - return; - - rs->MoveFirst(); - while (!rs->EndOfFile) { - uint64_t id = rs->Fields->Item["persistenceId"]->Value; - QPID_LOG(notice, " -> " << id); - rs->MoveNext(); - } -#else - for (Iterator iter = begin(); iter != end(); ++iter) { - uint64_t id = *iter.first; - QPID_LOG(notice, " -> " << id); - } -#endif -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.h b/qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.h deleted file mode 100644 index 4d1c338746..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/BlobRecordset.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_STORE_MSSQL_BLOBRECORDSET_H -#define QPID_STORE_MSSQL_BLOBRECORDSET_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 "Recordset.h" -#include -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class BlobRecordset - * - * Class for the "blob" records that record an id, varbinary(max) pair. - */ -class BlobRecordset : public Recordset { -protected: - -public: - void add(const qpid::broker::Persistable& item); - - // Remove a record given its Id. - void remove(uint64_t id); - void remove(const qpid::broker::Persistable& item); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_BLOBRECORDSET_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/DatabaseConnection.cpp b/qpid/cpp/src/qpid/store/ms-sql/DatabaseConnection.cpp deleted file mode 100644 index 3219ea526a..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/DatabaseConnection.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 "DatabaseConnection.h" -#include "Exception.h" -#include -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; -} - -namespace qpid { -namespace store { -namespace ms_sql { - -DatabaseConnection::DatabaseConnection() : conn(0) -{ -} - -DatabaseConnection::~DatabaseConnection() -{ - close(); -} - -void -DatabaseConnection::open(const std::string& connectString, - const std::string& dbName) -{ - if (conn && conn->State == adStateOpen) - return; - std::string adoConnect = "Provider=SQLOLEDB;" + connectString; - try { - TESTHR(conn.CreateInstance(__uuidof(Connection))); - conn->ConnectionString = adoConnect.c_str(); - conn->Open("", "", "", adConnectUnspecified); - if (dbName.length() > 0) - conn->DefaultDatabase = dbName.c_str(); - } - catch(_com_error &e) { - close(); - throw ADOException("MSSQL can't open " + dbName + " at " + adoConnect, e); - } -} - -void -DatabaseConnection::close() -{ - if (conn && conn->State == adStateOpen) - conn->Close(); - conn = 0; -} - -std::string -DatabaseConnection::getErrors() -{ - long errCount = conn->Errors->Count; - if (errCount <= 0) - return ""; - // Collection ranges from 0 to nCount -1. - std::ostringstream messages; - ErrorPtr pErr = NULL; - for (long i = 0 ; i < errCount ; i++ ) { - if (i > 0) - messages << "\n"; - messages << "[" << i << "] "; - pErr = conn->Errors->GetItem(i); - messages << "Error " << pErr->Number << ": " - << (LPCSTR)pErr->Description; - } - messages << std::ends; - return messages.str(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/DatabaseConnection.h b/qpid/cpp/src/qpid/store/ms-sql/DatabaseConnection.h deleted file mode 100644 index 785d1587c5..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/DatabaseConnection.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_STORE_MSSQL_DATABASECONNECTION_H -#define QPID_STORE_MSSQL_DATABASECONNECTION_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. - * - */ - -// Bring in ADO 2.8 (yes, I know it says "15", but that's it...) -#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ - no_namespace rename("EOF", "EndOfFile") - -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class DatabaseConnection - * - * Represents a connection to the SQL database. This class wraps the - * needed _ConnectionPtr for ADO as well as the needed COM initialization - * and cleanup that each thread requires. It is expected that this class - * will be maintained in thread-specific storage so it has no locks. - */ -class DatabaseConnection { -protected: - _ConnectionPtr conn; - -public: - DatabaseConnection(); - ~DatabaseConnection(); - void open(const std::string& connectString, - const std::string& dbName = ""); - void close(); - operator _ConnectionPtr () { return conn; } - - void beginTransaction() { conn->BeginTrans(); } - void commitTransaction() {conn->CommitTrans(); } - void rollbackTransaction() { conn->RollbackTrans(); } - - std::string getErrors(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_DATABASECONNECTION_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/Exception.h b/qpid/cpp/src/qpid/store/ms-sql/Exception.h deleted file mode 100644 index 65ec3388ff..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/Exception.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef QPID_STORE_MSSQL_EXCEPTION_H -#define QPID_STORE_MSSQL_EXCEPTION_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 -#include -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -class Exception : public qpid::store::StorageProvider::Exception -{ -protected: - std::string text; -public: - Exception(const std::string& _text) : text(_text) {} - virtual ~Exception() {} - virtual const char* what() const throw() { return text.c_str(); } -}; - -class ADOException : public Exception -{ -public: - ADOException(const std::string& _text, - _com_error &e, - const std::string& providerErrors = "") - : Exception(_text) { - text += ": "; - text += e.ErrorMessage(); - IErrorInfo *i = e.ErrorInfo(); - if (i != 0) { - text += ": "; - _bstr_t wmsg = e.Description(); - text += (const char *)wmsg; - i->Release(); - } - if (providerErrors.length() > 0) - text += providerErrors; - } -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_EXCEPTION_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/MSSqlProvider.cpp b/qpid/cpp/src/qpid/store/ms-sql/MSSqlProvider.cpp deleted file mode 100644 index 1432cc8fca..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/MSSqlProvider.cpp +++ /dev/null @@ -1,1286 +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 -#include -#include -#include -#include -#include -#include -#include "AmqpTransaction.h" -#include "BlobAdapter.h" -#include "BlobRecordset.h" -#include "BindingRecordset.h" -#include "MessageMapRecordset.h" -#include "MessageRecordset.h" -#include "TplRecordset.h" -#include "DatabaseConnection.h" -#include "Exception.h" -#include "State.h" -#include "VariantHelper.h" - -// Bring in ADO 2.8 (yes, I know it says "15", but that's it...) -#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ - no_namespace rename("EOF", "EndOfFile") -#include -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; - -// Table names -const std::string TblBinding("tblBinding"); -const std::string TblConfig("tblConfig"); -const std::string TblExchange("tblExchange"); -const std::string TblMessage("tblMessage"); -const std::string TblMessageMap("tblMessageMap"); -const std::string TblQueue("tblQueue"); -const std::string TblTpl("tblTPL"); -} - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class MSSqlProvider - * - * Implements a qpid::store::StorageProvider that uses Microsoft SQL Server as - * the backend data store for Qpid. - */ -class MSSqlProvider : public qpid::store::StorageProvider -{ -protected: - void finalizeMe(); - - void dump(); - -public: - MSSqlProvider(); - ~MSSqlProvider(); - - virtual qpid::Options* getOptions() { return &options; } - - virtual void earlyInitialize (Plugin::Target& target); - virtual void initialize(Plugin::Target& target); - - /** - * Receive notification that this provider is the one that will actively - * handle provider storage for the target. If the provider is to be used, - * this method will be called after earlyInitialize() and before any - * recovery operations (recovery, in turn, precedes call to initialize()). - */ - virtual void activate(MessageStorePlugin &store); - - /** - * @name Methods inherited from qpid::broker::MessageStore - */ - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const qpid::framing::FieldTable& args); - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue); - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args); - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange); - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config); - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config); - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr& msg); - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg); - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr& msg, - const std::string& data); - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue); - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue); - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: this is a no-op for this provider. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const PersistableQueue& queue) {}; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) - {return 0;} - //@} - - /** - * @name Methods inherited from qpid::broker::TransactionalStore - */ - //@{ - virtual std::auto_ptr begin(); - virtual std::auto_ptr begin(const std::string& xid); - virtual void prepare(qpid::broker::TPCTransactionContext& txn); - virtual void commit(qpid::broker::TransactionContext& txn); - virtual void abort(qpid::broker::TransactionContext& txn); - virtual void collectPreparedXids(std::set& xids); - //@} - - virtual void recoverConfigs(qpid::broker::RecoveryManager& recoverer); - virtual void recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap); - virtual void recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap); - virtual void recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap); - virtual void recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap); - virtual void recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap); - -private: - struct ProviderOptions : public qpid::Options - { - std::string connectString; - std::string catalogName; - - ProviderOptions(const std::string &name) - : qpid::Options(name), - catalogName("QpidStore") - { - const enum { NAMELEN = MAX_COMPUTERNAME_LENGTH + 1 }; - TCHAR myName[NAMELEN]; - DWORD myNameLen = NAMELEN; - GetComputerName(myName, &myNameLen); - connectString = "Data Source="; - connectString += myName; - connectString += "\\SQLEXPRESS;Integrated Security=SSPI"; - addOptions() - ("connect", - qpid::optValue(connectString, "STRING"), - "Connection string for the database to use. Will prepend " - "Provider=SQLOLEDB;") - ("catalog", - qpid::optValue(catalogName, "DB NAME"), - "Catalog (database) name") - ; - } - }; - ProviderOptions options; - - // Each thread has a separate connection to the database and also needs - // to manage its COM initialize/finalize individually. This is done by - // keeping a thread-specific State. - boost::thread_specific_ptr dbState; - - State *initState(); - DatabaseConnection *initConnection(void); - void createDb(DatabaseConnection *db, const std::string &name); -}; - -static MSSqlProvider static_instance_registers_plugin; - -void -MSSqlProvider::finalizeMe() -{ - dbState.reset(); -} - -MSSqlProvider::MSSqlProvider() - : options("MS SQL Provider options") -{ -} - -MSSqlProvider::~MSSqlProvider() -{ -} - -void -MSSqlProvider::earlyInitialize(Plugin::Target &target) -{ - MessageStorePlugin *store = dynamic_cast(&target); - if (store) { - // If the database init fails, report it and don't register; give - // the rest of the broker a chance to run. - // - // Don't try to initConnection() since that will fail if the - // database doesn't exist. Instead, try to open a connection without - // a database name, then search for the database. There's still a - // chance this provider won't be selected for the store too, so be - // be sure to close the database connection before return to avoid - // leaving a connection up that will not be used. - try { - initState(); // This initializes COM - std::auto_ptr db(new DatabaseConnection()); - db->open(options.connectString, ""); - _ConnectionPtr conn(*db); - _RecordsetPtr pCatalogs = NULL; - VariantHelper catalogName(options.catalogName); - pCatalogs = conn->OpenSchema(adSchemaCatalogs, catalogName); - if (pCatalogs->EndOfFile) { - // Database doesn't exist; create it - QPID_LOG(notice, - "MSSQL: Creating database " + options.catalogName); - createDb(db.get(), options.catalogName); - } - else { - QPID_LOG(notice, - "MSSQL: Database located: " + options.catalogName); - } - if (pCatalogs) { - if (pCatalogs->State == adStateOpen) - pCatalogs->Close(); - pCatalogs = 0; - } - db->close(); - store->providerAvailable("MSSQL", this); - } - catch (qpid::Exception &e) { - QPID_LOG(error, e.what()); - return; - } - store->addFinalizer(boost::bind(&MSSqlProvider::finalizeMe, this)); - } -} - -void -MSSqlProvider::initialize(Plugin::Target& target) -{ -} - -void -MSSqlProvider::activate(MessageStorePlugin &store) -{ - QPID_LOG(info, "MS SQL Provider is up"); -} - -void -MSSqlProvider::create(PersistableQueue& queue, - const qpid::framing::FieldTable& /*args needed for jrnl*/) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - try { - db->beginTransaction(); - rsQueues.open(db, TblQueue); - rsQueues.add(queue); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating queue " + queue.getName(), e, errs); - } -} - -/** - * Destroy a durable queue - */ -void -MSSqlProvider::destroy(PersistableQueue& queue) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - BindingRecordset rsBindings; - MessageRecordset rsMessages; - MessageMapRecordset rsMessageMaps; - try { - db->beginTransaction(); - rsQueues.open(db, TblQueue); - rsBindings.open(db, TblBinding); - rsMessages.open(db, TblMessage); - rsMessageMaps.open(db, TblMessageMap); - // Remove bindings first; the queue IDs can't be ripped out from - // under the references in the bindings table. Then remove the - // message->queue entries for the queue, also because the queue can't - // be deleted while there are references to it. If there are messages - // orphaned by removing the queue references, they're deleted by - // a trigger on the tblMessageMap table. Lastly, the queue record - // can be removed. - rsBindings.removeForQueue(queue.getPersistenceId()); - rsMessageMaps.removeForQueue(queue.getPersistenceId()); - rsQueues.remove(queue); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting queue " + queue.getName(), e, errs); - } -} - -/** - * Record the existence of a durable exchange - */ -void -MSSqlProvider::create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - try { - db->beginTransaction(); - rsExchanges.open(db, TblExchange); - rsExchanges.add(exchange); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating exchange " + exchange.getName(), - e, - errs); - } -} - -/** - * Destroy a durable exchange - */ -void -MSSqlProvider::destroy(const PersistableExchange& exchange) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsExchanges.open(db, TblExchange); - rsBindings.open(db, TblBinding); - // Remove bindings first; the exchange IDs can't be ripped out from - // under the references in the bindings table. - rsBindings.removeForExchange(exchange.getPersistenceId()); - rsExchanges.remove(exchange); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting exchange " + exchange.getName(), - e, - errs); - } -} - -/** - * Record a binding - */ -void -MSSqlProvider::bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsBindings.open(db, TblBinding); - rsBindings.add(exchange.getPersistenceId(), - queue.getPersistenceId(), - key, - args); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error binding exchange " + exchange.getName() + - " to queue " + queue.getName(), - e, - errs); - } -} - -/** - * Forget a binding - */ -void -MSSqlProvider::unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsBindings.open(db, TblBinding); - rsBindings.remove(exchange.getPersistenceId(), - queue.getPersistenceId(), - key, - args); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error unbinding exchange " + exchange.getName() + - " from queue " + queue.getName(), - e, - errs); - } -} - -/** - * Record generic durable configuration - */ -void -MSSqlProvider::create(const PersistableConfig& config) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - try { - db->beginTransaction(); - rsConfigs.open(db, TblConfig); - rsConfigs.add(config); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating config " + config.getName(), e, errs); - } -} - -/** - * Destroy generic durable configuration - */ -void -MSSqlProvider::destroy(const PersistableConfig& config) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - try { - db->beginTransaction(); - rsConfigs.open(db, TblConfig); - rsConfigs.remove(config); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting config " + config.getName(), e, errs); - } -} - -/** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ -void -MSSqlProvider::stage(const boost::intrusive_ptr& msg) -{ - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.add(msg); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error staging message", e, errs); - } -} - -/** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ -void -MSSqlProvider::destroy(PersistableMessage& msg) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.remove(msg); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting message", e, errs); - } -} - -/** - * Appends content to a previously staged message - */ -void -MSSqlProvider::appendContent(const boost::intrusive_ptr& msg, - const std::string& data) -{ - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.append(msg, data); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error appending to message", e, errs); - } -} - -/** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ -void -MSSqlProvider::loadContent(const qpid::broker::PersistableQueue& /*queue*/, - const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length) -{ - // SQL store keeps all messages in one table, so we don't need the - // queue reference. - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - rsMessages.open(db, TblMessage); - rsMessages.loadContent(msg, data, offset, length); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - throw ADOException("Error loading message content", e, errs); - } -} - -/** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * @param ctxt The transaction context under which this enqueue happens. - * @param msg The message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - */ -void -MSSqlProvider::enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) -{ - // If this enqueue is in the context of a transaction, use the specified - // transaction to nest a new transaction for this operation. However, if - // this is not in the context of a transaction, then just use the thread's - // DatabaseConnection with a ADO transaction. - DatabaseConnection *db = 0; - std::string xid; - AmqpTransaction *atxn = dynamic_cast (ctxt); - if (atxn == 0) { - db = initConnection(); - db->beginTransaction(); - } - else { - (void)initState(); // Ensure this thread is initialized - // It's a transactional enqueue; if it's TPC, grab the xid. - AmqpTPCTransaction *tpcTxn = dynamic_cast (ctxt); - if (tpcTxn) - xid = tpcTxn->getXid(); - db = atxn->dbConn(); - try { - atxn->sqlBegin(); - } - catch(_com_error &e) { - throw ADOException("Error queuing message", e, db->getErrors()); - } - } - - MessageRecordset rsMessages; - MessageMapRecordset rsMap; - try { - if (msg->getPersistenceId() == 0) { // Message itself not yet saved - rsMessages.open(db, TblMessage); - rsMessages.add(msg); - } - rsMap.open(db, TblMessageMap); - rsMap.add(msg->getPersistenceId(), queue.getPersistenceId(), xid); - if (atxn) - atxn->sqlCommit(); - else - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - if (atxn) - atxn->sqlAbort(); - else - db->rollbackTransaction(); - throw ADOException("Error queuing message", e, errs); - } - msg->enqueueComplete(); -} - -/** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * @param ctxt The transaction context under which this dequeue happens. - * @param msg The message to dequeue - * @param queue The queue from which it is to be dequeued - */ -void -MSSqlProvider::dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) -{ - // If this dequeue is in the context of a transaction, use the specified - // transaction to nest a new transaction for this operation. However, if - // this is not in the context of a transaction, then just use the thread's - // DatabaseConnection with a ADO transaction. - DatabaseConnection *db = 0; - std::string xid; - AmqpTransaction *atxn = dynamic_cast (ctxt); - if (atxn == 0) { - db = initConnection(); - db->beginTransaction(); - } - else { - (void)initState(); // Ensure this thread is initialized - // It's a transactional dequeue; if it's TPC, grab the xid. - AmqpTPCTransaction *tpcTxn = dynamic_cast (ctxt); - if (tpcTxn) - xid = tpcTxn->getXid(); - db = atxn->dbConn(); - try { - atxn->sqlBegin(); - } - catch(_com_error &e) { - throw ADOException("Error queuing message", e, db->getErrors()); - } - } - - MessageMapRecordset rsMap; - try { - rsMap.open(db, TblMessageMap); - // TPC dequeues are just marked pending and will actually be removed - // when the transaction commits; Single-phase dequeues are removed - // now, relying on the SQL transaction to put it back if the - // transaction doesn't commit. - if (!xid.empty()) { - rsMap.pendingRemove(msg->getPersistenceId(), - queue.getPersistenceId(), - xid); - } - else { - rsMap.remove(msg->getPersistenceId(), - queue.getPersistenceId()); - } - if (atxn) - atxn->sqlCommit(); - else - db->commitTransaction(); - } - catch(ms_sql::Exception&) { - if (atxn) - atxn->sqlAbort(); - else - db->rollbackTransaction(); - throw; - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - if (atxn) - atxn->sqlAbort(); - else - db->rollbackTransaction(); - throw ADOException("Error dequeuing message", e, errs); - } - msg->dequeueComplete(); -} - -std::auto_ptr -MSSqlProvider::begin() -{ - (void)initState(); // Ensure this thread is initialized - - // Transactions are associated with the Connection, so this transaction - // context needs its own connection. At the time of writing, single-phase - // transactions are dealt with completely on one thread, so we really - // could just use the thread-specific DatabaseConnection for this. - // However, that would introduce an ugly, hidden coupling, so play - // it safe and handle this just like a TPC transaction, which actually - // can be prepared and committed/aborted from different threads, - // making it a bad idea to try using the thread-local DatabaseConnection. - boost::shared_ptr db(new DatabaseConnection); - db->open(options.connectString, options.catalogName); - std::auto_ptr tx(new AmqpTransaction(db)); - tx->sqlBegin(); - std::auto_ptr tc(tx); - return tc; -} - -std::auto_ptr -MSSqlProvider::begin(const std::string& xid) -{ - (void)initState(); // Ensure this thread is initialized - boost::shared_ptr db(new DatabaseConnection); - db->open(options.connectString, options.catalogName); - std::auto_ptr tx(new AmqpTPCTransaction(db, xid)); - tx->sqlBegin(); - - TplRecordset rsTpl; - try { - tx->sqlBegin(); - rsTpl.open(db.get(), TblTpl); - rsTpl.add(xid); - tx->sqlCommit(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - tx->sqlAbort(); - throw ADOException("Error adding TPL record", e, errs); - } - - std::auto_ptr tc(tx); - return tc; -} - -void -MSSqlProvider::prepare(qpid::broker::TPCTransactionContext& txn) -{ - // Commit all the marked-up enqueue/dequeue ops and the TPL record. - // On commit/rollback the TPL will be removed and the TPL markups - // on the message map will be cleaned up as well. - (void)initState(); // Ensure this thread is initialized - AmqpTPCTransaction *atxn = dynamic_cast (&txn); - if (atxn == 0) - throw qpid::broker::InvalidTransactionContextException(); - try { - atxn->sqlCommit(); - } - catch(_com_error &e) { - throw ADOException("Error preparing", e, atxn->dbConn()->getErrors()); - } - atxn->setPrepared(); -} - -void -MSSqlProvider::commit(qpid::broker::TransactionContext& txn) -{ - (void)initState(); // Ensure this thread is initialized - /* - * One-phase transactions simply commit the outer SQL transaction - * that was begun on begin(). Two-phase transactions are different - - * the SQL transaction started on begin() was committed on prepare() - * so all the SQL records reflecting the enqueue/dequeue actions for - * the transaction are recorded but with xid markups on them to reflect - * that they are prepared but not committed. Now go back and remove - * the markups, deleting those marked for removal. - */ - AmqpTPCTransaction *p2txn = dynamic_cast (&txn); - if (p2txn == 0) { - AmqpTransaction *p1txn = dynamic_cast (&txn); - if (p1txn == 0) - throw qpid::broker::InvalidTransactionContextException(); - p1txn->sqlCommit(); - return; - } - - DatabaseConnection *db(p2txn->dbConn()); - TplRecordset rsTpl; - MessageMapRecordset rsMessageMap; - try { - db->beginTransaction(); - rsTpl.open(db, TblTpl); - rsMessageMap.open(db, TblMessageMap); - rsMessageMap.commitPrepared(p2txn->getXid()); - rsTpl.remove(p2txn->getXid()); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error committing transaction", e, errs); - } -} - -void -MSSqlProvider::abort(qpid::broker::TransactionContext& txn) -{ - (void)initState(); // Ensure this thread is initialized - /* - * One-phase and non-prepared two-phase transactions simply abort - * the outer SQL transaction that was begun on begin(). However, prepared - * two-phase transactions are different - the SQL transaction started - * on begin() was committed on prepare() so all the SQL records - * reflecting the enqueue/dequeue actions for the transaction are - * recorded but with xid markups on them to reflect that they are - * prepared but not committed. Now go back and remove the markups, - * deleting those marked for addition. - */ - AmqpTPCTransaction *p2txn = dynamic_cast (&txn); - if (p2txn == 0 || !p2txn->isPrepared()) { - AmqpTransaction *p1txn = dynamic_cast (&txn); - if (p1txn == 0) - throw qpid::broker::InvalidTransactionContextException(); - p1txn->sqlAbort(); - return; - } - - DatabaseConnection *db(p2txn->dbConn()); - TplRecordset rsTpl; - MessageMapRecordset rsMessageMap; - try { - db->beginTransaction(); - rsTpl.open(db, TblTpl); - rsMessageMap.open(db, TblMessageMap); - rsMessageMap.abortPrepared(p2txn->getXid()); - rsTpl.remove(p2txn->getXid()); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error committing transaction", e, errs); - } - - - (void)initState(); // Ensure this thread is initialized - AmqpTransaction *atxn = dynamic_cast (&txn); - if (atxn == 0) - throw qpid::broker::InvalidTransactionContextException(); - atxn->sqlAbort(); -} - -void -MSSqlProvider::collectPreparedXids(std::set& xids) -{ - DatabaseConnection *db = initConnection(); - try { - TplRecordset rsTpl; - rsTpl.open(db, TblTpl); - rsTpl.recover(xids); - } - catch(_com_error &e) { - throw ADOException("Error reading TPL", e, db->getErrors()); - } -} - -// @TODO Much of this recovery code is way too similar... refactor to -// a recover template method on BlobRecordset. - -void -MSSqlProvider::recoverConfigs(qpid::broker::RecoveryManager& recoverer) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - BlobRecordset rsConfigs; - rsConfigs.open(db, TblConfig); - _RecordsetPtr p = (_RecordsetPtr)rsConfigs; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Config instance and reset its ID. - broker::RecoverableConfig::shared_ptr config = - recoverer.recoverConfig(blob); - config->setPersistenceId(id); - p->MoveNext(); - } - } - catch(_com_error &e) { - throw ADOException("Error recovering configs", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - BlobRecordset rsExchanges; - rsExchanges.open(db, TblExchange); - _RecordsetPtr p = (_RecordsetPtr)rsExchanges; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Exchange instance, reset its ID, and remember the - // ones restored for matching up when recovering bindings. - broker::RecoverableExchange::shared_ptr exchange = - recoverer.recoverExchange(blob); - exchange->setPersistenceId(id); - exchangeMap[id] = exchange; - p->MoveNext(); - } - } - catch(_com_error &e) { - throw ADOException("Error recovering exchanges", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - BlobRecordset rsQueues; - rsQueues.open(db, TblQueue); - _RecordsetPtr p = (_RecordsetPtr)rsQueues; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Queue instance and reset its ID. - broker::RecoverableQueue::shared_ptr queue = - recoverer.recoverQueue(blob); - queue->setPersistenceId(id); - queueMap[id] = queue; - p->MoveNext(); - } - } - catch(_com_error &e) { - throw ADOException("Error recovering queues", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - BindingRecordset rsBindings; - rsBindings.open(db, TblBinding); - rsBindings.recover(recoverer, exchangeMap, queueMap); - } - catch(_com_error &e) { - throw ADOException("Error recovering bindings", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - MessageRecordset rsMessages; - rsMessages.open(db, TblMessage); - rsMessages.recover(recoverer, messageMap); - - MessageMapRecordset rsMessageMaps; - rsMessageMaps.open(db, TblMessageMap); - rsMessageMaps.recover(messageQueueMap); - } - catch(_com_error &e) { - throw ADOException("Error recovering messages", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap) -{ - DatabaseConnection *db = initConnection(); - std::set xids; - try { - TplRecordset rsTpl; - rsTpl.open(db, TblTpl); - rsTpl.recover(xids); - } - catch(_com_error &e) { - throw ADOException("Error recovering TPL records", e, db->getErrors()); - } - - try { - // Rebuild the needed RecoverableTransactions. - for (std::set::const_iterator iXid = xids.begin(); - iXid != xids.end(); - ++iXid) { - boost::shared_ptr dbX(new DatabaseConnection); - dbX->open(options.connectString, options.catalogName); - std::auto_ptr tx(new AmqpTPCTransaction(dbX, - *iXid)); - tx->setPrepared(); - std::auto_ptr tc(tx); - dtxMap[*iXid] = recoverer.recoverTransaction(*iXid, tc); - } - } - catch(_com_error &e) { - throw ADOException("Error recreating dtx connection", e); - } -} - -////////////// Internal Methods - -State * -MSSqlProvider::initState() -{ - State *state = dbState.get(); // See if thread has initialized - if (!state) { - state = new State; - dbState.reset(state); - } - return state; -} - -DatabaseConnection * -MSSqlProvider::initConnection(void) -{ - State *state = initState(); - if (state->dbConn != 0) - return state->dbConn; // And the DatabaseConnection is set up too - std::auto_ptr db(new DatabaseConnection); - db->open(options.connectString, options.catalogName); - state->dbConn = db.release(); - return state->dbConn; -} - -void -MSSqlProvider::createDb(DatabaseConnection *db, const std::string &name) -{ - const std::string dbCmd = "CREATE DATABASE " + name; - const std::string useCmd = "USE " + name; - const std::string tableCmd = "CREATE TABLE "; - const std::string colSpecs = - " (persistenceId bigint PRIMARY KEY NOT NULL IDENTITY(1,1)," - " fieldTableBlob varbinary(MAX) NOT NULL)"; - const std::string bindingSpecs = - " (exchangeId bigint REFERENCES tblExchange(persistenceId) NOT NULL," - " queueId bigint REFERENCES tblQueue(persistenceId) NOT NULL," - " routingKey varchar(255)," - " fieldTableBlob varbinary(MAX))"; - const std::string messageMapSpecs = - " (messageId bigint REFERENCES tblMessage(persistenceId) NOT NULL," - " queueId bigint REFERENCES tblQueue(persistenceId) NOT NULL," - " prepareStatus tinyint CHECK (prepareStatus IS NULL OR " - " prepareStatus IN (1, 2))," - " xid varbinary(512) REFERENCES tblTPL(xid)" - " CONSTRAINT CK_NoDups UNIQUE NONCLUSTERED (messageId, queueId) )"; - const std::string tplSpecs = " (xid varbinary(512) PRIMARY KEY NOT NULL)"; - // SET NOCOUNT ON added to prevent extra result sets from - // interfering with SELECT statements. (Added by SQL Management) - const std::string removeUnrefMsgsTrigger = - "CREATE TRIGGER dbo.RemoveUnreferencedMessages " - "ON tblMessageMap AFTER DELETE AS BEGIN " - "SET NOCOUNT ON; " - "DELETE FROM tblMessage " - "WHERE tblMessage.persistenceId IN " - " (SELECT messageId FROM deleted) AND" - " NOT EXISTS(SELECT * FROM tblMessageMap" - " WHERE tblMessageMap.messageId IN" - " (SELECT messageId FROM deleted)) " - "END"; - - _variant_t unused; - _bstr_t dbStr = dbCmd.c_str(); - _ConnectionPtr conn(*db); - try { - conn->Execute(dbStr, &unused, adExecuteNoRecords); - _bstr_t useStr = useCmd.c_str(); - conn->Execute(useStr, &unused, adExecuteNoRecords); - std::string makeTable = tableCmd + TblQueue + colSpecs; - _bstr_t makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblExchange + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblConfig + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblMessage + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblBinding + bindingSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblTpl + tplSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblMessageMap + messageMapSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - _bstr_t addTriggerStr = removeUnrefMsgsTrigger.c_str(); - conn->Execute(addTriggerStr, &unused, adExecuteNoRecords); - } - catch(_com_error &e) { - throw ADOException("MSSQL can't create " + name, e, db->getErrors()); - } -} - -void -MSSqlProvider::dump() -{ - // dump all db records to qpid_log - QPID_LOG(notice, "DB Dump: (not dumping anything)"); - // rsQueues.dump(); -} - - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/MessageMapRecordset.cpp b/qpid/cpp/src/qpid/store/ms-sql/MessageMapRecordset.cpp deleted file mode 100644 index ce9fa61010..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/MessageMapRecordset.cpp +++ /dev/null @@ -1,267 +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 -#include -#include - -#include "MessageMapRecordset.h" -#include "BlobEncoder.h" -#include "DatabaseConnection.h" -#include "Exception.h" -#include "VariantHelper.h" - -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; -} - -namespace qpid { -namespace store { -namespace ms_sql { - -void -MessageMapRecordset::open(DatabaseConnection* conn, const std::string& table) -{ - init(conn, table); -} - -void -MessageMapRecordset::add(uint64_t messageId, - uint64_t queueId, - const std::string& xid) -{ - std::ostringstream command; - command << "INSERT INTO " << tableName - << " (messageId, queueId"; - if (!xid.empty()) - command << ", prepareStatus, xid"; - command << ") VALUES (" << messageId << "," << queueId; - if (!xid.empty()) - command << "," << PREPARE_ADD << ",?"; - command << ")" << std::ends; - - _CommandPtr cmd = NULL; - _ParameterPtr xidVal = NULL; - TESTHR(cmd.CreateInstance(__uuidof(Command))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.str().c_str(); - cmd->CommandType = adCmdText; - if (!xid.empty()) { - TESTHR(xidVal.CreateInstance(__uuidof(Parameter))); - xidVal->Name = "@xid"; - xidVal->Type = adVarBinary; - xidVal->Size = xid.length(); - xidVal->Direction = adParamInput; - xidVal->Value = BlobEncoder(xid); - cmd->Parameters->Append(xidVal); - } - cmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords); -} - -void -MessageMapRecordset::remove(uint64_t messageId, uint64_t queueId) -{ - std::ostringstream command; - command << "DELETE FROM " << tableName - << " WHERE queueId = " << queueId - << " AND messageId = " << messageId << std::ends; - _CommandPtr cmd = NULL; - TESTHR(cmd.CreateInstance(__uuidof(Command))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.str().c_str(); - cmd->CommandType = adCmdText; - _variant_t deletedRecords; - cmd->Execute(&deletedRecords, NULL, adCmdText | adExecuteNoRecords); - if ((long)deletedRecords == 0) - throw ms_sql::Exception("Message does not exist in queue mapping"); - // Trigger on deleting the mapping takes care of deleting orphaned - // message record from tblMessage. -} - -void -MessageMapRecordset::pendingRemove(uint64_t messageId, - uint64_t queueId, - const std::string& xid) -{ - // Look up the mapping for the specified message and queue. There - // should be only one because of the uniqueness constraint in the - // SQL table. Update it to reflect it's pending delete with - // the specified xid. - std::ostringstream command; - command << "UPDATE " << tableName - << " SET prepareStatus=" << PREPARE_REMOVE - << " , xid=?" - << " WHERE queueId = " << queueId - << " AND messageId = " << messageId << std::ends; - - _CommandPtr cmd = NULL; - _ParameterPtr xidVal = NULL; - TESTHR(cmd.CreateInstance(__uuidof(Command))); - TESTHR(xidVal.CreateInstance(__uuidof(Parameter))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.str().c_str(); - cmd->CommandType = adCmdText; - xidVal->Name = "@xid"; - xidVal->Type = adVarBinary; - xidVal->Size = xid.length(); - xidVal->Direction = adParamInput; - xidVal->Value = BlobEncoder(xid); - cmd->Parameters->Append(xidVal); - cmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords); -} - -void -MessageMapRecordset::removeForQueue(uint64_t queueId) -{ - std::ostringstream command; - command << "DELETE FROM " << tableName - << " WHERE queueId = " << queueId << std::ends; - _CommandPtr cmd = NULL; - - TESTHR(cmd.CreateInstance(__uuidof(Command))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.str().c_str(); - cmd->CommandType = adCmdText; - cmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords); -} - -void -MessageMapRecordset::commitPrepared(const std::string& xid) -{ - // Find all the records for the specified xid. Records marked as adding - // are now permanent so remove the xid and prepareStatus. Records marked - // as removing are removed entirely. - openRs(); - MessageMap m; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&m); - for (; !rs->EndOfFile; rs->MoveNext()) { - if (m.xidStatus != adFldOK) - continue; - const std::string x(m.xid, m.xidLength); - if (x != xid) - continue; - if (m.prepareStatus == PREPARE_REMOVE) { - rs->Delete(adAffectCurrent); - } - else { - _variant_t dbNull; - dbNull.ChangeType(VT_NULL); - rs->Fields->GetItem("prepareStatus")->Value = dbNull; - rs->Fields->GetItem("xid")->Value = dbNull; - } - rs->Update(); - } - piAdoRecordBinding->Release(); -} - -void -MessageMapRecordset::abortPrepared(const std::string& xid) -{ - // Find all the records for the specified xid. Records marked as adding - // need to be removed while records marked as removing are put back to - // no xid and no prepareStatus. - openRs(); - MessageMap m; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&m); - for (; !rs->EndOfFile; rs->MoveNext()) { - if (m.xidStatus != adFldOK) - continue; - const std::string x(m.xid, m.xidLength); - if (x != xid) - continue; - if (m.prepareStatus == PREPARE_ADD) { - rs->Delete(adAffectCurrent); - } - else { - _variant_t dbNull; - dbNull.ChangeType(VT_NULL); - rs->Fields->GetItem("prepareStatus")->Value = dbNull; - rs->Fields->GetItem("xid")->Value = dbNull; - } - rs->Update(); - } - piAdoRecordBinding->Release(); -} - -void -MessageMapRecordset::recover(MessageQueueMap& msgMap) -{ - openRs(); - if (rs->BOF && rs->EndOfFile) - return; // Nothing to do - rs->MoveFirst(); - MessageMap b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - while (!rs->EndOfFile) { - qpid::store::QueueEntry entry(b.queueId); - if (b.xidStatus == adFldOK && b.xidLength > 0) { - entry.xid.assign(b.xid, b.xidLength); - entry.tplStatus = - b.prepareStatus == PREPARE_ADD ? QueueEntry::ADDING - : QueueEntry::REMOVING; - } - else { - entry.tplStatus = QueueEntry::NONE; - } - msgMap[b.messageId].push_back(entry); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -void -MessageMapRecordset::dump() -{ - openRs(); - Recordset::dump(); - if (rs->EndOfFile && rs->BOF) // No records - return; - rs->MoveFirst(); - - MessageMap m; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&m); - - while (!rs->EndOfFile) { - QPID_LOG(notice, "msg " << m.messageId << " on queue " << m.queueId); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/MessageMapRecordset.h b/qpid/cpp/src/qpid/store/ms-sql/MessageMapRecordset.h deleted file mode 100644 index 1b0c2f073e..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/MessageMapRecordset.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef QPID_STORE_MSSQL_MESSAGEMAPRECORDSET_H -#define QPID_STORE_MSSQL_MESSAGEMAPRECORDSET_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 -#include "Recordset.h" -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class MessageMapRecordset - * - * Class for the message map (message -> queue) records. - */ -class MessageMapRecordset : public Recordset { - - // These values are defined in a constraint on the tblMessageMap table. - // the prepareStatus column can only be null, 1, or 2. - enum { PREPARE_ADD=1, PREPARE_REMOVE=2 }; - - class MessageMap : public CADORecordBinding { - BEGIN_ADO_BINDING(MessageMap) - ADO_FIXED_LENGTH_ENTRY2(1, adBigInt, messageId, FALSE) - ADO_FIXED_LENGTH_ENTRY2(2, adBigInt, queueId, FALSE) - ADO_FIXED_LENGTH_ENTRY2(3, adTinyInt, prepareStatus, FALSE) - ADO_VARIABLE_LENGTH_ENTRY(4, adVarBinary, xid, sizeof(xid), - xidStatus, xidLength, FALSE) - END_ADO_BINDING() - - public: - uint64_t messageId; - uint64_t queueId; - uint8_t prepareStatus; - char xid[512]; - int xidStatus; - uint32_t xidLength; - }; - - void selectOnXid(const std::string& xid); - -public: - virtual void open(DatabaseConnection* conn, const std::string& table); - - // Add a new mapping - void add(uint64_t messageId, - uint64_t queueId, - const std::string& xid = ""); - - // Remove a specific mapping. - void remove(uint64_t messageId, uint64_t queueId); - - // Mark the indicated message->queue entry pending removal. The entry - // for the mapping is updated to indicate pending removal with the - // specified xid. - void pendingRemove(uint64_t messageId, - uint64_t queueId, - const std::string& xid); - - // Remove mappings for all messages on a specified queue. - void removeForQueue(uint64_t queueId); - - // Commit records recorded as prepared. - void commitPrepared(const std::string& xid); - - // Abort prepared changes. - void abortPrepared(const std::string& xid); - - // Recover the mappings of message ID -> vector. - void recover(MessageQueueMap& msgMap); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_MESSAGEMAPRECORDSET_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.cpp b/qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.cpp deleted file mode 100644 index 495f1a08c2..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.cpp +++ /dev/null @@ -1,184 +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 -#include - -#include "MessageRecordset.h" -#include "BlobAdapter.h" -#include "BlobEncoder.h" -#include "VariantHelper.h" - -#include - -class qpid::broker::PersistableMessage; - -namespace qpid { -namespace store { -namespace ms_sql { - -void -MessageRecordset::add(const boost::intrusive_ptr& msg) -{ - BlobEncoder blob (msg); // Marshall headers and content to a blob - rs->AddNew(); - rs->Fields->GetItem("fieldTableBlob")->AppendChunk(blob); - rs->Update(); - uint64_t id = rs->Fields->Item["persistenceId"]->Value; - msg->setPersistenceId(id); -} - -void -MessageRecordset::append(const boost::intrusive_ptr& msg, - const std::string& data) -{ - // Look up the message by its Id - std::ostringstream filter; - filter << "persistenceId = " << msg->getPersistenceId() << std::ends; - rs->PutFilter (VariantHelper(filter.str())); - if (rs->RecordCount == 0) { - throw Exception("Can't append to message not stored in database"); - } - BlobEncoder blob (data); // Marshall string data to a blob - rs->Fields->GetItem("fieldTableBlob")->AppendChunk(blob); - rs->Update(); -} - -void -MessageRecordset::remove(const boost::intrusive_ptr& msg) -{ - BlobRecordset::remove(msg->getPersistenceId()); -} - -void -MessageRecordset::loadContent(const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length) -{ - // Look up the message by its Id - std::ostringstream filter; - filter << "persistenceId = " << msg->getPersistenceId() << std::ends; - rs->PutFilter (VariantHelper(filter.str())); - if (rs->RecordCount == 0) { - throw Exception("Can't load message not stored in database"); - } - - // NOTE! If this code needs to change, please verify the encoding - // code in BlobEncoder. - long blobSize = rs->Fields->Item["fieldTableBlob"]->ActualSize; - uint32_t headerSize; - const size_t headerFieldLength = sizeof(headerSize); - BlobAdapter blob(headerFieldLength); - blob = - rs->Fields->Item["fieldTableBlob"]->GetChunk((long)headerFieldLength); - headerSize = ((qpid::framing::Buffer&)blob).getLong(); - - // GetChunk always begins reading where the previous GetChunk left off, - // so we can't just tell it to ignore the header and read the data. - // So, read the header plus the offset, plus the desired data, then - // copy the desired data to the supplied string. If this ends up asking - // for more than is available in the field, reduce it to what's there. - long getSize = headerSize + offset + length; - if (getSize + (long)headerFieldLength > blobSize) { - size_t reduce = (getSize + headerFieldLength) - blobSize; - getSize -= reduce; - length -= reduce; - } - BlobAdapter header_plus(getSize); - header_plus = rs->Fields->Item["fieldTableBlob"]->GetChunk(getSize); - uint8_t *throw_away = new uint8_t[headerSize + offset]; - ((qpid::framing::Buffer&)header_plus).getRawData(throw_away, headerSize + offset); - delete throw_away; - ((qpid::framing::Buffer&)header_plus).getRawData(data, length); -} - -void -MessageRecordset::recover(qpid::broker::RecoveryManager& recoverer, - std::map& messageMap) -{ - if (rs->BOF && rs->EndOfFile) - return; // Nothing to do - rs->MoveFirst(); - Binding b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - while (!rs->EndOfFile) { - // The blob was written as normal, but with the header length - // prepended in a uint32_t. Due to message staging threshold - // limits, the header may be all that's read in; get it first, - // recover that message header, then see if the rest is needed. - // - // NOTE! If this code needs to change, please verify the encoding - // code in BlobEncoder. - long blobSize = rs->Fields->Item["fieldTableBlob"]->ActualSize; - uint32_t headerSize; - const size_t headerFieldLength = sizeof(headerSize); - BlobAdapter blob(headerFieldLength); - blob = - rs->Fields->Item["fieldTableBlob"]->GetChunk((long)headerFieldLength); - headerSize = ((qpid::framing::Buffer&)blob).getLong(); - BlobAdapter header(headerSize); - header = rs->Fields->Item["fieldTableBlob"]->GetChunk(headerSize); - broker::RecoverableMessage::shared_ptr msg; - msg = recoverer.recoverMessage(header); - msg->setPersistenceId(b.messageId); - messageMap[b.messageId] = msg; - - // Now, do we need the rest of the content? - long contentLength = blobSize - headerFieldLength - headerSize; - if (contentLength > 0 && msg->loadContent(contentLength)) { - BlobAdapter content(contentLength); - content = - rs->Fields->Item["fieldTableBlob"]->GetChunk(contentLength); - msg->decodeContent(content); - } - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -void -MessageRecordset::dump() -{ - Recordset::dump(); - if (rs->EndOfFile && rs->BOF) // No records - return; - rs->MoveFirst(); - - Binding b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - - while (VARIANT_FALSE == rs->EndOfFile) { - QPID_LOG(notice, "Msg " << b.messageId); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.h b/qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.h deleted file mode 100644 index 698b2561fe..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/MessageRecordset.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef QPID_STORE_MSSQL_MESSAGERECORDSET_H -#define QPID_STORE_MSSQL_MESSAGERECORDSET_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 -#include "BlobRecordset.h" -#include -#include -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class MessageRecordset - * - * Class for storing and recovering messages. Messages are primarily blobs - * and handled similarly. However, messages larger than the staging threshold - * are not contained completely in memory; they're left mostly in the store - * and the header is held in memory. So when the message "blob" is saved, - * an additional size-of-the-header field is prepended to the blob. - * On recovery, the size-of-the-header is used to get only what's needed - * until it's determined if the entire message is to be recovered to memory. - */ -class MessageRecordset : public BlobRecordset { - class Binding : public CADORecordBinding { - BEGIN_ADO_BINDING(Binding) - ADO_FIXED_LENGTH_ENTRY2(1, adBigInt, messageId, FALSE) - END_ADO_BINDING() - - public: - uint64_t messageId; - }; - -public: - // Store a message. Store the header size (4 bytes) then the regular - // blob comprising the message. - void add(const boost::intrusive_ptr& msg); - - // Append additional content to an existing message. - void append(const boost::intrusive_ptr& msg, - const std::string& data); - - // Remove an existing message - void remove(const boost::intrusive_ptr& msg); - - // Load all or part of a stored message. This skips the header parts and - // loads content. - void loadContent(const boost::intrusive_ptr& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - // Recover messages and save a map of those recovered. - void recover(qpid::broker::RecoveryManager& recoverer, - std::map& messageMap); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_MESSAGERECORDSET_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/Recordset.cpp b/qpid/cpp/src/qpid/store/ms-sql/Recordset.cpp deleted file mode 100644 index e706799951..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/Recordset.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include -#include - -#include "Recordset.h" -#include "BlobEncoder.h" -#include "DatabaseConnection.h" -#include "VariantHelper.h" - -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; -} - -namespace qpid { -namespace store { -namespace ms_sql { - - -void -Recordset::init(DatabaseConnection* conn, const std::string& table) -{ - dbConn = conn; - TESTHR(rs.CreateInstance(__uuidof(::Recordset))); - tableName = table; -} - -void -Recordset::openRs() -{ - // Client-side cursors needed to get access to newly added - // identity column immediately. Recordsets need this to get the - // persistence ID for the broker objects. - rs->CursorLocation = adUseClient; - _ConnectionPtr p = *dbConn; - rs->Open(tableName.c_str(), - _variant_t((IDispatch *)p, true), - adOpenStatic, - adLockOptimistic, - adCmdTable); -} - -void -Recordset::open(DatabaseConnection* conn, const std::string& table) -{ - init(conn, table); - openRs(); -} - -void -Recordset::close() -{ - if (rs && rs->State == adStateOpen) - rs->Close(); -} - -void -Recordset::requery() -{ - // Restore the recordset to reflect all current records. - rs->Filter = ""; - rs->Requery(-1); -} - -void -Recordset::dump() -{ - long count = rs->RecordCount; - QPID_LOG(notice, "DB Dump: " + tableName << - ": " << count << " records"); -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/Recordset.h b/qpid/cpp/src/qpid/store/ms-sql/Recordset.h deleted file mode 100644 index 032b2bd434..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/Recordset.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef QPID_STORE_MSSQL_RECORDSET_H -#define QPID_STORE_MSSQL_RECORDSET_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. - * - */ - - -// Bring in ADO 2.8 (yes, I know it says "15", but that's it...) -#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ - no_namespace rename("EOF", "EndOfFile") -#include -#include -#include -#if 0 -#include -#endif - -namespace qpid { -namespace store { -namespace ms_sql { - -class DatabaseConnection; - -/** - * @class Recordset - * - * Represents an ADO Recordset, abstracting out the common operations needed - * on the common tables used that have 2 fields, persistence ID and blob. - */ -class Recordset { -protected: - _RecordsetPtr rs; - DatabaseConnection* dbConn; - std::string tableName; - - void init(DatabaseConnection* conn, const std::string& table); - void openRs(); - -public: - Recordset() : rs(0), dbConn(0) {} - virtual ~Recordset() { close(); rs = 0; dbConn = 0; } - - /** - * Default open() reads all records into the recordset. - */ - virtual void open(DatabaseConnection* conn, const std::string& table); - void close(); - void requery(); - operator _RecordsetPtr () { return rs; } - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_RECORDSET_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.cpp b/qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.cpp deleted file mode 100644 index 6ad7725570..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.cpp +++ /dev/null @@ -1,71 +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 "SqlTransaction.h" -#include "DatabaseConnection.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -SqlTransaction::SqlTransaction(const boost::shared_ptr& _db) - : db(_db), transDepth(0) -{ -} - -SqlTransaction::~SqlTransaction() -{ - if (transDepth > 0) - this->abort(); -} - -void -SqlTransaction::begin() -{ - _bstr_t beginCmd("BEGIN TRANSACTION"); - _ConnectionPtr c = *db; - c->Execute(beginCmd, NULL, adExecuteNoRecords); - ++transDepth; -} - -void -SqlTransaction::commit() -{ - if (transDepth > 0) { - _bstr_t commitCmd("COMMIT TRANSACTION"); - _ConnectionPtr c = *db; - c->Execute(commitCmd, NULL, adExecuteNoRecords); - --transDepth; - } -} - -void -SqlTransaction::abort() -{ - if (transDepth > 0) { - _bstr_t rollbackCmd("ROLLBACK TRANSACTION"); - _ConnectionPtr c = *db; - c->Execute(rollbackCmd, NULL, adExecuteNoRecords); - transDepth = 0; - } -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.h b/qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.h deleted file mode 100644 index 8b5239b786..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/SqlTransaction.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef QPID_STORE_MSSQL_SQLTRANSACTION_H -#define QPID_STORE_MSSQL_SQLTRANSACTION_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 -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -class DatabaseConnection; - -/** - * @class SqlTransaction - * - * Class representing an SQL transaction. - * Since ADO w/ SQLOLEDB can't do nested transaction via its BeginTrans(), - * et al, nested transactions are carried out with direct SQL commands. - * To ensure the state of this is known, keep track of how deeply the - * transactions are nested. This is more of a safety/sanity check since - * AMQP doesn't provide nested transactions. - */ -class SqlTransaction { - - boost::shared_ptr db; - - // Since ADO w/ SQLOLEDB can't do nested transaction via its BeginTrans(), - // et al, nested transactions are carried out with direct SQL commands. - // To ensure the state of this is known, keep track of how deeply the - // transactions are nested. - unsigned int transDepth; - -public: - SqlTransaction(const boost::shared_ptr& _db); - ~SqlTransaction(); - - DatabaseConnection *dbConn() { return db.get(); } - - void begin(); - void commit(); - void abort(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_SQLTRANSACTION_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/State.cpp b/qpid/cpp/src/qpid/store/ms-sql/State.cpp deleted file mode 100644 index 720603dd11..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/State.cpp +++ /dev/null @@ -1,45 +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 "State.h" -#include "DatabaseConnection.h" -#include "Exception.h" -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -State::State() : dbConn(0) -{ - HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); - if (hr != S_OK && hr != S_FALSE) - throw Exception("Error initializing COM"); -} - -State::~State() -{ - if (dbConn) - delete dbConn; - ::CoUninitialize(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/State.h b/qpid/cpp/src/qpid/store/ms-sql/State.h deleted file mode 100644 index 6350bc5bd2..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/State.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_STORE_MSSQL_STATE_H -#define QPID_STORE_MSSQL_STATE_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 store { -namespace ms_sql { - -class DatabaseConnection; - -/** - * @struct State - * - * Represents a thread's state for accessing ADO and the database. - * Creating an instance of State initializes COM for this thread, and - * destroying it uninitializes COM. There's also a DatabaseConnection - * for this thread's default access to the database. More DatabaseConnections - * can always be created, but State has one that can always be used by - * the thread whose state is represented. - * - * This class is intended to be one-per-thread, so it should be accessed - * via thread-specific storage. - */ -struct State { - State(); - ~State(); - DatabaseConnection *dbConn; -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_STATE_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/TplRecordset.cpp b/qpid/cpp/src/qpid/store/ms-sql/TplRecordset.cpp deleted file mode 100644 index 1309d921a9..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/TplRecordset.cpp +++ /dev/null @@ -1,128 +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 -#include -#include - -#include "TplRecordset.h" -#include "BlobEncoder.h" -#include "DatabaseConnection.h" -#include "VariantHelper.h" - -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; -} - -namespace qpid { -namespace store { -namespace ms_sql { - -void -TplRecordset::open(DatabaseConnection* conn, const std::string& table) -{ - init(conn, table); - // Don't actually open until we know what to do. It's far easier and more - // efficient to simply do most of these TPL/xid ops in a single statement. -} - -void -TplRecordset::add(const std::string& xid) -{ - const std::string command = - "INSERT INTO " + tableName + " ( xid ) VALUES ( ? )"; - _CommandPtr cmd = NULL; - _ParameterPtr xidVal = NULL; - - TESTHR(cmd.CreateInstance(__uuidof(Command))); - TESTHR(xidVal.CreateInstance(__uuidof(Parameter))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.c_str(); - cmd->CommandType = adCmdText; - xidVal->Name = "@xid"; - xidVal->Type = adVarBinary; - xidVal->Size = xid.length(); - xidVal->Direction = adParamInput; - xidVal->Value = BlobEncoder(xid); - cmd->Parameters->Append(xidVal); - cmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords); -} - -void -TplRecordset::remove(const std::string& xid) -{ - // Look up the item by its xid - const std::string command = - "DELETE FROM " + tableName + " WHERE xid = ?"; - _CommandPtr cmd = NULL; - _ParameterPtr xidVal = NULL; - - TESTHR(cmd.CreateInstance(__uuidof(Command))); - TESTHR(xidVal.CreateInstance(__uuidof(Parameter))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.c_str(); - cmd->CommandType = adCmdText; - xidVal->Name = "@xid"; - xidVal->Type = adVarBinary; - xidVal->Size = xid.length(); - xidVal->Direction = adParamInput; - xidVal->Value = BlobEncoder(xid); - cmd->Parameters->Append(xidVal); - _variant_t deletedRecords; - cmd->Execute(&deletedRecords, NULL, adCmdText | adExecuteNoRecords); -} - -void -TplRecordset::recover(std::set& xids) -{ - openRs(); - if (rs->BOF && rs->EndOfFile) - return; // Nothing to do - rs->MoveFirst(); - while (!rs->EndOfFile) { - _variant_t wxid = rs->Fields->Item["xid"]->Value; - char *xidBytes; - SafeArrayAccessData(wxid.parray, (void **)&xidBytes); - std::string xid(xidBytes, rs->Fields->Item["xid"]->ActualSize); - xids.insert(xid); - SafeArrayUnaccessData(wxid.parray); - rs->MoveNext(); - } -} - -void -TplRecordset::dump() -{ - Recordset::dump(); - if (rs->EndOfFile && rs->BOF) // No records - return; - - rs->MoveFirst(); - while (!rs->EndOfFile) { - _bstr_t wxid = rs->Fields->Item["xid"]->Value; - QPID_LOG(notice, " -> " << (const char *)wxid); - rs->MoveNext(); - } -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/TplRecordset.h b/qpid/cpp/src/qpid/store/ms-sql/TplRecordset.h deleted file mode 100644 index fbde51738c..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/TplRecordset.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef QPID_STORE_MSSQL_TPLRECORDSET_H -#define QPID_STORE_MSSQL_TPLRECORDSET_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 "Recordset.h" -#include -#include - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class TplRecordset - * - * Class for the TPL (Transaction Prepared List) records. - */ -class TplRecordset : public Recordset { -protected: - -public: - virtual void open(DatabaseConnection* conn, const std::string& table); - - void add(const std::string& xid); - - // Remove a record given its xid. - void remove(const std::string& xid); - - // Recover prepared transaction XIDs. - void recover(std::set& xids); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_TPLRECORDSET_H */ diff --git a/qpid/cpp/src/qpid/store/ms-sql/VariantHelper.cpp b/qpid/cpp/src/qpid/store/ms-sql/VariantHelper.cpp deleted file mode 100644 index acec95c1f9..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/VariantHelper.cpp +++ /dev/null @@ -1,71 +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 -#include "VariantHelper.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -template -VariantHelper::VariantHelper() -{ - var.vt = VT_EMPTY; -} - -template -VariantHelper::operator const _variant_t& () const -{ - return var; -} - -// Specialization for using _variant_t to wrap a std::string -VariantHelper::VariantHelper(const std::string &init) -{ - if (init.empty() || init.length() == 0) { - var.vt = VT_BSTR; - var.bstrVal = NULL; - } - else { - var.SetString(init.c_str()); - } -} - -VariantHelper& -VariantHelper::operator=(const std::string &rhs) -{ - if (rhs.empty() || rhs.length() == 0) { - var.vt = VT_BSTR; - var.bstrVal = NULL; - } - else { - var.SetString(rhs.c_str()); - } - return *this; -} - -VariantHelper::operator const _variant_t& () const -{ - return var; -} - -}}} // namespace qpid::store::ms_sql diff --git a/qpid/cpp/src/qpid/store/ms-sql/VariantHelper.h b/qpid/cpp/src/qpid/store/ms-sql/VariantHelper.h deleted file mode 100644 index 723dbc3b76..0000000000 --- a/qpid/cpp/src/qpid/store/ms-sql/VariantHelper.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_STORE_MSSQL_VARIANTHELPER_H -#define QPID_STORE_MSSQL_VARIANTHELPER_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 - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class VariantHelper - * - * Class template to wrap the details of working with _variant_t objects. - */ -template class VariantHelper { -private: - _variant_t var; - -public: - VariantHelper(); - VariantHelper(const Wrapped &init); - - VariantHelper& operator =(const Wrapped& rhs); - operator const _variant_t& () const; -}; - -// Specialization for using _variant_t to wrap a std::string -template<> class VariantHelper { -private: - _variant_t var; - -public: - VariantHelper(const std::string &init); - VariantHelper& operator =(const std::string& rhs); - operator const _variant_t& () const; -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_VARIANTHELPER_H */ diff --git a/qpid/cpp/src/qpid/sys/AggregateOutput.cpp b/qpid/cpp/src/qpid/sys/AggregateOutput.cpp deleted file mode 100644 index 773ea68e55..0000000000 --- a/qpid/cpp/src/qpid/sys/AggregateOutput.cpp +++ /dev/null @@ -1,89 +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/sys/AggregateOutput.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { -namespace sys { - -AggregateOutput::AggregateOutput() : busy(false) {} - -namespace { -// Clear the busy flag and notify waiting threads in destructor. -struct ScopedBusy { - bool& flag; - Monitor& monitor; - ScopedBusy(bool& f, Monitor& m) : flag(f), monitor(m) { f = true; } - ~ScopedBusy() { flag = false; monitor.notifyAll(); } -}; -} - -bool AggregateOutput::doOutput() { - Mutex::ScopedLock l(lock); - ScopedBusy sb(busy, lock); - - while (!tasks.empty()) { - OutputTask* t=tasks.front(); - tasks.pop_front(); - taskSet.erase(t); - bool didOutput; - { - // Allow concurrent call to addOutputTask. - // removeOutputTask will wait till !busy before removing a task. - Mutex::ScopedUnlock u(lock); - didOutput = t->doOutput(); - } - if (didOutput) { - if (taskSet.insert(t).second) { - tasks.push_back(t); - } - return true; - } - } - return false; -} - -void AggregateOutput::addOutputTask(OutputTask* task) { - Mutex::ScopedLock l(lock); - if (taskSet.insert(task).second) { - tasks.push_back(task); - } -} - -void AggregateOutput::removeOutputTask(OutputTask* task) { - Mutex::ScopedLock l(lock); - while (busy) lock.wait(); - taskSet.erase(task); - tasks.erase(std::remove(tasks.begin(), tasks.end(), task), tasks.end()); -} - -void AggregateOutput::removeAll() -{ - Mutex::ScopedLock l(lock); - while (busy) lock.wait(); - taskSet.clear(); - tasks.clear(); -} - - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/AggregateOutput.h b/qpid/cpp/src/qpid/sys/AggregateOutput.h deleted file mode 100644 index c8dd8d989a..0000000000 --- a/qpid/cpp/src/qpid/sys/AggregateOutput.h +++ /dev/null @@ -1,76 +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. - * - */ -#ifndef _AggregateOutput_ -#define _AggregateOutput_ - -#include "qpid/sys/Monitor.h" -#include "qpid/sys/OutputTask.h" - -#include "qpid/CommonImportExport.h" - -#include -#include -#include - -namespace qpid { -namespace sys { - -/** - * Holds a collection of output tasks, doOutput picks the next one to execute. - * - * Tasks are automatically removed if their doOutput() or hasOutput() returns false. - * - * Thread safe. addOutputTask may be called in one connection thread while - * doOutput is called in another. - */ - -class QPID_COMMON_CLASS_EXTERN AggregateOutput : public OutputTask -{ - typedef std::deque TaskList; - typedef std::set TaskSet; - - Monitor lock; - TaskList tasks; - TaskSet taskSet; - bool busy; - - public: - QPID_COMMON_EXTERN AggregateOutput(); - - // These may be called concurrently with any function. - QPID_COMMON_EXTERN void addOutputTask(OutputTask* t); - - // These functions must not be called concurrently with each other. - QPID_COMMON_EXTERN bool doOutput(); - QPID_COMMON_EXTERN void removeOutputTask(OutputTask* t); - QPID_COMMON_EXTERN void removeAll(); - - /** Apply f to each OutputTask* in the tasks list */ - template void eachOutput(F f) { - Mutex::ScopedLock l(lock); - std::for_each(tasks.begin(), tasks.end(), f); - } -}; - -}} // namespace qpid::sys - - -#endif diff --git a/qpid/cpp/src/qpid/sys/AsynchIO.h b/qpid/cpp/src/qpid/sys/AsynchIO.h deleted file mode 100644 index 09402e9e44..0000000000 --- a/qpid/cpp/src/qpid/sys/AsynchIO.h +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef _sys_AsynchIO -#define _sys_AsynchIO -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 - -#include -#include - -namespace qpid { -namespace sys { - -struct SecuritySettings; -class Socket; -class Poller; - -/* - * Asynchronous acceptor: accepts connections then does a callback with the - * accepted fd - */ -class AsynchAcceptor { -public: - typedef boost::function1 Callback; - - QPID_COMMON_EXTERN static AsynchAcceptor* create(const Socket& s, Callback callback); - virtual ~AsynchAcceptor() {}; - virtual void start(boost::shared_ptr poller) = 0; -}; - -/* - * Asynchronous connector: starts the process of initiating a connection and - * invokes a callback when completed or failed. - */ -class AsynchConnector { -public: - typedef boost::function1 ConnectedCallback; - typedef boost::function3 FailedCallback; - typedef boost::function1 RequestCallback; - - // Call create() to allocate a new AsynchConnector object with the - // specified poller, addressing, and callbacks. - // This method is implemented in platform-specific code to - // create a correctly typed object. The platform code also manages - // deletes. To correctly manage heaps when needed, the allocate and - // delete should both be done from the same class/library. - QPID_COMMON_EXTERN static AsynchConnector* create(const Socket& s, - const std::string& hostname, - const std::string& port, - ConnectedCallback connCb, - FailedCallback failCb); - virtual void start(boost::shared_ptr poller) = 0; - virtual void stop() {}; - virtual void requestCallback(RequestCallback) = 0; -protected: - AsynchConnector() {} - virtual ~AsynchConnector() {} -}; - -struct AsynchIOBufferBase { - char* bytes; - int32_t byteCount; - int32_t dataStart; - int32_t dataCount; - - AsynchIOBufferBase(char* const b, const int32_t s) : - bytes(b), - byteCount(s), - dataStart(0), - dataCount(0) - {} - - virtual ~AsynchIOBufferBase() - {} - - void squish() { - if (dataStart != 0) { - ::memmove(bytes, bytes + dataStart, dataCount); - dataStart = 0; - } - } -}; - -/* - * Asychronous reader/writer: - * Reader accepts buffers to read into; reads into the provided buffers - * and then does a callback with the buffer and amount read. Optionally it - * can callback when there is something to read but no buffer to read it into. - * - * Writer accepts a buffer and queues it for writing; can also be given - * a callback for when writing is "idle" (ie fd is writable, but nothing - * to write). - */ -class AsynchIO { -public: - typedef AsynchIOBufferBase BufferBase; - - typedef boost::function2 ReadCallback; - typedef boost::function1 EofCallback; - typedef boost::function1 DisconnectCallback; - typedef boost::function2 ClosedCallback; - typedef boost::function1 BuffersEmptyCallback; - typedef boost::function1 IdleCallback; - typedef boost::function1 RequestCallback; - - // Call create() to allocate a new AsynchIO object with the specified - // callbacks. This method is implemented in platform-specific code to - // create a correctly typed object. The platform code also manages - // deletes. To correctly manage heaps when needed, the allocate and - // delete should both be done from the same class/library. - QPID_COMMON_EXTERN static AsynchIO* create(const Socket& s, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0); -public: - /* - * Size of IO buffers - this is the maximum possible frame size + 1 - */ - const static uint32_t MaxBufferSize = 65536; - - /* - * Number of IO buffers allocated - 1 for reading and 1 for writing. - */ - const static uint32_t BufferCount = 2; - - virtual void queueForDeletion() = 0; - - virtual void start(boost::shared_ptr poller) = 0; - virtual void createBuffers(uint32_t size = MaxBufferSize) = 0; - virtual void queueReadBuffer(BufferBase* buff) = 0; - virtual void unread(BufferBase* buff) = 0; - virtual void queueWrite(BufferBase* buff) = 0; - virtual void notifyPendingWrite() = 0; - virtual void queueWriteClose() = 0; - virtual bool writeQueueEmpty() = 0; - virtual void requestCallback(RequestCallback) = 0; - virtual BufferBase* getQueuedBuffer() = 0; - - virtual SecuritySettings getSecuritySettings() = 0; - -protected: - // Derived class manages lifetime; must be constructed using the - // static create() method. Deletes not allowed from outside. - AsynchIO() {} - virtual ~AsynchIO() {} -}; - -}} - -#endif // _sys_AsynchIO diff --git a/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp b/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp deleted file mode 100644 index 2037ba38ab..0000000000 --- a/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp +++ /dev/null @@ -1,235 +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/sys/AsynchIOHandler.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/Timer.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/log/Statement.h" - -#include - -namespace qpid { -namespace sys { - -struct ProtocolTimeoutTask : public sys::TimerTask { - AsynchIOHandler& handler; - std::string id; - Duration timeout; - - ProtocolTimeoutTask(const std::string& i, const Duration& timeout_, AsynchIOHandler& h) : - TimerTask(timeout_, "ProtocolTimeout"), - handler(h), - id(i), - timeout(timeout_) - {} - - void fire() { - // If this fires it means that we didn't negotiate the connection in the timeout period - // Schedule closing the connection for the io thread - QPID_LOG(error, "Connection " << id << " No protocol received after " << timeout - << ", closing"); - handler.abort(); - } -}; - -AsynchIOHandler::AsynchIOHandler(const std::string& id, ConnectionCodec::Factory* f, bool isClient0, bool nodict0) : - identifier(id), - aio(0), - factory(f), - codec(0), - readError(false), - isClient(isClient0), - nodict(nodict0), - headerSent(false) -{} - -AsynchIOHandler::~AsynchIOHandler() { - if (codec) - codec->closed(); - if (timeoutTimerTask) - timeoutTimerTask->cancel(); - delete codec; -} - -namespace { - SecuritySettings getSecuritySettings(AsynchIO* aio, bool nodict) - { - SecuritySettings settings = aio->getSecuritySettings(); - settings.nodict = nodict; - return settings; - } -} - -void AsynchIOHandler::init(qpid::sys::AsynchIO* a, qpid::sys::Timer& timer, uint32_t maxTime) { - aio = a; - - // Start timer for this connection - timeoutTimerTask = new ProtocolTimeoutTask(identifier, maxTime*TIME_MSEC, *this); - timer.add(timeoutTimerTask); - - // Give connection some buffers to use - aio->createBuffers(); - - if (isClient) { - codec = factory->create(*this, identifier, getSecuritySettings(aio, nodict)); - } -} - -void AsynchIOHandler::write(const framing::ProtocolInitiation& data) -{ - QPID_LOG(debug, "SENT [" << identifier << "]: INIT(" << data << ")"); - AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); - assert(buff); - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void AsynchIOHandler::abort() { - // Don't disconnect if we're already disconnecting - if (!readError) { - aio->requestCallback(boost::bind(&AsynchIOHandler::eof, this, _1)); - } - aio->queueWriteClose(); -} - -void AsynchIOHandler::connectionEstablished() { - if (timeoutTimerTask) { - timeoutTimerTask->cancel(); - timeoutTimerTask = 0; - } -} - -void AsynchIOHandler::activateOutput() { - aio->notifyPendingWrite(); -} - -void AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) { - if (readError) { - return; - } - - size_t decoded = 0; - if (codec) { // Already initiated - try { - decoded = codec->decode(buff->bytes+buff->dataStart, buff->dataCount); - }catch(const std::exception& e){ - QPID_LOG(error, e.what()); - readError = true; - aio->queueWriteClose(); - } - }else{ - framing::Buffer in(buff->bytes+buff->dataStart, buff->dataCount); - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - decoded = in.getPosition(); - - QPID_LOG(debug, "RECV [" << identifier << "]: INIT(" << protocolInit << ")"); - try { - codec = factory->create(protocolInit.getVersion(), *this, identifier, getSecuritySettings(aio, nodict)); - if (!codec) { - //TODO: may still want to revise this... - //send valid version header & close connection. - write(framing::ProtocolInitiation(factory->supportedVersion())); - readError = true; - aio->queueWriteClose(); - } else { - //read any further data that may already have been sent - decoded += codec->decode(buff->bytes+buff->dataStart+in.getPosition(), buff->dataCount-in.getPosition()); - } - } catch (const std::exception& e) { - QPID_LOG(error, e.what()); - readError = true; - aio->queueWriteClose(); - } - } - } - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (decoded != size_t(buff->dataCount)) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += decoded; - buff->dataCount -= decoded; - aio->unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio->queueReadBuffer(buff); - } -} - -void AsynchIOHandler::eof(AsynchIO& a) { - disconnect(a); - readError = true; - aio->queueWriteClose(); -} - -void AsynchIOHandler::closedSocket(AsynchIO&, const Socket& s) { - // If we closed with data still to send log a warning - if (!aio->writeQueueEmpty()) { - QPID_LOG(warning, "CLOSING [" << identifier << "] unsent data (probably due to client disconnect)"); - } - delete &s; - aio->queueForDeletion(); - delete this; -} - -void AsynchIOHandler::disconnect(AsynchIO&) { - QPID_LOG(debug, "DISCONNECTED [" << identifier << "]"); - if (codec) codec->closed(); -} - -// Notifications -void AsynchIOHandler::nobuffs(AsynchIO&) { -} - -void AsynchIOHandler::idle(AsynchIO&){ - if (isClient && !headerSent) { - write(framing::ProtocolInitiation(codec->getVersion())); - headerSent = true; - return; - } - if (codec == 0) return; - if (!codec->canEncode()) { - return; - } - AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); - if (buff) { - try { - size_t encoded=codec->encode(buff->bytes, buff->byteCount); - buff->dataCount = encoded; - aio->queueWrite(buff); - if (!codec->isClosed()) { - return; - } - } catch (const std::exception& e) { - QPID_LOG(error, e.what()); - } - } - readError = true; - aio->queueWriteClose(); -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/AsynchIOHandler.h b/qpid/cpp/src/qpid/sys/AsynchIOHandler.h deleted file mode 100644 index 698ac5fc9c..0000000000 --- a/qpid/cpp/src/qpid/sys/AsynchIOHandler.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _sys_AsynchIOHandler_h -#define _sys_AsynchIOHandler_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/OutputControl.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" -#include "qpid/CommonImportExport.h" - -#include - -namespace qpid { - -namespace framing { - class ProtocolInitiation; -} - -namespace sys { - -class AsynchIO; -struct AsynchIOBufferBase; -class Socket; -class Timer; -class TimerTask; - -class AsynchIOHandler : public OutputControl { - std::string identifier; - AsynchIO* aio; - ConnectionCodec::Factory* factory; - ConnectionCodec* codec; - bool readError; - bool isClient; - bool nodict; - bool headerSent; - boost::intrusive_ptr timeoutTimerTask; - - void write(const framing::ProtocolInitiation&); - - public: - QPID_COMMON_EXTERN AsynchIOHandler(const std::string& id, qpid::sys::ConnectionCodec::Factory* f, bool isClient, bool nodict); - QPID_COMMON_EXTERN ~AsynchIOHandler(); - QPID_COMMON_EXTERN void init(AsynchIO* a, Timer& timer, uint32_t maxTime); - - // Output side - QPID_COMMON_EXTERN void abort(); - QPID_COMMON_EXTERN void connectionEstablished(); - QPID_COMMON_EXTERN void activateOutput(); - - // Input side - QPID_COMMON_EXTERN void readbuff(AsynchIO& aio, AsynchIOBufferBase* buff); - QPID_COMMON_EXTERN void eof(AsynchIO& aio); - QPID_COMMON_EXTERN void disconnect(AsynchIO& aio); - - // Notifications - QPID_COMMON_EXTERN void nobuffs(AsynchIO& aio); - QPID_COMMON_EXTERN void idle(AsynchIO& aio); - QPID_COMMON_EXTERN void closedSocket(AsynchIO& aio, const Socket& s); -}; - -}} // namespace qpid::sys - -#endif // _sys_AsynchIOHandler_h diff --git a/qpid/cpp/src/qpid/sys/AtomicCount.h b/qpid/cpp/src/qpid/sys/AtomicCount.h deleted file mode 100644 index 94580c61f3..0000000000 --- a/qpid/cpp/src/qpid/sys/AtomicCount.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _posix_AtomicCount_h -#define _posix_AtomicCount_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 -#include "qpid/sys/ScopedIncrement.h" - -namespace qpid { -namespace sys { - -/** - * Atomic counter. - */ -class AtomicCount { - public: - typedef ::qpid::sys::ScopedDecrement ScopedDecrement; - typedef ::qpid::sys::ScopedIncrement ScopedIncrement; - - AtomicCount(long value = 0) : count(value) {} - - void operator++() { ++count ; } - - long operator--() { return --count; } - - operator long() const { return count; } - - private: - boost::detail::atomic_count count; -}; - - -}} - - -#endif // _posix_AtomicCount_h diff --git a/qpid/cpp/src/qpid/sys/AtomicValue.h b/qpid/cpp/src/qpid/sys/AtomicValue.h deleted file mode 100644 index bf995f991e..0000000000 --- a/qpid/cpp/src/qpid/sys/AtomicValue.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef QPID_SYS_ATOMICVALUE_H -#define QPID_SYS_ATOMICVALUE_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. - * - */ - -// Have to check for clang before gcc as clang pretends to be gcc too -#if defined( __clang__ ) -// Use the clang doesn't support atomic builtins for 64 bit values, so use the slow versions -#include "qpid/sys/AtomicValue_mutex.h" - -#elif defined( __GNUC__ ) && __GNUC__ >= 4 && ( defined( __i686__ ) || defined( __x86_64__ ) ) -// Use the Gnu C built-in atomic operations if compiling with gcc on a suitable platform. -#include "qpid/sys/AtomicValue_gcc.h" - -#else -// Fall-back to mutex locked operations if we don't have atomic ops. -#include "qpid/sys/AtomicValue_mutex.h" -#endif - -#endif /*!QPID_SYS_ATOMICVALUE_GCC_H*/ diff --git a/qpid/cpp/src/qpid/sys/AtomicValue_gcc.h b/qpid/cpp/src/qpid/sys/AtomicValue_gcc.h deleted file mode 100644 index 724bae422e..0000000000 --- a/qpid/cpp/src/qpid/sys/AtomicValue_gcc.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef QPID_SYS_ATOMICVALUE_GCC_H -#define QPID_SYS_ATOMICVALUE_GCC_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. - * - */ - -#if !defined(QPID_SYS_ATOMICVALUE_H) -#error "This file should only be included via AtomicValue.h." -#endif - -namespace qpid { -namespace sys { - -/** - * Atomic value of type T. T must be an integral type of size 1,2,4 or 8 bytes. - * All operations are atomic and preform a full memory barrier unless otherwise noted. - */ -template -class AtomicValue -{ - public: - AtomicValue(T init=0) : value(init) {} - - // Not atomic. Don't call concurrently with atomic ops. - AtomicValue& operator=(T newValue) { value = newValue; return *this; } - - // Update and return new value. - inline T operator+=(T n) { return __sync_add_and_fetch(&value, n); } - inline T operator-=(T n) { return __sync_sub_and_fetch(&value, n); } - inline T operator++() { return *this += 1; } - inline T operator--() { return *this -= 1; } - - // Update and return old value. - inline T fetchAndAdd(T n) { return __sync_fetch_and_add(&value, n); } - inline T fetchAndSub(T n) { return __sync_fetch_and_sub(&value, n); } - inline T operator++(int) { return fetchAndAdd(1); } - inline T operator--(int) { return fetchAndSub(1); } - - /** If current value == testval then set to newval. Returns the old value. */ - T valueCompareAndSwap(T testval, T newval) { return __sync_val_compare_and_swap(&value, testval, newval); } - - /** If current value == testval then set to newval. Returns true if the swap was performed. */ - bool boolCompareAndSwap(T testval, T newval) { return __sync_bool_compare_and_swap(&value, testval, newval); } - - T get() const { return const_cast*>(this)->fetchAndAdd(static_cast(0)); } - - private: - T value; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_ATOMICVALUE_GCC_H*/ diff --git a/qpid/cpp/src/qpid/sys/AtomicValue_mutex.h b/qpid/cpp/src/qpid/sys/AtomicValue_mutex.h deleted file mode 100644 index e4d433e7f5..0000000000 --- a/qpid/cpp/src/qpid/sys/AtomicValue_mutex.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QPID_SYS_ATOMICVALUE_MUTEX_H -#define QPID_SYS_ATOMICVALUE_MUTEX_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. - * - */ - -#if !defined(QPID_SYS_ATOMICVALUE_H) -#error "This file should only be included via AtomicValue.h." -#endif - -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace sys { - -/** - * Atomic value of type T. T must be an integral type of size 1,2,4 or 8 bytes. - * All operations are atomic and preform a full memory barrier unless otherwise noted. - */ -template -class AtomicValue -{ - public: - AtomicValue(T init=0) : value(init) {} - - // Update and return new value. - inline T operator+=(T n) { Lock l(lock); return value += n; } - inline T operator-=(T n) { Lock l(lock); return value -= n; } - inline T operator++() { return *this += 1; } - inline T operator--() { return *this -= 1; } - - // Update and return old value. - inline T fetchAndAdd(T n) { Lock l(lock); T old=value; value += n; return old; } - inline T fetchAndSub(T n) { Lock l(lock); T old=value; value -= n; return old; } - inline T operator++(int) { return fetchAndAdd(1); } - inline T operator--(int) { return fetchAndSub(1); } - - AtomicValue& operator=(T newval) { Lock l(lock); value = newval; return *this; } - - /** If current value == testval then set to newval. Returns the old value. */ - T valueCompareAndSwap(T testval, T newval) { - Lock l(lock); - T old=value; - if (value == testval) value = newval; - return old; - } - - /** If current value == testval then set to newval. Returns true if the swap was performed. */ - bool boolCompareAndSwap(T testval, T newval) { - Lock l(lock); - if (value == testval) { value = newval; return true; } - return false; - } - - T get() const { Lock l(lock); return value; } - - private: - typedef Mutex::ScopedLock Lock; - T value; - mutable Mutex lock; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_ATOMICVALUE_MUTEX_H*/ diff --git a/qpid/cpp/src/qpid/sys/BlockingQueue.h b/qpid/cpp/src/qpid/sys/BlockingQueue.h deleted file mode 100644 index ca6b529930..0000000000 --- a/qpid/cpp/src/qpid/sys/BlockingQueue.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef QPID_SYS_BLOCKINGQUEUE_H -#define QPID_SYS_BLOCKINGQUEUE_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/Waitable.h" - -#include - -namespace qpid { -namespace sys { - -/** - * A simple blocking queue template - */ -template -class BlockingQueue -{ - mutable sys::Waitable waitable; - std::queue queue; - -public: - BlockingQueue() {} - ~BlockingQueue() { close(); } - - /** Pop from the queue, block up to timeout if empty. - *@param result Set to value popped from queue. - *@param timeout Defaults to infinite. - *@return true if result was set, false if queue empty after timeout. - */ - bool pop(T& result, Duration timeout=TIME_INFINITE) { - Mutex::ScopedLock l(waitable); - { - Waitable::ScopedWait w(waitable); - if (timeout == TIME_INFINITE) { - while (queue.empty()) waitable.wait(); - } else if (timeout) { - AbsTime deadline(now(),timeout); - while (queue.empty() && deadline > now()) waitable.wait(deadline); - } else { - //ensure zero timeout pop does not miss the fact that - //queue is closed - waitable.checkException(); - } - } - if (queue.empty()) return false; - result = queue.front(); - queue.pop(); - if (!queue.empty()) - waitable.notify(); // Notify another waiter. - return true; - } - - T pop(Duration timeout=TIME_INFINITE) { - T result; - bool ok = pop(result, timeout); - if (!ok) - throw Exception("Timed out waiting on a blocking queue"); - return result; - } - - /** Push a value onto the queue. - * Note it is not an error to push onto a closed queue. - */ - void push(const T& t) { - Mutex::ScopedLock l(waitable); - queue.push(t); - waitable.notify(); // Notify a waiter. - } - - /** - * Close the queue. - *@ex exception to throw to waiting threads. ClosedException by default. - */ - void close(const ExceptionHolder& ex=ExceptionHolder(new ClosedException())) - { - Mutex::ScopedLock l(waitable); - if (!waitable.hasException()) { - waitable.setException(ex); - waitable.notifyAll(); - waitable.waitWaiters(); // Ensure no threads are still waiting. - } - } - - /** Open a closed queue. */ - void open() { - Mutex::ScopedLock l(waitable); - waitable.resetException(); - } - - bool isClosed() const { - Mutex::ScopedLock l(waitable); - return waitable.hasException(); - } - - bool empty() const { - Mutex::ScopedLock l(waitable); - return queue.empty(); - } - size_t size() const { - Mutex::ScopedLock l(waitable); - return queue.size(); - } -}; - -}} - - - -#endif /*!QPID_SYS_BLOCKINGQUEUE_H*/ diff --git a/qpid/cpp/src/qpid/sys/Codec.h b/qpid/cpp/src/qpid/sys/Codec.h deleted file mode 100644 index e398403e47..0000000000 --- a/qpid/cpp/src/qpid/sys/Codec.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_SYS_CODEC_H -#define QPID_SYS_CODEC_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 - -namespace qpid { -namespace sys { - -/** - * Generic codec interface - */ -class Codec -{ - public: - virtual ~Codec() {} - - /** Decode from buffer, return number of bytes decoded. - * @return may be less than size if there was incomplete - * data at the end of the buffer. - */ - virtual std::size_t decode(const char* buffer, std::size_t size) = 0; - - - /** Encode into buffer, return number of bytes encoded */ - virtual std::size_t encode(char* buffer, std::size_t size) = 0; - - /** Return true if we have data to encode */ - virtual bool canEncode() = 0; -}; -}} // namespace qpid::sys - -#endif /*!QPID_SYS_CODEC_H*/ diff --git a/qpid/cpp/src/qpid/sys/Condition.h b/qpid/cpp/src/qpid/sys/Condition.h deleted file mode 100644 index 9be4b357fe..0000000000 --- a/qpid/cpp/src/qpid/sys/Condition.h +++ /dev/null @@ -1,33 +0,0 @@ -#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/ConnectionCodec.h b/qpid/cpp/src/qpid/sys/ConnectionCodec.h deleted file mode 100644 index 8b5b69cdb4..0000000000 --- a/qpid/cpp/src/qpid/sys/ConnectionCodec.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QPID_SYS_CONNECTION_CODEC_H -#define QPID_SYS_CONNECTION_CODEC_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/Codec.h" -#include "qpid/framing/ProtocolVersion.h" - -namespace qpid { - -namespace sys { - -class InputHandlerFactory; -class OutputControl; -struct SecuritySettings; - -/** - * Interface of coder/decoder for a connection of a specific protocol - * version. - */ -class ConnectionCodec : public Codec { - public: - virtual ~ConnectionCodec() {} - - /** Network connection was closed from other end. */ - virtual void closed() = 0; - - virtual bool isClosed() const = 0; - - virtual framing::ProtocolVersion getVersion() const = 0; - - struct Factory { - virtual ~Factory() {} - - /** Return 0 if version unknown */ - virtual ConnectionCodec* create( - const framing::ProtocolVersion&, OutputControl&, const std::string& id, - const SecuritySettings& - ) = 0; - - /** Return "preferred" codec for outbound connections. */ - virtual ConnectionCodec* create( - OutputControl&, const std::string& id, const SecuritySettings& - ) = 0; - - virtual framing::ProtocolVersion supportedVersion() const = 0; - }; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_CONNECTION_CODEC_H*/ diff --git a/qpid/cpp/src/qpid/sys/ConnectionInputHandler.h b/qpid/cpp/src/qpid/sys/ConnectionInputHandler.h deleted file mode 100644 index f6fcdb7479..0000000000 --- a/qpid/cpp/src/qpid/sys/ConnectionInputHandler.h +++ /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. - * - */ -#ifndef _ConnectionInputHandler_ -#define _ConnectionInputHandler_ - -#include "qpid/framing/InputHandler.h" -#include "qpid/sys/OutputTask.h" - -namespace qpid { -namespace sys { - - -/** - * ConnectionInputHandler provides methods to process incoming frames - * using InputHandler::receive() and to generate outgoing messages in - * OutputTask::doOutput() - * - */ - - class ConnectionInputHandler : - public qpid::framing::InputHandler, - public OutputTask - { - public: - - virtual void closed() = 0; - }; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/sys/ConnectionInputHandlerFactory.h b/qpid/cpp/src/qpid/sys/ConnectionInputHandlerFactory.h deleted file mode 100644 index 9bb7e13686..0000000000 --- a/qpid/cpp/src/qpid/sys/ConnectionInputHandlerFactory.h +++ /dev/null @@ -1,54 +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. - * - */ -#ifndef _ConnectionInputHandlerFactory_ -#define _ConnectionInputHandlerFactory_ - -#include -#include - -namespace qpid { -namespace sys { - -class ConnectionOutputHandler; -class ConnectionInputHandler; - -/** - * Callback interface used by the Acceptor to - * create a ConnectionInputHandler for each new connection. - */ -class ConnectionInputHandlerFactory : private boost::noncopyable -{ - public: - /** - *@param out handler for connection output. - *@param id identify the connection for management purposes. - */ - virtual ConnectionInputHandler* create(ConnectionOutputHandler* out, - const std::string& id, - bool isClient) = 0; - - virtual ~ConnectionInputHandlerFactory(){} -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/sys/ConnectionOutputHandler.h b/qpid/cpp/src/qpid/sys/ConnectionOutputHandler.h deleted file mode 100644 index 3b1440d613..0000000000 --- a/qpid/cpp/src/qpid/sys/ConnectionOutputHandler.h +++ /dev/null @@ -1,42 +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. - * - */ -#ifndef _ConnectionOutputHandler_ -#define _ConnectionOutputHandler_ - -#include "qpid/framing/FrameHandler.h" -#include "qpid/sys/OutputControl.h" - -namespace qpid { -namespace sys { - -/** - * Provides the output handler associated with a connection. - */ -class ConnectionOutputHandler : public virtual qpid::framing::FrameHandler, public OutputControl -{ - public: - virtual void close() = 0; -}; - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/sys/CopyOnWriteArray.h b/qpid/cpp/src/qpid/sys/CopyOnWriteArray.h deleted file mode 100644 index 41384fc5a4..0000000000 --- a/qpid/cpp/src/qpid/sys/CopyOnWriteArray.h +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef QPID_SYS_COPYONWRITEARRAY_H -#define QPID_SYS_COPYONWRITEARRAY_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 -#include -#include - -namespace qpid { -namespace sys { - -/** - * An array that copies on adding/removing element allowing lock-free - * iteration. - */ -template -class CopyOnWriteArray -{ -public: - typedef boost::shared_ptr > ConstPtr; - - CopyOnWriteArray() {} - CopyOnWriteArray(const CopyOnWriteArray& c) : array(c.array) {} - - bool empty() - { - Mutex::ScopedLock l(lock); - return array ? array->empty() : true; - } - - void add(T& t) - { - Mutex::ScopedLock l(lock); - ArrayPtr copy(array ? new std::vector(*array) : new std::vector()); - copy->push_back(t); - array = copy; - } - - bool remove(T& t) - { - Mutex::ScopedLock l(lock); - if (array && std::find(array->begin(), array->end(), t) != array->end()) { - ArrayPtr copy(new std::vector(*array)); - copy->erase(std::find(copy->begin(), copy->end(), t)); - array = copy; - return true; - } else { - return false; - } - } - - bool clear() - { - Mutex::ScopedLock l(lock); - if (array && !array->empty()) { - ArrayPtr copy; - array = copy; - return true; - } else { - return false; - } - } - - template - bool add_unless(T& t, F f) - { - Mutex::ScopedLock l(lock); - if (array && std::find_if(array->begin(), array->end(), f) != array->end()) { - return false; - } else { - ArrayPtr copy(array ? new std::vector(*array) : new std::vector()); - copy->push_back(t); - array = copy; - return true; - } - } - - template - bool remove_if(F f) - { - Mutex::ScopedLock l(lock); - if (array && std::find_if(array->begin(), array->end(), f) != array->end()) { - ArrayPtr copy(new std::vector(*array)); - copy->erase(std::remove_if(copy->begin(), copy->end(), f), copy->end()); - array = copy; - return true; - } - return false; - } - - template - bool modify_if(TestFn f, ModifierFn & m) - { - if (!array) - return false; - { - Mutex::ScopedLock l(lock); - if (std::find_if(array->begin(), array->end(), f) != array->end()) - { - ArrayPtr copy(new std::vector(*array)); - m(*std::find_if(copy->begin(), copy->end(), f)); - array = copy; - return true; - } - } - return false; - } - - template - F for_each(F f) - { - ArrayPtr a; - { - Mutex::ScopedLock l(lock); - a = array; - } - if (!a) return f; - return std::for_each(a->begin(), a->end(), f); - } - - ConstPtr snapshot() - { - ConstPtr a; - { - Mutex::ScopedLock l(lock); - a = array; - } - return a; - } - -private: - typedef boost::shared_ptr< std::vector > ArrayPtr; - Mutex lock; - ArrayPtr array; -}; - -}} - - - -#endif /*!QPID_SYS_COPYONWRITEARRAY_H*/ diff --git a/qpid/cpp/src/qpid/sys/DeletionManager.h b/qpid/cpp/src/qpid/sys/DeletionManager.h deleted file mode 100644 index c1fea19f30..0000000000 --- a/qpid/cpp/src/qpid/sys/DeletionManager.h +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef _sys_DeletionManager_h -#define _sys_DeletionManager_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 -#include -#include - -namespace qpid { -namespace sys { - -struct deleter -{ - template - void operator()(T* ptr){ delete ptr;} -}; - -/** - * DeletionManager keeps track of handles that need to be deleted but may still be - * in use by one of the threads concurrently. - * - * The mode of operation is like this: - * - When we want to delete but we might still be using the handle we - * * Transfer ownership of the handle to this class - * * Mark the handle as (potentially) in use by every thread - * - Then subsequently at points where the thread code knows it isn't - * using any handles it declares that it is using no handles - * - When the last thread declares no use of a handle it automatically - * gets deleted by the shared_ptr implementation - * - * The class only has static members and data and so can only be used once for - * any particular handle type - */ -template -class DeletionManager -{ - struct ThreadStatus; - -public: - // Mark every thread as using the handle - it will be deleted - // below after every thread marks the handle as unused - static void markForDeletion(H* handle) { - allThreadsStatuses.addHandle(shared_ptr(handle)); - } - - // Mark this thread is not using any handle - - // handles get deleted here when no one else - // is using them either - static void markAllUnusedInThisThread() { - ThreadStatus* threadStatus = getThreadStatus(); - ScopedLock l(threadStatus->lock); - - // The actual deletions will happen here when all the shared_ptr - // ref counts hit 0 (that is when every thread marks the handle unused) - threadStatus->handles.clear(); - } - - static void destroyThreadState() { - ThreadStatus* threadStatus = getThreadStatus(); - allThreadsStatuses.delThreadStatus(threadStatus); - delete threadStatus; - threadStatus = 0; - } - -private: - - static ThreadStatus*& getThreadStatus() { - static __thread ThreadStatus* threadStatus = 0; - - // Thread local vars can't be dynamically constructed so we need - // to check whether we've made it yet and construct it if not - // (no locking necessary for the check as it's thread local!) - if (!threadStatus) { - threadStatus = new ThreadStatus; - allThreadsStatuses.addThreadStatus(threadStatus); - } - - return threadStatus; - } - - typedef boost::shared_ptr shared_ptr; - - // In theory we know that we never need more handles than the number of - // threads runnning so we could use a fixed size array. However at this point - // in the code we don't have easy access to this information. - struct ThreadStatus - { - Mutex lock; - std::vector handles; - }; - - class AllThreadsStatuses - { - Mutex lock; - std::vector statuses; - - struct handleAdder - { - shared_ptr handle; - - handleAdder(shared_ptr h): handle(h) {} - - void operator()(ThreadStatus* ptr) { - ScopedLock l(ptr->lock); - ptr->handles.push_back(handle); - } - }; - - public: - // Need this to be able to do static initialisation - explicit AllThreadsStatuses(int) {} - - ~AllThreadsStatuses() { - ScopedLock l(lock); - std::for_each(statuses.begin(), statuses.end(), deleter()); - } - - void addThreadStatus(ThreadStatus* t) { - ScopedLock l(lock); - statuses.push_back(t); - } - - void delThreadStatus(ThreadStatus* t) { - ScopedLock l(lock); - typename std::vector::iterator it = - std::find(statuses.begin(),statuses.end(), t); - if (it != statuses.end()) { - statuses.erase(it); - } - } - - void addHandle(shared_ptr h) { - ScopedLock l(lock); - std::for_each(statuses.begin(), statuses.end(), handleAdder(h)); - } - }; - - static AllThreadsStatuses allThreadsStatuses; -}; - -}} -#endif // _sys_DeletionManager_h diff --git a/qpid/cpp/src/qpid/sys/DispatchHandle.cpp b/qpid/cpp/src/qpid/sys/DispatchHandle.cpp deleted file mode 100644 index 5d6fc4e72f..0000000000 --- a/qpid/cpp/src/qpid/sys/DispatchHandle.cpp +++ /dev/null @@ -1,352 +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/sys/DispatchHandle.h" -#include "qpid/log/Statement.h" - -#include - -#include - -#include - -namespace qpid { -namespace sys { - -DispatchHandle::DispatchHandle(const IOHandle& h, Callback rCb, Callback wCb, Callback dCb) : - PollerHandle(h), - readableCallback(rCb), - writableCallback(wCb), - disconnectedCallback(dCb), - state(IDLE) -{ -} - - -DispatchHandle::~DispatchHandle() { -} - -void DispatchHandle::startWatch(Poller::shared_ptr poller0) { - bool r = readableCallback; - bool w = writableCallback; - - ScopedLock lock(stateLock); - assert(state == IDLE); - - poller = poller0; - poller->registerHandle(*this); - state = WAITING; - Poller::Direction dir = r ? - ( w ? Poller::INOUT : Poller::INPUT ) : - ( w ? Poller::OUTPUT : Poller::NONE ); - poller->monitorHandle(*this, dir); -} - -void DispatchHandle::rewatch() { - bool r = readableCallback; - bool w = writableCallback; - if (!r && !w) { - return; - } - Poller::Direction dir = r ? - ( w ? Poller::INOUT : Poller::INPUT ) : - ( w ? Poller::OUTPUT : Poller::NONE ); - - ScopedLock lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->monitorHandle(*this, dir); -} - -void DispatchHandle::rewatchRead() { - if (!readableCallback) { - return; - } - - ScopedLock lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->monitorHandle(*this, Poller::INPUT); -} - -void DispatchHandle::rewatchWrite() { - if (!writableCallback) { - return; - } - - ScopedLock lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->monitorHandle(*this, Poller::OUTPUT); -} - -void DispatchHandle::unwatchRead() { - if (!readableCallback) { - return; - } - - ScopedLock lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->unmonitorHandle(*this, Poller::INPUT); -} - -void DispatchHandle::unwatchWrite() { - if (!writableCallback) { - return; - } - - ScopedLock lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->unmonitorHandle(*this, Poller::OUTPUT); -} - -void DispatchHandle::unwatch() { - ScopedLock lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->unmonitorHandle(*this, Poller::INOUT); -} - -void DispatchHandle::stopWatch() { - ScopedLock lock(stateLock); - switch (state) { - case IDLE: - assert(state != IDLE); - return; - case STOPPING: - assert(state != STOPPING); - return; - case CALLING: - state = STOPPING; - break; - case WAITING: - state = IDLE; - break; - case DELETING: - return; - } - assert(poller); - poller->unregisterHandle(*this); - poller.reset(); -} - -// If we are in the IDLE/STOPPING state we can't do the callback as we've -// not/no longer got the fd registered in any poller -void DispatchHandle::call(Callback iCb) { - assert(iCb); - ScopedLock lock(stateLock); - switch (state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - interruptedCallbacks.push(iCb); - assert(poller); - (void) poller->interrupt(*this); - } -} - -// The slightly strange switch structure -// is to ensure that the lock is released before -// we do the delete -void DispatchHandle::doDelete() { - { - ScopedLock lock(stateLock); - // Ensure that we're no longer watching anything - switch (state) { - case IDLE: - state = DELETING; - break; - case STOPPING: - state = DELETING; - return; - case WAITING: - state = DELETING; - assert(poller); - (void) poller->interrupt(*this); - poller->unregisterHandle(*this); - return; - case CALLING: - state = DELETING; - assert(poller); - poller->unregisterHandle(*this); - return; - case DELETING: - return; - } - } - // If we're IDLE we can do this right away - delete this; -} - -void DispatchHandle::processEvent(Poller::EventType type) { - - // Phase I - { - ScopedLock lock(stateLock); - - switch(state) { - case IDLE: - // Can get here if a non connection thread stops watching - // whilst we were stuck in the above lock - return; - case WAITING: - state = CALLING; - break; - case CALLING: - assert(state!=CALLING); - return; - case STOPPING: - assert(state!=STOPPING); - return; - case DELETING: - // Need to make sure we clean up any pending callbacks in this case - std::swap(callbacks, interruptedCallbacks); - goto saybyebye; - } - - std::swap(callbacks, interruptedCallbacks); - } - - // Do callbacks - whilst we are doing the callbacks we are prevented from processing - // the same handle until we re-enable it. To avoid rentering the callbacks for a single - // handle re-enabling in the callbacks is actually deferred until they are complete. - try { - switch (type) { - case Poller::READABLE: - readableCallback(*this); - break; - case Poller::WRITABLE: - writableCallback(*this); - break; - case Poller::READ_WRITABLE: - readableCallback(*this); - writableCallback(*this); - break; - case Poller::DISCONNECTED: - if (disconnectedCallback) { - disconnectedCallback(*this); - } - break; - case Poller::INTERRUPTED: - { - // We'll actually do the interrupt below - } - break; - default: - assert(false); - } - - // If we have any callbacks do them now - - // (because we use a copy from before the previous callbacks we won't - // do anything yet that was just added) - while (callbacks.size() > 0) { - { - ScopedLock lock(stateLock); - switch (state) { - case DELETING: - goto finishcallbacks; - default: - break; - } - } - Callback cb = callbacks.front(); - assert(cb); - cb(*this); - callbacks.pop(); - } - } catch (std::exception& e) { - // One of the callbacks threw an exception - that's not allowed - QPID_LOG(error, "Caught exception in state: " << state << " with event: " << type << ": " << e.what()); - // It would be nice to clean up and delete ourselves here, but we can't - } - -finishcallbacks: - { - ScopedLock lock(stateLock); - switch (state) { - case IDLE: - assert(state!=IDLE); - return; - case STOPPING: - state = IDLE; - return; - case WAITING: - assert(state!=WAITING); - return; - case CALLING: - state = WAITING; - return; - case DELETING: - break; - } - } - -saybyebye: - delete this; -} - -}} diff --git a/qpid/cpp/src/qpid/sys/DispatchHandle.h b/qpid/cpp/src/qpid/sys/DispatchHandle.h deleted file mode 100644 index 115a3c44f7..0000000000 --- a/qpid/cpp/src/qpid/sys/DispatchHandle.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef _sys_DispatchHandle_h -#define _sys_DispatchHandle_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/Poller.h" -#include "qpid/sys/Mutex.h" -#include "qpid/CommonImportExport.h" -#include - -#include - -namespace qpid { -namespace sys { - -class DispatchHandleRef; -/** - * In order to have your own handle (file descriptor on Unix) watched by the poller - * you need to: - * - * - Subclass IOHandle, in the constructor supply an appropriate - * IOHandlerPrivate object for the platform. - * - * - Construct a DispatchHandle passing it your IOHandle and - * callback functions for read, write and disconnect events. - * - * - Ensure the DispatchHandle is not deleted until the poller is no longer using it. - * TODO: astitcher document DispatchHandleRef to simplify this. - * - * When an event occurs on the handle, the poller calls the relevant callback and - * stops watching that handle. Your callback can call rewatch() or related functions - * to re-enable polling. - */ -class DispatchHandle : public PollerHandle { - friend class DispatchHandleRef; -public: - typedef boost::function1 Callback; - typedef std::queue CallbackQueue; - -private: - Callback readableCallback; - Callback writableCallback; - Callback disconnectedCallback; - CallbackQueue interruptedCallbacks; - CallbackQueue callbacks; // Double buffer - Poller::shared_ptr poller; - Mutex stateLock; - enum { - IDLE, - STOPPING, - WAITING, - CALLING, - DELETING - } state; - -public: - /** - * Provide a handle to poll and a set of callbacks. Note - * callbacks can be 0, meaning you are not interested in that - * event. - * - *@param h: the handle to watch. The IOHandle encapsulates a - * platfrom-specific handle to an IO object (e.g. a file descriptor - * on Unix.) - *@param rCb Callback called when the handle is readable. - *@param wCb Callback called when the handle is writable. - *@param dCb Callback called when the handle is disconnected. - */ - QPID_COMMON_EXTERN DispatchHandle(const IOHandle& h, Callback rCb, Callback wCb, Callback dCb); - QPID_COMMON_EXTERN ~DispatchHandle(); - - /** Add this DispatchHandle to the poller to be watched. */ - QPID_COMMON_EXTERN void startWatch(Poller::shared_ptr poller); - - /** Resume watching for all non-0 callbacks. */ - QPID_COMMON_EXTERN void rewatch(); - /** Resume watching for read only. */ - QPID_COMMON_EXTERN void rewatchRead(); - - /** Resume watching for write only. */ - QPID_COMMON_EXTERN void rewatchWrite(); - - /** Stop watching temporarily. The DispatchHandle remains - associated with the poller and can be re-activated using - rewatch. */ - QPID_COMMON_EXTERN void unwatch(); - /** Stop watching for read */ - QPID_COMMON_EXTERN void unwatchRead(); - /** Stop watching for write */ - QPID_COMMON_EXTERN void unwatchWrite(); - - /** Stop watching permanently. Disassociates from the poller. */ - QPID_COMMON_EXTERN void stopWatch(); - - /** Interrupt watching this handle and make a serialised callback that respects the - * same exclusivity guarantees as the other callbacks - */ - QPID_COMMON_EXTERN void call(Callback iCb); - -protected: - QPID_COMMON_EXTERN void doDelete(); - -private: - QPID_COMMON_EXTERN void processEvent(Poller::EventType dir); -}; - -class DispatchHandleRef { - DispatchHandle* ref; - -public: - typedef boost::function1 Callback; - DispatchHandleRef(const IOHandle& h, Callback rCb, Callback wCb, Callback dCb) : - ref(new DispatchHandle(h, rCb, wCb, dCb)) - {} - - ~DispatchHandleRef() { ref->doDelete(); } - - void startWatch(Poller::shared_ptr poller) { ref->startWatch(poller); } - void rewatch() { ref->rewatch(); } - void rewatchRead() { ref->rewatchRead(); } - void rewatchWrite() { ref->rewatchWrite(); } - void unwatch() { ref->unwatch(); } - void unwatchRead() { ref->unwatchRead(); } - void unwatchWrite() { ref->unwatchWrite(); } - void stopWatch() { ref->stopWatch(); } - void call(Callback iCb) { ref->call(iCb); } -}; - -}} - -#endif // _sys_DispatchHandle_h diff --git a/qpid/cpp/src/qpid/sys/Dispatcher.cpp b/qpid/cpp/src/qpid/sys/Dispatcher.cpp deleted file mode 100644 index 5f52dcd990..0000000000 --- a/qpid/cpp/src/qpid/sys/Dispatcher.cpp +++ /dev/null @@ -1,40 +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/sys/Dispatcher.h" - -#include - -namespace qpid { -namespace sys { - -Dispatcher::Dispatcher(Poller::shared_ptr poller0) : - poller(poller0) { -} - -Dispatcher::~Dispatcher() { -} - -void Dispatcher::run() { - poller->run(); -} - -}} diff --git a/qpid/cpp/src/qpid/sys/Dispatcher.h b/qpid/cpp/src/qpid/sys/Dispatcher.h deleted file mode 100644 index e8213d0579..0000000000 --- a/qpid/cpp/src/qpid/sys/Dispatcher.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _sys_Dispatcher_h -#define _sys_Dispatcher_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/Poller.h" -#include "qpid/sys/Runnable.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace sys { - -class Dispatcher : public Runnable { - const Poller::shared_ptr poller; - -public: - QPID_COMMON_EXTERN Dispatcher(Poller::shared_ptr poller); - QPID_COMMON_EXTERN ~Dispatcher(); - - QPID_COMMON_EXTERN void run(); -}; - -}} - -#endif // _sys_Dispatcher_h diff --git a/qpid/cpp/src/qpid/sys/ExceptionHolder.h b/qpid/cpp/src/qpid/sys/ExceptionHolder.h deleted file mode 100644 index 4bc934cf75..0000000000 --- a/qpid/cpp/src/qpid/sys/ExceptionHolder.h +++ /dev/null @@ -1,71 +0,0 @@ -#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 - - -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 ExceptionHolder(Ex* ex) { wrap(ex); } - template 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 struct Wrapper : public Raisable { - Wrapper(Ex* ptr) : exception(ptr) {} - void raise() const { throw *exception; } - std::string what() const { return exception->what(); } - boost::shared_ptr exception; - }; - template void wrap(Ex* ex) { wrapper.reset(new Wrapper(ex)); } - boost::shared_ptr wrapper; -}; - - -}} // namespace qpid::sys - - -#endif /*!QPID_EXCEPTIONHOLDER_H*/ diff --git a/qpid/cpp/src/qpid/sys/FileSysDir.h b/qpid/cpp/src/qpid/sys/FileSysDir.h deleted file mode 100755 index 7432fe39c9..0000000000 --- a/qpid/cpp/src/qpid/sys/FileSysDir.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef QPID_SYS_FILESYSDIR_H -#define QPID_SYS_FILESYSDIR_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 - -namespace qpid { -namespace sys { - -/** - * @class FileSysDir - * - * Represents a filesystem directory accessible from the local host. - * This class simply checks existence of, and creates, a directory. It could - * be added to later to list contents, etc. - */ -class FileSysDir -{ - const std::string dirPath; - - public: - - FileSysDir (std::string path) : dirPath(path) {} - ~FileSysDir () {} - - /** - * Check to see if the directory exists and is a directory. Throws an - * exception if there is an error checking existence or if the path - * exists but is not a directory. - * - * @retval true if the path exists and is a directory. - * @retval false if the path does not exist. - */ - bool exists (void) const; - - void mkdir(void); - - typedef void Callback(const std::string&); - - /** - * Call the Callback function for every regular file in the directory - * - * @param cb Callback function that receives the full path to the file - */ - void forEachFile(Callback cb) const; - - std::string getPath () { return dirPath; } -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_FILESYSDIR_H*/ diff --git a/qpid/cpp/src/qpid/sys/Fork.h b/qpid/cpp/src/qpid/sys/Fork.h deleted file mode 100644 index 4ec061f7bc..0000000000 --- a/qpid/cpp/src/qpid/sys/Fork.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef QPID_SYS_FORK_H -#define QPID_SYS_FORK_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 "posix/Fork.h" - -#endif /*!QPID_SYS_FORK_H*/ diff --git a/qpid/cpp/src/qpid/sys/FreeBSD/uuid.cpp b/qpid/cpp/src/qpid/sys/FreeBSD/uuid.cpp deleted file mode 100644 index 076056b2af..0000000000 --- a/qpid/cpp/src/qpid/sys/FreeBSD/uuid.cpp +++ /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. - * - */ - -#include "qpid/sys/uuid.h" - -#include -#include - -extern "C" -void uuid_generate (uint8_t out[qpid::sys::UuidSize]) -{ - uuid_t uuid; - uint32_t status; - uuid_create(&uuid, &status); - out[0] = (uuid.time_low & 0xff000000) >> 24; - out[1] = (uuid.time_low & 0x00ff0000) >> 16; - out[2] = (uuid.time_low & 0x0000ff00) >> 8; - out[3] = (uuid.time_low & 0x000000ff); - out[4] = (uuid.time_mid & 0xff00) >> 8; - out[5] = (uuid.time_mid & 0x00ff); - out[6] = (uuid.time_hi_and_version & 0xff00) >> 8; - out[7] = (uuid.time_hi_and_version & 0x00ff); - out[8] = uuid.clock_seq_hi_and_reserved; - out[9] = uuid.clock_seq_low; - ::memcpy(&out[10], &uuid.node, sizeof(uuid.node)); -} diff --git a/qpid/cpp/src/qpid/sys/IOHandle.h b/qpid/cpp/src/qpid/sys/IOHandle.h deleted file mode 100644 index 06ae65f879..0000000000 --- a/qpid/cpp/src/qpid/sys/IOHandle.h +++ /dev/null @@ -1,36 +0,0 @@ -#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/LockFile.h b/qpid/cpp/src/qpid/sys/LockFile.h deleted file mode 100644 index 14a76cbf3e..0000000000 --- a/qpid/cpp/src/qpid/sys/LockFile.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _sys_LockFile_h -#define _sys_LockFile_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 -#include -#include - -#include "qpid/CommonImportExport.h" -#include "qpid/sys/IntegerTypes.h" - -namespace qpid { -namespace sys { - -class LockFilePrivate; - -/** - * @class LockFile - * - * LockFile represents a locked file suitable for a coarse-grain system - * lock. For example, the broker uses this to ensure that only one broker - * runs. A common usage idiom is to store the current "owner" process ID - * in the lock file - if the lock file exists, but the stored process ID - * doesn't, the old owner has probably died without cleaning up the lock - * file. - */ -class LockFile : private boost::noncopyable -{ - std::string path; - bool created; - boost::shared_ptr impl; - -protected: - int read(void*, size_t) const; - int write(void*, size_t) const; - -public: - QPID_COMMON_EXTERN LockFile(const std::string& path_, bool create); - QPID_COMMON_EXTERN ~LockFile(); -}; - -}} /* namespace qpid::sys */ - -#endif /*!_sys_LockFile_h*/ - - - diff --git a/qpid/cpp/src/qpid/sys/LockPtr.h b/qpid/cpp/src/qpid/sys/LockPtr.h deleted file mode 100644 index 738a864317..0000000000 --- a/qpid/cpp/src/qpid/sys/LockPtr.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef QPID_SYS_LOCKPTR_H -#define QPID_SYS_LOCKPTR_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 - -namespace qpid { -namespace sys { - -class Mutex; - -/** - * LockPtr is a smart pointer to T. It is constructed from a volatile - * T* and a Lock (by default a Mutex). It const_casts away the - * volatile qualifier and locks the Lock for the duration of its - * - * Used in conjuntion with the "volatile" keyword to get the compiler - * to help enforce correct concurrent use of mutli-threaded objects. - * See ochttp://www.ddj.com/cpp/184403766 for a detailed discussion. - * - * To summarize the convention: - * - Declare thread-safe member functions as volatile. - * - Declare instances of the class that may be called concurrently as volatile. - * - Use LockPtr to cast away the volatile qualifier while taking a lock. - * - * This means that code calling on a concurrently-used object - * (declared volatile) can only call thread-safe (volatile) member - * functions. Code that needs to use thread-unsafe members must use a - * LockPtr, thereby acquiring the lock and making it safe to do so. - * - * A good type-safe pattern is the internally-locked object: - * - It has it's own private lock member. - * - All public functions are thread safe and declared volatile. - * - Any thread-unsafe, non-volatile functions are private. - * - Only member function implementations use LockPtr to access private functions. - * - * This encapsulates all the locking logic inside the class. - * - * One nice feature of this convention is the common case where you - * need a public, locked version of some function foo() and also a - * private unlocked version to avoid recursive locks. They can be declared as - * volatile and non-volatile overloads of the same function: - * - * // public - * void Thing::foo() volatile { LockPtr(this, myLock)->foo(); } - * // private - * void Thing::foo() { ... do stuff ...} - */ - -template class LockPtr : public boost::noncopyable { - public: - LockPtr(volatile T* p, Lock& l) : ptr(const_cast(p)), lock(l) { lock.lock(); } - LockPtr(volatile T* p, volatile Lock& l) : ptr(const_cast(p)), lock(const_cast(l)) { lock.lock(); } - ~LockPtr() { lock.unlock(); } - - T& operator*() { return *ptr; } - T* operator->() { return ptr; } - - private: - T* ptr; - Lock& lock; -}; - - -}} // namespace qpid::sys - - -#endif /*!QPID_SYS_LOCKPTR_H*/ diff --git a/qpid/cpp/src/qpid/sys/MemStat.cpp b/qpid/cpp/src/qpid/sys/MemStat.cpp deleted file mode 100644 index c71fba785c..0000000000 --- a/qpid/cpp/src/qpid/sys/MemStat.cpp +++ /dev/null @@ -1,31 +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/sys/MemStat.h" - -// Null memory stats provider: -// This is for platforms that do not have a way to get allocated -// memory status -void qpid::sys::MemStat::loadMemInfo(qmf::org::apache::qpid::broker::Memory*) -{ -} - - diff --git a/qpid/cpp/src/qpid/sys/MemStat.h b/qpid/cpp/src/qpid/sys/MemStat.h deleted file mode 100644 index d855786cd5..0000000000 --- a/qpid/cpp/src/qpid/sys/MemStat.h +++ /dev/null @@ -1,38 +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. - * - */ -#ifndef sys_MemStat -#define sys_MemStat - -#include "qpid/CommonImportExport.h" -#include "qmf/org/apache/qpid/broker/Memory.h" - -namespace qpid { -namespace sys { - - class QPID_COMMON_CLASS_EXTERN MemStat { - public: - QPID_COMMON_EXTERN static void loadMemInfo(qmf::org::apache::qpid::broker::Memory* object); - }; - -}} - -#endif - diff --git a/qpid/cpp/src/qpid/sys/MemoryMappedFile.h b/qpid/cpp/src/qpid/sys/MemoryMappedFile.h deleted file mode 100644 index ecf38e98e6..0000000000 --- a/qpid/cpp/src/qpid/sys/MemoryMappedFile.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef QPID_SYS_MEMORYMAPPEDFILE_H -#define QPID_SYS_MEMORYMAPPEDFILE_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 - -namespace qpid { -namespace sys { - -class MemoryMappedFilePrivate; -/** - * Abstraction of memory mapping functionality - */ -class MemoryMappedFile { - public: - QPID_COMMON_EXTERN MemoryMappedFile(); - QPID_COMMON_EXTERN ~MemoryMappedFile(); - /** - * Opens a file that can be mapped by region into memory - */ - QPID_COMMON_EXTERN void open(const std::string& name, const std::string& directory); - /** - * Closes and removes the file that can be mapped by region into memory - */ - QPID_COMMON_EXTERN void close(); - /** - * Returns the page size - */ - QPID_COMMON_EXTERN size_t getPageSize(); - /** - * Load a portion of the file into memory - */ - QPID_COMMON_EXTERN char* map(size_t offset, size_t size); - /** - * Evict a portion of the file from memory - */ - QPID_COMMON_EXTERN void unmap(char* region, size_t size); - /** - * Flush any changes to a previously mapped region of the file - * back to disk - */ - QPID_COMMON_EXTERN void flush(char* region, size_t size); - /** - * Expand the capacity of the file - */ - QPID_COMMON_EXTERN void expand(size_t offset); - /** - * Returns true if memory mapping is supported, false otherwise - */ - QPID_COMMON_EXTERN static bool isSupported(); - private: - MemoryMappedFilePrivate* state; - - MemoryMappedFile(const MemoryMappedFile&); - MemoryMappedFile& operator=(const MemoryMappedFile&); -}; -}} // namespace qpid::sys - -#endif /*!QPID_SYS_MEMORYMAPPEDFILE_H*/ diff --git a/qpid/cpp/src/qpid/sys/Monitor.h b/qpid/cpp/src/qpid/sys/Monitor.h deleted file mode 100644 index 123bf92dcb..0000000000 --- a/qpid/cpp/src/qpid/sys/Monitor.h +++ /dev/null @@ -1,49 +0,0 @@ -#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 deleted file mode 100644 index e718586a39..0000000000 --- a/qpid/cpp/src/qpid/sys/Mutex.h +++ /dev/null @@ -1,91 +0,0 @@ -#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 ScopedLock -{ - public: - ScopedLock(L& l) : mutex(l) { mutex.lock(); } - ~ScopedLock() { mutex.unlock(); } - private: - L& mutex; -}; - -template -class ScopedUnlock -{ - public: - ScopedUnlock(L& l) : mutex(l) { mutex.unlock(); } - ~ScopedUnlock() { mutex.lock(); } - private: - L& mutex; -}; - -template -class ScopedRlock -{ - public: - ScopedRlock(L& l) : mutex(l) { mutex.rlock(); } - ~ScopedRlock() { mutex.unlock(); } - private: - L& mutex; -}; - -template -class ScopedWlock -{ - public: - ScopedWlock(L& l) : mutex(l) { mutex.wlock(); } - ~ScopedWlock() { mutex.unlock(); } - private: - L& mutex; -}; - -template -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/sys/OutputControl.h b/qpid/cpp/src/qpid/sys/OutputControl.h deleted file mode 100644 index f990594637..0000000000 --- a/qpid/cpp/src/qpid/sys/OutputControl.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef QPID_SYS_OUTPUT_CONTROL_H -#define QPID_SYS_OUTPUT_CONTROL_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 sys { - - class OutputControl - { - public: - virtual ~OutputControl() {} - virtual void abort() = 0; - virtual void connectionEstablished() = 0; - virtual void activateOutput() = 0; - }; - -} -} - - -#endif /*!QPID_SYS_OUTPUT_CONTROL_H*/ diff --git a/qpid/cpp/src/qpid/sys/OutputTask.h b/qpid/cpp/src/qpid/sys/OutputTask.h deleted file mode 100644 index fb08a63cd0..0000000000 --- a/qpid/cpp/src/qpid/sys/OutputTask.h +++ /dev/null @@ -1,41 +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. - * - */ -#ifndef _OutputTask_ -#define _OutputTask_ - -namespace qpid { -namespace sys { - - class OutputTask - { - public: - virtual ~OutputTask() {} - /** Generate some output. - *@return true if output was generated, false if there is no work to do. - */ - virtual bool doOutput() = 0; - }; - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/sys/Path.h b/qpid/cpp/src/qpid/sys/Path.h deleted file mode 100644 index 9b440b3c00..0000000000 --- a/qpid/cpp/src/qpid/sys/Path.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_SYS_PATH_H -#define QPID_SYS_PATH_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 - -namespace qpid { -namespace sys { - -/** - * @class Path - * - * Represents a filesystem path with some basic operations. Can be extended. - */ -class QPID_COMMON_CLASS_EXTERN Path { - - std::string path; - - public: - // Path separator, forward or backslash - static const QPID_COMMON_EXTERN std::string separator; - - Path(const std::string& path_=std::string()) : path(path_) {} - - std::string str() const { return path; } - bool empty() const { return path.empty(); } - - QPID_COMMON_EXTERN bool exists() const; - QPID_COMMON_EXTERN bool isFile() const; - QPID_COMMON_EXTERN bool isDirectory() const; - QPID_COMMON_EXTERN bool isAbsolute() const; - - /** Join with appropriate path separator. */ - Path& operator+=(const Path& tail) { path = path + separator + tail.path; return *this; } -}; - -inline Path operator+(const Path& head, const Path& tail) { Path p(head); return p += tail; } - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_PATH_H*/ diff --git a/qpid/cpp/src/qpid/sys/PipeHandle.h b/qpid/cpp/src/qpid/sys/PipeHandle.h deleted file mode 100755 index 8aac76996b..0000000000 --- a/qpid/cpp/src/qpid/sys/PipeHandle.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _sys_PipeHandle_h -#define _sys_PipeHandle_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/CommonImportExport.h" -#include - -// This class is a portability wrapper around pipe fds. -// It currently exists primarily and solely for the purpose of -// integration with single-threaded components that require QMF -// integration through a signalling fd. - -namespace qpid { -namespace sys { - - class PipeHandle { - private: - int writeFd; - int readFd; - public: - QPID_COMMON_EXTERN PipeHandle(bool nonBlocking=true); - QPID_COMMON_EXTERN ~PipeHandle(); - QPID_COMMON_EXTERN int read(void* buf, size_t bufSize); - QPID_COMMON_EXTERN int write(const void* buf, size_t bufSize); - QPID_COMMON_EXTERN int getReadHandle(); - }; - -}} - -#endif /*!_sys_PipeHandle_h*/ diff --git a/qpid/cpp/src/qpid/sys/PollableCondition.h b/qpid/cpp/src/qpid/sys/PollableCondition.h deleted file mode 100644 index 2eb6f2d947..0000000000 --- a/qpid/cpp/src/qpid/sys/PollableCondition.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_SYS_POLLABLECONDITION_H -#define QPID_SYS_POLLABLECONDITION_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/Poller.h" -#include "qpid/CommonImportExport.h" -#include -#include - - -namespace qpid { -namespace sys { - -class PollableConditionPrivate; - -class PollableCondition { -public: - typedef boost::function1 Callback; - - QPID_COMMON_EXTERN PollableCondition(const Callback& cb, - const boost::shared_ptr& poller); - - QPID_COMMON_EXTERN ~PollableCondition(); - - /** - * Set the condition. Triggers callback to Callback from Poller. - */ - QPID_COMMON_EXTERN void set(); - - /** - * Clear the condition. Stops callbacks from Poller. - */ - QPID_COMMON_EXTERN void clear(); - - private: - PollableConditionPrivate *impl; - - Callback callback; - boost::shared_ptr poller; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_POLLABLECONDITION_H*/ diff --git a/qpid/cpp/src/qpid/sys/PollableQueue.h b/qpid/cpp/src/qpid/sys/PollableQueue.h deleted file mode 100644 index 5a3e281e9f..0000000000 --- a/qpid/cpp/src/qpid/sys/PollableQueue.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef QPID_SYS_POLLABLEQUEUE_H -#define QPID_SYS_POLLABLEQUEUE_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/PollableCondition.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Thread.h" -#include -#include -#include -#include -#include "qpid/log/Statement.h" // FIXME aconway 2011-08-05: - -namespace qpid { -namespace sys { - -class Poller; - -/** - * A queue whose item processing is dispatched by sys::Poller. - * Any thread can push to the queue; items pushed trigger an event the Poller - * recognizes. When a Poller I/O thread dispatches the event, a - * user-specified callback is invoked with all items on the queue. - */ -template -class PollableQueue { - public: - typedef std::deque Batch; - typedef T value_type; - - /** - * Callback to process a batch of items from the queue. - * - * @param batch Queue of values to process. Any items remaining - * on return from Callback are put back on the queue. - * @return iterator pointing to the first un-processed item in batch. - * Items from this point up to batch.end() are put back on the queue. - */ - typedef boost::function Callback; - - /** - * Constructor; sets necessary parameters. - * - * @param cb Callback that will be called to process items on the - * queue. Will be called from a Poller I/O thread. - * @param poller Poller to use for dispatching queue events. - */ - PollableQueue(const Callback& cb, - const boost::shared_ptr& poller); - - ~PollableQueue(); - - /** Push a value onto the queue. Thread safe */ - void push(const T& t); - - /** Start polling. */ - void start(); - - /** Stop polling and wait for the current callback, if any, to complete. */ - void stop(); - - /** Are we currently stopped?*/ - bool isStopped() const { ScopedLock l(lock); return stopped; } - - size_t size() { ScopedLock l(lock); return queue.size(); } - bool empty() { ScopedLock l(lock); return queue.empty(); } - - /** - * Allow any queued events to be processed; intended for calling - * after all dispatch threads exit the Poller loop in order to - * ensure clean shutdown with no events left on the queue. - */ - void shutdown(); - - private: - typedef sys::Monitor::ScopedLock ScopedLock; - typedef sys::Monitor::ScopedUnlock ScopedUnlock; - - void dispatch(PollableCondition& cond); - void process(); - - mutable sys::Monitor lock; - Callback callback; - PollableCondition condition; - Batch queue, batch; - Thread dispatcher; - bool stopped; -}; - -template PollableQueue::PollableQueue( - const Callback& cb, const boost::shared_ptr& p) - : callback(cb), - condition(boost::bind(&PollableQueue::dispatch, this, _1), p), - stopped(true) -{ -} - -template void PollableQueue::start() { - ScopedLock l(lock); - if (!stopped) return; - stopped = false; - if (!queue.empty()) condition.set(); -} - -template PollableQueue::~PollableQueue() { -} - -template void PollableQueue::push(const T& t) { - ScopedLock l(lock); - if (queue.empty() && !stopped) condition.set(); - queue.push_back(t); -} - -template void PollableQueue::dispatch(PollableCondition& cond) { - ScopedLock l(lock); - assert(!dispatcher); - dispatcher = Thread::current(); - process(); - dispatcher = Thread(); - if (queue.empty()) cond.clear(); - if (stopped) lock.notifyAll(); -} - -template void PollableQueue::process() { - // Called with lock held - if (!stopped && !queue.empty()) { - assert(batch.empty()); - batch.swap(queue); - typename Batch::const_iterator putBack; - { - ScopedUnlock u(lock); // Allow concurrent push to queue. - putBack = callback(batch); - } - // put back unprocessed items. - queue.insert(queue.begin(), putBack, typename Batch::const_iterator(batch.end())); - batch.clear(); - } -} - -template void PollableQueue::shutdown() { - ScopedLock l(lock); - process(); -} - -template void PollableQueue::stop() { - ScopedLock l(lock); - if (stopped) return; - condition.clear(); - stopped = true; - // Avoid deadlock if stop is called from the dispatch thread - if (dispatcher && dispatcher != Thread::current()) - while (dispatcher) lock.wait(); -} - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_POLLABLEQUEUE_H*/ diff --git a/qpid/cpp/src/qpid/sys/Poller.h b/qpid/cpp/src/qpid/sys/Poller.h deleted file mode 100644 index 01ee139ee6..0000000000 --- a/qpid/cpp/src/qpid/sys/Poller.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef _sys_Poller_h -#define _sys_Poller_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" -#include "qpid/sys/Runnable.h" -#include "qpid/CommonImportExport.h" -#include - -namespace qpid { -namespace sys { - -/** - * Poller is an abstract base class that registers callbacks to be - * called when there is IO activity. Concrete derived classes - * implement polling APIs such as epoll or equivalents on other - * operating systems. - * - * On the broker, Connection::received() is called with incoming - * frames from clients, and Connection::doOutput() is called when a - * connection is writeable. - * - * @see DispatchHandler for more details of normal use. - */ -class PollerHandle; -class PollerPrivate; -class Poller : public Runnable { - PollerPrivate* const impl; - -public: - typedef boost::shared_ptr shared_ptr; - - enum Direction { - NONE = 0, - INPUT, - OUTPUT, - INOUT - }; - - enum EventType { - INVALID = 0, - READABLE, - WRITABLE, - READ_WRITABLE, - DISCONNECTED, - SHUTDOWN, - TIMEOUT, - INTERRUPTED - }; - - struct Event { - PollerHandle* handle; - EventType type; - - Event(PollerHandle* handle0, EventType type0) : - handle(handle0), - type(type0) { - } - - void process(); - }; - - QPID_COMMON_EXTERN Poller(); - QPID_COMMON_EXTERN ~Poller(); - /** Note: this function is async-signal safe */ - QPID_COMMON_EXTERN void shutdown(); - - // Interrupt waiting for a specific poller handle - // returns true if we could interrupt the handle - // - in this case on return the handle is no longer being monitored, - // but we will receive an event from some invocation of poller::wait - // with the handle and the INTERRUPTED event type - // if it returns false then the handle is not being monitored by the poller - // - This can either be because it has just received an event which has been - // reported and has not been reenabled since. - // - Because it was removed from the monitoring set - // - Or because it is already being interrupted - QPID_COMMON_EXTERN bool interrupt(PollerHandle& handle); - - // Poller run loop - QPID_COMMON_EXTERN void run(); - - QPID_COMMON_EXTERN void registerHandle(PollerHandle& handle); - QPID_COMMON_EXTERN void unregisterHandle(PollerHandle& handle); - QPID_COMMON_EXTERN void monitorHandle(PollerHandle& handle, Direction dir); - QPID_COMMON_EXTERN void unmonitorHandle(PollerHandle& handle, Direction dir); - QPID_COMMON_EXTERN Event wait(Duration timeout = TIME_INFINITE); - - QPID_COMMON_EXTERN bool hasShutdown(); -}; - -/** - * Handle class to use for polling - */ -class IOHandle; -class PollerHandlePrivate; -class PollerHandle { - friend class Poller; - friend class PollerPrivate; - friend struct Poller::Event; - - PollerHandlePrivate* const impl; - QPID_COMMON_INLINE_EXTERN virtual void processEvent(Poller::EventType) {}; - -public: - QPID_COMMON_EXTERN PollerHandle(const IOHandle& h); - QPID_COMMON_EXTERN virtual ~PollerHandle(); -}; - -inline void Poller::Event::process() { - handle->processEvent(type); -} - -}} -#endif // _sys_Poller_h diff --git a/qpid/cpp/src/qpid/sys/Probes.h b/qpid/cpp/src/qpid/sys/Probes.h deleted file mode 100644 index d30181c357..0000000000 --- a/qpid/cpp/src/qpid/sys/Probes.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _sys_Probes -#define _sys_Probes -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 "config.h" - -#ifdef HAVE_SYS_SDT_H -#include -#endif - -// Pragmatically it seems that Linux and Solaris versions of sdt.h which support -// user static probes define up to DTRACE_PROBE8, but FreeBSD 8 which doesn't -// support usdt only defines up to DTRACE_PROBE4 - FreeBSD 9 which does support usdt -// defines up to DTRACE_PROBE5. - -#ifdef DTRACE_PROBE5 -// Versions for Linux Systemtap/Solaris/FreeBSD 9 -#define QPID_PROBE(probe) DTRACE_PROBE(qpid, probe) -#define QPID_PROBE1(probe, p1) DTRACE_PROBE1(qpid, probe, p1) -#define QPID_PROBE2(probe, p1, p2) DTRACE_PROBE2(qpid, probe, p1, p2) -#define QPID_PROBE3(probe, p1, p2, p3) DTRACE_PROBE3(qpid, probe, p1, p2, p3) -#define QPID_PROBE4(probe, p1, p2, p3, p4) DTRACE_PROBE4(qpid, probe, p1, p2, p3, p4) -#define QPID_PROBE5(probe, p1, p2, p3, p4, p5) DTRACE_PROBE5(qpid, probe, p1, p2, p3, p4, p5) -#else -// FreeBSD 8 -#define QPID_PROBE(probe) -#define QPID_PROBE1(probe, p1) -#define QPID_PROBE2(probe, p1, p2) -#define QPID_PROBE3(probe, p1, p2, p3) -#define QPID_PROBE4(probe, p1, p2, p3, p4) -#define QPID_PROBE5(probe, p1, p2, p3, p4, p5) -#endif - -#ifdef DTRACE_PROBE8 -// Versions for Linux Systemtap -#define QPID_PROBE6(probe, p1, p2, p3, p4, p5, p6) DTRACE_PROBE6(qpid, probe, p1, p2, p3, p4, p5, p6) -#define QPID_PROBE7(probe, p1, p2, p3, p4, p5, p6, p7) DTRACE_PROBE7(qpid, probe, p1, p2, p3, p4, p5, p6, p7) -#define QPID_PROBE8(probe, p1, p2, p3, p4, p5, p6, p7, p8) DTRACE_PROBE8(qpid, probe, p1, p2, p3, p4, p5, p6, p7, p8) -#else -// Versions for Solaris/FreeBSD -#define QPID_PROBE6(probe, p1, p2, p3, p4, p5, p6) -#define QPID_PROBE7(probe, p1, p2, p3, p4, p5, p6, p7) -#define QPID_PROBE8(probe, p1, p2, p3, p4, p5, p6, p7, p8) -#endif - -#endif // _sys_Probes diff --git a/qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp b/qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp deleted file mode 100644 index 9a7b8ef201..0000000000 --- a/qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp +++ /dev/null @@ -1,393 +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/sys/TransportFactory.h" - -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/NameGenerator.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/sys/SecuritySettings.h" - -#include -#include -#include - -#include - -using std::auto_ptr; -using std::string; -using std::stringstream; - -namespace qpid { -namespace sys { - -class RdmaIOHandler : public OutputControl { - std::string identifier; - ConnectionCodec::Factory* factory; - ConnectionCodec* codec; - bool readError; - - sys::Mutex pollingLock; - bool polling; - - Rdma::AsynchIO* aio; - Rdma::Connection::intrusive_ptr connection; - - void write(const framing::ProtocolInitiation&); - void disconnectAction(); - - public: - RdmaIOHandler(Rdma::Connection::intrusive_ptr c, ConnectionCodec::Factory* f); - ~RdmaIOHandler(); - void init(Rdma::AsynchIO* a); - void start(Poller::shared_ptr poller); - - // Output side - void close(); - void abort(); - void connectionEstablished(); - void activateOutput(); - void initProtocolOut(); - - // Input side - void readbuff(Rdma::AsynchIO& aio, Rdma::Buffer* buff); - void initProtocolIn(Rdma::Buffer* buff); - - // Notifications - void full(Rdma::AsynchIO& aio); - void idle(Rdma::AsynchIO& aio); - void error(Rdma::AsynchIO& aio); - void disconnected(); - void drained(); -}; - -RdmaIOHandler::RdmaIOHandler(Rdma::Connection::intrusive_ptr c, qpid::sys::ConnectionCodec::Factory* f) : - identifier(broker::QPID_NAME_PREFIX+c->getFullName()), - factory(f), - codec(0), - readError(false), - polling(false), - connection(c) -{ -} - -RdmaIOHandler::~RdmaIOHandler() { - if (codec) - codec->closed(); - delete codec; - delete aio; -} - -void RdmaIOHandler::init(Rdma::AsynchIO* a) { - aio = a; -} - -void RdmaIOHandler::start(Poller::shared_ptr poller) { - Mutex::ScopedLock l(pollingLock); - assert(!polling); - - polling = true; - - aio->start(poller); -} - -void RdmaIOHandler::write(const framing::ProtocolInitiation& data) -{ - QPID_LOG(debug, "Rdma: SENT [" << identifier << "]: INIT(" << data << ")"); - Rdma::Buffer* buff = aio->getSendBuffer(); - assert(buff); - framing::Buffer out(buff->bytes(), buff->byteCount()); - data.encode(out); - buff->dataCount(data.encodedSize()); - aio->queueWrite(buff); -} - -void RdmaIOHandler::close() { - aio->drainWriteQueue(boost::bind(&RdmaIOHandler::drained, this)); -} - -// TODO: Dummy implementation, need to fill this in for heartbeat timeout to work -void RdmaIOHandler::abort() { -} - -// TODO: Dummy implementation, need to fill this in for connection establishment timeout to work -void RdmaIOHandler::connectionEstablished() { -} - -void RdmaIOHandler::activateOutput() { - aio->notifyPendingWrite(); -} - -void RdmaIOHandler::idle(Rdma::AsynchIO&) { - // TODO: Shouldn't need this test as idle() should only ever be called when - // the connection is writable anyway - if ( !aio->writable() ) { - return; - } - if (codec == 0) return; - if (!codec->canEncode()) { - return; - } - Rdma::Buffer* buff = aio->getSendBuffer(); - if (buff) { - size_t encoded=codec->encode(buff->bytes(), buff->byteCount()); - buff->dataCount(encoded); - aio->queueWrite(buff); - if (codec->isClosed()) { - close(); - } - } -} - -void RdmaIOHandler::initProtocolOut() { - // We mustn't have already started the conversation - // but we must be able to send - assert( codec == 0 ); - assert( aio->writable() ); - codec = factory->create(*this, identifier, SecuritySettings()); - write(framing::ProtocolInitiation(codec->getVersion())); -} - -void RdmaIOHandler::error(Rdma::AsynchIO&) { - disconnected(); -} - -namespace { - void stopped(RdmaIOHandler* async) { - delete async; - } -} - -void RdmaIOHandler::disconnectAction() { - { - Mutex::ScopedLock l(pollingLock); - // If we're closed already then we'll get to drained() anyway - if (!polling) return; - polling = false; - } - aio->stop(boost::bind(&stopped, this)); -} - -void RdmaIOHandler::disconnected() { - aio->requestCallback(boost::bind(&RdmaIOHandler::disconnectAction, this)); -} - -void RdmaIOHandler::drained() { - // We know we've drained the write queue now, but we don't have to do anything - // because we can rely on the client to disconnect to trigger the connection - // cleanup. -} - -void RdmaIOHandler::full(Rdma::AsynchIO&) { - QPID_LOG(debug, "Rdma: buffer full [" << identifier << "]"); -} - -// The logic here is subtly different from TCP as RDMA is message oriented -// so we define that an RDMA message is a frame - in this case there is no putting back -// of any message remainder - there shouldn't be any. And what we read here can't be -// smaller than a frame -void RdmaIOHandler::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) { - if (readError) { - return; - } - try { - if (codec) { - (void) codec->decode(buff->bytes(), buff->dataCount()); - }else{ - // Need to start protocol processing - initProtocolIn(buff); - } - }catch(const std::exception& e){ - QPID_LOG(error, e.what()); - readError = true; - close(); - } -} - -void RdmaIOHandler::initProtocolIn(Rdma::Buffer* buff) { - framing::Buffer in(buff->bytes(), buff->dataCount()); - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - QPID_LOG(debug, "Rdma: RECV [" << identifier << "]: INIT(" << protocolInit << ")"); - - codec = factory->create(protocolInit.getVersion(), *this, identifier, SecuritySettings()); - - // If we failed to create the codec then we don't understand the offered protocol version - if (!codec) { - // send valid version header & close connection. - write(framing::ProtocolInitiation(framing::highestProtocolVersion)); - readError = true; - close(); - } - } -} - -class RdmaIOProtocolFactory : public TransportAcceptor, public TransportConnector { - auto_ptr listener; - const uint16_t listeningPort; - - public: - RdmaIOProtocolFactory(int16_t port, int backlog); - void accept(Poller::shared_ptr, ConnectionCodec::Factory*); - void connect(Poller::shared_ptr, const std::string& name, const string& host, const std::string& port, ConnectionCodec::Factory*, ConnectFailedCallback); - - uint16_t getPort() const; - - private: - bool request(Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectionCodec::Factory*); - void established(Poller::shared_ptr, Rdma::Connection::intrusive_ptr); - void connected(Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectionCodec::Factory*); - void connectionError(Rdma::Connection::intrusive_ptr, Rdma::ErrorType); - void disconnected(Rdma::Connection::intrusive_ptr); - void rejected(Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectFailedCallback); -}; - -// Static instance to initialise plugin -static class RdmaIOPlugin : public Plugin { - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - // Check whether we actually have any rdma devices - if ( Rdma::deviceCount() == 0 ) { - QPID_LOG(info, "Rdma: Disabled: no rdma devices found"); - return; - } - - broker::Broker* broker = dynamic_cast(&target); - // Only provide to a Broker - if (broker) { - boost::shared_ptr protocol(new RdmaIOProtocolFactory(broker->getPortOption(), broker->getConnectionBacklog())); - uint16_t port = protocol->getPort(); - QPID_LOG(notice, "Rdma: Listening on RDMA port " << port); - broker->registerTransport("rdma", protocol, protocol, port); - } - } -} rdmaPlugin; - -RdmaIOProtocolFactory::RdmaIOProtocolFactory(int16_t port, int /*backlog*/) : - listeningPort(port) -{} - -void RdmaIOProtocolFactory::established(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr ci) { - RdmaIOHandler* async = ci->getContext(); - async->start(poller); -} - -bool RdmaIOProtocolFactory::request(Rdma::Connection::intrusive_ptr ci, const Rdma::ConnectionParams& cp, - ConnectionCodec::Factory* f) { - try { - if (cp.rdmaProtocolVersion == 0) { - QPID_LOG(warning, "Rdma: connection from protocol version 0 client"); - } - RdmaIOHandler* async = new RdmaIOHandler(ci, f); - Rdma::AsynchIO* aio = - new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit, Rdma::DEFAULT_WR_ENTRIES, - boost::bind(&RdmaIOHandler::readbuff, async, _1, _2), - boost::bind(&RdmaIOHandler::idle, async, _1), - 0, // boost::bind(&RdmaIOHandler::full, async, _1), - boost::bind(&RdmaIOHandler::error, async, _1)); - async->init(aio); - - // Record aio so we can get it back from a connection - ci->addContext(async); - return true; - } catch (const Rdma::Exception& e) { - QPID_LOG(error, "Rdma: Cannot accept new connection (Rdma exception): " << e.what()); - } catch (const std::exception& e) { - QPID_LOG(error, "Rdma: Cannot accept new connection (unknown exception): " << e.what()); - } - - // If we get here we caught an exception so reject connection - return false; -} - -void RdmaIOProtocolFactory::connectionError(Rdma::Connection::intrusive_ptr, Rdma::ErrorType) { -} - -void RdmaIOProtocolFactory::disconnected(Rdma::Connection::intrusive_ptr ci) { - // If we've got a connection already tear it down, otherwise ignore - RdmaIOHandler* async = ci->getContext(); - if (async) { - // Make sure we don't disconnect more than once - ci->removeContext(); - async->disconnected(); - } -} - -uint16_t RdmaIOProtocolFactory::getPort() const { - return listeningPort; // Immutable no need for lock. -} - -void RdmaIOProtocolFactory::accept(Poller::shared_ptr poller, ConnectionCodec::Factory* fact) { - listener.reset( - new Rdma::Listener( - Rdma::ConnectionParams(65536, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&RdmaIOProtocolFactory::established, this, poller, _1), - boost::bind(&RdmaIOProtocolFactory::connectionError, this, _1, _2), - boost::bind(&RdmaIOProtocolFactory::disconnected, this, _1), - boost::bind(&RdmaIOProtocolFactory::request, this, _1, _2, fact))); - - SocketAddress sa("",boost::lexical_cast(listeningPort)); - listener->start(poller, sa); -} - -// Only used for outgoing connections (in federation) -void RdmaIOProtocolFactory::rejected(Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectFailedCallback failed) { - failed(-1, "Connection rejected"); -} - -// Do the same as connection request and established but mark a client too -void RdmaIOProtocolFactory::connected(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr ci, const Rdma::ConnectionParams& cp, - ConnectionCodec::Factory* f) { - (void) request(ci, cp, f); - established(poller, ci); - RdmaIOHandler* async = ci->getContext(); - async->initProtocolOut(); -} - -void RdmaIOProtocolFactory::connect( - Poller::shared_ptr poller, - const std::string& /*name*/, - const std::string& host, const std::string& port, - ConnectionCodec::Factory* f, - ConnectFailedCallback failed) -{ - Rdma::Connector* c = - new Rdma::Connector( - Rdma::ConnectionParams(8000, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&RdmaIOProtocolFactory::connected, this, poller, _1, _2, f), - boost::bind(&RdmaIOProtocolFactory::connectionError, this, _1, _2), - boost::bind(&RdmaIOProtocolFactory::disconnected, this, _1), - boost::bind(&RdmaIOProtocolFactory::rejected, this, _1, _2, failed)); - - SocketAddress sa(host, port); - c->start(poller, sa); -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/Runnable.cpp b/qpid/cpp/src/qpid/sys/Runnable.cpp deleted file mode 100644 index 325d87c91b..0000000000 --- a/qpid/cpp/src/qpid/sys/Runnable.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * 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/Runnable.h" -#include - -namespace qpid { -namespace sys { - -Runnable::~Runnable() {} - -Runnable::Functor Runnable::functor() -{ - return boost::bind(&Runnable::run, this); -} - -}} diff --git a/qpid/cpp/src/qpid/sys/Runnable.h b/qpid/cpp/src/qpid/sys/Runnable.h deleted file mode 100644 index fed7663cb6..0000000000 --- a/qpid/cpp/src/qpid/sys/Runnable.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _Runnable_ -#define _Runnable_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace sys { - -/** - * Interface for objects that can be run, e.g. in a thread. - */ -class QPID_COMMON_CLASS_EXTERN Runnable -{ - public: - /** Type to represent a runnable as a Functor */ - typedef boost::function0 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/qpid/sys/ScopedIncrement.h b/qpid/cpp/src/qpid/sys/ScopedIncrement.h deleted file mode 100644 index 8645ab2484..0000000000 --- a/qpid/cpp/src/qpid/sys/ScopedIncrement.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _posix_ScopedIncrement_h -#define _posix_ScopedIncrement_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 -#include - -namespace qpid { -namespace sys { - -/** - * Increment counter in constructor and decrement in destructor. - * Optionally call a function if the decremented counter value is 0. - * Note the function must not throw, it is called in the destructor. - */ -template > -class ScopedIncrement : boost::noncopyable -{ - public: - ScopedIncrement(T& c, F f=0) - : count(c), callback(f) { ++count; } - ~ScopedIncrement() { if (--count == 0 && callback) callback(); } - - private: - T& count; - F callback; -}; - - -/** Decrement counter in constructor and increment in destructor. */ -template -class ScopedDecrement : boost::noncopyable -{ - public: - ScopedDecrement(T& c) : count(c) { value = --count; } - ~ScopedDecrement() { ++count; } - - /** Return the value after the decrement. */ - operator long() { return value; } - - private: - T& count; - long value; -}; - - -}} - - -#endif // _posix_ScopedIncrement_h diff --git a/qpid/cpp/src/qpid/sys/SecurityLayer.h b/qpid/cpp/src/qpid/sys/SecurityLayer.h deleted file mode 100644 index 317ada16de..0000000000 --- a/qpid/cpp/src/qpid/sys/SecurityLayer.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef QPID_SYS_SECURITYLAYER_H -#define QPID_SYS_SECURITYLAYER_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/Codec.h" - -namespace qpid { -namespace sys { - -/** - * Defines interface to a SASL negotiated Security Layer (for - * encryption/integrity) - */ -class SecurityLayer : public Codec -{ - public: - SecurityLayer(int ssf_) : ssf(ssf_) {} - int getSsf() const { return ssf; } - virtual void init(Codec*) = 0; - virtual ~SecurityLayer() {} - private: - int ssf; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_SECURITYLAYER_H*/ diff --git a/qpid/cpp/src/qpid/sys/SecuritySettings.h b/qpid/cpp/src/qpid/sys/SecuritySettings.h deleted file mode 100644 index d595cad660..0000000000 --- a/qpid/cpp/src/qpid/sys/SecuritySettings.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_SYS_SECURITYSETTINGS_H -#define QPID_SYS_SECURITYSETTINGS_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 - -namespace qpid { -namespace sys { - -/** - * Conveys security information from a given transport to the upper - * layers. - */ -struct SecuritySettings -{ - /** - * Security Strength Factor (SSF). Possible values are: - * - * @li 0 No security - * @li 1 Integrity checking only - * @li >1 Integrity and confidentiality with the number - * giving the encryption key length. - */ - unsigned int ssf; - /** - * An authorisation id - */ - std::string authid; - - /** - * Disables SASL mechanisms that are vulnerable to passive - * dictionary-based password attacks - */ - bool nodict; - - SecuritySettings() : ssf(0), nodict(false) {} -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_SECURITYSETTINGS_H*/ diff --git a/qpid/cpp/src/qpid/sys/Semaphore.h b/qpid/cpp/src/qpid/sys/Semaphore.h deleted file mode 100644 index 9d70f89aeb..0000000000 --- a/qpid/cpp/src/qpid/sys/Semaphore.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef _sys_Semaphore_h -#define _sys_Semaphore_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/Monitor.h" - -namespace qpid { -namespace sys { - -class Semaphore -{ -public: - Semaphore(uint c = 1) : count(c) {} - - void lock() { acquire(); } - void unlock() { release(); } - bool trylock() { return tryAcquire(); } - - bool tryAcquire() - { - Monitor::ScopedLock l(monitor); - if (count) { - count--; - return true; - } else { - return false; - } - } - - void acquire() - { - Monitor::ScopedLock l(monitor); - while (count == 0) monitor.wait(); - count--; - } - - void release(uint n) - { - Monitor::ScopedLock l(monitor); - if (count==0) monitor.notifyAll(); - count+=n; - } - - void release() - { - release(1); - } - - void forceLock() - { - Monitor::ScopedLock l(monitor); - count = 0; - } - -private: - Monitor monitor; - uint count; -}; - -}} - -#endif /*!_sys_Semaphore_h*/ diff --git a/qpid/cpp/src/qpid/sys/Shlib.cpp b/qpid/cpp/src/qpid/sys/Shlib.cpp deleted file mode 100644 index 342d726876..0000000000 --- a/qpid/cpp/src/qpid/sys/Shlib.cpp +++ /dev/null @@ -1,38 +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/sys/Shlib.h" - -#include "qpid/log/Statement.h" - -namespace qpid { -namespace sys { - -AutoShlib::~AutoShlib() throw() { - try { - unload(); - } catch(const std::exception& e) { - QPID_LOG(error, "Unloading shared library: " << e.what()); - } -} - -// Note: Other functions are defined in apr/Shlib.cpp or posix/Shlib.cpp. - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/Shlib.h b/qpid/cpp/src/qpid/sys/Shlib.h deleted file mode 100644 index 2ce5a49fcb..0000000000 --- a/qpid/cpp/src/qpid/sys/Shlib.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef QPID_SYS_SHLIB_H -#define QPID_SYS_SHLIB_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/sys/IntegerTypes.h" -#include -#include - -namespace qpid { -namespace sys { - -/** Encapsulates a shared library handle. - *@see AutoShlib - */ -class Shlib { - public: - /** Load a shared library */ - Shlib(const char* libname) { load(libname); } - - /** Load a shared library */ - Shlib(const std::string& libname) { load(libname.c_str()); } - - /** Unload shared library. */ - QPID_COMMON_EXTERN void unload(); - - /** Look up symbol. */ - QPID_COMMON_EXTERN void* getSymbol(const char* symbol); - - /** Look up symbol in shared library, cast it to the desired - * pointer type, void* by default. - */ - template - T getSymbol(const char* symbol) { - // Double cast avoids warning about casting object to function pointer - return reinterpret_cast(reinterpret_cast( - this->getSymbol(symbol))); - } - - private: - void* handle; - QPID_COMMON_EXTERN void load(const char* libname); -}; - -/** A shared library handle that unloads the shlib in it's dtor */ -class AutoShlib : public Shlib { - public: - /** Load shared library */ - AutoShlib(const std::string& libname) : Shlib(libname) {} - /** Calls unload() */ - QPID_COMMON_EXTERN ~AutoShlib() throw(); -}; - - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_SHLIB_H*/ diff --git a/qpid/cpp/src/qpid/sys/ShutdownHandler.h b/qpid/cpp/src/qpid/sys/ShutdownHandler.h deleted file mode 100644 index 88baecb5b6..0000000000 --- a/qpid/cpp/src/qpid/sys/ShutdownHandler.h +++ /dev/null @@ -1,37 +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. - * - */ -#ifndef _ShutdownHandler_ -#define _ShutdownHandler_ - -namespace qpid { -namespace sys { - - class ShutdownHandler - { - public: - virtual void shutdown() = 0; - virtual ~ShutdownHandler(){} - }; - -} -} - -#endif diff --git a/qpid/cpp/src/qpid/sys/Socket.h b/qpid/cpp/src/qpid/sys/Socket.h deleted file mode 100644 index d2bbde8f9a..0000000000 --- a/qpid/cpp/src/qpid/sys/Socket.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef _sys_Socket_h -#define _sys_Socket_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/CommonImportExport.h" -#include - -namespace qpid { -namespace sys { - -class Duration; -class IOHandle; -class SocketAddress; - -class Socket -{ -public: - virtual ~Socket() {}; - - virtual operator const IOHandle&() const = 0; - - /** Set socket non blocking */ - virtual void setNonblocking() const = 0; - - virtual void setTcpNoDelay() const = 0; - - virtual void connect(const SocketAddress&) const = 0; - virtual void finishConnect(const SocketAddress&) const = 0; - - virtual void close() const = 0; - - /** Bind to a port and start listening. - *@param port 0 means choose an available port. - *@param backlog maximum number of pending connections. - *@return The bound port. - */ - virtual int listen(const SocketAddress&, int backlog = 10) const = 0; - - /** - * Returns an address (host and port) for the remote end of the - * socket - */ - virtual std::string getPeerAddress() const = 0; - - /** - * Returns an address (host and port) for the local end of the - * socket - */ - virtual std::string getLocalAddress() const = 0; - - /** - * Returns the full address of the connection: local and remote host and port. - */ - QPID_COMMON_INLINE_EXTERN std::string getFullAddress() const { return getLocalAddress()+"-"+getPeerAddress(); } - - /** - * Returns the error code stored in the socket. This may be used - * to determine the result of a non-blocking connect. - */ - virtual int getError() const = 0; - - /** - * Returns error text for last read/write error code - */ - virtual std::string lastErrorCodeText() const = 0; - - /** - * Accept a connection from a socket that is already listening - * and has an incoming connection - */ - virtual Socket* accept() const = 0; - - /** Read up to count bytes into buffer - * If return is positive read that number of bytes; - * if 0 then end of input stream (or disconnected) - * if <0 then error, in this case an error text can be fetched - * using lastErrorCodeText(). - */ - virtual int read(void *buf, size_t count) const = 0; - - /** Write up to count bytes into buffer - * If return is positive wrote that number of bytes; - * if 0 then stream closed (or disconnected) - * if <0 then error, in this case an error text can be fetched - * using lastErrorCodeText(). - */ - virtual int write(const void *buf, size_t count) const = 0; - - /* Transport security related: */ - virtual int getKeyLen() const = 0; - virtual std::string getPeerAuthId() const = 0; - virtual std::string getLocalAuthId() const = 0; -}; - -/** Make the default socket for whatever platform we are executing on - */ -QPID_COMMON_EXTERN Socket* createSocket(); - -}} -#endif /*!_sys_Socket_h*/ diff --git a/qpid/cpp/src/qpid/sys/SocketAddress.h b/qpid/cpp/src/qpid/sys/SocketAddress.h deleted file mode 100644 index 00b05f4c6c..0000000000 --- a/qpid/cpp/src/qpid/sys/SocketAddress.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _sys_SocketAddress_h -#define _sys_SocketAddress_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/CommonImportExport.h" -#include - -struct addrinfo; -struct sockaddr; - -namespace qpid { -namespace sys { - -class SocketAddress { - friend const ::addrinfo& getAddrInfo(const SocketAddress&); - -public: - /** Create a SocketAddress from hostname and port*/ - QPID_COMMON_EXTERN SocketAddress(const std::string& host, const std::string& port); - QPID_COMMON_EXTERN SocketAddress(const SocketAddress&); - QPID_COMMON_EXTERN SocketAddress& operator=(const SocketAddress&); - QPID_COMMON_EXTERN ~SocketAddress(); - - QPID_COMMON_EXTERN void firstAddress() const; - QPID_COMMON_EXTERN bool nextAddress() const; - QPID_COMMON_EXTERN std::string asString(bool numeric=true, - bool dispNameOnly=false, - bool hideDecoration=false) const; - QPID_COMMON_EXTERN std::string getHost() const; - - QPID_COMMON_EXTERN static std::string asString(::sockaddr const * const addr, - size_t addrlen, - bool dispNameOnly=false, - bool hideDecoration=false); - QPID_COMMON_EXTERN static uint16_t getPort(::sockaddr const * const addr); - - QPID_COMMON_EXTERN bool isIp() const; - - QPID_COMMON_EXTERN std::string comparisonDetails(const SocketAddress& ) const; - - QPID_COMMON_EXTERN bool isComparable(const SocketAddress& saHi) const; - - QPID_COMMON_EXTERN bool inRange(const SocketAddress& , - const SocketAddress& ) const; - QPID_COMMON_EXTERN bool inRange(const struct addrinfo&, - const struct addrinfo&, - const struct addrinfo&) const; - - QPID_COMMON_EXTERN bool compareAddresses(const struct addrinfo&, - const struct addrinfo&, - int&) const; - -private: - std::string host; - std::string port; - mutable ::addrinfo* addrInfo; - mutable ::addrinfo* currentAddrInfo; -}; - -}} -#endif /*!_sys_SocketAddress_h*/ diff --git a/qpid/cpp/src/qpid/sys/SocketTransport.cpp b/qpid/cpp/src/qpid/sys/SocketTransport.cpp deleted file mode 100644 index 36edcf24a3..0000000000 --- a/qpid/cpp/src/qpid/sys/SocketTransport.cpp +++ /dev/null @@ -1,221 +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. - * - */ -// Turn off unintialised warnings as errors when compiling under Red Enterprise Linux 6 -// as an unitialised variable warning is unavoidable there. -#if __GNUC__ == 4 && __GNUC_MINOR__ == 4 -#pragma GCC diagnostic warning "-Wuninitialized" -#endif - -#include "qpid/sys/SocketTransport.h" - -#include "qpid/broker/NameGenerator.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/AsynchIOHandler.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/SystemInfo.h" - -#include -#include - -namespace qpid { -namespace sys { - -namespace { - void establishedCommon( - AsynchIOHandler* async, - boost::shared_ptr poller, const SocketTransportOptions& opts, Timer* timer, - const Socket& s) - { - if (opts.tcpNoDelay) { - s.setTcpNoDelay(); - QPID_LOG(debug, "Set TCP_NODELAY on connection to " << s.getPeerAddress()); - } - - AsynchIO* aio = AsynchIO::create - (s, - boost::bind(&AsynchIOHandler::readbuff, async, _1, _2), - boost::bind(&AsynchIOHandler::eof, async, _1), - boost::bind(&AsynchIOHandler::disconnect, async, _1), - boost::bind(&AsynchIOHandler::closedSocket, async, _1, _2), - boost::bind(&AsynchIOHandler::nobuffs, async, _1), - boost::bind(&AsynchIOHandler::idle, async, _1)); - - async->init(aio, *timer, opts.maxNegotiateTime); - aio->start(poller); - } - - void establishedIncoming( - boost::shared_ptr poller, const SocketTransportOptions& opts, Timer* timer, - const Socket& s, ConnectionCodec::Factory* f) - { - AsynchIOHandler* async = new AsynchIOHandler(broker::QPID_NAME_PREFIX+s.getFullAddress(), f, false, opts.nodict); - establishedCommon(async, poller, opts, timer, s); - } - - void establishedOutgoing( - boost::shared_ptr poller, const SocketTransportOptions& opts, Timer* timer, - const Socket& s, ConnectionCodec::Factory* f, const std::string& name) - { - AsynchIOHandler* async = new AsynchIOHandler(name, f, true, opts.nodict); - establishedCommon(async, poller, opts, timer, s); - } - - void connectFailed( - const Socket& s, int ec, const std::string& emsg, - SocketConnector::ConnectFailedCallback failedCb) - { - failedCb(ec, emsg); - s.close(); - delete &s; - } - - // Expand list of Interfaces and addresses to a list of addresses - std::vector expandInterfaces(const std::vector& interfaces) { - std::vector addresses; - // If there are no specific interfaces listed use a single "" to listen on every interface - if (interfaces.empty()) { - addresses.push_back(""); - return addresses; - } - for (unsigned i = 0; i < interfaces.size(); ++i) { - const std::string& interface = interfaces[i]; - if (!(SystemInfo::getInterfaceAddresses(interface, addresses))) { - // We don't have an interface of that name - - // Check for IPv6 ('[' ']') brackets and remove them - // then pass to be looked up directly - if (interface[0]=='[' && interface[interface.size()-1]==']') { - addresses.push_back(interface.substr(1, interface.size()-2)); - } else { - addresses.push_back(interface); - } - } - } - return addresses; - } -} - -SocketAcceptor::SocketAcceptor(bool tcpNoDelay, bool nodict, uint32_t maxNegotiateTime, Timer& timer0) : - timer(timer0), - options(tcpNoDelay, nodict, maxNegotiateTime), - established(boost::bind(&establishedIncoming, _1, options, &timer, _2, _3)) -{} - -SocketAcceptor::SocketAcceptor(bool tcpNoDelay, bool nodict, uint32_t maxNegotiateTime, Timer& timer0, const EstablishedCallback& established0) : - timer(timer0), - options(tcpNoDelay, nodict, maxNegotiateTime), - established(established0) -{} - -void SocketAcceptor::addListener(Socket* socket) -{ - listeners.push_back(socket); -} - -uint16_t SocketAcceptor::listen(const std::vector& interfaces, uint16_t port, int backlog, const SocketFactory& factory) -{ - std::vector addresses = expandInterfaces(interfaces); - std::string sport(boost::lexical_cast(port)); - - if (addresses.empty()) { - // We specified some interfaces, but couldn't find addresses for them - QPID_LOG(warning, "TCP/TCP6: No specified network interfaces found: Not Listening"); - return 0; - } - - int listeningPort = 0; - for (unsigned i = 0; i s(factory()); - uint16_t lport = s->listen(sa, backlog); - QPID_LOG(debug, "Listened to: " << lport); - addListener(s.release()); - - if (listeningPort==0) listeningPort = lport; - } catch (std::exception& e) { - QPID_LOG(warning, "Couldn't listen to: " << sa.asString() << ": " << e.what()); - } - } while (sa.nextAddress()); - } - if (listeningPort==0) { - throw Exception("Couldn't find any network address to listen to"); - } - return listeningPort; -} - -void SocketAcceptor::accept(boost::shared_ptr poller, ConnectionCodec::Factory* f) -{ - for (unsigned i = 0; i poller, - const std::string& name, - const std::string& host, const std::string& port, - ConnectionCodec::Factory* fact, - ConnectFailedCallback failed) -{ - // Note that the following logic does not cause a memory leak. - // The allocated Socket is freed either by the AsynchConnector - // upon connection failure or by the AsynchIO upon connection - // shutdown. The allocated AsynchConnector frees itself when it - // is no longer needed. - Socket* socket = factory(); - try { - AsynchConnector* c = AsynchConnector::create( - *socket, - host, - port, - boost::bind(&establishedOutgoing, poller, options, &timer, _1, fact, name), - boost::bind(&connectFailed, _1, _2, _3, failed)); - c->start(poller); - } catch (std::exception&) { - // TODO: Design question - should we do the error callback and also throw? - int errCode = socket->getError(); - connectFailed(*socket, errCode, strError(errCode), failed); - throw; - } -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/SocketTransport.h b/qpid/cpp/src/qpid/sys/SocketTransport.h deleted file mode 100644 index 5aca52c372..0000000000 --- a/qpid/cpp/src/qpid/sys/SocketTransport.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef QPID_SYS_SOCKETTRANSPORT_H -#define QPID_SYS_SOCKETTRANSPORT_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/TransportFactory.h" - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/ConnectionCodec.h" -#include -#include - -namespace qpid { -namespace sys { - -class AsynchAcceptor; -class Poller; -class Timer; -class Socket; -typedef boost::function0 SocketFactory; -typedef boost::function3, const Socket&, ConnectionCodec::Factory*> EstablishedCallback; - -struct SocketTransportOptions { - bool tcpNoDelay; - bool nodict; - uint32_t maxNegotiateTime; - - SocketTransportOptions(bool t, bool d, uint32_t m) : - tcpNoDelay(t), - nodict(d), - maxNegotiateTime(m) - {} -}; - -class SocketAcceptor : public TransportAcceptor { - boost::ptr_vector listeners; - boost::ptr_vector acceptors; - Timer& timer; - SocketTransportOptions options; - const EstablishedCallback established; - -public: - SocketAcceptor(bool tcpNoDelay, bool nodict, uint32_t maxNegotiateTime, Timer& timer); - SocketAcceptor(bool tcpNoDelay, bool nodict, uint32_t maxNegotiateTime, Timer& timer, const EstablishedCallback& established); - - // Create sockets from list of interfaces and listen to them - uint16_t listen(const std::vector& interfaces, uint16_t port, int backlog, const SocketFactory& factory); - - // Import sockets that are already being listened to - void addListener(Socket* socket); - - void accept(boost::shared_ptr poller, ConnectionCodec::Factory* f); -}; - -class SocketConnector : public TransportConnector { - Timer& timer; - const SocketFactory factory; - SocketTransportOptions options; - -public: - SocketConnector(bool tcpNoDelay, bool nodict, uint32_t maxNegotiateTime, Timer& timer, const SocketFactory& factory); - - void connect(boost::shared_ptr poller, - const std::string& name, - const std::string& host, const std::string& port, - ConnectionCodec::Factory* f, - ConnectFailedCallback failed); -}; - -}} - -#endif diff --git a/qpid/cpp/src/qpid/sys/SslPlugin.cpp b/qpid/cpp/src/qpid/sys/SslPlugin.cpp deleted file mode 100644 index 0ec31b1e47..0000000000 --- a/qpid/cpp/src/qpid/sys/SslPlugin.cpp +++ /dev/null @@ -1,143 +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/sys/TransportFactory.h" - -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/SocketTransport.h" -#include "qpid/sys/ssl/util.h" -#include "qpid/sys/ssl/SslSocket.h" - -#include - -namespace qpid { -namespace sys { - -class Timer; - -using namespace qpid::sys::ssl; - -struct SslServerOptions : ssl::SslOptions -{ - uint16_t port; - bool clientAuth; - bool nodict; - - SslServerOptions() : port(5671), - clientAuth(false), - nodict(false) - { - addOptions() - ("ssl-port", optValue(port, "PORT"), "Port on which to listen for SSL connections") - ("ssl-require-client-authentication", optValue(clientAuth), - "Forces clients to authenticate in order to establish an SSL connection") - ("ssl-sasl-no-dict", optValue(nodict), - "Disables SASL mechanisms that are vulnerable to passive dictionary-based password attacks"); - } -}; - -namespace { - Socket* createServerSSLSocket(const SslServerOptions& options) { - return new SslSocket(options.certName, options.clientAuth); - } - - Socket* createServerSSLMuxSocket(const SslServerOptions& options) { - return new SslMuxSocket(options.certName, options.clientAuth); - } - - Socket* createClientSSLSocket() { - return new SslSocket(); - } - -} - -// Static instance to initialise plugin -static struct SslPlugin : public Plugin { - SslServerOptions options; - bool nssInitialized; - bool multiplex; - - Options* getOptions() { return &options; } - - SslPlugin() : nssInitialized(false), multiplex(false) {} - ~SslPlugin() { if (nssInitialized) ssl::shutdownNSS(); } - - void earlyInitialize(Target& target) { - broker::Broker* broker = dynamic_cast(&target); - if (broker && broker->shouldListen("ssl")) { - if (options.certDbPath.empty()) { - QPID_LOG(notice, "SSL plugin not enabled, you must set --ssl-cert-db to enable it."); - broker->disableListening("ssl"); - return; - } - - try { - ssl::initNSS(options, true); - nssInitialized = true; - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL plugin: " << e.what()); - broker->disableListening("ssl"); - return; - } - - if (broker->getPortOption() == options.port && // AMQP & AMQPS ports are the same - broker->getPortOption() != 0 && - broker->shouldListen("tcp")) { - multiplex = true; - broker->disableListening("tcp"); - } - } - } - - void initialize(Target& target) { - QPID_LOG(trace, "Initialising SSL plugin"); - broker::Broker* broker = dynamic_cast(&target); - // Only provide to a Broker - if (broker) { - uint16_t port = options.port; - TransportAcceptor::shared_ptr ta; - if (broker->shouldListen("ssl")) { - SocketAcceptor* sa = - new SocketAcceptor(broker->getTcpNoDelay(), options.nodict, broker->getMaxNegotiateTime(), broker->getTimer()); - port = sa->listen(broker->getListenInterfaces(), options.port, broker->getConnectionBacklog(), - multiplex ? - boost::bind(&createServerSSLMuxSocket, options) : - boost::bind(&createServerSSLSocket, options)); - if ( port!=0 ) { - ta.reset(sa); - QPID_LOG(notice, "Listening for " << - (multiplex ? "SSL or TCP" : "SSL") << - " connections on TCP/TCP6 port " << - port); - } - } - TransportConnector::shared_ptr tc( - new SocketConnector(broker->getTcpNoDelay(), options.nodict, broker->getMaxNegotiateTime(), broker->getTimer(), - &createClientSSLSocket)); - broker->registerTransport("ssl", ta, tc, port); - } - } -} sslPlugin; - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/StateMonitor.h b/qpid/cpp/src/qpid/sys/StateMonitor.h deleted file mode 100644 index eac37a8543..0000000000 --- a/qpid/cpp/src/qpid/sys/StateMonitor.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_SYS_STATEMONITOR_H -#define QPID_SYS_STATEMONITOR_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/Waitable.h" - -#include - -namespace qpid { -namespace sys { - -/** - * A monitor with an enum state value. - * - *@param Enum: enum type to use for states. - *@param EnumMax: Highest enum value. - */ -template -class StateMonitor : public Waitable -{ - public: - struct Set : public std::bitset { - Set() {} - Set(Enum s) { set(s); } - Set(Enum s, Enum t) { std::bitset::set(s).set(t); } - Set(Enum s, Enum t, Enum u) { std::bitset::set(s).set(t).set(u); } - Set(Enum s, Enum t, Enum u, Enum v) { std::bitset::set(s).set(t).set(u).set(v); } - }; - - - StateMonitor(Enum initial) { state=initial; } - - /** @pre Caller holds a ScopedLock. */ - void set(Enum s) { state=s; notifyAll(); } - /** @pre Caller holds a ScopedLock. */ - StateMonitor& operator=(Enum s) { set(s); return *this; } - - /** @pre Caller holds a ScopedLock. */ - Enum get() const { return state; } - /** @pre Caller holds a ScopedLock. */ - operator Enum() const { return state; } - - /** @pre Caller holds a ScopedLock */ - void waitFor(Enum s) { ScopedWait w(*this); while (s != state) wait(); } - /** @pre Caller holds a ScopedLock */ - void waitFor(Set s) { ScopedWait w(*this); while (!s.test(state)) wait(); } - /** @pre Caller holds a ScopedLock */ - void waitNot(Enum s) { ScopedWait w(*this); while (s == state) wait(); } - /** @pre Caller holds a ScopedLock */ - void waitNot(Set s) { ScopedWait w(*this); while (s.test(state)) wait(); } - - private: - Enum state; -}; - -}} - - -#endif /*!QPID_SYS_STATEMONITOR_H*/ diff --git a/qpid/cpp/src/qpid/sys/StrError.h b/qpid/cpp/src/qpid/sys/StrError.h deleted file mode 100644 index 36489dd0fc..0000000000 --- a/qpid/cpp/src/qpid/sys/StrError.h +++ /dev/null @@ -1,36 +0,0 @@ -#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 - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace sys { - -/** Get the error message for a system number err, e.g. errno. */ -QPID_COMMON_EXTERN std::string strError(int err); - -}} // namespace qpid - -#endif // _sys_StrError_h diff --git a/qpid/cpp/src/qpid/sys/SystemInfo.h b/qpid/cpp/src/qpid/sys/SystemInfo.h deleted file mode 100644 index 1b5720a5f0..0000000000 --- a/qpid/cpp/src/qpid/sys/SystemInfo.h +++ /dev/null @@ -1,109 +0,0 @@ -#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 - -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& 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& 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/TCPIOPlugin.cpp b/qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp deleted file mode 100644 index 9e240ad7e3..0000000000 --- a/qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp +++ /dev/null @@ -1,61 +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/sys/TransportFactory.h" - -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SocketTransport.h" - -namespace qpid { -namespace sys { - -// Static instance to initialise plugin -static class TCPIOPlugin : public Plugin { - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - broker::Broker* broker = dynamic_cast(&target); - // Only provide to a Broker - if (broker) { - uint16_t port = broker->getPortOption(); - TransportAcceptor::shared_ptr ta; - if (broker->shouldListen("tcp")) { - SocketAcceptor* aa = new SocketAcceptor(broker->getTcpNoDelay(), false, broker->getMaxNegotiateTime(), broker->getTimer()); - ta.reset(aa); - port = aa->listen(broker->getListenInterfaces(), port, broker->getConnectionBacklog(), &createSocket); - if ( port!=0 ) { - QPID_LOG(notice, "Listening on TCP/TCP6 port " << port); - } - } - - TransportConnector::shared_ptr tc(new SocketConnector(broker->getTcpNoDelay(), false, broker->getMaxNegotiateTime(), broker->getTimer(), &createSocket)); - - broker->registerTransport("tcp", ta, tc, port); - } - } -} tcpPlugin; - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/Thread.h b/qpid/cpp/src/qpid/sys/Thread.h deleted file mode 100644 index cb0a1adce6..0000000000 --- a/qpid/cpp/src/qpid/sys/Thread.h +++ /dev/null @@ -1,73 +0,0 @@ -#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 -#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 -#elif defined (__IBMCPP__) -# 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 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 deleted file mode 100644 index 8a82b5f826..0000000000 --- a/qpid/cpp/src/qpid/sys/Time.h +++ /dev/null @@ -1,181 +0,0 @@ -#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 -#include - -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. - * There is a specific way to construct a Duration since the Unix Epoch, - * 1970-1-1-00:00: - * - * int64_t nanosec_since_epoch = Duration::FromEpoch(); - * - * 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 epoch(); - QPID_COMMON_EXTERN static AbsTime FarFuture(); - QPID_COMMON_EXTERN static AbsTime Zero(); - - 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::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); - - /** Duration since the Unix epoch: 1970-01-01T00:00:00 */ - QPID_COMMON_EXTERN static Duration FromEpoch(); - - 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::max(); - -/** Absolute time zero point */ -const AbsTime ZERO = AbsTime::Zero(); - -/** 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/Timer.cpp b/qpid/cpp/src/qpid/sys/Timer.cpp deleted file mode 100644 index f8eef2c9ec..0000000000 --- a/qpid/cpp/src/qpid/sys/Timer.cpp +++ /dev/null @@ -1,235 +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/sys/Timer.h" -#include "qpid/sys/Mutex.h" -#include "qpid/log/Statement.h" - -#include - -using boost::intrusive_ptr; -using std::max; - -namespace qpid { -namespace sys { - -TimerTask::TimerTask(Duration timeout, const std::string& n) : - name(n), - sortTime(AbsTime::FarFuture()), - period(timeout), - nextFireTime(AbsTime::now(), timeout), - state(WAITING) -{} - -TimerTask::TimerTask(AbsTime time, const std::string& n) : - name(n), - sortTime(AbsTime::FarFuture()), - period(0), - nextFireTime(time), - state(WAITING) -{} - -TimerTask::~TimerTask() {} - -bool TimerTask::readyToFire() const { - return !(nextFireTime > AbsTime::now()); -} - -bool TimerTask::prepareToFire() { - Monitor::ScopedLock l(stateMonitor); - if (state != CANCELLED) { - state = CALLING; - return true; - } else { - return false; - } -} - -void TimerTask::fireTask() { - fire(); -} - -void TimerTask::finishFiring() { - Monitor::ScopedLock l(stateMonitor); - if (state != CANCELLED) { - state = WAITING; - stateMonitor.notifyAll(); - } -} - -// This can only be used to setup the next fire time. After the Timer has already fired -void TimerTask::setupNextFire() { - if (period && readyToFire()) { - nextFireTime = max(AbsTime::now(), AbsTime(nextFireTime, period)); - } else { - QPID_LOG(error, name << " couldn't setup next timer firing: " << Duration(nextFireTime, AbsTime::now()) << "[" << period << "]"); - } -} - -// Only allow tasks to be delayed -void TimerTask::restart() { - nextFireTime = max(nextFireTime, AbsTime(AbsTime::now(), period)); -} - -void TimerTask::cancel() { - Monitor::ScopedLock l(stateMonitor); - while (state == CALLING) { - stateMonitor.wait(); - } - state = CANCELLED; -} - -// TODO AStitcher 21/08/09 The threshholds for emitting warnings are a little arbitrary -Timer::Timer() : - active(false), - late(50 * TIME_MSEC), - overran(2 * TIME_MSEC), - lateCancel(500 * TIME_MSEC), - warn(60 * TIME_SEC) -{ - start(); -} - -Timer::~Timer() -{ - stop(); -} - -class TimerTaskCallbackScope { - TimerTask& tt; -public: - explicit TimerTaskCallbackScope(TimerTask& t) : - tt(t) - {} - - operator bool() { - return !tt.prepareToFire(); - } - - ~TimerTaskCallbackScope() { - tt.finishFiring(); - } -}; - -void Timer::run() -{ - Monitor::ScopedLock l(monitor); - while (active) { - if (tasks.empty()) { - monitor.wait(); - } else { - intrusive_ptr t = tasks.top(); - tasks.pop(); - assert(!(t->nextFireTime < t->sortTime)); - - // warn on extreme lateness - AbsTime start(AbsTime::now()); - Duration delay(t->sortTime, start); - { - TimerTaskCallbackScope s(*t); - if (s) { - if (delay > lateCancel) { - QPID_LOG(debug, t->name << " cancelled timer woken up " << - delay / TIME_MSEC << "ms late"); - } - continue; - } else if(Duration(t->nextFireTime, start) >= 0) { - { - Monitor::ScopedUnlock u(monitor); - fire(t); - } - // Warn if callback overran next timer's start. - AbsTime end(AbsTime::now()); - Duration overrun (0); - if (!tasks.empty()) { - overrun = Duration(tasks.top()->nextFireTime, end); - } - bool warningsEnabled; // TimerWarning enabled - QPID_LOG_TEST(debug, warningsEnabled); // TimerWarning emitted at debug level - if (warningsEnabled) { - if (overrun > overran) { - if (delay > overran) // if delay is significant to an overrun. - warn.lateAndOverran(t->name, delay, overrun, Duration(start, end)); - else - warn.overran(t->name, overrun, Duration(start, end)); - } - else if (delay > late) - warn.late(t->name, delay); - } - continue; - } else { - // If the timer was adjusted into the future it might no longer - // be the next event, so push and then get top to make sure - // You can only push events into the future - t->sortTime = t->nextFireTime; - tasks.push(t); - } - } - assert(!tasks.empty()); - monitor.wait(tasks.top()->sortTime); - } - } -} - -void Timer::add(intrusive_ptr task) -{ - Monitor::ScopedLock l(monitor); - task->sortTime = task->nextFireTime; - tasks.push(task); - monitor.notify(); -} - -void Timer::start() -{ - Monitor::ScopedLock l(monitor); - if (!active) { - active = true; - runner = Thread(this); - } -} - -void Timer::stop() -{ - { - Monitor::ScopedLock l(monitor); - if (!active) return; - active = false; - monitor.notifyAll(); - } - runner.join(); -} - -// Allow subclasses to override behavior when firing a task. -void Timer::fire(boost::intrusive_ptr t) { - try { - t->fireTask(); - } catch (const std::exception& e) { - QPID_LOG(error, "Exception thrown by timer task " << t->getName() << ": " << e.what()); - } -} - -bool operator<(const intrusive_ptr& a, - const intrusive_ptr& b) -{ - // Lower priority if time is later - return a.get() && b.get() && a->sortTime > b->sortTime; -} - -}} diff --git a/qpid/cpp/src/qpid/sys/Timer.h b/qpid/cpp/src/qpid/sys/Timer.h deleted file mode 100644 index 6281e08913..0000000000 --- a/qpid/cpp/src/qpid/sys/Timer.h +++ /dev/null @@ -1,166 +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. - * - */ -#ifndef sys_Timer -#define sys_Timer - -#include "qpid/sys/TimerWarnings.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/RefCounted.h" -#include "qpid/CommonImportExport.h" -#include -#include - -#include - -namespace qpid { -namespace sys { - -class Timer; - -class TimerTask : public RefCounted { - friend class Timer; - friend class TimerTaskCallbackScope; - friend bool operator<(const boost::intrusive_ptr&, - const boost::intrusive_ptr&); - - std::string name; - AbsTime sortTime; - Duration period; - AbsTime nextFireTime; - qpid::sys::Monitor stateMonitor; - enum {WAITING, CALLING, CANCELLED} state; - - bool prepareToFire(); - void finishFiring(); - bool readyToFire() const; - void fireTask(); - - public: - /** Create a periodic TimerTask - * - * This TimerTask type will trigger after the specified duration - * and can also be retriggered again after the same duration - * by using setupNextFire() after it has been fired. - * - * Before it has been triggered you can use restart() to push off - * triggering the TimerTask by the specified duration. - */ - QPID_COMMON_EXTERN TimerTask(Duration period, const std::string& name); - - /** Create a TimerTask that fires at a given absolute time - * - * This is a once only Timer and cannot be restarted after it has fired. - */ - QPID_COMMON_EXTERN TimerTask(AbsTime fireTime, const std::string& name); - - QPID_COMMON_EXTERN virtual ~TimerTask(); - - /** Adjust a periodic TimerTask for next firing time - * - * Called after a TimerTask has been triggered - probably in the fire() - * callback function itself. This will set up a TimerTask for the next - * triggering. - * - * Note that the TimerTask will need to be added again to the Timer. - */ - QPID_COMMON_EXTERN void setupNextFire(); - - /** Restart a TimerTask so to delay it being firing - * - * This can be called either with the TimerTask already added to a Timer - * or after the task has been triggered. It has the effect of delaying - * the task triggering by the initially specified duration. - */ - QPID_COMMON_EXTERN void restart(); - - /** Cancel a TimerTask so that it is no longer triggered - * - * After cancelling the only thing you can do nothing further - * with a TimerTask. - * - * The Timer will delete the cancelled TimerTask. - */ - QPID_COMMON_EXTERN void cancel(); - - std::string getName() const { return name; } - - protected: - // Must be overridden with callback - virtual void fire() = 0; -}; - -// For the priority_queue order -bool operator<(const boost::intrusive_ptr& a, - const boost::intrusive_ptr& b); - -class Timer : private Runnable { - qpid::sys::Monitor monitor; - std::priority_queue > tasks; - qpid::sys::Thread runner; - bool active; - - // Runnable interface - void run(); - - public: - QPID_COMMON_EXTERN Timer(); - QPID_COMMON_EXTERN virtual ~Timer(); - - /** Add an TimerTask to the Timer queue - * - * Once a TimerTask has been triggered by (calling its fire() function) - * the TimerTask is no longer on the Timer queue and needs to be added again. - * - * Note that TimerTasks must never be added more than once to a Timer - * and must never be added simultaneuosly to multiple Timers. - */ - QPID_COMMON_EXTERN virtual void add(boost::intrusive_ptr task); - - /** Start the Timer - * - * This will start a new thread that runs the Timer and the fire callbacks. - */ - QPID_COMMON_EXTERN virtual void start(); - - /** Stop the Timer - * - * This will stop the Timer and its thread. - */ - QPID_COMMON_EXTERN virtual void stop(); - - protected: - QPID_COMMON_EXTERN virtual void fire(boost::intrusive_ptr task); - - // Allow derived classes to change the late/overran thresholds. - Duration late; - Duration overran; - Duration lateCancel; - TimerWarnings warn; -}; - - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/sys/TimerWarnings.cpp b/qpid/cpp/src/qpid/sys/TimerWarnings.cpp deleted file mode 100644 index 00fb0d9db6..0000000000 --- a/qpid/cpp/src/qpid/sys/TimerWarnings.cpp +++ /dev/null @@ -1,82 +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 "TimerWarnings.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace sys { - -TimerWarnings::TimerWarnings(Duration reportInterval) : - interval(reportInterval), - nextReport(now(), reportInterval) -{} - -void TimerWarnings::late(const std::string& task, Duration delay) { - taskStats[task].lateDelay.add(delay); - log(); -} - -void TimerWarnings::overran(const std::string& task, Duration overrun, Duration time) -{ - taskStats[task].overranOverrun.add(overrun); - taskStats[task].overranTime.add(time); - log(); -} - -void TimerWarnings::lateAndOverran( - const std::string& task, Duration delay, Duration overrun, Duration time) -{ - taskStats[task].lateAndOverranDelay.add(delay); - taskStats[task].lateAndOverranOverrun.add(overrun); - taskStats[task].lateAndOverranTime.add(time); - log(); -} - -void TimerWarnings::log() { - if (!taskStats.empty() && nextReport < now()) { - for (TaskStatsMap::iterator i = taskStats.begin(); i != taskStats.end(); ++i) { - std::string task = i->first; - TaskStats& stats = i->second; - if (stats.lateDelay.count) - QPID_LOG(debug, task << " task late " - << stats.lateDelay.count << " times by " - << stats.lateDelay.average()/TIME_MSEC << "ms on average."); - - if (stats.overranOverrun.count) - QPID_LOG(debug, task << " task overran " - << stats.overranOverrun.count << " times by " - << stats.overranOverrun.average()/TIME_MSEC << "ms (taking " - << stats.overranTime.average() << "ns) on average."); - - if (stats.lateAndOverranOverrun.count) - QPID_LOG(debug, task << " task late and overran " - << stats.lateAndOverranOverrun.count << " times: late " - << stats.lateAndOverranDelay.average()/TIME_MSEC << "ms, overran " - << stats.lateAndOverranOverrun.average()/TIME_MSEC << "ms (taking " - << stats.lateAndOverranTime.average() << "ns) on average."); - - } - nextReport = AbsTime(now(), interval); - taskStats.clear(); - } -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/TimerWarnings.h b/qpid/cpp/src/qpid/sys/TimerWarnings.h deleted file mode 100644 index 337a434ab5..0000000000 --- a/qpid/cpp/src/qpid/sys/TimerWarnings.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef QPID_SYS_TIMERWARNINGS_H -#define QPID_SYS_TIMERWARNINGS_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" -#include -#include - -namespace qpid { -namespace sys { - -/** - * The Timer class logs warnings when timer tasks are late and/or overrun. - * - * It is too expensive to log a warning for every late/overrun - * incident, doing so aggravates the problem of tasks over-running and - * being late. - * - * This class collects statistical data about each incident and prints - * an aggregated report at regular intervals. - */ -class TimerWarnings -{ - public: - TimerWarnings(Duration reportInterval); - - void late(const std::string& task, Duration delay); - - void overran(const std::string& task, Duration overrun, Duration time); - - void lateAndOverran(const std::string& task, - Duration delay, Duration overrun, Duration time); - - private: - struct Statistic { - Statistic() : total(0), count(0) {} - void add(int64_t value) { total += value; ++count; } - int64_t average() const { return count ? total/count : 0; } - int64_t total; - int64_t count; - }; - - // Keep statistics for 3 classes of incident: late, overrun and both. - struct TaskStats { - Statistic lateDelay; // Just late - Statistic overranOverrun, overranTime; // Just overrun - // Both - Statistic lateAndOverranDelay, lateAndOverranOverrun, lateAndOverranTime; - }; - - typedef std::map TaskStatsMap; - - void log(); - - Duration interval; - AbsTime nextReport; - TaskStatsMap taskStats; -}; -}} // namespace qpid::sys - -#endif /*!QPID_SYS_TIMERWARNINGS_H*/ diff --git a/qpid/cpp/src/qpid/sys/TransportFactory.h b/qpid/cpp/src/qpid/sys/TransportFactory.h deleted file mode 100644 index 06aa168024..0000000000 --- a/qpid/cpp/src/qpid/sys/TransportFactory.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef QPID_SYS_TRANSPORTFACTORY_H -#define QPID_SYS_TRANSPORTFACTORY_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/SharedObject.h" -#include "qpid/sys/ConnectionCodec.h" -#include -#include -#include - -namespace qpid { -namespace sys { - -class AsynchAcceptor; -class Poller; -class Timer; - -class TransportAcceptor : public qpid::SharedObject -{ - public: - virtual ~TransportAcceptor() = 0; - virtual void accept(boost::shared_ptr, ConnectionCodec::Factory*) = 0; -}; - -inline TransportAcceptor::~TransportAcceptor() {} - -class TransportConnector : public qpid::SharedObject -{ -public: - typedef boost::function2 ConnectFailedCallback; - - virtual ~TransportConnector() = 0; - virtual void connect( - boost::shared_ptr, - const std::string& name, - const std::string& host, const std::string& port, - ConnectionCodec::Factory* codec, - ConnectFailedCallback failed) = 0; -}; - -inline TransportConnector::~TransportConnector() {} - -}} - -#endif diff --git a/qpid/cpp/src/qpid/sys/Waitable.h b/qpid/cpp/src/qpid/sys/Waitable.h deleted file mode 100644 index 56f71023c5..0000000000 --- a/qpid/cpp/src/qpid/sys/Waitable.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef QPID_SYS_WAITABLE_H -#define QPID_SYS_WAITABLE_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/Monitor.h" -#include "qpid/sys/ExceptionHolder.h" -#include - -namespace qpid { -namespace sys { - -/** - * A monitor that keeps track of waiting threads. Threads declare a - * ScopedWait around wait() inside a ScopedLock to be considered - * waiters. - * - * Allows waiting threads to be interrupted by an exception. - */ -class Waitable : public Monitor { - public: - Waitable() : waiters(0) {} - - ~Waitable() { assert(waiters == 0); } - - /** Use this inside a scoped lock around the - * call to wait() to be counted as a waiter. - */ - struct ScopedWait { - Waitable& w; - ScopedWait(Waitable& w_) : w(w_) { ++w.waiters; } - ~ScopedWait() { if (--w.waiters==0) w.notifyAll(); } - }; - - /** Block till there are no more waiters in ScopedWaits. - * waitWaiters() does not raise an exception even if waiters - * were interrupted by one. - *@pre Must be called inside a ScopedLock but NOT a ScopedWait. - */ - void waitWaiters() { - while (waiters != 0) - Monitor::wait(); - } - - /** Returns the number of outstanding ScopedWaits. - * Must be called with the lock held. - */ - size_t hasWaiters() const { - return waiters; - } - - /** Set an execption to interrupt waiters in ScopedWait. - * Must be called with the lock held. - */ - void setException(const ExceptionHolder& e) { - exception = e; - notifyAll(); - - } - - /** True if the waitable has an exception */ - bool hasException() const { return exception; } - - /** Throws if the waitable has an exception */ - void checkException() const { exception.raise(); } - - /** Clear the exception if any */ - void resetException() { exception.reset(); } - - /** Throws an exception if one is set before or during the wait. */ - void wait() { - exception.raise(); - Monitor::wait(); - exception.raise(); - } - - /** Throws an exception if one is set before or during the wait. */ - bool wait(const AbsTime& absoluteTime) { - exception.raise(); - bool result = Monitor::wait(absoluteTime); - exception.raise(); - return result; - } - - private: - size_t waiters; - ExceptionHolder exception; - - friend struct ScopedWait; -}; - -}} // namespace qpid::sys - - - -#endif /*!QPID_SYS_WAITABLE_H*/ diff --git a/qpid/cpp/src/qpid/sys/aix/SystemInfo.cpp b/qpid/cpp/src/qpid/sys/aix/SystemInfo.cpp deleted file mode 100644 index d28d9b7b37..0000000000 --- a/qpid/cpp/src/qpid/sys/aix/SystemInfo.cpp +++ /dev/null @@ -1,201 +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/log/Statement.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef HOST_NAME_MAX -# define HOST_NAME_MAX 256 -#endif - -using namespace std; - -namespace qpid { -namespace sys { - -long SystemInfo::concurrency() { - return sysconf(_SC_NPROCESSORS_ONLN); -} - -bool SystemInfo::getLocalHostname (Address &address) { - char name[HOST_NAME_MAX]; - if (::gethostname(name, sizeof(name)) != 0) - return false; - address.host = name; - return true; -} - -static const string LOOPBACK("127.0.0.1"); -static const string TCP("tcp"); - -// Test IPv4 address for loopback -inline bool IN_IS_ADDR_LOOPBACK(const ::in_addr* a) { - return ((ntohl(a->s_addr) & 0xff000000) == 0x7f000000); -} - -inline bool isLoopback(const ::sockaddr* addr) { - switch (addr->sa_family) { - case AF_INET: return IN_IS_ADDR_LOOPBACK(&((const ::sockaddr_in*)(const void*)addr)->sin_addr); - case AF_INET6: return IN6_IS_ADDR_LOOPBACK(&((const ::sockaddr_in6*)(const void*)addr)->sin6_addr); - default: return false; - } -} - -namespace { - class HandleCloser : public IOHandle { - public: - HandleCloser(int fd) : IOHandle(fd) {} - ~HandleCloser() { ::close(fd); fd = -1; } - }; - - inline bool isInetOrInet6(::sockaddr* sa) { - switch (sa->sa_family) { - case AF_INET: - case AF_INET6: - return true; - default: - return false; - } - } - - inline void *InetAddr(::sockaddr* sa) { - switch (sa->sa_family) { - case AF_INET: - return &(reinterpret_cast(sa)->sin_addr); - case AF_INET6: - return &(reinterpret_cast(sa)->sin6_addr); - default: - return 0; - } - } - - typedef std::map > InterfaceInfo; - std::map > cachedInterfaces; - - void cacheInterfaceInfo() { - int status = 0; - int handle = ::socket (PF_INET, SOCK_DGRAM, 0); - QPID_POSIX_CHECK(handle); - HandleCloser h(handle); - - size_t num_ifs = 0; - struct ifconf ifc; - status = ::ioctl(handle, SIOCGSIZIFCONF, (caddr_t)&ifc.ifc_len); - QPID_POSIX_CHECK(status); - - std::auto_ptr auto_ifc_buf(new char[ifc.ifc_len]); - memset (auto_ifc_buf.get(), 0, ifc.ifc_len); - - status = ::ioctl(handle, SIOCGIFCONF, (caddr_t)auto_ifc_buf.get()); - QPID_POSIX_CHECK(status); - - char *buf_start = auto_ifc_buf.get(); - char *buf_end = buf_start + ifc.ifc_len; - - for (char *ptr = buf_start; ptr < buf_end; ) { - struct ifreq *req = reinterpret_cast(ptr); - ptr += IFNAMSIZ; - ptr += req->ifr_addr.sa_len; - if (!strcmp("lo0", req->ifr_name) || !isInetOrInet6(&req->ifr_addr)) - continue; - char dots[INET6_ADDRSTRLEN]; - if (! ::inet_ntop(req->ifr_addr.sa_family, InetAddr(&req->ifr_addr), dots, sizeof(dots))) - throw QPID_POSIX_ERROR(errno); - std::string address(dots); - cachedInterfaces[req->ifr_name].push_back(address); - } - } -} - -bool SystemInfo::getInterfaceAddresses(const std::string& interface, std::vector& addresses) { - if ( cachedInterfaces.empty() ) cacheInterfaceInfo(); - InterfaceInfo::iterator i = cachedInterfaces.find(interface); - if ( i==cachedInterfaces.end() ) return false; - std::copy(i->second.begin(), i->second.end(), std::back_inserter(addresses)); - return true; -} - -void SystemInfo::getInterfaceNames(std::vector& names ) { - if ( cachedInterfaces.empty() ) cacheInterfaceInfo(); - - for (InterfaceInfo::const_iterator i = cachedInterfaces.begin(); i!=cachedInterfaces.end(); ++i) { - names.push_back(i->first); - } -} - -void SystemInfo::getSystemId (std::string &osName, - std::string &nodeName, - std::string &release, - std::string &version, - std::string &machine) -{ - struct utsname _uname; - if (uname (&_uname) == 0) - { - osName = _uname.sysname; - nodeName = _uname.nodename; - release = _uname.release; - version = _uname.version; - machine = _uname.machine; - } -} - -uint32_t SystemInfo::getProcessId() -{ - return (uint32_t) ::getpid(); -} - -uint32_t SystemInfo::getParentProcessId() -{ - return (uint32_t) ::getppid(); -} - -// AIX specific -string SystemInfo::getProcessName() -{ - struct procsinfo my_info; - pid_t my_pid = getpid(); - int status = getprocs(&my_info, sizeof(my_info), 0, 0, &my_pid, 1); - QPID_POSIX_CHECK(status); - std::string my_name(my_info.pi_comm); - return my_name; -} - -// Always true. Only Windows has exception cases. -bool SystemInfo::threadSafeShutdown() -{ - return true; -} - - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp b/qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp deleted file mode 100644 index 79d9d08a59..0000000000 --- a/qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp +++ /dev/null @@ -1,129 +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 -#include "qpid/sys/cyrus/CyrusSecurityLayer.h" -#include -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include - -namespace qpid { -namespace sys { -namespace cyrus { - -CyrusSecurityLayer::CyrusSecurityLayer(sasl_conn_t* c, uint16_t maxFrameSize, int ssf) : - SecurityLayer(ssf), conn(c), decrypted(0), decryptedSize(0), encrypted(0), encryptedSize(0), codec(0), maxInputSize(0), - decodeBuffer(maxFrameSize), encodeBuffer(maxFrameSize), encoded(0) -{ - const void* value(0); - int result = sasl_getprop(conn, SASL_MAXOUTBUF, &value); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL encode error: " << sasl_errdetail(conn))); - } - maxInputSize = *(reinterpret_cast(value)); -} - -size_t CyrusSecurityLayer::decode(const char* input, size_t size) -{ - size_t inStart = 0; - do { - size_t inSize = std::min(size - inStart, maxInputSize); - int result = sasl_decode(conn, input + inStart, inSize, &decrypted, &decryptedSize); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL decode error: " << sasl_errdetail(conn))); - } - inStart += inSize; - size_t copied = 0; - do { - size_t count = std::min(decryptedSize - copied, decodeBuffer.size - decodeBuffer.position); - ::memcpy(decodeBuffer.data + decodeBuffer.position, decrypted + copied, count); - copied += count; - decodeBuffer.position += count; - size_t decodedSize = codec->decode(decodeBuffer.data, decodeBuffer.position); - if (decodedSize == 0) break; - if (decodedSize < decodeBuffer.position) { - ::memmove(decodeBuffer.data, decodeBuffer.data + decodedSize, decodeBuffer.position - decodedSize); - } - decodeBuffer.position -= decodedSize; - } while (copied < decryptedSize); - } while (inStart < size); - return size; -} - -size_t CyrusSecurityLayer::encode(char* buffer, size_t size) -{ - size_t processed = 0;//records how many bytes have been written to buffer - do { - if (!encrypted) { - if (!encoded) { - encodeBuffer.position = 0; - encoded = codec->encode(encodeBuffer.data, encodeBuffer.size); - if (!encoded) break;//nothing more to do - } - - size_t encryptable = std::min(encoded, maxInputSize); - int result = sasl_encode(conn, encodeBuffer.data + encodeBuffer.position, encryptable, &encrypted, &encryptedSize); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL encode error: " << sasl_errdetail(conn))); - } - encodeBuffer.position += encryptable; - encoded -= encryptable; - } - size_t remaining = size - processed; - if (remaining < encryptedSize) { - //can't fit all encrypted data in the buffer we've - //been given, copy in what we can and hold on to the - //rest until the next call - ::memcpy(buffer + processed, encrypted, remaining); - processed += remaining; - encrypted += remaining; - encryptedSize -= remaining; - } else { - ::memcpy(buffer + processed, encrypted, encryptedSize); - processed += encryptedSize; - encrypted = 0; - encryptedSize = 0; - } - } while (processed < size); - return processed; -} - -bool CyrusSecurityLayer::canEncode() -{ - return codec && (encrypted || codec->canEncode()); -} - -void CyrusSecurityLayer::init(qpid::sys::Codec* c) -{ - codec = c; -} - -CyrusSecurityLayer::DataBuffer::DataBuffer(size_t s) : position(0), size(s) -{ - data = new char[size]; -} - -CyrusSecurityLayer::DataBuffer::~DataBuffer() -{ - delete[] data; -} - -}}} // namespace qpid::sys::cyrus diff --git a/qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h b/qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h deleted file mode 100644 index ae86ba5569..0000000000 --- a/qpid/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_SYS_CYRUS_CYRUSSECURITYLAYER_H -#define QPID_SYS_CYRUS_CYRUSSECURITYLAYER_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/sys/SecurityLayer.h" -#include - -namespace qpid { -namespace sys { -namespace cyrus { - - -/** - * Implementation of SASL security layer using cyrus-sasl library - */ -class CyrusSecurityLayer : public qpid::sys::SecurityLayer -{ - public: - CyrusSecurityLayer(sasl_conn_t*, uint16_t maxFrameSize, int ssf); - size_t decode(const char* buffer, size_t size); - size_t encode(char* buffer, size_t size); - bool canEncode(); - void init(qpid::sys::Codec*); - private: - struct DataBuffer - { - char* data; - size_t position; - const size_t size; - DataBuffer(size_t); - ~DataBuffer(); - }; - - sasl_conn_t* conn; - const char* decrypted; - unsigned decryptedSize; - const char* encrypted; - unsigned encryptedSize; - qpid::sys::Codec* codec; - size_t maxInputSize; - DataBuffer decodeBuffer; - DataBuffer encodeBuffer; - size_t encoded; -}; -}}} // namespace qpid::sys::cyrus - -#endif /*!QPID_SYS_CYRUS_CYRUSSECURITYLAYER_H*/ diff --git a/qpid/cpp/src/qpid/sys/epoll/EpollPoller.cpp b/qpid/cpp/src/qpid/sys/epoll/EpollPoller.cpp deleted file mode 100644 index 6fdf99637f..0000000000 --- a/qpid/cpp/src/qpid/sys/epoll/EpollPoller.cpp +++ /dev/null @@ -1,677 +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/sys/Poller.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/AtomicCount.h" -#include "qpid/sys/DeletionManager.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/log/Statement.h" - -#include -#include -#include - -#include -#include -#include -#include - -namespace qpid { -namespace sys { - -// Deletion manager to handle deferring deletion of PollerHandles to when they definitely aren't being used -DeletionManager PollerHandleDeletionManager; - -// Instantiate (and define) class static for DeletionManager -template <> -DeletionManager::AllThreadsStatuses DeletionManager::allThreadsStatuses(0); - -class PollerHandlePrivate { - friend class Poller; - friend class PollerPrivate; - friend class PollerHandle; - - enum FDStat { - ABSENT, - MONITORED, - INACTIVE, - HUNGUP, - MONITORED_HUNGUP, - INTERRUPTED, - INTERRUPTED_HUNGUP, - DELETED - }; - - ::__uint32_t events; - const IOHandle* ioHandle; - PollerHandle* pollerHandle; - FDStat stat; - Mutex lock; - - PollerHandlePrivate(const IOHandle* h, PollerHandle* p) : - events(0), - ioHandle(h), - pollerHandle(p), - stat(ABSENT) { - } - - int fd() const { - return ioHandle->fd; - } - - bool isActive() const { - return stat == MONITORED || stat == MONITORED_HUNGUP; - } - - void setActive() { - stat = (stat == HUNGUP || stat == INTERRUPTED_HUNGUP) - ? MONITORED_HUNGUP - : MONITORED; - } - - bool isInactive() const { - return stat == INACTIVE || stat == HUNGUP; - } - - void setInactive() { - stat = INACTIVE; - } - - bool isIdle() const { - return stat == ABSENT; - } - - void setIdle() { - stat = ABSENT; - } - - bool isHungup() const { - return - stat == MONITORED_HUNGUP || - stat == HUNGUP || - stat == INTERRUPTED_HUNGUP; - } - - void setHungup() { - assert(stat == MONITORED); - stat = HUNGUP; - } - - bool isInterrupted() const { - return stat == INTERRUPTED || stat == INTERRUPTED_HUNGUP; - } - - void setInterrupted() { - stat = (stat == MONITORED_HUNGUP || stat == HUNGUP) - ? INTERRUPTED_HUNGUP - : INTERRUPTED; - } - - bool isDeleted() const { - return stat == DELETED; - } - - void setDeleted() { - stat = DELETED; - } -}; - -PollerHandle::PollerHandle(const IOHandle& h) : - impl(new PollerHandlePrivate(&h, this)) -{} - -PollerHandle::~PollerHandle() { - { - ScopedLock l(impl->lock); - if (impl->isDeleted()) { - return; - } - impl->pollerHandle = 0; - if (impl->isInterrupted()) { - impl->setDeleted(); - return; - } - assert(impl->isIdle()); - impl->setDeleted(); - } - PollerHandleDeletionManager.markForDeletion(impl); -} - -class HandleSet -{ - Mutex lock; - std::set handles; - public: - void add(PollerHandle*); - void remove(PollerHandle*); - void cleanup(); -}; - -void HandleSet::add(PollerHandle* h) -{ - ScopedLock l(lock); - handles.insert(h); -} -void HandleSet::remove(PollerHandle* h) -{ - ScopedLock l(lock); - handles.erase(h); -} -void HandleSet::cleanup() -{ - // Inform all registered handles of disconnection - std::set copy; - handles.swap(copy); - for (std::set::const_iterator i = copy.begin(); i != copy.end(); ++i) { - Poller::Event event(*i, Poller::DISCONNECTED); - event.process(); - } -} - -/** - * Concrete implementation of Poller to use the Linux specific epoll - * interface - */ -class PollerPrivate { - friend class Poller; - - static const int DefaultFds = 256; - - struct ReadablePipe { - int fds[2]; - - /** - * This encapsulates an always readable pipe which we can add - * to the epoll set to force epoll_wait to return - */ - ReadablePipe() { - QPID_POSIX_CHECK(::pipe(fds)); - // Just write the pipe's fds to the pipe - QPID_POSIX_CHECK(::write(fds[1], fds, 2)); - } - - ~ReadablePipe() { - ::close(fds[0]); - ::close(fds[1]); - } - - int getFD() { - return fds[0]; - } - }; - - ReadablePipe alwaysReadable; - int alwaysReadableFd; - - class InterruptHandle: public PollerHandle { - std::queue handles; - - void processEvent(Poller::EventType) { - PollerHandle* handle = handles.front(); - handles.pop(); - assert(handle); - - // Synthesise event - Poller::Event event(handle, Poller::INTERRUPTED); - - // Process synthesised event - event.process(); - } - - public: - InterruptHandle() : - PollerHandle(DummyIOHandle) - {} - - void addHandle(PollerHandle& h) { - handles.push(&h); - } - - PollerHandle* getHandle() { - PollerHandle* handle = handles.front(); - handles.pop(); - return handle; - } - - bool queuedHandles() { - return handles.size() > 0; - } - }; - - const int epollFd; - bool isShutdown; - InterruptHandle interruptHandle; - HandleSet registeredHandles; - AtomicCount threadCount; - - static ::__uint32_t directionToEpollEvent(Poller::Direction dir) { - switch (dir) { - case Poller::INPUT: return ::EPOLLIN; - case Poller::OUTPUT: return ::EPOLLOUT; - case Poller::INOUT: return ::EPOLLIN | ::EPOLLOUT; - default: return 0; - } - } - - static Poller::EventType epollToDirection(::__uint32_t events) { - // POLLOUT & POLLHUP are mutually exclusive really, but at least socketpairs - // can give you both! - events = (events & ::EPOLLHUP) ? events & ~::EPOLLOUT : events; - ::__uint32_t e = events & (::EPOLLIN | ::EPOLLOUT); - switch (e) { - case ::EPOLLIN: return Poller::READABLE; - case ::EPOLLOUT: return Poller::WRITABLE; - case ::EPOLLIN | ::EPOLLOUT: return Poller::READ_WRITABLE; - default: - return (events & (::EPOLLHUP | ::EPOLLERR)) ? - Poller::DISCONNECTED : Poller::INVALID; - } - } - - PollerPrivate() : - alwaysReadableFd(alwaysReadable.getFD()), - epollFd(::epoll_create(DefaultFds)), - isShutdown(false) { - QPID_POSIX_CHECK(epollFd); - // Add always readable fd into our set (but not listening to it yet) - ::epoll_event epe; - epe.events = 0; - epe.data.u64 = 1; - QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_ADD, alwaysReadableFd, &epe)); - } - - ~PollerPrivate() { - // It's probably okay to ignore any errors here as there can't be data loss - ::close(epollFd); - - // Need to put the interruptHandle in idle state to delete it - static_cast(interruptHandle).impl->setIdle(); - } - - void resetMode(PollerHandlePrivate& handle); - - void interrupt() { - ::epoll_event epe; - // Use EPOLLONESHOT so we only wake a single thread - epe.events = ::EPOLLIN | ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &static_cast(interruptHandle); - QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_MOD, alwaysReadableFd, &epe)); - } - - void interruptAll() { - ::epoll_event epe; - // Not EPOLLONESHOT, so we eventually get all threads - epe.events = ::EPOLLIN; - epe.data.u64 = 2; // Keep valgrind happy - QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_MOD, alwaysReadableFd, &epe)); - } -}; - -void Poller::registerHandle(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(eh.isIdle()); - - ::epoll_event epe; - epe.events = ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - - impl->registeredHandles.add(&handle); - QPID_POSIX_CHECK(::epoll_ctl(impl->epollFd, EPOLL_CTL_ADD, eh.fd(), &epe)); - - eh.setActive(); -} - -void Poller::unregisterHandle(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(!eh.isIdle()); - - impl->registeredHandles.remove(&handle); - int rc = ::epoll_ctl(impl->epollFd, EPOLL_CTL_DEL, eh.fd(), 0); - // Ignore EBADF since deleting a nonexistent fd has the overall required result! - // And allows the case where a sloppy program closes the fd and then does the delFd() - if (rc == -1 && errno != EBADF) { - QPID_POSIX_CHECK(rc); - } - - eh.setIdle(); -} - -void PollerPrivate::resetMode(PollerHandlePrivate& eh) { - PollerHandle* ph; - { - ScopedLock l(eh.lock); - assert(!eh.isActive()); - - if (eh.isIdle() || eh.isDeleted()) { - return; - } - - if (eh.events==0) { - eh.setActive(); - return; - } - - if (!eh.isInterrupted()) { - ::epoll_event epe; - epe.events = eh.events | ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - - int rc = ::epoll_ctl(epollFd, EPOLL_CTL_MOD, eh.fd(), &epe); - // If something has closed the fd in the meantime try adding it back - if (rc ==-1 && errno == ENOENT) { - eh.setIdle(); // Reset our handle as if starting from scratch - rc = ::epoll_ctl(epollFd, EPOLL_CTL_ADD, eh.fd(), &epe); - } - QPID_POSIX_CHECK(rc); - - eh.setActive(); - return; - } - ph = eh.pollerHandle; - } - - PollerHandlePrivate& ihp = *static_cast(interruptHandle).impl; - ScopedLock l(ihp.lock); - interruptHandle.addHandle(*ph); - ihp.setActive(); - interrupt(); -} - -void Poller::monitorHandle(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(!eh.isIdle()); - - ::__uint32_t oldEvents = eh.events; - eh.events |= PollerPrivate::directionToEpollEvent(dir); - - // If no change nothing more to do - avoid unnecessary system call - if (oldEvents==eh.events) { - return; - } - - // If we're not actually listening wait till we are to perform change - if (!eh.isActive()) { - return; - } - - ::epoll_event epe; - epe.events = eh.events | ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - - QPID_POSIX_CHECK(::epoll_ctl(impl->epollFd, EPOLL_CTL_MOD, eh.fd(), &epe)); -} - -void Poller::unmonitorHandle(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(!eh.isIdle()); - - ::__uint32_t oldEvents = eh.events; - eh.events &= ~PollerPrivate::directionToEpollEvent(dir); - - // If no change nothing more to do - avoid unnecessary system call - if (oldEvents==eh.events) { - return; - } - - // If we're not actually listening wait till we are to perform change - if (!eh.isActive()) { - return; - } - - ::epoll_event epe; - epe.events = eh.events | ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - - QPID_POSIX_CHECK(::epoll_ctl(impl->epollFd, EPOLL_CTL_MOD, eh.fd(), &epe)); -} - -void Poller::shutdown() { - // NB: this function must be async-signal safe, it must not - // call any function that is not async-signal safe. - - // Allow sloppy code to shut us down more than once - if (impl->isShutdown) - return; - - // Don't use any locking here - isShutdown will be visible to all - // after the epoll_ctl() anyway (it's a memory barrier) - impl->isShutdown = true; - - impl->interruptAll(); -} - -bool Poller::interrupt(PollerHandle& handle) { - { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - if (eh.isIdle() || eh.isDeleted()) { - return false; - } - - if (eh.isInterrupted()) { - return true; - } - - // Stop monitoring handle for read or write - ::epoll_event epe; - epe.events = 0; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - QPID_POSIX_CHECK(::epoll_ctl(impl->epollFd, EPOLL_CTL_MOD, eh.fd(), &epe)); - - if (eh.isInactive()) { - eh.setInterrupted(); - return true; - } - eh.setInterrupted(); - } - - PollerPrivate::InterruptHandle& ih = impl->interruptHandle; - PollerHandlePrivate& eh = *static_cast(ih).impl; - ScopedLock l(eh.lock); - ih.addHandle(handle); - - impl->interrupt(); - eh.setActive(); - return true; -} - -void Poller::run() { - // Ensure that we exit thread responsibly under all circumstances - try { - // Make sure we can't be interrupted by signals at a bad time - ::sigset_t ss; - ::sigfillset(&ss); - ::pthread_sigmask(SIG_SETMASK, &ss, 0); - - ++(impl->threadCount); - do { - Event event = wait(); - - // If can read/write then dispatch appropriate callbacks - if (event.handle) { - event.process(); - } else { - // Handle shutdown - switch (event.type) { - case SHUTDOWN: - PollerHandleDeletionManager.destroyThreadState(); - //last thread to respond to shutdown cleans up: - if (--(impl->threadCount) == 0) impl->registeredHandles.cleanup(); - return; - default: - // This should be impossible - assert(false); - } - } - } while (true); - } catch (const std::exception& e) { - QPID_LOG(error, "IO worker thread exiting with unhandled exception: " << e.what()); - } - PollerHandleDeletionManager.destroyThreadState(); - --(impl->threadCount); -} - -bool Poller::hasShutdown() -{ - return impl->isShutdown; -} - -Poller::Event Poller::wait(Duration timeout) { - static __thread PollerHandlePrivate* lastReturnedHandle = 0; - epoll_event epe; - int timeoutMs = (timeout == TIME_INFINITE) ? -1 : timeout / TIME_MSEC; - AbsTime targetTimeout = - (timeout == TIME_INFINITE) ? - FAR_FUTURE : - AbsTime(now(), timeout); - - if (lastReturnedHandle) { - impl->resetMode(*lastReturnedHandle); - lastReturnedHandle = 0; - } - - // Repeat until we weren't interrupted by signal - do { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - int rc = ::epoll_wait(impl->epollFd, &epe, 1, timeoutMs); - if (rc ==-1 && errno != EINTR) { - QPID_POSIX_CHECK(rc); - } else if (rc > 0) { - assert(rc == 1); - void* dataPtr = epe.data.ptr; - - // Check if this is an interrupt - PollerPrivate::InterruptHandle& interruptHandle = impl->interruptHandle; - if (dataPtr == &interruptHandle) { - // If we are shutting down we need to rearm the shutdown interrupt to - // ensure everyone still sees it. It's okay that this might be overridden - // below as we will be back here if it is. - if (impl->isShutdown) { - impl->interruptAll(); - } - PollerHandle* wrappedHandle = 0; - { - ScopedLock l(interruptHandle.impl->lock); - if (interruptHandle.impl->isActive()) { - wrappedHandle = interruptHandle.getHandle(); - // If there is an interrupt queued behind this one we need to arm it - // We do it this way so that another thread can pick it up - if (interruptHandle.queuedHandles()) { - impl->interrupt(); - interruptHandle.impl->setActive(); - } else { - interruptHandle.impl->setInactive(); - } - } - } - if (wrappedHandle) { - PollerHandlePrivate& eh = *wrappedHandle->impl; - { - ScopedLock l(eh.lock); - if (!eh.isDeleted()) { - if (!eh.isIdle()) { - eh.setInactive(); - } - lastReturnedHandle = &eh; - assert(eh.pollerHandle == wrappedHandle); - return Event(wrappedHandle, INTERRUPTED); - } - } - PollerHandleDeletionManager.markForDeletion(&eh); - } - continue; - } - - // Check for shutdown - if (impl->isShutdown) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, SHUTDOWN); - } - - PollerHandlePrivate& eh = *static_cast(dataPtr); - ScopedLock l(eh.lock); - - // the handle could have gone inactive since we left the epoll_wait - if (eh.isActive()) { - PollerHandle* handle = eh.pollerHandle; - assert(handle); - - // If the connection has been hungup we could still be readable - // (just not writable), allow us to readable until we get here again - if (epe.events & ::EPOLLHUP) { - if (eh.isHungup()) { - eh.setInactive(); - // Don't set up last Handle so that we don't reset this handle - // on re-entering Poller::wait. This means that we will never - // be set active again once we've returned disconnected, and so - // can never be returned again. - return Event(handle, DISCONNECTED); - } - eh.setHungup(); - } else { - eh.setInactive(); - } - lastReturnedHandle = &eh; - return Event(handle, PollerPrivate::epollToDirection(epe.events)); - } - } - // We only get here if one of the following: - // * epoll_wait was interrupted by a signal - // * epoll_wait timed out - // * the state of the handle changed after being returned by epoll_wait - // - // The only things we can do here are return a timeout or wait more. - // Obviously if we timed out we return timeout; if the wait was meant to - // be indefinite then we should never return with a time out so we go again. - // If the wait wasn't indefinite, we check whether we are after the target wait - // time or not - if (timeoutMs == -1) { - continue; - } - if (rc == 0 && now() > targetTimeout) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, TIMEOUT); - } - } while (true); -} - -// Concrete constructors -Poller::Poller() : - impl(new PollerPrivate()) -{} - -Poller::~Poller() { - delete impl; -} - -}} diff --git a/qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp b/qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp deleted file mode 100644 index a05e66f545..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp +++ /dev/null @@ -1,655 +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/sys/AsynchIO.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Probes.h" -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/Time.h" -#include "qpid/log/Statement.h" - -// TODO The basic algorithm here is not really POSIX specific and with a -// bit more abstraction could (should) be promoted to be platform portable -// - The POSIX specific code here is ignoring SIGPIPE which should really -// be part of the socket code. -// - And checking errno to detect specific read/write conditions. -// -#include -#include - -#include -#include -#include - -namespace qpid { -namespace sys { -namespace posix { - -namespace { - -struct StaticInit { - StaticInit() { - /** - * Make *process* not generate SIGPIPE when writing to closed - * pipe/socket (necessary as default action is to terminate process) - */ - ::signal(SIGPIPE, SIG_IGN); - }; -} init; - -/* - * We keep per thread state to avoid locking overhead. The assumption is that - * on average all the connections are serviced by all the threads so the state - * recorded in each thread is about the same. If this turns out not to be the - * case we could rebalance the info occasionally. - */ -__thread int threadReadTotal = 0; -__thread int threadReadCount = 0; -__thread int threadWriteTotal = 0; -__thread int threadWriteCount = 0; -__thread int64_t threadMaxIoTimeNs = 2 * 1000000; // start at 2ms -} - -/* - * Asynch Acceptor - */ -class AsynchAcceptor : public qpid::sys::AsynchAcceptor { -public: - AsynchAcceptor(const Socket& s, AsynchAcceptor::Callback callback); - ~AsynchAcceptor(); - void start(Poller::shared_ptr poller); - -private: - void readable(DispatchHandle& handle); - -private: - AsynchAcceptor::Callback acceptedCallback; - DispatchHandle handle; - const Socket& socket; - -}; - -AsynchAcceptor::AsynchAcceptor(const Socket& s, - AsynchAcceptor::Callback callback) : - acceptedCallback(callback), - handle((const IOHandle&)s, boost::bind(&AsynchAcceptor::readable, this, _1), 0, 0), - socket(s) { - - s.setNonblocking(); -} - -AsynchAcceptor::~AsynchAcceptor() { - handle.stopWatch(); -} - -void AsynchAcceptor::start(Poller::shared_ptr poller) { - handle.startWatch(poller); -} - -/* - * We keep on accepting as long as there is something to accept - */ -void AsynchAcceptor::readable(DispatchHandle& h) { - Socket* s; - do { - errno = 0; - // TODO: Currently we ignore the peers address, perhaps we should - // log it or use it for connection acceptance. - try { - s = socket.accept(); - if (s) { - acceptedCallback(*s); - } else { - break; - } - } catch (const std::exception& e) { - QPID_LOG(error, "Could not accept socket: " << e.what()); - break; - } - } while (true); - - h.rewatch(); -} - -/* - * POSIX version of AsynchIO TCP socket connector. - * - * The class is implemented in terms of DispatchHandle to allow it to be - * deleted by deleting the contained DispatchHandle. - */ -class AsynchConnector : public qpid::sys::AsynchConnector, - private DispatchHandle { - -private: - void connComplete(DispatchHandle& handle); - void requestedCall(RequestCallback rCb); - -private: - ConnectedCallback connCallback; - FailedCallback failCallback; - const Socket& socket; - SocketAddress sa; - -public: - AsynchConnector(const Socket& socket, - const std::string& hostname, - const std::string& port, - ConnectedCallback connCb, - FailedCallback failCb); - void start(Poller::shared_ptr poller); - void stop(); - void requestCallback(RequestCallback rCb); -}; - -AsynchConnector::AsynchConnector(const Socket& s, - const std::string& hostname, - const std::string& port, - ConnectedCallback connCb, - FailedCallback failCb) : - DispatchHandle((const IOHandle&)s, - 0, - boost::bind(&AsynchConnector::connComplete, this, _1), - boost::bind(&AsynchConnector::connComplete, this, _1)), - connCallback(connCb), - failCallback(failCb), - socket(s), - sa(hostname, port) -{ - socket.setNonblocking(); - - // Note, not catching any exceptions here, also has effect of destructing - QPID_LOG(info, "Connecting: " << sa.asString()); - socket.connect(sa); -} - -void AsynchConnector::start(Poller::shared_ptr poller) -{ - startWatch(poller); -} - -void AsynchConnector::stop() -{ - stopWatch(); -} - -void AsynchConnector::requestCallback(RequestCallback callback) { - // TODO creating a function object every time isn't all that - // efficient - if this becomes heavily used do something better (what?) - assert(callback); - DispatchHandle::call(boost::bind(&AsynchConnector::requestedCall, this, callback)); -} - -void AsynchConnector::requestedCall(RequestCallback callback) { - assert(callback); - callback(*this); -} - -void AsynchConnector::connComplete(DispatchHandle& h) -{ - int errCode = socket.getError(); - if (errCode == 0) { - h.stopWatch(); - try { - socket.finishConnect(sa); - } catch (const std::exception& e) { - failCallback(socket, 0, e.what()); - DispatchHandle::doDelete(); - return; - } - connCallback(socket); - } else { - // Retry while we cause an immediate exception - // (asynch failure will be handled by re-entering here at the top) - while (sa.nextAddress()) { - try { - // Try next address without deleting ourselves - QPID_LOG(debug, "Ignored socket connect error: " << strError(errCode)); - QPID_LOG(info, "Retrying connect: " << sa.asString()); - socket.connect(sa); - return; - } catch (const std::exception& e) { - QPID_LOG(debug, "Ignored socket connect exception: " << e.what()); - } - errCode = socket.getError(); - } - h.stopWatch(); - failCallback(socket, errCode, strError(errCode)); - } - DispatchHandle::doDelete(); -} - -/* - * POSIX version of AsynchIO reader/writer - * - * The class is implemented in terms of DispatchHandle to allow it to be - * deleted by deleting the contained DispatchHandle. - */ -class AsynchIO : public qpid::sys::AsynchIO, private DispatchHandle { - -public: - AsynchIO(const Socket& s, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0); - - // Methods inherited from qpid::sys::AsynchIO - - virtual void queueForDeletion(); - - virtual void start(Poller::shared_ptr poller); - virtual void createBuffers(uint32_t size); - virtual void queueReadBuffer(BufferBase* buff); - virtual void unread(BufferBase* buff); - virtual void queueWrite(BufferBase* buff); - virtual void notifyPendingWrite(); - virtual void queueWriteClose(); - virtual bool writeQueueEmpty(); - virtual void requestCallback(RequestCallback); - virtual BufferBase* getQueuedBuffer(); - virtual SecuritySettings getSecuritySettings(); - -private: - ~AsynchIO(); - - // Methods that are callback targets from Dispatcher. - void readable(DispatchHandle& handle); - void writeable(DispatchHandle& handle); - void disconnected(DispatchHandle& handle); - void requestedCall(RequestCallback); - void close(DispatchHandle& handle); - -private: - ReadCallback readCallback; - EofCallback eofCallback; - DisconnectCallback disCallback; - ClosedCallback closedCallback; - BuffersEmptyCallback emptyCallback; - IdleCallback idleCallback; - const Socket& socket; - std::deque bufferQueue; - std::deque writeQueue; - std::vector buffers; - boost::shared_array bufferMemory; - bool queuedClose; - /** - * This flag is used to detect and handle concurrency between - * calls to notifyPendingWrite() (which can be made from any thread) and - * the execution of the writeable() method (which is always on the - * thread processing this handle. - */ - volatile bool writePending; -}; - -AsynchIO::AsynchIO(const Socket& s, - ReadCallback rCb, EofCallback eofCb, DisconnectCallback disCb, - ClosedCallback cCb, BuffersEmptyCallback eCb, IdleCallback iCb) : - - DispatchHandle((const IOHandle&)s, - boost::bind(&AsynchIO::readable, this, _1), - boost::bind(&AsynchIO::writeable, this, _1), - boost::bind(&AsynchIO::disconnected, this, _1)), - readCallback(rCb), - eofCallback(eofCb), - disCallback(disCb), - closedCallback(cCb), - emptyCallback(eCb), - idleCallback(iCb), - socket(s), - queuedClose(false), - writePending(false) { - - s.setNonblocking(); -} - -AsynchIO::~AsynchIO() { -} - -void AsynchIO::queueForDeletion() { - DispatchHandle::doDelete(); -} - -void AsynchIO::start(Poller::shared_ptr poller) { - DispatchHandle::startWatch(poller); -} - -void AsynchIO::createBuffers(uint32_t size) { - // Allocate all the buffer memory at once - bufferMemory.reset(new char[size*BufferCount]); - - // Create the Buffer structs in a vector - // And push into the buffer queue - buffers.reserve(BufferCount); - for (uint32_t i = 0; i < BufferCount; i++) { - buffers.push_back(BufferBase(&bufferMemory[i*size], size)); - queueReadBuffer(&buffers[i]); - } -} - -void AsynchIO::queueReadBuffer(BufferBase* buff) { - assert(buff); - buff->dataStart = 0; - buff->dataCount = 0; - - bool queueWasEmpty = bufferQueue.empty(); - bufferQueue.push_back(buff); - if (queueWasEmpty) - DispatchHandle::rewatchRead(); -} - -void AsynchIO::unread(BufferBase* buff) { - assert(buff); - buff->squish(); - - bool queueWasEmpty = bufferQueue.empty(); - bufferQueue.push_front(buff); - if (queueWasEmpty) - DispatchHandle::rewatchRead(); -} - -void AsynchIO::queueWrite(BufferBase* buff) { - assert(buff); - // If we've already closed the socket then throw the write away - if (queuedClose) { - queueReadBuffer(buff); - return; - } else { - writeQueue.push_front(buff); - } - writePending = false; - DispatchHandle::rewatchWrite(); -} - -// This can happen outside the callback context -void AsynchIO::notifyPendingWrite() { - writePending = true; - DispatchHandle::rewatchWrite(); -} - -void AsynchIO::queueWriteClose() { - queuedClose = true; - DispatchHandle::rewatchWrite(); -} - -bool AsynchIO::writeQueueEmpty() { - return writeQueue.empty(); -} - -void AsynchIO::requestCallback(RequestCallback callback) { - // TODO creating a function object every time isn't all that - // efficient - if this becomes heavily used do something better (what?) - assert(callback); - DispatchHandle::call(boost::bind(&AsynchIO::requestedCall, this, callback)); -} - -void AsynchIO::requestedCall(RequestCallback callback) { - assert(callback); - callback(*this); -} - -/** Return a queued buffer if there are enough - * to spare - */ -AsynchIO::BufferBase* AsynchIO::getQueuedBuffer() { - BufferBase* buff = bufferQueue.empty() ? 0 : bufferQueue.back(); - // An "unread" buffer is reserved for future read operations (which - // take from the front of the queue). - if (!buff || (buff->dataCount && bufferQueue.size() == 1)) { - QPID_LOG(error, "No IO buffers available"); - return 0; - } - assert(buff->dataCount == 0); - bufferQueue.pop_back(); - return buff; -} - -/* - * We keep on reading as long as we have something to read, a buffer - * to put it in and reading is not stopped by flow control. - */ -void AsynchIO::readable(DispatchHandle& h) { - AbsTime readStartTime = AbsTime::now(); - size_t total = 0; - int readCalls = 0; - do { - // (Try to) get a buffer - if (!bufferQueue.empty()) { - // Read into buffer - BufferBase* buff = bufferQueue.front(); - assert(buff); - bufferQueue.pop_front(); - errno = 0; - int readCount = buff->byteCount-buff->dataCount; - int rc = socket.read(buff->bytes + buff->dataCount, readCount); - ++readCalls; - if (rc > 0) { - buff->dataCount += rc; - threadReadTotal += rc; - total += rc; - - readCallback(*this, buff); - int64_t duration = Duration(readStartTime, AbsTime::now()); - if (rc != readCount) { - // If we didn't fill the read buffer then time to stop reading - QPID_PROBE4(asynchio_read_finished_done, &h, duration, total, readCalls); - break; - } - - // Stop reading if we've overrun our timeslot - if ( duration > threadMaxIoTimeNs) { - QPID_PROBE4(asynchio_read_finished_maxtime, &h, duration, total, readCalls); - break; - } - - } else { - // Put buffer back (at front so it doesn't interfere with unread buffers) - bufferQueue.push_front(buff); - assert(buff); - - QPID_PROBE5(asynchio_read_finished_error, &h, Duration(readStartTime, AbsTime::now()), total, readCalls, errno); - // Eof or other side has gone away - if (rc == 0 || errno == ECONNRESET) { - eofCallback(*this); - h.unwatchRead(); - break; - } else if (errno == EAGAIN) { - // We have just put a buffer back so we know - // we can carry on watching for reads - break; - } else { - // Report error then just treat as a socket disconnect - QPID_LOG(error, "Error reading socket: " << socket.lastErrorCodeText() ); - eofCallback(*this); - h.unwatchRead(); - break; - } - } - } else { - // Something to read but no buffer - if (emptyCallback) { - emptyCallback(*this); - } - // If we still have no buffers we can't do anything more - if (bufferQueue.empty()) { - h.unwatchRead(); - QPID_PROBE4(asynchio_read_finished_nobuffers, &h, Duration(readStartTime, AbsTime::now()), total, readCalls); - break; - } - - } - } while (true); - - ++threadReadCount; - return; -} - -/* - * We carry on writing whilst we have data to write and we can write - */ -void AsynchIO::writeable(DispatchHandle& h) { - AbsTime writeStartTime = AbsTime::now(); - size_t total = 0; - int writeCalls = 0; - do { - // See if we've got something to write - if (!writeQueue.empty()) { - // Write buffer - BufferBase* buff = writeQueue.back(); - writeQueue.pop_back(); - errno = 0; - assert(buff->dataStart+buff->dataCount <= buff->byteCount); - int rc = socket.write(buff->bytes+buff->dataStart, buff->dataCount); - int64_t duration = Duration(writeStartTime, AbsTime::now()); - ++writeCalls; - if (rc >= 0) { - threadWriteTotal += rc; - total += rc; - - // If we didn't write full buffer put rest back - if (rc != buff->dataCount) { - buff->dataStart += rc; - buff->dataCount -= rc; - writeQueue.push_back(buff); - QPID_PROBE4(asynchio_write_finished_done, &h, duration, total, writeCalls); - break; - } - - // Recycle the buffer - queueReadBuffer(buff); - - // Stop writing if we've overrun our timeslot - if (duration > threadMaxIoTimeNs) { - QPID_PROBE4(asynchio_write_finished_maxtime, &h, duration, total, writeCalls); - break; - } - } else { - // Put buffer back - writeQueue.push_back(buff); - QPID_PROBE5(asynchio_write_finished_error, &h, duration, total, writeCalls, errno); - - if (errno == ECONNRESET || errno == EPIPE) { - // Just stop watching for write here - we'll get a - // disconnect callback soon enough - h.unwatchWrite(); - break; - } else if (errno == EAGAIN) { - // We have just put a buffer back so we know - // we can carry on watching for writes - break; - } else { - // Report error then just treat as a socket disconnect - QPID_LOG(error, "Error writing socket: " << socket.lastErrorCodeText() ); - h.unwatchWrite(); - break; - } - } - } else { - int64_t duration = Duration(writeStartTime, AbsTime::now()); - (void) duration; // force duration to be used if no probes are compiled - - // If we're waiting to close the socket then can do it now as there is nothing to write - if (queuedClose) { - close(h); - QPID_PROBE4(asynchio_write_finished_closed, &h, duration, total, writeCalls); - break; - } - // Fd is writable, but nothing to write - if (idleCallback) { - writePending = false; - idleCallback(*this); - } - // If we still have no buffers to write we can't do anything more - if (writeQueue.empty() && !writePending && !queuedClose) { - h.unwatchWrite(); - // The following handles the case where writePending is - // set to true after the test above; in this case its - // possible that the unwatchWrite overwrites the - // desired rewatchWrite so we correct that here - if (writePending) - h.rewatchWrite(); - QPID_PROBE4(asynchio_write_finished_nodata, &h, duration, total, writeCalls); - break; - } - } - } while (true); - - ++threadWriteCount; - return; -} - -void AsynchIO::disconnected(DispatchHandle& h) { - // If we have not already queued close then call disconnected callback before closing - if (!queuedClose && disCallback) disCallback(*this); - close(h); -} - -/* - * Close the socket and callback to say we've done it - */ -void AsynchIO::close(DispatchHandle& h) { - h.stopWatch(); - socket.close(); - if (closedCallback) { - closedCallback(*this, socket); - } -} - -SecuritySettings AsynchIO::getSecuritySettings() { - SecuritySettings settings; - settings.ssf = socket.getKeyLen(); - settings.authid = socket.getPeerAuthId(); - return settings; -} - -} // namespace posix - -AsynchAcceptor* AsynchAcceptor::create(const Socket& s, - Callback callback) -{ - return new posix::AsynchAcceptor(s, callback); -} - -AsynchConnector* AsynchConnector::create(const Socket& s, - const std::string& hostname, - const std::string& port, - ConnectedCallback connCb, - FailedCallback failCb) -{ - return new posix::AsynchConnector(s, hostname, port, connCb, failCb); -} - -AsynchIO* AsynchIO::create(const Socket& s, - AsynchIO::ReadCallback rCb, - AsynchIO::EofCallback eofCb, - AsynchIO::DisconnectCallback disCb, - AsynchIO::ClosedCallback cCb, - AsynchIO::BuffersEmptyCallback eCb, - AsynchIO::IdleCallback iCb) -{ - return new posix::AsynchIO(s, rCb, eofCb, disCb, cCb, eCb, iCb); -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/BSDSocket.cpp b/qpid/cpp/src/qpid/sys/posix/BSDSocket.cpp deleted file mode 100644 index 12066642ac..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/BSDSocket.cpp +++ /dev/null @@ -1,284 +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/sys/posix/BSDSocket.h" - -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace sys { - -namespace { -std::string getName(int fd, bool local) -{ - ::sockaddr_storage name_s; // big enough for any socket address - ::sockaddr* name = (::sockaddr*)&name_s; - ::socklen_t namelen = sizeof(name_s); - - if (local) { - QPID_POSIX_CHECK( ::getsockname(fd, name, &namelen) ); - } else { - QPID_POSIX_CHECK( ::getpeername(fd, name, &namelen) ); - } - - return SocketAddress::asString(name, namelen); -} - -uint16_t getLocalPort(int fd) -{ - ::sockaddr_storage name_s; // big enough for any socket address - ::sockaddr* name = (::sockaddr*)&name_s; - ::socklen_t namelen = sizeof(name_s); - - QPID_POSIX_CHECK( ::getsockname(fd, name, &namelen) ); - - return SocketAddress::getPort(name); -} -} - -BSDSocket::BSDSocket() : - handle(new IOHandle), - fd(-1), - lastErrorCode(0), - nonblocking(false), - nodelay(false) -{} - -Socket* createSocket() -{ - return new BSDSocket; -} - -BSDSocket::BSDSocket(int fd0) : - handle(new IOHandle(fd0)), - fd(fd0), - lastErrorCode(0), - nonblocking(false), - nodelay(false) -{} - -BSDSocket::~BSDSocket() -{} - -BSDSocket::operator const IOHandle&() const -{ - return *handle; -} - -void BSDSocket::createSocket(const SocketAddress& sa) const -{ - int& socket = fd; - if (socket != -1) BSDSocket::close(); - int s = ::socket(getAddrInfo(sa).ai_family, getAddrInfo(sa).ai_socktype, 0); - if (s < 0) throw QPID_POSIX_ERROR(errno); - socket = s; - *handle = IOHandle(s); - - try { - if (nonblocking) setNonblocking(); - if (nodelay) setTcpNoDelay(); - if (getAddrInfo(sa).ai_family == AF_INET6) { - int flag = 1; - int result = ::setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&flag, sizeof(flag)); - QPID_POSIX_CHECK(result); - } - } catch (std::exception&) { - ::close(s); - socket = -1; - *handle = IOHandle(); - throw; - } -} - -void BSDSocket::setNonblocking() const { - int& socket = fd; - nonblocking = true; - if (socket != -1) { - QPID_POSIX_CHECK(::fcntl(socket, F_SETFL, O_NONBLOCK)); - } -} - -void BSDSocket::setTcpNoDelay() const -{ - int& socket = fd; - nodelay = true; - if (socket != -1) { - int flag = 1; - int result = ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); - QPID_POSIX_CHECK(result); - } -} - -void BSDSocket::connect(const SocketAddress& addr) const -{ - // The display name for an outbound connection needs to be the name that was specified - // for the address rather than a resolved IP address as we don't know which of - // the IP addresses is actually the one that will be connected to. - peername = addr.asString(false); - - // However the string we compare with the local port must be numeric or it might not - // match when it should as getLocalAddress() will always be numeric - std::string connectname = addr.asString(); - - createSocket(addr); - - const int& socket = fd; - // TODO the correct thing to do here is loop on failure until you've used all the returned addresses - if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) < 0) && - (errno != EINPROGRESS)) { - throw Exception(QPID_MSG(strError(errno) << ": " << peername)); - } - // When connecting to a port on the same host which no longer has - // a process associated with it, the OS occasionally chooses the - // remote port (which is unoccupied) as the port to bind the local - // end of the socket, resulting in a "circular" connection. - // - // Raise an error if we see such a connection, since we know there is - // no listener on the peer address. - // - if (getLocalAddress() == connectname) { - close(); - throw Exception(QPID_MSG("Connection refused: " << peername)); - } -} - -void BSDSocket::finishConnect(const SocketAddress&) const -{ -} - -void -BSDSocket::close() const -{ - int& socket = fd; - if (socket == -1) return; - if (::close(socket) < 0) throw QPID_POSIX_ERROR(errno); - socket = -1; - *handle = IOHandle(); -} - -int BSDSocket::listen(const SocketAddress& sa, int backlog) const -{ - createSocket(sa); - - const int& socket = fd; - int yes=1; - QPID_POSIX_CHECK(::setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes))); - - if (::bind(socket, getAddrInfo(sa).ai_addr, getAddrInfo(sa).ai_addrlen) < 0) - throw Exception(QPID_MSG("Can't bind to port " << sa.asString() << ": " << strError(errno))); - if (::listen(socket, backlog) < 0) - throw Exception(QPID_MSG("Can't listen on port " << sa.asString() << ": " << strError(errno))); - - return getLocalPort(socket); -} - -Socket* BSDSocket::accept() const -{ - int afd = ::accept(fd, 0, 0); - if ( afd >= 0) { - BSDSocket* s = new BSDSocket(afd); - s->localname = localname; - return s; - } - else if (errno == EAGAIN) - return 0; - else throw QPID_POSIX_ERROR(errno); -} - -std::string BSDSocket::lastErrorCodeText() const -{ - std::stringstream s; - s << strError(lastErrorCode); - s << "(" << lastErrorCode << ")"; - return s.str(); -} - -int BSDSocket::read(void *buf, size_t count) const -{ - int rc = ::read(fd, buf, count); - lastErrorCode = errno; - return rc; -} - -int BSDSocket::write(const void *buf, size_t count) const -{ - int rc = ::write(fd, buf, count); - lastErrorCode = errno; - return rc; -} - -std::string BSDSocket::getPeerAddress() const -{ - if (peername.empty()) { - peername = getName(fd, false); - } - return peername; -} - -std::string BSDSocket::getLocalAddress() const -{ - if (localname.empty()) { - localname = getName(fd, true); - } - return localname; -} - -int BSDSocket::getError() const -{ - int result; - socklen_t rSize = sizeof (result); - - if (::getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &rSize) < 0) - throw QPID_POSIX_ERROR(errno); - - return result; -} - -int BSDSocket::getKeyLen() const -{ - return 0; -} - -std::string BSDSocket::getPeerAuthId() const -{ - return std::string(); -} - -std::string BSDSocket::getLocalAuthId() const -{ - return "dummy"; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/BSDSocket.h b/qpid/cpp/src/qpid/sys/posix/BSDSocket.h deleted file mode 100644 index e8373f6df9..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/BSDSocket.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef QPID_SYS_BSDSOCKET_H -#define QPID_SYS_BSDSOCKET_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/Socket.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/CommonImportExport.h" -#include - -#include - -namespace qpid { -namespace sys { - -class Duration; -class IOHandle; -class SocketAddress; - -namespace ssl { -class SslMuxSocket; -} - -class QPID_COMMON_CLASS_EXTERN BSDSocket : public Socket -{ -public: - /** Create a socket wrapper for descriptor. */ - QPID_COMMON_EXTERN BSDSocket(); - - /** Construct socket with existing fd (posix specific and not in Socket interface) */ - QPID_COMMON_EXTERN BSDSocket(int fd); - - QPID_COMMON_EXTERN virtual ~BSDSocket(); - - QPID_COMMON_EXTERN operator const IOHandle&() const; - - QPID_COMMON_EXTERN virtual void setNonblocking() const; - QPID_COMMON_EXTERN virtual void setTcpNoDelay() const; - - QPID_COMMON_EXTERN std::string getPeerAddress() const; - QPID_COMMON_EXTERN std::string getLocalAddress() const; - - QPID_COMMON_EXTERN int getError() const; - QPID_COMMON_EXTERN virtual std::string lastErrorCodeText() const; - - QPID_COMMON_EXTERN virtual void connect(const SocketAddress&) const; - QPID_COMMON_EXTERN virtual void finishConnect(const SocketAddress&) const; - QPID_COMMON_EXTERN virtual int listen(const SocketAddress&, int backlog = 10) const; - QPID_COMMON_EXTERN virtual Socket* accept() const; - QPID_COMMON_EXTERN virtual int read(void *buf, size_t count) const; - QPID_COMMON_EXTERN virtual int write(const void *buf, size_t count) const; - QPID_COMMON_EXTERN virtual void close() const; - - QPID_COMMON_EXTERN virtual int getKeyLen() const; - QPID_COMMON_EXTERN virtual std::string getPeerAuthId() const; - QPID_COMMON_EXTERN virtual std::string getLocalAuthId() const; - -protected: - /** Create socket */ - void createSocket(const SocketAddress&) const; - - mutable boost::scoped_ptr handle; - mutable std::string localname; - mutable std::string peername; - mutable int fd; - mutable int lastErrorCode; - mutable bool nonblocking; - mutable bool nodelay; -}; - -}} -#endif /*!QPID_SYS_BSDSOCKET_H*/ diff --git a/qpid/cpp/src/qpid/sys/posix/Condition.cpp b/qpid/cpp/src/qpid/sys/posix/Condition.cpp deleted file mode 100644 index f629e50cd7..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Condition.cpp +++ /dev/null @@ -1,45 +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 "Condition.h" - -namespace qpid { -namespace sys { - -namespace { - -struct ClockMonotonicAttr { - ::pthread_condattr_t attr; - - ClockMonotonicAttr() { - QPID_POSIX_ASSERT_THROW_IF(pthread_condattr_init(&attr)); - QPID_POSIX_ASSERT_THROW_IF(pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)); - } -}; - -} - -Condition::Condition() { - static ClockMonotonicAttr attr; - QPID_POSIX_ASSERT_THROW_IF(pthread_cond_init(&condition, &attr.attr)); -} - -}} diff --git a/qpid/cpp/src/qpid/sys/posix/Condition.h b/qpid/cpp/src/qpid/sys/posix/Condition.h deleted file mode 100644 index 66f95d5fc8..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Condition.h +++ /dev/null @@ -1,82 +0,0 @@ -#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 -#include -#include - -namespace qpid { -namespace sys { - -/** - * A condition variable for thread synchronization. - */ -class Condition -{ - public: - Condition(); - ~Condition(); - void wait(Mutex&); - bool wait(Mutex&, const AbsTime& absoluteTime); - void notify(); - void notifyAll(); - - private: - pthread_cond_t condition; -}; - -inline Condition::~Condition() { - QPID_POSIX_ABORT_IF(pthread_cond_destroy(&condition)); -} - -inline void Condition::wait(Mutex& mutex) { - QPID_POSIX_ASSERT_THROW_IF(pthread_cond_wait(&condition, &mutex.mutex)); -} - -inline bool Condition::wait(Mutex& mutex, const AbsTime& absoluteTime){ - struct timespec ts; - toTimespec(ts, 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; -} - -inline void Condition::notify(){ - QPID_POSIX_ASSERT_THROW_IF(pthread_cond_signal(&condition)); -} - -inline 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/FileSysDir.cpp b/qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp deleted file mode 100755 index cec580164d..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * 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/FileSysDir.h" -#include "qpid/sys/StrError.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace sys { - -bool FileSysDir::exists (void) const -{ - const char *cpath = dirPath.c_str (); - struct stat s; - if (::stat(cpath, &s)) { - if (errno == ENOENT) { - return false; - } - throw qpid::Exception (strError(errno) + - ": Can't check directory: " + dirPath); - } - if (S_ISDIR(s.st_mode)) - return true; - throw qpid::Exception(dirPath + " is not a directory"); -} - -void FileSysDir::mkdir(void) -{ - if (::mkdir(dirPath.c_str(), 0755)) - throw Exception ("Can't create directory: " + dirPath); -} - -void FileSysDir::forEachFile(Callback cb) const { - - ::dirent** namelist; - - int n = scandir(dirPath.c_str(), &namelist, 0, alphasort); - if (n == -1) throw Exception (strError(errno) + ": Can't scan directory: " + dirPath); - - for (int i = 0; id_name; - // Filter out non files/stat problems etc. - struct ::stat s; - // Can't throw here without leaking memory, so just do nothing with - // entries for which stat() fails. - if (!::stat(fullpath.c_str(), &s)) { - if (S_ISREG(s.st_mode)) { - cb(fullpath); - } - } - ::free(namelist[i]); - } - ::free(namelist); -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/Fork.cpp b/qpid/cpp/src/qpid/sys/posix/Fork.cpp deleted file mode 100644 index a0d404a16e..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Fork.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * 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/Fork.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace sys { - -using namespace std; - -namespace { - -void writeStr(int fd, const std::string& str) { - const char* WRITE_ERR = "Error writing to parent process"; - int size = str.size(); - if (int(sizeof(size)) > ::write(fd, &size, sizeof(size))) throw ErrnoException(WRITE_ERR); - if (size > ::write(fd, str.data(), size)) throw ErrnoException(WRITE_ERR); -} - -string readStr(int fd) { - string value; - const char* READ_ERR = "Error reading from forked process"; - int size; - if (int(sizeof(size)) > ::read(fd, &size, sizeof(size))) throw ErrnoException(READ_ERR); - if (size > 0) { // Read string message - value.resize(size); - if (size > ::read(fd, const_cast(value.data()), size)) throw ErrnoException(READ_ERR); - } - return value; -} - -} // namespace - -Fork::Fork() {} -Fork::~Fork() {} - -void Fork::fork() { - pid_t pid = ::fork(); - if (pid < 0) throw ErrnoException("Failed to fork the process"); - if (pid == 0) child(); - else parent(pid); -} - -ForkWithMessage::ForkWithMessage() { - pipeFds[0] = pipeFds[1] = -1; -} - -struct AutoCloseFd { - int fd; - AutoCloseFd(int d) : fd(d) {} - ~AutoCloseFd() { ::close(fd); } -}; - -void ForkWithMessage::fork() { - if(::pipe(pipeFds) < 0) throw ErrnoException("Can't create pipe"); - pid_t pid = ::fork(); - if(pid < 0) throw ErrnoException("Fork fork failed"); - if (pid == 0) { // Child - AutoCloseFd ac(pipeFds[1]); // Write side. - ::close(pipeFds[0]); // Read side - try { - child(); - } - catch (const std::exception& e) { - QPID_LOG(error, "Error in forked child: " << e.what()); - std::string msg = e.what(); - if (msg.empty()) msg = " "; // Make sure we send a non-empty error string. - writeStr(pipeFds[1], msg); - } - } - else { // Parent - close(pipeFds[1]); // Write side. - AutoCloseFd ac(pipeFds[0]); // Read side - parent(pid); - } -} - -string ForkWithMessage::wait(int timeout) { // parent waits for child. - errno = 0; - struct timeval tv; - tv.tv_sec = timeout; - tv.tv_usec = 0; - - fd_set fds; - FD_ZERO(&fds); - FD_SET(pipeFds[0], &fds); - int n=select(FD_SETSIZE, &fds, 0, 0, &tv); - if(n<0) throw ErrnoException("Error waiting for fork"); - if (n==0) throw Exception("Timed out waiting for fork"); - - string error = readStr(pipeFds[0]); - if (error.empty()) return readStr(pipeFds[0]); - else throw Exception("Error in forked process: " + error); -} - -// Write empty error string followed by value string to pipe. -void ForkWithMessage::ready(const string& value) { // child - // Write empty string for error followed by value. - writeStr(pipeFds[1], string()); // No error - writeStr(pipeFds[1], value); -} - - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/Fork.h b/qpid/cpp/src/qpid/sys/posix/Fork.h deleted file mode 100644 index 698c61ed30..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Fork.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef QPID_SYS_POSIX_FORK_H -#define QPID_SYS_POSIX_FORK_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 -#include - -namespace qpid { -namespace sys { - -/** - * Fork the process. Call parent() in parent and child() in child. - */ -class Fork { - public: - Fork(); - virtual ~Fork(); - - /** - * Fork the process. - * Calls parent() in the parent process, child() in the child. - */ - virtual void fork(); - - protected: - - /** Called in parent process. - *@child pid of child process - */ - virtual void parent(pid_t child) = 0; - - /** Called in child process */ - virtual void child() = 0; -}; - -/** - * Like Fork but also allows the child to send a string message - * or throw an exception to the parent. - */ -class ForkWithMessage : public Fork { - public: - ForkWithMessage(); - void fork(); - - protected: - /** Call from parent(): wait for child to send a value or throw exception. - * @timeout in seconds to wait for response. - * @return value passed by child to ready(). - */ - std::string wait(int timeout); - - /** Call from child(): Send a value to the parent. - *@param value returned by parent call to wait(). - */ - void ready(const std::string& value); - - private: - int pipeFds[2]; -}; - -}} // namespace qpid::sys - - - -#endif /*!QPID_SYS_POSIX_FORK_H*/ diff --git a/qpid/cpp/src/qpid/sys/posix/IOHandle.cpp b/qpid/cpp/src/qpid/sys/posix/IOHandle.cpp deleted file mode 100644 index d3f502a63c..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/IOHandle.cpp +++ /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. - * - */ - -#include "qpid/sys/posix/PrivatePosix.h" - -namespace qpid { -namespace sys { - -NullIOHandle DummyIOHandle; - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/LockFile.cpp b/qpid/cpp/src/qpid/sys/posix/LockFile.cpp deleted file mode 100755 index 9fdf83f1bd..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/LockFile.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * 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/LockFile.h" -#include "qpid/sys/posix/PidFile.h" - -#include -#include -#include -#include -#include - -#include "qpid/sys/posix/check.h" - -namespace qpid { -namespace sys { - -class LockFilePrivate { - friend class LockFile; - friend class PidFile; - - int fd; - -public: - LockFilePrivate(int f) : fd(f) {} -}; - -LockFile::LockFile(const std::string& path_, bool create) - : path(path_), created(create) { - - errno = 0; - int flags=create ? O_WRONLY|O_CREAT|O_NOFOLLOW : O_RDWR; - int fd = ::open(path.c_str(), flags, 0644); - if (fd < 0) throw ErrnoException("Cannot open lock file " + path, errno); - if (::lockf(fd, F_TLOCK, 0) < 0) { - ::close(fd); - throw ErrnoException("Cannot lock " + path, errno); - } - impl.reset(new LockFilePrivate(fd)); -} - -LockFile::~LockFile() { - if (impl) { - int f = impl->fd; - if (f >= 0) { - if(::lockf(f, F_ULOCK, 0)) {} // Suppress warnings about ignoring return value. - ::close(f); - impl->fd = -1; - } - } -} - -int LockFile::read(void* bytes, size_t len) const { - if (!impl) - throw Exception("Lock file not open: " + path); - - ssize_t rc = ::read(impl->fd, bytes, len); - if ((ssize_t)len > rc) { - throw Exception("Cannot read lock file: " + path); - } - return rc; -} - -int LockFile::write(void* bytes, size_t len) const { - if (!impl) - throw Exception("Lock file not open: " + path); - - ssize_t rc = ::write(impl->fd, bytes, len); - if ((ssize_t)len > rc) { - throw Exception("Cannot write lock file: " + path); - } - return rc; -} - -PidFile::PidFile(const std::string& path_, bool create): - LockFile(path_, create) -{} - -pid_t PidFile::readPid(void) const { - pid_t pid; - int desired_read = sizeof(pid_t); - read(&pid, desired_read); - return pid; -} - -void PidFile::writePid(void) { - pid_t pid = getpid(); - int desired_write = sizeof(pid_t); - write(&pid, desired_write); -} - -}} /* namespace qpid::sys */ diff --git a/qpid/cpp/src/qpid/sys/posix/MemStat.cpp b/qpid/cpp/src/qpid/sys/posix/MemStat.cpp deleted file mode 100644 index 2fbf119cab..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/MemStat.cpp +++ /dev/null @@ -1,38 +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/sys/MemStat.h" - -#include - -void qpid::sys::MemStat::loadMemInfo(qmf::org::apache::qpid::broker::Memory* object) -{ - struct mallinfo info(mallinfo()); - - object->set_malloc_arena(info.arena); - object->set_malloc_ordblks(info.ordblks); - object->set_malloc_hblks(info.hblks); - object->set_malloc_hblkhd(info.hblkhd); - object->set_malloc_uordblks(info.uordblks); - object->set_malloc_fordblks(info.fordblks); - object->set_malloc_keepcost(info.keepcost); -} - diff --git a/qpid/cpp/src/qpid/sys/posix/MemoryMappedFile.cpp b/qpid/cpp/src/qpid/sys/posix/MemoryMappedFile.cpp deleted file mode 100644 index b4292aa4bc..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/MemoryMappedFile.cpp +++ /dev/null @@ -1,125 +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/sys/MemoryMappedFile.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include -#include -#include -#include - -namespace qpid { -namespace sys { -namespace { -const std::string PAGEFILE_PREFIX("pf_"); -const std::string PATH_SEPARATOR("/"); -const std::string ESCAPE("%"); -const std::string VALID("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-."); -std::string getFileName(const std::string& name, const std::string& dir) -{ - std::stringstream filename; - if (dir.size()) filename << dir << PATH_SEPARATOR << PAGEFILE_PREFIX; - size_t start = 0; - while (true) { - size_t i = name.find_first_not_of(VALID, start); - if (i == std::string::npos) { - filename << name.substr(start); - return filename.str(); - } else { - if (i > start) filename << name.substr(start, i-start); - filename << ESCAPE << (int) name.at(i); - start = i+1; - } - } - -} -} - -class MemoryMappedFilePrivate -{ - friend class MemoryMappedFile; - std::string path; - int fd; - MemoryMappedFilePrivate() : fd(0) {} -}; -MemoryMappedFile::MemoryMappedFile() : state(new MemoryMappedFilePrivate) {} -MemoryMappedFile::~MemoryMappedFile() { delete state; } - -void MemoryMappedFile::open(const std::string& name, const std::string& directory) -{ - // Ensure directory exists - if ( ::mkdir(directory.c_str(), S_IRWXU | S_IRGRP | S_IXGRP )!=0 && errno!=EEXIST ) { - throw qpid::Exception(QPID_MSG("Failed to create memory mapped file directory " << directory << ": " << qpid::sys::strError(errno))); - } - - state->path = getFileName(name, directory); - - int flags = O_CREAT | O_TRUNC | O_RDWR; - int fd = ::open(state->path.c_str(), flags, S_IRUSR | S_IWUSR); - if (fd == -1) throw qpid::Exception(QPID_MSG("Failed to open memory mapped file " << state->path << ": " << qpid::sys::strError(errno) << " [flags=" << flags << "]")); - state->fd = fd; -} - -void MemoryMappedFile::close() -{ - ::close(state->fd); - ::unlink(state->path.c_str()); -} - -size_t MemoryMappedFile::getPageSize() -{ - return ::sysconf(_SC_PAGE_SIZE); -} - -char* MemoryMappedFile::map(size_t offset, size_t size) -{ - int protection = PROT_READ | PROT_WRITE; - char* region = (char*) ::mmap(0, size, protection, MAP_SHARED, state->fd, offset); - if (region == MAP_FAILED) { - throw qpid::Exception(QPID_MSG("Failed to map page into memory: " << qpid::sys::strError(errno))); - } - return region; - -} - -void MemoryMappedFile::unmap(char* region, size_t size) -{ - ::munmap(region, size); -} - -void MemoryMappedFile::flush(char* region, size_t size) -{ - ::msync(region, size, MS_ASYNC); -} - -void MemoryMappedFile::expand(size_t offset) -{ - if ((::lseek(state->fd, offset - 1, SEEK_SET) == -1) || (::write(state->fd, "", 1) == -1)) { - throw qpid::Exception(QPID_MSG("Failed to expand paged queue file: " << qpid::sys::strError(errno))); - } -} - -bool MemoryMappedFile::isSupported() -{ - return true; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/Mutex.cpp b/qpid/cpp/src/qpid/sys/posix/Mutex.cpp deleted file mode 100644 index 0e1f0d30c2..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Mutex.cpp +++ /dev/null @@ -1,46 +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/sys/Mutex.h" - -namespace qpid { -namespace sys { - -/** - * Initialise a recursive mutex attr for use in creating mutexes later - * (we use pthread_once to make sure it is initialised exactly once) - */ - -namespace { -pthread_once_t onceControl = PTHREAD_ONCE_INIT; -pthread_mutexattr_t mutexattr; - -void initMutexattr() { - pthread_mutexattr_init(&mutexattr); - pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); -} -} - -const pthread_mutexattr_t* Mutex::getAttribute() { - pthread_once(&onceControl, initMutexattr); - return &mutexattr; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/Mutex.h b/qpid/cpp/src/qpid/sys/posix/Mutex.h deleted file mode 100644 index e2b21b5a56..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Mutex.h +++ /dev/null @@ -1,158 +0,0 @@ -#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 -#include - -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 ScopedLock; - typedef ::qpid::sys::ScopedUnlock 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 ScopedRlock; - typedef ::qpid::sys::ScopedWlock 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 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/Path.cpp b/qpid/cpp/src/qpid/sys/posix/Path.cpp deleted file mode 100644 index 063e3cfc51..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Path.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * 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/Path.h" -#include "qpid/sys/StrError.h" -#include "qpid/Exception.h" - -#include -#include - -#include - - - -namespace qpid { -namespace sys { - -const std::string Path::separator("/"); - -namespace { -// Return true for success, false for ENOENT, throw otherwise. -bool getStat(const std::string& path, struct ::stat& s) { - if (::stat(path.c_str(), &s)) { - if (errno == ENOENT) return false; - throw Exception(strError(errno) + ": Invalid path: " + path); - } - return true; -} - -bool isFlag(const std::string& path, unsigned long flag) { - struct ::stat s; - return getStat(path, s) && (s.st_mode & flag); -} -} - -bool Path::exists () const { - struct ::stat s; - return getStat(path, s); -} - -bool Path::isFile() const { return isFlag(path, S_IFREG); } -bool Path::isDirectory() const { return isFlag(path, S_IFDIR); } -bool Path::isAbsolute() const { return (path.size() > 0 && path[0] == separator[0]); } - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/PidFile.h b/qpid/cpp/src/qpid/sys/posix/PidFile.h deleted file mode 100644 index fb19d407f4..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/PidFile.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _sys_PidFile_h -#define _sys_PidFile_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/LockFile.h" - -#include "qpid/CommonImportExport.h" -#include "qpid/sys/IntegerTypes.h" - -#include -#include -#include - -namespace qpid { -namespace sys { - -class PidFile : public LockFile -{ -public: - QPID_COMMON_EXTERN PidFile(const std::string& path_, bool create); - - /** - * Read the process ID from the lock file. This method assumes that - * if there is a process ID in the file, it was written there by - * writePid(); thus, it's at the start of the file. - * - * Throws an exception if there is an error reading the file. - * - * @returns The stored process ID. No validity check is done on it. - */ - QPID_COMMON_EXTERN pid_t readPid(void) const; - - /** - * Write the current process's ID to the lock file. It's written at - * the start of the file and will overwrite any other content that - * may be in the file. - * - * Throws an exception if the write fails. - */ - QPID_COMMON_EXTERN void writePid(void); -}; - -}} /* namespace qpid::sys */ - -#endif /*!_sys_PidFile_h*/ diff --git a/qpid/cpp/src/qpid/sys/posix/PipeHandle.cpp b/qpid/cpp/src/qpid/sys/posix/PipeHandle.cpp deleted file mode 100755 index 4b19783338..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/PipeHandle.cpp +++ /dev/null @@ -1,64 +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/sys/PipeHandle.h" -#include "qpid/sys/posix/check.h" -#include -#include -#include - -namespace qpid { -namespace sys { - -PipeHandle::PipeHandle(bool nonBlocking) { - - int pair[2]; - pair[0] = pair[1] = -1; - - if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) == -1) - throw qpid::Exception(QPID_MSG("Creation of pipe failed")); - - writeFd = pair[0]; - readFd = pair[1]; - - // Set the socket to non-blocking - if (nonBlocking) { - int flags = fcntl(readFd, F_GETFL); - fcntl(readFd, F_SETFL, flags | O_NONBLOCK); - } -} - -PipeHandle::~PipeHandle() { - close(readFd); - close(writeFd); -} - -int PipeHandle::read(void* buf, size_t bufSize) { - return ::read(readFd,buf,bufSize); -} - -int PipeHandle::write(const void* buf, size_t bufSize) { - return ::write(writeFd,buf,bufSize); -} - -int PipeHandle::getReadHandle() { - return readFd; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/PollableCondition.cpp b/qpid/cpp/src/qpid/sys/posix/PollableCondition.cpp deleted file mode 100644 index aa129faf20..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/PollableCondition.cpp +++ /dev/null @@ -1,118 +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/sys/PollableCondition.h" -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/Exception.h" - -#include - -#include -#include - -namespace qpid { -namespace sys { - -class PollableConditionPrivate : public sys::IOHandle { - friend class PollableCondition; - -private: - PollableConditionPrivate(const sys::PollableCondition::Callback& cb, - sys::PollableCondition& parent, - const boost::shared_ptr& poller); - ~PollableConditionPrivate(); - - void dispatch(sys::DispatchHandle& h); - void set(); - void clear(); - -private: - PollableCondition::Callback cb; - PollableCondition& parent; - boost::shared_ptr poller; - int writeFd; - std::auto_ptr handle; -}; - -PollableConditionPrivate::PollableConditionPrivate( - const sys::PollableCondition::Callback& cb, - sys::PollableCondition& parent, - const boost::shared_ptr& poller -) : cb(cb), parent(parent) -{ - int fds[2]; - if (::pipe(fds) == -1) - throw ErrnoException(QPID_MSG("Can't create PollableCondition")); - fd = fds[0]; - writeFd = fds[1]; - if (::fcntl(fd, F_SETFL, O_NONBLOCK) == -1) - throw ErrnoException(QPID_MSG("Can't create PollableCondition")); - if (::fcntl(writeFd, F_SETFL, O_NONBLOCK) == -1) - throw ErrnoException(QPID_MSG("Can't create PollableCondition")); - handle.reset (new DispatchHandleRef( - *this, - boost::bind(&sys::PollableConditionPrivate::dispatch, this, _1), - 0, 0)); - handle->startWatch(poller); - handle->unwatch(); - - // Make the read FD readable - static const char dummy=0; - ssize_t n = ::write(writeFd, &dummy, 1); - if (n == -1 && errno != EAGAIN) - throw ErrnoException("Error setting PollableCondition"); -} - -PollableConditionPrivate::~PollableConditionPrivate() { - handle->stopWatch(); - close(writeFd); -} - -void PollableConditionPrivate::dispatch(sys::DispatchHandle&) { - cb(parent); -} - -void PollableConditionPrivate::set() { - handle->rewatch(); -} - -void PollableConditionPrivate::clear() { - handle->unwatch(); -} - - -PollableCondition::PollableCondition(const Callback& cb, - const boost::shared_ptr& poller -) : impl(new PollableConditionPrivate(cb, *this, poller)) -{ -} - -PollableCondition::~PollableCondition() -{ - delete impl; -} - -void PollableCondition::set() { impl->set(); } - -void PollableCondition::clear() { impl->clear(); } - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/PosixPoller.cpp b/qpid/cpp/src/qpid/sys/posix/PosixPoller.cpp deleted file mode 100644 index ae839b2e20..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/PosixPoller.cpp +++ /dev/null @@ -1,793 +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/sys/Poller.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/AtomicCount.h" -#include "qpid/sys/DeletionManager.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Condition.h" - -#include -#include -#include - -#include -#include -#include -#include - -/* - * - * This is a qpid::sys::Poller implementation for Posix systems. - * - * This module follows the structure of the Linux EpollPoller as closely as possible - * to simplify maintainability. Noteworthy differences: - * - * The Linux epoll_xxx() calls present one event at a time to multiple callers whereas poll() - * returns one or more events to a single caller. The EventStream class layers a - * "one event per call" view of the poll() result to multiple threads. - * - * The HandleSet is the master set of in-use PollerHandles. The EventStream - * maintains a snapshot copy taken just before the call to poll() that remains static - * until all flagged events have been processed. - * - * There is an additional window where the PollerHandlePrivate class may survive the - * parent PollerHandle destructor, i.e. between snapshots. - * - * Safe interrupting of the Poller is implemented using the "self-pipe trick". - * - */ - -namespace qpid { -namespace sys { - -// Deletion manager to handle deferring deletion of PollerHandles to when they definitely aren't being used -DeletionManager PollerHandleDeletionManager; - -// Instantiate (and define) class static for DeletionManager -template <> -DeletionManager::AllThreadsStatuses DeletionManager::allThreadsStatuses(0); - -class PollerHandlePrivate { - friend class Poller; - friend class PollerPrivate; - friend class PollerHandle; - friend class HandleSet; - - enum FDStat { - ABSENT, - MONITORED, - INACTIVE, - HUNGUP, - MONITORED_HUNGUP, - INTERRUPTED, - INTERRUPTED_HUNGUP, - DELETED - }; - - short events; - const IOHandle* ioHandle; - PollerHandle* pollerHandle; - FDStat stat; - Mutex lock; - - PollerHandlePrivate(const IOHandle* h, PollerHandle* p) : - events(0), - ioHandle(h), - pollerHandle(p), - stat(ABSENT) { - } - - int fd() const { - return ioHandle->fd; - } - - bool isActive() const { - return stat == MONITORED || stat == MONITORED_HUNGUP; - } - - void setActive() { - stat = (stat == HUNGUP || stat == INTERRUPTED_HUNGUP) - ? MONITORED_HUNGUP - : MONITORED; - } - - bool isInactive() const { - return stat == INACTIVE || stat == HUNGUP; - } - - void setInactive() { - stat = INACTIVE; - } - - bool isIdle() const { - return stat == ABSENT; - } - - void setIdle() { - stat = ABSENT; - } - - bool isHungup() const { - return - stat == MONITORED_HUNGUP || - stat == HUNGUP || - stat == INTERRUPTED_HUNGUP; - } - - void setHungup() { - assert(stat == MONITORED); - stat = HUNGUP; - } - - bool isInterrupted() const { - return stat == INTERRUPTED || stat == INTERRUPTED_HUNGUP; - } - - void setInterrupted() { - stat = (stat == MONITORED_HUNGUP || stat == HUNGUP) - ? INTERRUPTED_HUNGUP - : INTERRUPTED; - } - - bool isDeleted() const { - return stat == DELETED; - } - - void setDeleted() { - stat = DELETED; - } -}; - -PollerHandle::PollerHandle(const IOHandle& h) : - impl(new PollerHandlePrivate(&h, this)) -{} - -PollerHandle::~PollerHandle() { - { - ScopedLock l(impl->lock); - if (impl->isDeleted()) { - return; - } - impl->pollerHandle = 0; - if (impl->isInterrupted()) { - impl->setDeleted(); - return; - } - assert(impl->isIdle()); - impl->setDeleted(); - } - PollerHandleDeletionManager.markForDeletion(impl); -} - -class HandleSet -{ - Mutex lock; - bool stale; - std::set handles; - public: - HandleSet() : stale(true) {} - void add(PollerHandlePrivate*); - void remove(PollerHandlePrivate*); - void cleanup(); - bool snapshot(std::vector& , std::vector&); - void setStale(); -}; - -void HandleSet::add(PollerHandlePrivate* h) -{ - ScopedLock l(lock); - handles.insert(h); -} -void HandleSet::remove(PollerHandlePrivate* h) -{ - ScopedLock l(lock); - handles.erase(h); -} -void HandleSet::cleanup() -{ - // Inform all registered handles of disconnection - std::set copy; - handles.swap(copy); - for (std::set::const_iterator i = copy.begin(); i != copy.end(); ++i) { - PollerHandlePrivate& eh = **i; - { - ScopedLock l(eh.lock); - if (!eh.isDeleted()) { - Poller::Event event((*i)->pollerHandle, Poller::DISCONNECTED); - event.process(); - } - } - } -} -void HandleSet::setStale() -{ - // invalidate cached pollfds for next snapshot - ScopedLock l(lock); - stale = true; -} - -/** - * Concrete implementation of Poller to use Posix poll() - * interface - */ -class PollerPrivate { - friend class Poller; - friend class EventStream; - friend class HandleSet; - - class SignalPipe { - /** - * Used to wakeup a thread in ::poll() - */ - int fds[2]; - bool signaled; - bool permanent; - Mutex lock; - public: - SignalPipe() : signaled(false), permanent(false) { - QPID_POSIX_CHECK(::pipe(fds)); - } - - ~SignalPipe() { - ::close(fds[0]); - ::close(fds[1]); - } - - int getFD() { - return fds[0]; - } - - bool isSet() { - return signaled; - } - - void set() { - ScopedLock l(lock); - if (signaled) - return; - signaled = true; - QPID_POSIX_CHECK(::write(fds[1], " ", 1)); - } - - void reset() { - if (permanent) - return; - ScopedLock l(lock); - if (signaled) { - char ignore; - QPID_POSIX_CHECK(::read(fds[0], &ignore, 1)); - signaled = false; - } - } - - void setPermanently() { - // async signal safe calls only. No locking. - permanent = true; - signaled = true; - QPID_POSIX_CHECK(::write(fds[1], " ", 2)); - // poll() should never block now - } - }; - - // Collect pending events and serialize access. Maintain array of pollfd structs. - class EventStream { - typedef Poller::Event Event; - PollerPrivate& pollerPrivate; - SignalPipe& signalPipe; - std::queue interruptedHandles; - std::vector pollfds; - std::vector pollHandles; - Mutex streamLock; - Mutex serializeLock; - Condition serializer; - bool busy; - int currentPollfd; - int pollCount; - int waiters; - - public: - - EventStream(PollerPrivate* p) : pollerPrivate(*p), signalPipe(p->signalPipe), busy(false), - currentPollfd(0), pollCount(0), waiters(0) { - // The signal pipe is the first element of pollfds and pollHandles - pollfds.reserve(8); - pollfds.resize(1); - pollfds[0].fd = pollerPrivate.signalPipe.getFD(); - pollfds[0].events = POLLIN; - pollfds[0].revents = 0; - - pollHandles.reserve(8); - pollHandles.resize(1); - pollHandles[0] = 0; - } - - void addInterrupt(PollerHandle& handle) { - ScopedLock l(streamLock); - interruptedHandles.push(handle.impl); - } - - // Serialize access to the stream. - Event next(Duration timeout) { - AbsTime targetTimeout = - (timeout == TIME_INFINITE) ? - FAR_FUTURE : - AbsTime(now(), timeout); - - - ScopedLock l(serializeLock); - Event event(0, Poller::INVALID); - while (busy) { - waiters++; - bool timedout = !serializer.wait(serializeLock, targetTimeout); - waiters--; - - if (busy && timedout) { - return Event(0, Poller::TIMEOUT); - } - } - busy = true; - { - ScopedUnlock ul(serializeLock); - event = getEvent(targetTimeout); - } - busy = false; - - if (waiters > 0) - serializer.notify(); - return event; - } - - Event getEvent(AbsTime targetTimeout) { - bool timeoutPending = false; - - ScopedLock l(streamLock); // hold lock except for poll() - - // loop until poll event, async interrupt, or timeout - while (true) { - - // first check for any interrupts - while (interruptedHandles.size() > 0) { - PollerHandlePrivate& eh = *interruptedHandles.front(); - interruptedHandles.pop(); - { - ScopedLock lk(eh.lock); - if (!eh.isDeleted()) { - if (!eh.isIdle()) { - eh.setInactive(); - } - - // nullify the corresponding pollfd event, if any - int ehfd = eh.fd(); - std::vector::iterator i = pollfds.begin() + 1; // skip self pipe at front - for (; i != pollfds.end(); i++) { - if (i->fd == ehfd) { - i->events = 0; - if (i->revents) { - i->revents = 0; - pollCount--; - } - break; - } - } - return Event(eh.pollerHandle, Poller::INTERRUPTED); - } - } - PollerHandleDeletionManager.markForDeletion(&eh); - } - - // Check for shutdown - if (pollerPrivate.isShutdown) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, Poller::SHUTDOWN); - } - - // search for any remaining events from earlier poll() - int nfds = pollfds.size(); - while ((pollCount > 0) && (currentPollfd < nfds)) { - int index = currentPollfd++; - short evt = pollfds[index].revents; - if (evt != 0) { - pollCount--; - PollerHandlePrivate& eh = *pollHandles[index]; - ScopedLock l(eh.lock); - // stop polling this handle until resetMode() - pollfds[index].events = 0; - - // the handle could have gone inactive since snapshot taken - if (eh.isActive()) { - PollerHandle* handle = eh.pollerHandle; - assert(handle); - - // If the connection has been hungup we could still be readable - // (just not writable), allow us to readable until we get here again - if (evt & POLLHUP) { - if (eh.isHungup()) { - eh.setInactive(); - // Don't set up last Handle so that we don't reset this handle - // on re-entering Poller::wait. This means that we will never - // be set active again once we've returned disconnected, and so - // can never be returned again. - return Event(handle, Poller::DISCONNECTED); - } - eh.setHungup(); - } else { - eh.setInactive(); - } - return Event(handle, PollerPrivate::epollToDirection(evt)); - } - } - } - - if (timeoutPending) { - return Event(0, Poller::TIMEOUT); - } - - // no outstanding events, poll() for more - { - ScopedUnlock ul(streamLock); - - bool refreshed = pollerPrivate.registeredHandles.snapshot(pollHandles, pollfds); - if (refreshed) { - // we just drained all interruptedHandles and got a fresh snapshot - PollerHandleDeletionManager.markAllUnusedInThisThread(); - } - - if (!signalPipe.isSet()) { - int timeoutMs = -1; - if (!(targetTimeout == FAR_FUTURE)) { - timeoutMs = Duration(now(), targetTimeout) / TIME_MSEC; - if (timeoutMs < 0) - timeoutMs = 0; - } - - pollCount = ::poll(&pollfds[0], pollfds.size(), timeoutMs); - - if (pollCount ==-1 && errno != EINTR) { - QPID_POSIX_CHECK(pollCount); - } - else if (pollCount == 0) { - // timeout, unless shutdown or interrupt arrives in another thread - timeoutPending = true; - } - else { - if (pollfds[0].revents) { - pollCount--; // signal pipe doesn't count - } - } - } - else - pollCount = 0; - signalPipe.reset(); - } - currentPollfd = 1; - } - } - }; - - bool isShutdown; - HandleSet registeredHandles; - AtomicCount threadCount; - SignalPipe signalPipe; - EventStream eventStream; - - static short directionToEpollEvent(Poller::Direction dir) { - switch (dir) { - case Poller::INPUT: return POLLIN; - case Poller::OUTPUT: return POLLOUT; - case Poller::INOUT: return POLLIN | POLLOUT; - default: return 0; - } - } - - static Poller::EventType epollToDirection(short events) { - // POLLOUT & POLLHUP are mutually exclusive really, but at least socketpairs - // can give you both! - events = (events & POLLHUP) ? events & ~POLLOUT : events; - short e = events & (POLLIN | POLLOUT); - switch (e) { - case POLLIN: return Poller::READABLE; - case POLLOUT: return Poller::WRITABLE; - case POLLIN | POLLOUT: return Poller::READ_WRITABLE; - default: - return (events & (POLLHUP | POLLERR)) ? - Poller::DISCONNECTED : Poller::INVALID; - } - } - - PollerPrivate() : - isShutdown(false), eventStream(this) { - } - - ~PollerPrivate() {} - - void resetMode(PollerHandlePrivate& handle); - - void interrupt() { - signalPipe.set(); - } - - void interruptAll() { - // be async signal safe - signalPipe.setPermanently(); - } -}; - - -void Poller::registerHandle(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(eh.isIdle()); - - eh.setActive(); - impl->registeredHandles.add(handle.impl); - // not stale until monitored -} - -void Poller::unregisterHandle(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(!eh.isIdle()); - - eh.setIdle(); - impl->registeredHandles.remove(handle.impl); - impl->registeredHandles.setStale(); - impl->interrupt(); -} - -void PollerPrivate::resetMode(PollerHandlePrivate& eh) { - PollerHandle* ph; - { - // Called after an event has been processed for a handle - ScopedLock l(eh.lock); - assert(!eh.isActive()); - - if (eh.isIdle() || eh.isDeleted()) { - return; - } - - if (eh.events==0) { - eh.setActive(); - return; - } - - if (!eh.isInterrupted()) { - // Handle still in use, allow events to resume. - eh.setActive(); - registeredHandles.setStale(); - // Ouch. This scales poorly for large handle sets. - // TODO: avoid new snapshot, perhaps create an index to pollfds or a - // pending reset queue to be processed before each poll(). However, the real - // scalable solution is to implement the OS-specific epoll equivalent. - interrupt(); - return; - } - ph = eh.pollerHandle; - } - - eventStream.addInterrupt(*ph); - interrupt(); -} - -void Poller::monitorHandle(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(!eh.isIdle()); - - short oldEvents = eh.events; - eh.events |= PollerPrivate::directionToEpollEvent(dir); - - // If no change nothing more to do - avoid unnecessary system call - if (oldEvents==eh.events) { - return; - } - - // If we're not actually listening wait till we are to perform change - if (!eh.isActive()) { - return; - } - - // tell polling thread to update its pollfds - impl->registeredHandles.setStale(); - impl->interrupt(); -} - -void Poller::unmonitorHandle(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(!eh.isIdle()); - - short oldEvents = eh.events; - eh.events &= ~PollerPrivate::directionToEpollEvent(dir); - - // If no change nothing more to do - avoid unnecessary system call - if (oldEvents==eh.events) { - return; - } - - // If we're not actually listening wait till we are to perform change - if (!eh.isActive()) { - return; - } - - impl->registeredHandles.setStale(); - impl->interrupt(); -} - -void Poller::shutdown() { - // NB: this function must be async-signal safe, it must not - // call any function that is not async-signal safe. - - // Allow sloppy code to shut us down more than once - if (impl->isShutdown) - return; - - // Don't use any locking here - isShutdown will be visible to all - // after the write() anyway (it's a memory barrier) - impl->isShutdown = true; - - impl->interruptAll(); -} - -bool Poller::interrupt(PollerHandle& handle) { - { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - if (eh.isIdle() || eh.isDeleted()) { - return false; - } - - if (eh.isInterrupted()) { - return true; - } - - if (eh.isInactive()) { - eh.setInterrupted(); - return true; - } - eh.setInterrupted(); - eh.events = 0; - } - - impl->registeredHandles.setStale(); - impl->eventStream.addInterrupt(handle); - impl->interrupt(); - return true; -} - -void Poller::run() { - // Ensure that we exit thread responsibly under all circumstances - try { - // Make sure we can't be interrupted by signals at a bad time - ::sigset_t ss; - ::sigfillset(&ss); - ::pthread_sigmask(SIG_SETMASK, &ss, 0); - - ++(impl->threadCount); - do { - Event event = wait(); - - // If can read/write then dispatch appropriate callbacks - if (event.handle) { - event.process(); - } else { - // Handle shutdown - switch (event.type) { - case SHUTDOWN: - //last thread to respond to shutdown cleans up: - if (--(impl->threadCount) == 0) impl->registeredHandles.cleanup(); - PollerHandleDeletionManager.destroyThreadState(); - return; - default: - // This should be impossible - assert(false); - } - } - } while (true); - } catch (const std::exception& e) { - QPID_LOG(error, "IO worker thread exiting with unhandled exception: " << e.what()); - } - PollerHandleDeletionManager.destroyThreadState(); - --(impl->threadCount); -} - -bool Poller::hasShutdown() -{ - return impl->isShutdown; -} - -Poller::Event Poller::wait(Duration timeout) { - static __thread PollerHandlePrivate* lastReturnedHandle = 0; - - if (lastReturnedHandle) { - impl->resetMode(*lastReturnedHandle); - lastReturnedHandle = 0; - } - - Event event = impl->eventStream.next(timeout); - - switch (event.type) { - case INTERRUPTED: - case READABLE: - case WRITABLE: - case READ_WRITABLE: - lastReturnedHandle = event.handle->impl; - break; - default: - ; - } - - return event; -} - -// Concrete constructors -Poller::Poller() : - impl(new PollerPrivate()) -{} - -Poller::~Poller() { - delete impl; -} - - -bool HandleSet::snapshot(std::vector& hs , std::vector& fds) -{ - // Element 0 of the vectors is always the signal pipe, leave undisturbed - { - ScopedLock l(lock); - if (!stale) - return false; // no refresh done - - hs.resize(1); - for (std::set::const_iterator i = handles.begin(); i != handles.end(); ++i) { - hs.push_back(*i); - } - stale = false; - // have copy of handle set (in vector form), drop the lock and build the pollfds - } - - // sync pollfds to same sizing as the handles - int sz = hs.size(); - fds.resize(sz); - - for (int j = 1; j < sz; ++j) { - // create a pollfd entry for each handle - struct ::pollfd& pollfd = fds[j]; - PollerHandlePrivate& eh = *hs[j]; - ScopedLock lk(eh.lock); - - if (!eh.isInactive() && !eh.isDeleted()) { - pollfd.fd = eh.fd(); - pollfd.events = eh.events; - } else { - pollfd.fd = -1; // tell poll() to ignore this fd - pollfd.events = 0; - } - } - return true; -} - - -}} diff --git a/qpid/cpp/src/qpid/sys/posix/PrivatePosix.h b/qpid/cpp/src/qpid/sys/posix/PrivatePosix.h deleted file mode 100644 index 34a2022694..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/PrivatePosix.h +++ /dev/null @@ -1,65 +0,0 @@ -#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 AbsTime& 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/Shlib.cpp b/qpid/cpp/src/qpid/sys/posix/Shlib.cpp deleted file mode 100644 index 3fb685d5b8..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Shlib.cpp +++ /dev/null @@ -1,60 +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/sys/Shlib.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include - - -namespace qpid { -namespace sys { - -void Shlib::load(const char* name) { - ::dlerror(); - handle = ::dlopen(name, RTLD_NOW); - const char* error = ::dlerror(); - if (error) { - throw Exception(QPID_MSG(error << ": " << name)); - } -} - -void Shlib::unload() { - if (handle) { - ::dlerror(); - ::dlclose(handle); - const char* error = ::dlerror(); - if (error) { - throw Exception(QPID_MSG(error)); - } - handle = 0; - } -} - -void* Shlib::getSymbol(const char* name) { - ::dlerror(); - void* sym = ::dlsym(handle, name); - const char* error = ::dlerror(); - if (error) - throw Exception(QPID_MSG(error << ": " << name)); - return sym; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp b/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp deleted file mode 100644 index 4c860a7ef7..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp +++ /dev/null @@ -1,353 +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/sys/SocketAddress.h" - -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/log/Logger.h" - -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace sys { - -SocketAddress::SocketAddress(const std::string& host0, const std::string& port0) : - host(host0), - port(port0), - addrInfo(0), - currentAddrInfo(0) -{ -} - -SocketAddress::SocketAddress(const SocketAddress& sa) : - host(sa.host), - port(sa.port), - addrInfo(0), - currentAddrInfo(0) -{ -} - -SocketAddress& SocketAddress::operator=(const SocketAddress& sa) -{ - SocketAddress temp(sa); - - std::swap(temp, *this); - return *this; -} - -SocketAddress::~SocketAddress() -{ - if (addrInfo) { - ::freeaddrinfo(addrInfo); - } -} - -std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen, bool dispNameOnly, bool hideDecoration) -{ - char servName[NI_MAXSERV]; - char dispName[NI_MAXHOST]; - if (int rc=::getnameinfo(addr, addrlen, - dispName, sizeof(dispName), - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw qpid::Exception(QPID_MSG(gai_strerror(rc))); - std::string s; - switch (addr->sa_family) { - case AF_INET: s += dispName; break; - case AF_INET6: - if (!hideDecoration) { - s += "["; s += dispName; s+= "]"; - } else { - s += dispName; - } - break; - case AF_UNIX: s += "UNIX:"; break; - default: throw Exception(QPID_MSG("Unexpected socket type")); - } - if (!dispNameOnly) { - s += ":"; - s += servName; - } - return s; -} - -uint16_t SocketAddress::getPort(::sockaddr const * const addr) -{ - switch (addr->sa_family) { - case AF_INET: return ntohs(((const ::sockaddr_in*)(const void*)addr)->sin_port); - case AF_INET6: return ntohs(((const ::sockaddr_in6*)(const void*)addr)->sin6_port); - default:throw Exception(QPID_MSG("Unexpected socket type")); - } -} - -std::string SocketAddress::asString(bool numeric, bool dispNameOnly, bool hideDecoration) const -{ - if (!numeric) - return host + ":" + port; - // Canonicalise into numeric id - const ::addrinfo& ai = getAddrInfo(*this); - - return asString(ai.ai_addr, ai.ai_addrlen, dispNameOnly, hideDecoration); -} - -std::string SocketAddress::getHost() const -{ - return host; -} - -/** - * Return true if this SocketAddress is IPv4 or IPv6 - */ -bool SocketAddress::isIp() const -{ - const ::addrinfo& ai = getAddrInfo(*this); - return ai.ai_family == AF_INET || ai.ai_family == AF_INET6; -} - -/** - * this represents the low address of an ACL address range. - * Given rangeHi that represents the high address, - * return a string showing the numeric comparisons that the - * inRange checks will do for address pair. - */ -std::string SocketAddress::comparisonDetails(const SocketAddress& rangeHi) const -{ - std::ostringstream os; - SocketAddress thisSa(*this); - SocketAddress rangeHiSa(rangeHi); - (void) getAddrInfo(thisSa); - (void) getAddrInfo(rangeHiSa); - os << "(" << thisSa.asString(true, true, false) << - "," << rangeHiSa.asString(true, true, false) << ")"; - while (thisSa.nextAddress()) { - if (!rangeHiSa.nextAddress()) { - throw(Exception(QPID_MSG("Comparison iteration fails: " + (*this).asString() + - rangeHi.asString()))); - } - os << ",(" << thisSa.asString(true, true, false) << - "," << rangeHiSa.asString(true, true, false) << ")"; - } - if (rangeHiSa.nextAddress()) { - throw(Exception(QPID_MSG("Comparison iteration fails: " + (*this).asString() + - rangeHi.asString()))); - } - std::string result = os.str(); - return result; -} - -/** - * For ACL address matching make sure that the two addresses, *this - * which is the low address and hiPeer which is the high address, are - * both numeric ip addresses of the same family and that hi > *this. - * - * Note that if the addresses resolve to more than one struct addrinfo - * then this and the hiPeer must be equal. This avoids having to do - * difficult range checks where the this and hiPeer both resolve to - * multiple IPv4 or IPv6 addresses. - * - * This check is run at acl file load time and not at run tme. - */ -bool SocketAddress::isComparable(const SocketAddress& hiPeer) const { - try { - // May only compare if this socket is IPv4 or IPv6 - SocketAddress lo(*this); - const ::addrinfo& peerLoInfo = getAddrInfo(lo); - if (!(peerLoInfo.ai_family == AF_INET || peerLoInfo.ai_family == AF_INET6)) { - return false; - } - try { - // May only compare if peer socket is same family - SocketAddress hi(hiPeer); - const ::addrinfo& peerHiInfo = getAddrInfo(hi); - if (peerLoInfo.ai_family != peerHiInfo.ai_family) { - return false; - } - // Host names that resolve to lists are allowed if they are equal. - // For example: localhost, or fjord.lab.example.com - if ((*this).asString() == hiPeer.asString()) { - return true; - } - // May only compare if this and peer resolve to single address. - if (lo.nextAddress() || hi.nextAddress()) { - return false; - } - // Make sure that the lo/hi relationship is ok - int res; - if (!compareAddresses(peerLoInfo, peerHiInfo, res) || res < 0) { - return false; - } - return true; - } catch (Exception) { - // failed to resolve hi - return false; - } - } catch (Exception) { - // failed to resolve lo - return false; - } -} - -/** - * *this SocketAddress was created from the numeric IP address of a - * connecting host. - * The lo and hi addresses are the limit checks from the ACL file. - * Return true if this address is in range of any of the address pairs - * in the limit check range. - * - * This check is executed on every incoming connection. - */ -bool SocketAddress::inRange(const SocketAddress& lo, - const SocketAddress& hi) const -{ - (*this).firstAddress(); - lo.firstAddress(); - hi.firstAddress(); - const ::addrinfo& thisInfo = getAddrInfo(*this); - const ::addrinfo& loInfo = getAddrInfo(lo); - const ::addrinfo& hiInfo = getAddrInfo(hi); - if (inRange(thisInfo, loInfo, hiInfo)) { - return true; - } - while (lo.nextAddress()) { - if (!hi.nextAddress()) { - assert (false); - throw(Exception(QPID_MSG("Comparison iteration fails: " + - lo.asString() + hi.asString()))); - } - const ::addrinfo& loInfo = getAddrInfo(lo); - const ::addrinfo& hiInfo = getAddrInfo(hi); - if (inRange(thisInfo, loInfo, hiInfo)) { - return true; - } - } - return false; -} - -/** - * *this SocketAddress was created from the numeric IP address of a - * connecting host. - * The lo and hi addresses are one binary address pair from a range - * given in an ACL file. - * Return true if this binary address is '>= lo' and '<= hi'. - */ -bool SocketAddress::inRange(const ::addrinfo& thisInfo, - const ::addrinfo& lo, - const ::addrinfo& hi) const -{ - int resLo; - int resHi; - if (!compareAddresses(lo, thisInfo, resLo)) { - return false; - } - if (!compareAddresses(hi, thisInfo, resHi)) { - return false; - } - if (resLo < 0) { - return false; - } - if (resHi > 0) { - return false; - } - return true; -} - -/** - * Compare this address against two binary low/high addresses. - * return true with result holding the comparison. - */ -bool SocketAddress::compareAddresses(const struct addrinfo& lo, - const struct addrinfo& hi, - int& result) const -{ - if (lo.ai_family != hi.ai_family) { - return false; - } - if (lo.ai_family == AF_INET) { - void* taddr; - - taddr = (void*)lo.ai_addr; - struct sockaddr_in* sin4lo = (struct sockaddr_in*)taddr; - taddr = (void*)hi.ai_addr; - struct sockaddr_in* sin4hi = (struct sockaddr_in*)taddr; - result = memcmp(&sin4hi->sin_addr, &sin4lo->sin_addr, sizeof(in_addr)); - } else if (lo.ai_family == AF_INET6) { - void* taddr; - - taddr = (void*)lo.ai_addr; - struct sockaddr_in6* sin6lo = (struct sockaddr_in6*)taddr; - taddr = (void*)hi.ai_addr; - struct sockaddr_in6* sin6hi = (struct sockaddr_in6*)taddr; - result = memcmp(&sin6hi->sin6_addr, &sin6lo->sin6_addr, sizeof(in6_addr)); - } else { - assert (false); - return false; - } - return true; -} - -void SocketAddress::firstAddress() const { - if (addrInfo) { - currentAddrInfo = addrInfo; - } else { - (void) getAddrInfo(*this); - } -} - -bool SocketAddress::nextAddress() const { - bool r = currentAddrInfo->ai_next != 0; - if (r) - currentAddrInfo = currentAddrInfo->ai_next; - return r; -} - -const ::addrinfo& getAddrInfo(const SocketAddress& sa) -{ - if (!sa.addrInfo) { - ::addrinfo hints; - ::memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6 - hints.ai_socktype = SOCK_STREAM; - - const char* node = 0; - if (sa.host.empty()) { - hints.ai_flags = AI_PASSIVE; - } else { - hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for - node = sa.host.c_str(); - } - const char* service = sa.port.empty() ? "0" : sa.port.c_str(); - - int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo); - if (n != 0) - throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n))); - sa.currentAddrInfo = sa.addrInfo; - } - - return *sa.currentAddrInfo; -} - -}} diff --git a/qpid/cpp/src/qpid/sys/posix/StrError.cpp b/qpid/cpp/src/qpid/sys/posix/StrError.cpp deleted file mode 100644 index 633e20213c..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/StrError.cpp +++ /dev/null @@ -1,41 +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/sys/StrError.h" - -#include - -namespace qpid { -namespace sys { - -std::string strError(int err) { - char buf[512] = "Unknown error"; -#ifdef _GNU_SOURCE - // GNU strerror_r returns the message - return ::strerror_r(err, buf, sizeof(buf)); -#else - // POSIX strerror_r doesn't return the buffer - ::strerror_r(err, buf, sizeof(buf)); - return std::string(buf); -#endif -} - -}} diff --git a/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp b/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp deleted file mode 100755 index 2a42a5b2a7..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp +++ /dev/null @@ -1,201 +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/log/Statement.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/posix/check.h" -#include -#include -#include -#include // For FreeBSD -#include // For FreeBSD -#include // For FreeBSD -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef HOST_NAME_MAX -# define HOST_NAME_MAX 256 -#endif - -using namespace std; - -namespace qpid { -namespace sys { - -long SystemInfo::concurrency() { -#ifdef _SC_NPROCESSORS_ONLN // Linux specific. - return sysconf(_SC_NPROCESSORS_ONLN); -#else - return -1; -#endif -} - -bool SystemInfo::getLocalHostname (Address &address) { - char name[HOST_NAME_MAX]; - if (::gethostname(name, sizeof(name)) != 0) - return false; - address.host = name; - return true; -} - -static const string LOOPBACK("127.0.0.1"); -static const string TCP("tcp"); - -// Test IPv4 address for loopback -inline bool IN_IS_ADDR_LOOPBACK(const ::in_addr* a) { - return ((ntohl(a->s_addr) & 0xff000000) == 0x7f000000); -} - -inline bool isLoopback(const ::sockaddr* addr) { - switch (addr->sa_family) { - case AF_INET: return IN_IS_ADDR_LOOPBACK(&((const ::sockaddr_in*)(const void*)addr)->sin_addr); - case AF_INET6: return IN6_IS_ADDR_LOOPBACK(&((const ::sockaddr_in6*)(const void*)addr)->sin6_addr); - default: return false; - } -} - -namespace { - inline socklen_t sa_len(::sockaddr* sa) - { - switch (sa->sa_family) { - case AF_INET: - return sizeof(struct sockaddr_in); - case AF_INET6: - return sizeof(struct sockaddr_in6); - default: - return sizeof(struct sockaddr_storage); - } - } - - inline bool isInetOrInet6(::sockaddr* sa) { - switch (sa->sa_family) { - case AF_INET: - case AF_INET6: - return true; - default: - return false; - } - } - typedef std::map > InterfaceInfo; - std::map > cachedInterfaces; - - void cacheInterfaceInfo() { - // Get interface info - ::ifaddrs* interfaceInfo; - QPID_POSIX_CHECK( ::getifaddrs(&interfaceInfo) ); - - char name[NI_MAXHOST]; - for (::ifaddrs* info = interfaceInfo; info != 0; info = info->ifa_next) { - - // Only use IPv4/IPv6 interfaces - if (!info->ifa_addr || !isInetOrInet6(info->ifa_addr)) continue; - - int rc=::getnameinfo(info->ifa_addr, sa_len(info->ifa_addr), - name, sizeof(name), 0, 0, - NI_NUMERICHOST); - if (rc >= 0) { - std::string address(name); - cachedInterfaces[info->ifa_name].push_back(address); - } else { - throw qpid::Exception(QPID_MSG(gai_strerror(rc))); - } - } - ::freeifaddrs(interfaceInfo); - } -} - -bool SystemInfo::getInterfaceAddresses(const std::string& interface, std::vector& addresses) { - if ( cachedInterfaces.empty() ) cacheInterfaceInfo(); - InterfaceInfo::iterator i = cachedInterfaces.find(interface); - if ( i==cachedInterfaces.end() ) return false; - std::copy(i->second.begin(), i->second.end(), std::back_inserter(addresses)); - return true; -} - -void SystemInfo::getInterfaceNames(std::vector& names ) { - if ( cachedInterfaces.empty() ) cacheInterfaceInfo(); - - for (InterfaceInfo::const_iterator i = cachedInterfaces.begin(); i!=cachedInterfaces.end(); ++i) { - names.push_back(i->first); - } -} - -void SystemInfo::getSystemId (std::string &osName, - std::string &nodeName, - std::string &release, - std::string &version, - std::string &machine) -{ - struct utsname _uname; - if (uname (&_uname) == 0) - { - osName = _uname.sysname; - nodeName = _uname.nodename; - release = _uname.release; - version = _uname.version; - machine = _uname.machine; - } -} - -uint32_t SystemInfo::getProcessId() -{ - return (uint32_t) ::getpid(); -} - -uint32_t SystemInfo::getParentProcessId() -{ - return (uint32_t) ::getppid(); -} - -// Linux specific (Solaris has quite different stuff in /proc) -string SystemInfo::getProcessName() -{ - string value; - - ifstream input("/proc/self/status"); - if (input.good()) { - while (!input.eof()) { - string key; - input >> key; - if (key == "Name:") { - input >> value; - break; - } - } - input.close(); - } - - return value; -} - -// Always true. Only Windows has exception cases. -bool SystemInfo::threadSafeShutdown() -{ - return true; -} - - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/posix/Thread.cpp b/qpid/cpp/src/qpid/sys/posix/Thread.cpp deleted file mode 100644 index 349e35d643..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Thread.cpp +++ /dev/null @@ -1,88 +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/sys/Thread.h" - -#include "qpid/sys/Runnable.h" -#include "qpid/sys/posix/check.h" - -#include - -namespace qpid { -namespace sys { - -namespace { -void* runRunnable(void* p) -{ - static_cast(p)->run(); - return 0; -} -} - -class ThreadPrivate { -public: - pthread_t thread; - - ThreadPrivate(Runnable* runnable) { - QPID_POSIX_ASSERT_THROW_IF(::pthread_create(&thread, NULL, runRunnable, runnable)); - } - - ThreadPrivate() : thread(::pthread_self()) {} -}; - -Thread::Thread() {} - -Thread::Thread(Runnable* runnable) : impl(new ThreadPrivate(runnable)) {} - -Thread::Thread(Runnable& runnable) : impl(new ThreadPrivate(&runnable)) {} - -Thread::operator bool() { - return !!impl; -} - -bool Thread::operator==(const Thread& t) const { - return pthread_equal(impl->thread, t.impl->thread) != 0; -} - -bool Thread::operator!=(const Thread& t) const { - return !(*this==t); -} - -void Thread::join(){ - if (impl) { - QPID_POSIX_ASSERT_THROW_IF(::pthread_join(impl->thread, 0)); - } -} - -unsigned long Thread::logId() { - // This does need to be the C cast operator as - // pthread_t could be either a pointer or an integer - // and so we can't know static_cast<> or reinterpret_cast<> - return (unsigned long) ::pthread_self(); -} - -Thread Thread::current() { - Thread t; - t.impl.reset(new ThreadPrivate()); - return t; -} - -}} diff --git a/qpid/cpp/src/qpid/sys/posix/Time.cpp b/qpid/cpp/src/qpid/sys/posix/Time.cpp deleted file mode 100644 index 10a5d944b1..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Time.cpp +++ /dev/null @@ -1,162 +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/sys/posix/PrivatePosix.h" - -#include "qpid/sys/Time.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { -int64_t max_abstime() { return std::numeric_limits::max(); } -} - -namespace qpid { -namespace sys { - -AbsTime::AbsTime(const AbsTime& t, const Duration& d) : - timepoint(d == Duration::max() ? max_abstime() : t.timepoint+d.nanosecs) -{} - -AbsTime AbsTime::Zero() { - AbsTime epoch; epoch.timepoint = 0; - return epoch; -} - -AbsTime AbsTime::FarFuture() { - AbsTime ff; ff.timepoint = max_abstime(); return ff; -} - -AbsTime AbsTime::now() { - struct timespec ts; - ::clock_gettime(CLOCK_MONOTONIC, &ts); - AbsTime time_now; - time_now.timepoint = toTime(ts).nanosecs; - return time_now; -} - -AbsTime AbsTime::epoch() { - return AbsTime(now(), -Duration::FromEpoch()); -} - -Duration Duration::FromEpoch() { - struct timespec ts; - ::clock_gettime(CLOCK_REALTIME, &ts); - return toTime(ts).nanosecs; -} - -Duration::Duration(const AbsTime& start, const AbsTime& finish) : - nanosecs(finish.timepoint - start.timepoint) -{} - -namespace { -/** type conversion helper: an infinite timeout for time_t sized types **/ -const time_t TIME_T_MAX = std::numeric_limits::max(); -} - -struct timespec& toTimespec(struct timespec& ts, const AbsTime& a) { - Duration t(ZERO, a); - Duration secs = t / TIME_SEC; - ts.tv_sec = (secs > TIME_T_MAX) ? TIME_T_MAX : static_cast(secs); - ts.tv_nsec = static_cast(t % TIME_SEC); - return ts; -} - -Duration toTime(const struct timespec& ts) { - return ts.tv_sec*TIME_SEC + ts.tv_nsec; -} - -std::ostream& operator<<(std::ostream& o, const Duration& d) { - if (d >= TIME_SEC) return o << (double(d)/TIME_SEC) << "s"; - if (d >= TIME_MSEC) return o << (double(d)/TIME_MSEC) << "ms"; - if (d >= TIME_USEC) return o << (double(d)/TIME_USEC) << "us"; - return o << int64_t(d) << "ns"; -} - -std::istream& operator>>(std::istream& i, Duration& d) { - // Don't throw, let the istream throw if it's configured to do so. - double number; - i >> number; - if (i.fail()) return i; - - if (i.eof() || std::isspace(i.peek())) // No suffix - d = int64_t(number*TIME_SEC); - else { - std::stringbuf suffix; - i >> &suffix; - if (i.fail()) return i; - std::string suffix_str = suffix.str(); - if (suffix_str.compare("s") == 0) d = int64_t(number*TIME_SEC); - else if (suffix_str.compare("ms") == 0) d = int64_t(number*TIME_MSEC); - else if (suffix_str.compare("us") == 0) d = int64_t(number*TIME_USEC); - else if (suffix_str.compare("ns") == 0) d = int64_t(number*TIME_NSEC); - else i.setstate(std::ios::failbit); - } - return i; -} - -namespace { -inline std::ostream& outputFormattedTime(std::ostream& o, const ::time_t* time) { - ::tm timeinfo; - char time_string[100]; - ::strftime(time_string, 100, - "%Y-%m-%d %H:%M:%S", - localtime_r(time, &timeinfo)); - return o << time_string; -} -} - -std::ostream& operator<<(std::ostream& o, const AbsTime& t) { - ::time_t rawtime(t.timepoint/TIME_SEC); - return outputFormattedTime(o, &rawtime); -} - -void outputFormattedNow(std::ostream& o) { - ::time_t rawtime; - ::time(&rawtime); - outputFormattedTime(o, &rawtime); - o << " "; -} - -void outputHiresNow(std::ostream& o) { - ::timespec time; - ::clock_gettime(CLOCK_REALTIME, &time); - ::time_t seconds = time.tv_sec; - outputFormattedTime(o, &seconds); - o << "." << std::setw(9) << std::setfill('0') << time.tv_nsec << " "; -} - -void sleep(int secs) { - ::sleep(secs); -} - -void usleep(uint64_t usecs) { - ::usleep(usecs); -} - -}} diff --git a/qpid/cpp/src/qpid/sys/posix/Time.h b/qpid/cpp/src/qpid/sys/posix/Time.h deleted file mode 100755 index 62d734c816..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/Time.h +++ /dev/null @@ -1,34 +0,0 @@ -#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 deleted file mode 100644 index 1bfe5d6d78..0000000000 --- a/qpid/cpp/src/qpid/sys/posix/check.h +++ /dev/null @@ -1,53 +0,0 @@ -#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 -#include -#include -#include - -#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/rdma/RdmaClient.cpp b/qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp deleted file mode 100644 index 9bb82b4f35..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp +++ /dev/null @@ -1,247 +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/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -using std::vector; -using std::string; -using std::cout; -using std::cerr; -using std::copy; -using std::rand; - -using qpid::sys::Thread; -using qpid::sys::Poller; -using qpid::sys::Dispatcher; -using qpid::sys::SocketAddress; -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::sys::TIME_SEC; -using qpid::sys::TIME_INFINITE; - -namespace qpid { -namespace tests { - -// count of messages -int64_t smsgs = 0; -int64_t sbytes = 0; -int64_t rmsgs = 0; -int64_t rbytes = 0; - -int target = 1000000; -int msgsize = 200; -AbsTime startTime; -Duration sendingDuration(TIME_INFINITE); -Duration fullTestDuration(TIME_INFINITE); - -// Random generator -// This is an RNG designed by George Marsaglia see http://en.wikipedia.org/wiki/Xorshift -class Xor128Generator { - uint32_t x; - uint32_t y; - uint32_t z; - uint32_t w; - -public: - Xor128Generator() : - x(123456789),y(362436069),z(521288629),w(88675123) - {++(*this);} - - Xor128Generator& operator++() { - uint32_t t = x ^ (x << 11); - x = y; y = z; z = w; - w = w ^ (w >> 19) ^ t ^ (t >> 8); - return *this; - } - - uint32_t operator*() { - return w; - } -}; - -Xor128Generator output; -Xor128Generator input; - -void write(Rdma::AsynchIO& aio) { - while (aio.writable() && smsgs < target) { - Rdma::Buffer* b = aio.getSendBuffer(); - if (!b) break; - b->dataCount(msgsize); - uint32_t* ip = b->words(); - uint32_t* lip = ip + b->wordCount(); - while (ip != lip) {*ip++ = *output; ++output;} - aio.queueWrite(b); - ++smsgs; - sbytes += msgsize; - } -} - -void dataError(Rdma::AsynchIO&) { - cout << "Data error:\n"; -} - -void data(Poller::shared_ptr p, Rdma::AsynchIO& aio, Rdma::Buffer* b) { - ++rmsgs; - rbytes += b->dataCount(); - - // Check message is unaltered - bool match = true; - uint32_t* ip = b->words(); - uint32_t* lip = ip + b->wordCount(); - while (ip != lip) { if (*ip++ != *input) {match = false; break;} ++input;} - if (!match) { - cout << "Data doesn't match: at msg " << rmsgs << " byte " << rbytes-b->dataCount() << " (ish)\n"; - exit(1); - } - - // When all messages have been recvd stop - if (rmsgs < target) { - write(aio); - } else { - fullTestDuration = std::min(fullTestDuration, Duration(startTime, AbsTime::now())); - if (aio.incompletedWrites() == 0) - p->shutdown(); - } -} - -void full(Rdma::AsynchIO& a, Rdma::Buffer* b) { - // Warn as we shouldn't get here anymore - cerr << "!"; - - // Don't need to keep buffer just adjust the counts - --smsgs; - sbytes -= b->dataCount(); - - // Give buffer back - a.returnSendBuffer(b); -} - -void idle(Poller::shared_ptr p, Rdma::AsynchIO& aio) { - if (smsgs < target) { - write(aio); - } else { - sendingDuration = std::min(sendingDuration, Duration(startTime, AbsTime::now())); - if (rmsgs >= target && aio.incompletedWrites() == 0) - p->shutdown(); - } -} - -void drained(Rdma::AsynchIO&) { - cout << "Drained:\n"; -} - -void connected(Poller::shared_ptr poller, const Rdma::Connection::intrusive_ptr& ci, const Rdma::ConnectionParams& cp) { - cout << "Connected\n"; - Rdma::QueuePair::intrusive_ptr q = ci->getQueuePair(); - - Rdma::AsynchIO* aio = new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit , Rdma::DEFAULT_WR_ENTRIES, - boost::bind(&data, poller, _1, _2), - boost::bind(&idle, poller, _1), - &full, - dataError); - - startTime = AbsTime::now(); - write(*aio); - - aio->start(poller); -} - -void disconnected(boost::shared_ptr p, const Rdma::Connection::intrusive_ptr&) { - cout << "Disconnected\n"; - p->shutdown(); -} - -void connectionError(boost::shared_ptr p, const Rdma::Connection::intrusive_ptr&, const Rdma::ErrorType) { - cout << "Connection error\n"; - p->shutdown(); -} - -void rejected(boost::shared_ptr p, const Rdma::Connection::intrusive_ptr&, const Rdma::ConnectionParams&) { - cout << "Connection rejected\n"; - p->shutdown(); -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char* argv[]) { - vector args(&argv[0], &argv[argc]); - - string host = args[1]; - string port = (args.size() < 3) ? "20079" : args[2]; - - if (args.size() > 3) - msgsize = atoi(args[3].c_str()); - cout << "Message size: " << msgsize << "\n"; - - try { - boost::shared_ptr p(new Poller()); - - Rdma::Connector c( - Rdma::ConnectionParams(msgsize, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&connected, p, _1, _2), - boost::bind(&connectionError, p, _1, _2), - boost::bind(&disconnected, p, _1), - boost::bind(&rejected, p, _1, _2)); - - SocketAddress sa(host, port); - cout << "Connecting to: " << sa.asString() <<"\n"; - c.start(p, sa); - - // The poller loop blocks all signals so run in its own thread - Thread t(*p); - t.join(); - } catch (Rdma::Exception& e) { - int err = e.getError(); - cerr << "Error: " << e.what() << "(" << err << ")\n"; - } - - cout - << "Sent: " << smsgs - << "msgs (" << sbytes - << "bytes) in: " << double(sendingDuration)/TIME_SEC - << "s: " << double(smsgs)*TIME_SEC/sendingDuration - << "msgs/s(" << double(sbytes)*TIME_SEC/sendingDuration - << "bytes/s)\n"; - cout - << "Recd: " << rmsgs - << "msgs (" << rbytes - << "bytes) in: " << double(fullTestDuration)/TIME_SEC - << "s: " << double(rmsgs)*TIME_SEC/fullTestDuration - << "msgs/s(" << double(rbytes)*TIME_SEC/fullTestDuration - << "bytes/s)\n"; - -} diff --git a/qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp b/qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp deleted file mode 100644 index 2cc6573b74..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp +++ /dev/null @@ -1,724 +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/sys/rdma/RdmaIO.h" - -#include "qpid/log/Statement.h" - -#include -#include - -using qpid::sys::SocketAddress; -using qpid::sys::DispatchHandle; -using qpid::sys::Poller; -using qpid::sys::ScopedLock; -using qpid::sys::Mutex; - -namespace Rdma { - // Set packing as these are 'on the wire' structures -# pragma pack(push, 1) - - // Header structure for each transmitted frame - struct FrameHeader { - const static uint32_t FlagsMask = 0xf0000000; - uint32_t data; // written in network order - - FrameHeader() {} - FrameHeader(uint32_t credit, uint32_t flags = 0) { - data = htonl((credit & ~FlagsMask) | (flags & FlagsMask)); - } - - uint32_t credit() const { - return ntohl(data) & ~FlagsMask; - } - - uint32_t flags() const { - return ntohl(data) & FlagsMask; - } - }; - - const size_t FrameHeaderSize = sizeof(FrameHeader); - - // Structure for Connection Parameters on the network - // - // The original version (now called 0) of these parameters had a couple of mistakes: - // * No way to version the protocol (need to introduce a new protocol for iWarp) - // * Used host order int32 (but only deployed on LE archs as far as we know) - // so effectively was LE on the wire which is the opposite of network order. - // - // Fortunately the values sent were sufficiently restricted that a 16 bit short could - // be carved out to indicate the protocol version as these bits were always sent as 0. - // - // So the current version of parameters uses the last 2 bytes to indicate the protocol - // version, if this is 0 then we interpret the rest of the struct without byte swapping - // to remain compatible with the previous protocol. - struct NConnectionParams { - uint32_t maxRecvBufferSize; - uint16_t initialXmitCredit; - uint16_t rdmaProtocolVersion; - - NConnectionParams(const ConnectionParams& c) : - maxRecvBufferSize(c.rdmaProtocolVersion ? htonl(c.maxRecvBufferSize) : c.maxRecvBufferSize), - initialXmitCredit(c.rdmaProtocolVersion ? htons(c.initialXmitCredit) : c.initialXmitCredit), - // 0 is the same with/without byteswapping! - rdmaProtocolVersion(htons(c.rdmaProtocolVersion)) - {} - - operator ConnectionParams() const { - return - ConnectionParams( - rdmaProtocolVersion ? ntohl(maxRecvBufferSize) : maxRecvBufferSize, - rdmaProtocolVersion ? ntohs(initialXmitCredit) : initialXmitCredit, - ntohs(rdmaProtocolVersion)); - } - }; -# pragma pack(pop) - - class IOException : public std::exception { - std::string s; - - public: - IOException(std::string s0): s(s0) {} - ~IOException() throw() {} - - const char* what() const throw() { - return s.c_str(); - } - }; - - AsynchIO::AsynchIO( - QueuePair::intrusive_ptr q, - int version, - int size, - int xCredit, - int rCount, - ReadCallback rc, - IdleCallback ic, - FullCallback fc, - ErrorCallback ec - ) : - protocolVersion(version), - bufferSize(size), - recvCredit(0), - xmitCredit(xCredit), - recvBufferCount(rCount), - xmitBufferCount(xCredit), - outstandingWrites(0), - draining(false), - state(IDLE), - qp(q), - dataHandle(*qp, boost::bind(&AsynchIO::dataEvent, this), 0, 0), - readCallback(rc), - idleCallback(ic), - fullCallback(fc), - errorCallback(ec), - pendingWriteAction(boost::bind(&AsynchIO::writeEvent, this)) - { - if (protocolVersion > maxSupportedProtocolVersion) - throw IOException("Unsupported Rdma Protocol"); - qp->nonblocking(); - qp->notifyRecv(); - qp->notifySend(); - - // Prepost recv buffers before we go any further - qp->allocateRecvBuffers(recvBufferCount, bufferSize+FrameHeaderSize); - - // Create xmit buffers, reserve space for frame header. - qp->createSendBuffers(xmitBufferCount, bufferSize, FrameHeaderSize); - } - - AsynchIO::~AsynchIO() { - // Warn if we are deleting whilst there are still unreclaimed write buffers - if ( outstandingWrites>0 ) - QPID_LOG(error, "RDMA: qp=" << qp << ": Deleting queue before all write buffers finished"); - - // Turn off callbacks if necessary (before doing the deletes) - if (state != STOPPED) { - QPID_LOG(error, "RDMA: qp=" << qp << ": Deleting queue whilst not shutdown"); - dataHandle.stopWatch(); - } - // TODO: It might turn out to be more efficient in high connection loads to reuse the - // buffers rather than having to reregister them all the time (this would be straightforward if all - // connections haver the same buffer size and harder otherwise) - } - - void AsynchIO::start(Poller::shared_ptr poller) { - dataHandle.startWatch(poller); - } - - // State constraints - // On entry: None - // On exit: STOPPED - // Mark for deletion/Delete this object when we have no outstanding writes - void AsynchIO::stop(NotifyCallback nc) { - ScopedLock l(stateLock); - state = STOPPED; - notifyCallback = nc; - dataHandle.call(boost::bind(&AsynchIO::doStoppedCallback, this)); - } - - namespace { - void requestedCall(AsynchIO* aio, AsynchIO::RequestCallback callback) { - assert(callback); - callback(*aio); - } - } - - void AsynchIO::requestCallback(RequestCallback callback) { - // TODO creating a function object every time isn't all that - // efficient - if this becomes heavily used do something better (what?) - assert(callback); - dataHandle.call(boost::bind(&requestedCall, this, callback)); - } - - // Mark writing closed (so we don't accept any more writes or make any idle callbacks) - void AsynchIO::drainWriteQueue(NotifyCallback nc) { - draining = true; - notifyCallback = nc; - } - - void AsynchIO::queueBuffer(Buffer* buff, int credit) { - switch (protocolVersion) { - case 0: - if (!buff) { - Buffer* ob = getSendBuffer(); - // Have to send something as adapters hate it when you try to transfer 0 bytes - char* bytes = ob->bytes(); - bytes[0] = 0xFF & (credit >> 24); - bytes[1] = 0xFF & (credit >> 16); - bytes[2] = 0xFF & (credit >> 8); - bytes[3] = 0xFF & (credit ); - ob->dataCount(sizeof(uint32_t)); - qp->postSend(credit | IgnoreData, ob); - } else if (credit > 0) { - qp->postSend(credit, buff); - } else { - qp->postSend(buff); - } - break; - case 1: - if (!buff) - buff = getSendBuffer(); - // Add FrameHeader after frame data - FrameHeader header(credit); - assert(buff->dataCount() <= buff->byteCount()); // ensure app data doesn't impinge on reserved space. - ::memcpy(buff->bytes()+buff->dataCount(), &header, FrameHeaderSize); - buff->dataCount(buff->dataCount()+FrameHeaderSize); - qp->postSend(buff); - break; - } - } - - Buffer* AsynchIO::extractBuffer(const QueuePairEvent& e) { - Buffer* b = e.getBuffer(); - switch (protocolVersion) { - case 0: { - bool dataPresent = true; - // Get our xmitCredit if it was sent - if (e.immPresent() ) { - assert(xmitCredit>=0); - xmitCredit += (e.getImm() & ~FlagsMask); - dataPresent = ((e.getImm() & IgnoreData) == 0); - assert(xmitCredit>0); - } - if (!dataPresent) { - b->dataCount(0); - } - break; - } - case 1: - b->dataCount(b->dataCount()-FrameHeaderSize); - FrameHeader header; - ::memcpy(&header, b->bytes()+b->dataCount(), FrameHeaderSize); - assert(xmitCredit>=0); - xmitCredit += header.credit(); - assert(xmitCredit>=0); - break; - } - - return b; - } - - void AsynchIO::queueWrite(Buffer* buff) { - // Make sure we don't overrun our available buffers - // either at our end or the known available at the peers end - if (writable()) { - // TODO: We might want to batch up sending credit - int creditSent = recvCredit & ~FlagsMask; - queueBuffer(buff, creditSent); - recvCredit -= creditSent; - ++outstandingWrites; - --xmitCredit; - assert(xmitCredit>=0); - } else { - if (fullCallback) { - fullCallback(*this, buff); - } else { - QPID_LOG(error, "RDMA: qp=" << qp << ": Write queue full, but no callback, throwing buffer away"); - returnSendBuffer(buff); - } - } - } - - // State constraints - // On entry: None - // On exit: NOTIFY_PENDING || STOPPED - void AsynchIO::notifyPendingWrite() { - ScopedLock l(stateLock); - switch (state) { - case IDLE: - dataHandle.call(pendingWriteAction); - // Fall Thru - case NOTIFY: - state = NOTIFY_PENDING; - break; - case NOTIFY_PENDING: - case STOPPED: - break; - } - } - - // State constraints - // On entry: IDLE || STOPPED - // On exit: IDLE || STOPPED - void AsynchIO::dataEvent() { - { - ScopedLock l(stateLock); - - if (state == STOPPED) return; - - state = NOTIFY_PENDING; - } - processCompletions(); - - writeEvent(); - } - - // State constraints - // On entry: NOTIFY_PENDING || STOPPED - // On exit: IDLE || STOPPED - void AsynchIO::writeEvent() { - State newState; - do { - { - ScopedLock l(stateLock); - - switch (state) { - case STOPPED: - return; - default: - state = NOTIFY; - } - } - - doWriteCallback(); - - { - ScopedLock l(stateLock); - - newState = state; - switch (newState) { - case NOTIFY_PENDING: - case STOPPED: - break; - default: - state = IDLE; - } - } - } while (newState == NOTIFY_PENDING); - } - - void AsynchIO::processCompletions() { - QueuePair::intrusive_ptr q = qp->getNextChannelEvent(); - - // Re-enable notification for queue: - // This needs to happen before we could do anything that could generate more work completion - // events (ie the callbacks etc. in the following). - // This can't make us reenter this code as the handle attached to the completion queue will still be - // disabled by the poller until we leave this code - qp->notifyRecv(); - qp->notifySend(); - - int recvEvents = 0; - int sendEvents = 0; - - // If no event do nothing - if (!q) - return; - - assert(q == qp); - - // Repeat until no more events - do { - QueuePairEvent e(qp->getNextEvent()); - if (!e) - break; - - ::ibv_wc_status status = e.getEventStatus(); - if (status != IBV_WC_SUCCESS) { - // Need special check for IBV_WC_WR_FLUSH_ERR here - // we will get this for every send/recv queue entry that was pending - // when disconnected, these aren't real errors and mostly need to be ignored - if (status == IBV_WC_WR_FLUSH_ERR) { - QueueDirection dir = e.getDirection(); - if (dir == SEND) { - Buffer* b = e.getBuffer(); - ++sendEvents; - returnSendBuffer(b); - --outstandingWrites; - } else { - ++recvEvents; - } - continue; - } - errorCallback(*this); - // TODO: Probably need to flush queues at this point - return; - } - - // Test if recv (or recv with imm) - //::ibv_wc_opcode eventType = e.getEventType(); - QueueDirection dir = e.getDirection(); - if (dir == RECV) { - ++recvEvents; - - Buffer* b = extractBuffer(e); - - // if there was no data sent then the message was only to update our credit - if ( b->dataCount() > 0 ) { - readCallback(*this, b); - } - - // At this point the buffer has been consumed so put it back on the recv queue - // TODO: Is this safe to do if the connection is disconnected already? - qp->postRecv(b); - - // Received another message - ++recvCredit; - - // Send recvCredit if it is large enough (it will have got this large because we've not sent anything recently) - if (recvCredit > recvBufferCount/2) { - // TODO: This should use RDMA write with imm as there might not ever be a buffer to receive this message - // but this is a little unlikely, as to get in this state we have to have received messages without sending any - // for a while so its likely we've received an credit update from the far side. - if (writable()) { - int creditSent = recvCredit & ~FlagsMask; - queueBuffer(0, creditSent); - recvCredit -= creditSent; - ++outstandingWrites; - --xmitCredit; - assert(xmitCredit>=0); - } else { - QPID_LOG(warning, "RDMA: qp=" << qp << ": Unable to send unsolicited credit"); - } - } - } else { - Buffer* b = e.getBuffer(); - ++sendEvents; - returnSendBuffer(b); - --outstandingWrites; - } - } while (true); - - // Not sure if this is expected or not - if (recvEvents == 0 && sendEvents == 0) { - QPID_LOG(debug, "RDMA: qp=" << qp << ": Got channel event with no recv/send completions"); - } - } - - void AsynchIO::doWriteCallback() { - // TODO: maybe don't call idle unless we're low on write buffers - // Keep on calling the idle routine as long as we are writable and we got something to write last call - - // Do callback even if there are no available free buffers as the application itself might be - // holding onto buffers - while (writable()) { - int xc = xmitCredit; - idleCallback(*this); - // Check whether we actually wrote anything - if (xmitCredit == xc) { - QPID_LOG(debug, "RDMA: qp=" << qp << ": Called for data, but got none: xmitCredit=" << xmitCredit); - return; - } - } - - checkDrained(); - } - - void AsynchIO::checkDrained() { - // If we've got all the write confirmations and we're draining - // We might get deleted in the drained callback so return immediately - if (draining) { - if (outstandingWrites == 0) { - draining = false; - NotifyCallback nc; - nc.swap(notifyCallback); - nc(*this); - } - return; - } - } - - void AsynchIO::doStoppedCallback() { - // Ensure we can't get any more callbacks (except for the stopped callback) - dataHandle.stopWatch(); - - NotifyCallback nc; - nc.swap(notifyCallback); - nc(*this); - } - - ConnectionManager::ConnectionManager( - ErrorCallback errc, - DisconnectedCallback dc - ) : - state(IDLE), - ci(Connection::make()), - handle(*ci, boost::bind(&ConnectionManager::event, this, _1), 0, 0), - errorCallback(errc), - disconnectedCallback(dc) - { - QPID_LOG(debug, "RDMA: ci=" << ci << ": Creating ConnectionManager"); - ci->nonblocking(); - } - - ConnectionManager::~ConnectionManager() - { - QPID_LOG(debug, "RDMA: ci=" << ci << ": Deleting ConnectionManager"); - } - - void ConnectionManager::start(Poller::shared_ptr poller, const qpid::sys::SocketAddress& addr) { - startConnection(ci, addr); - handle.startWatch(poller); - } - - void ConnectionManager::doStoppedCallback() { - // Ensure we can't get any more callbacks (except for the stopped callback) - handle.stopWatch(); - - NotifyCallback nc; - nc.swap(notifyCallback); - nc(*this); - } - - void ConnectionManager::stop(NotifyCallback nc) { - state = STOPPED; - notifyCallback = nc; - handle.call(boost::bind(&ConnectionManager::doStoppedCallback, this)); - } - - void ConnectionManager::event(DispatchHandle&) { - if (state.get() == STOPPED) return; - connectionEvent(ci); - } - - Listener::Listener( - const ConnectionParams& cp, - EstablishedCallback ec, - ErrorCallback errc, - DisconnectedCallback dc, - ConnectionRequestCallback crc - ) : - ConnectionManager(errc, dc), - checkConnectionParams(cp), - connectionRequestCallback(crc), - establishedCallback(ec) - { - } - - void Listener::startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr) { - ci->bind(addr); - ci->listen(); - } - - namespace { - const int64_t PoisonContext = -1; - } - - void Listener::connectionEvent(Connection::intrusive_ptr ci) { - ConnectionEvent e(ci->getNextEvent()); - - // If (for whatever reason) there was no event do nothing - if (!e) - return; - - // Important documentation ommision the new rdma_cm_id - // you get from CONNECT_REQUEST has the same context info - // as its parent listening rdma_cm_id - ::rdma_cm_event_type eventType = e.getEventType(); - ::rdma_conn_param conn_param = e.getConnectionParam(); - Rdma::Connection::intrusive_ptr id = e.getConnection(); - - // Check for previous disconnection (it appears that you actually can get connection - // request events after a disconnect event in rare circumstances) - if (reinterpret_cast(id->getContext())==PoisonContext) - return; - - switch (eventType) { - case RDMA_CM_EVENT_CONNECT_REQUEST: { - // Make sure peer has sent params we can use - if (!conn_param.private_data || conn_param.private_data_len < sizeof(NConnectionParams)) { - QPID_LOG(warning, "Rdma: rejecting connection attempt: unusable connection parameters"); - id->reject(); - break; - } - - const NConnectionParams* rcp = static_cast(conn_param.private_data); - ConnectionParams cp = *rcp; - - // Reject if requested msg size is bigger than we allow - if ( - cp.maxRecvBufferSize > checkConnectionParams.maxRecvBufferSize || - cp.initialXmitCredit > checkConnectionParams.initialXmitCredit - ) { - QPID_LOG(warning, "Rdma: rejecting connection attempt: connection parameters out of range: (" - << cp.maxRecvBufferSize << ">" << checkConnectionParams.maxRecvBufferSize << " || " - << cp.initialXmitCredit << ">" << checkConnectionParams.initialXmitCredit - << ")"); - id->reject(&checkConnectionParams); - break; - } - - bool accept = true; - if (connectionRequestCallback) - accept = connectionRequestCallback(id, cp); - - if (accept) { - // Accept connection - cp.initialXmitCredit = checkConnectionParams.initialXmitCredit; - id->accept(conn_param, rcp); - } else { - // Reject connection - QPID_LOG(warning, "Rdma: rejecting connection attempt: application policy"); - id->reject(); - } - break; - } - case RDMA_CM_EVENT_ESTABLISHED: - establishedCallback(id); - break; - case RDMA_CM_EVENT_DISCONNECTED: - disconnectedCallback(id); - // Poison the id context so that we do no more callbacks on it - id->removeContext(); - id->addContext(reinterpret_cast(PoisonContext)); - break; - case RDMA_CM_EVENT_CONNECT_ERROR: - errorCallback(id, CONNECT_ERROR); - break; - default: - // Unexpected response - errorCallback(id, UNKNOWN); - //std::cerr << "Warning: unexpected response to listen - " << eventType << "\n"; - } - } - - Connector::Connector( - const ConnectionParams& cp, - ConnectedCallback cc, - ErrorCallback errc, - DisconnectedCallback dc, - RejectedCallback rc - ) : - ConnectionManager(errc, dc), - connectionParams(cp), - rejectedCallback(rc), - connectedCallback(cc) - { - } - - void Connector::startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr) { - ci->resolve_addr(addr); - } - - void Connector::connectionEvent(Connection::intrusive_ptr ci) { - ConnectionEvent e(ci->getNextEvent()); - - // If (for whatever reason) there was no event do nothing - if (!e) - return; - - ::rdma_cm_event_type eventType = e.getEventType(); - ::rdma_conn_param conn_param = e.getConnectionParam(); - Rdma::Connection::intrusive_ptr id = e.getConnection(); - switch (eventType) { - case RDMA_CM_EVENT_ADDR_RESOLVED: - // RESOLVE_ADDR - ci->resolve_route(); - break; - case RDMA_CM_EVENT_ADDR_ERROR: - // RESOLVE_ADDR - errorCallback(ci, ADDR_ERROR); - break; - case RDMA_CM_EVENT_ROUTE_RESOLVED: { - // RESOLVE_ROUTE: - NConnectionParams rcp(connectionParams); - ci->connect(&rcp); - break; - } - case RDMA_CM_EVENT_ROUTE_ERROR: - // RESOLVE_ROUTE: - errorCallback(ci, ROUTE_ERROR); - break; - case RDMA_CM_EVENT_CONNECT_ERROR: - // CONNECTING - errorCallback(ci, CONNECT_ERROR); - break; - case RDMA_CM_EVENT_UNREACHABLE: - // CONNECTING - errorCallback(ci, UNREACHABLE); - break; - case RDMA_CM_EVENT_REJECTED: { - // CONNECTING - - // We can get this event if our peer is not running on the other side - // in this case we could get nearly anything in the private data: - // From private_data == 0 && private_data_len == 0 (Chelsio iWarp) - // to 148 bytes of zeros (Mellanox IB) - // - // So assume that if the the private data is absent or not the size of - // the connection parameters it isn't valid - ConnectionParams cp(0, 0, 0); - if (conn_param.private_data && conn_param.private_data_len == sizeof(NConnectionParams)) { - // Extract private data from event - const NConnectionParams* rcp = static_cast(conn_param.private_data); - cp = *rcp; - } - rejectedCallback(ci, cp); - break; - } - case RDMA_CM_EVENT_ESTABLISHED: { - // CONNECTING - // Extract private data from event - assert(conn_param.private_data && conn_param.private_data_len >= sizeof(NConnectionParams)); - const NConnectionParams* rcp = static_cast(conn_param.private_data); - ConnectionParams cp = *rcp; - connectedCallback(ci, cp); - break; - } - case RDMA_CM_EVENT_DISCONNECTED: - // ESTABLISHED - disconnectedCallback(ci); - break; - default: - QPID_LOG(warning, "RDMA: Unexpected event in connect: " << eventType); - } - } -} diff --git a/qpid/cpp/src/qpid/sys/rdma/RdmaIO.h b/qpid/cpp/src/qpid/sys/rdma/RdmaIO.h deleted file mode 100644 index ec9caaf08d..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/RdmaIO.h +++ /dev/null @@ -1,250 +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. - * - */ -#ifndef Rdma_Acceptor_h -#define Rdma_Acceptor_h - -#include "qpid/sys/rdma/rdma_wrap.h" - -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/SocketAddress.h" - -#include - -#include - -namespace Rdma { - - class Connection; - - class AsynchIO - { - typedef boost::function1 ErrorCallback; - typedef boost::function2 ReadCallback; - typedef boost::function1 IdleCallback; - typedef boost::function2 FullCallback; - typedef boost::function1 NotifyCallback; - - int protocolVersion; - int bufferSize; - int recvCredit; - int xmitCredit; - int recvBufferCount; - int xmitBufferCount; - int outstandingWrites; - bool draining; - enum State {IDLE, NOTIFY, NOTIFY_PENDING, STOPPED}; - State state; - qpid::sys::Mutex stateLock; - QueuePair::intrusive_ptr qp; - qpid::sys::DispatchHandleRef dataHandle; - - ReadCallback readCallback; - IdleCallback idleCallback; - FullCallback fullCallback; - ErrorCallback errorCallback; - NotifyCallback notifyCallback; - qpid::sys::DispatchHandle::Callback pendingWriteAction; - - public: - typedef boost::function1 RequestCallback; - - // TODO: Instead of specifying a buffer size specify the amount of memory the AsynchIO class can use - // for buffers both read and write (allocate half to each up front) and fail if we cannot allocate that much - // locked memory - AsynchIO( - QueuePair::intrusive_ptr q, - int version, - int size, - int xCredit, - int rCount, - ReadCallback rc, - IdleCallback ic, - FullCallback fc, - ErrorCallback ec - ); - ~AsynchIO(); - - void start(qpid::sys::Poller::shared_ptr poller); - bool writable() const; - void queueWrite(Buffer* buff); - void notifyPendingWrite(); - void drainWriteQueue(NotifyCallback); - void stop(NotifyCallback); - void requestCallback(RequestCallback); - int incompletedWrites() const; - Buffer* getSendBuffer(); - void returnSendBuffer(Buffer*); - - private: - const static int maxSupportedProtocolVersion = 1; - - // Constants for the peer-peer command messages - // These are sent in the high bits if the imm data of an rdma message - // The low bits are used to send the credit - const static int FlagsMask = 0xF0000000; // Mask for all flag bits - be sure to update this if you add more command bits - const static int IgnoreData = 0x10000000; // Message contains no application data - - void dataEvent(); - void writeEvent(); - void processCompletions(); - void doWriteCallback(); - void checkDrained(); - void doStoppedCallback(); - - void queueBuffer(Buffer* buff, int credit); - Buffer* extractBuffer(const QueuePairEvent& e); - }; - - // We're only writable if: - // * not draining write queue - // * we've got space in the transmit queue - // * we've got credit to transmit - // * if there's only 1 transmit credit we must send some credit - inline bool AsynchIO::writable() const { - assert(xmitCredit>=0); - return !draining && - outstandingWrites < xmitBufferCount && - xmitCredit > 0 && - ( xmitCredit > 1 || recvCredit > 0); - } - - inline int AsynchIO::incompletedWrites() const { - return outstandingWrites; - } - - inline Buffer* AsynchIO::getSendBuffer() { - return qp->getSendBuffer(); - } - - inline void AsynchIO::returnSendBuffer(Buffer* b) { - qp->returnSendBuffer(b); - } - - // These are the parameters necessary to start the conversation - // * Each peer HAS to allocate buffers of the size of the maximum receive from its peer - // * Each peer HAS to know the initial "credit" it has for transmitting to its peer - struct ConnectionParams { - uint32_t maxRecvBufferSize; - uint16_t initialXmitCredit; - uint16_t rdmaProtocolVersion; - - // Default to protocol version 1 - ConnectionParams(uint32_t s, uint16_t c, uint16_t v = 1) : - maxRecvBufferSize(s), - initialXmitCredit(c), - rdmaProtocolVersion(v) - {} - }; - - enum ErrorType { - ADDR_ERROR, - ROUTE_ERROR, - CONNECT_ERROR, - UNREACHABLE, - UNKNOWN - }; - - typedef boost::function2 ErrorCallback; - typedef boost::function1 DisconnectedCallback; - - class ConnectionManager { - typedef boost::function1 NotifyCallback; - - enum State {IDLE, STOPPED}; - qpid::sys::AtomicValue state; - Connection::intrusive_ptr ci; - qpid::sys::DispatchHandleRef handle; - NotifyCallback notifyCallback; - - protected: - ErrorCallback errorCallback; - DisconnectedCallback disconnectedCallback; - - public: - ConnectionManager( - ErrorCallback errc, - DisconnectedCallback dc - ); - - virtual ~ConnectionManager(); - - void start(qpid::sys::Poller::shared_ptr poller, const qpid::sys::SocketAddress& addr); - void stop(NotifyCallback); - - private: - void event(qpid::sys::DispatchHandle& handle); - void doStoppedCallback(); - - virtual void startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr) = 0; - virtual void connectionEvent(Connection::intrusive_ptr ci) = 0; - }; - - typedef boost::function2 ConnectionRequestCallback; - typedef boost::function1 EstablishedCallback; - - class Listener : public ConnectionManager - { - ConnectionParams checkConnectionParams; - ConnectionRequestCallback connectionRequestCallback; - EstablishedCallback establishedCallback; - - public: - Listener( - const ConnectionParams& cp, - EstablishedCallback ec, - ErrorCallback errc, - DisconnectedCallback dc, - ConnectionRequestCallback crc = 0 - ); - - private: - void startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr); - void connectionEvent(Connection::intrusive_ptr ci); - }; - - typedef boost::function2 RejectedCallback; - typedef boost::function2 ConnectedCallback; - - class Connector : public ConnectionManager - { - ConnectionParams connectionParams; - RejectedCallback rejectedCallback; - ConnectedCallback connectedCallback; - - public: - Connector( - const ConnectionParams& cp, - ConnectedCallback cc, - ErrorCallback errc, - DisconnectedCallback dc, - RejectedCallback rc = 0 - ); - - private: - void startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr); - void connectionEvent(Connection::intrusive_ptr ci); - }; -} - -#endif // Rdma_Acceptor_h diff --git a/qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp b/qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp deleted file mode 100644 index 3764792d48..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/RdmaServer.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 "qpid/sys/Thread.h" -#include "qpid/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" - -#include - -#include -#include -#include -#include - -#include - -using std::vector; -using std::queue; -using std::string; -using std::cout; -using std::cerr; - -using qpid::sys::Thread; -using qpid::sys::SocketAddress; -using qpid::sys::Poller; - -// All the accepted connections -namespace qpid { -namespace tests { - -struct Buffer { - char* bytes() const {return bytes_;} - int32_t byteCount() const {return size;} - - Buffer(const int32_t s): - bytes_(new char[s]), - size(s) - { - } - - ~Buffer() { - delete [] bytes_; - } -private: - char* bytes_; - int32_t size; -}; - -struct ConRec { - Rdma::Connection::intrusive_ptr connection; - Rdma::AsynchIO* data; - queue queuedWrites; - - ConRec(Rdma::Connection::intrusive_ptr c) : - connection(c) - {} -}; - -void dataError(Rdma::AsynchIO&) { - cout << "Data error:\n"; -} - -void idle(ConRec* cr, Rdma::AsynchIO& a) { - // Need to make sure full is not called as it would reorder messages - while (!cr->queuedWrites.empty() && a.writable()) { - Rdma::Buffer* rbuf = a.getSendBuffer(); - if (!rbuf) break; - Buffer* buf = cr->queuedWrites.front(); - cr->queuedWrites.pop(); - std::copy(buf->bytes(), buf->bytes()+buf->byteCount(), rbuf->bytes()); - rbuf->dataCount(buf->byteCount()); - delete buf; - a.queueWrite(rbuf); - } -} - -void data(ConRec* cr, Rdma::AsynchIO& a, Rdma::Buffer* b) { - // Echo data back - Rdma::Buffer* buf = 0; - if (cr->queuedWrites.empty() && a.writable()) { - buf = a.getSendBuffer(); - } - if (buf) { - std::copy(b->bytes(), b->bytes()+b->dataCount(), buf->bytes()); - buf->dataCount(b->dataCount()); - a.queueWrite(buf); - } else { - Buffer* buf = new Buffer(b->dataCount()); - std::copy(b->bytes(), b->bytes()+b->dataCount(), buf->bytes()); - cr->queuedWrites.push(buf); - // Try to empty queue - idle(cr, a); - } -} - -void full(ConRec*, Rdma::AsynchIO&, Rdma::Buffer*) { - // Shouldn't ever be called - cout << "!"; -} - -void drained(Rdma::AsynchIO&) { - cout << "Drained:\n"; -} - -void disconnected(const Rdma::Connection::intrusive_ptr& ci) { - ConRec* cr = ci->getContext(); - cr->connection->disconnect(); - cr->data->drainWriteQueue(drained); - delete cr; - cout << "Disconnected: " << cr << "\n"; -} - -void connectionError(const Rdma::Connection::intrusive_ptr& ci, Rdma::ErrorType) { - ConRec* cr = ci->getContext(); - cr->connection->disconnect(); - if (cr) { - cr->data->drainWriteQueue(drained); - delete cr; - } - cout << "Connection error: " << cr << "\n"; -} - -bool connectionRequest(const Rdma::Connection::intrusive_ptr& ci, const Rdma::ConnectionParams& cp) { - cout << "Incoming connection: "; - - // For fun reject alternate connection attempts - static bool x = false; - x = true; - - // Must create aio here so as to prepost buffers *before* we accept connection - if (x) { - ConRec* cr = new ConRec(ci); - Rdma::AsynchIO* aio = - new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit, Rdma::DEFAULT_WR_ENTRIES, - boost::bind(data, cr, _1, _2), - boost::bind(idle, cr, _1), - boost::bind(full, cr, _1, _2), - dataError); - ci->addContext(cr); - cr->data = aio; - cout << "Accept=>" << cr << "\n"; - } else { - cout << "Reject\n"; - } - - return x; -} - -void connected(Poller::shared_ptr poller, const Rdma::Connection::intrusive_ptr& ci) { - static int cnt = 0; - ConRec* cr = ci->getContext(); - cout << "Connected: " << cr << "(" << ++cnt << ")\n"; - - cr->data->start(poller); -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char* argv[]) { - vector args(&argv[0], &argv[argc]); - - std::string port = (args.size() < 2) ? "20079" : args[1]; - cout << "Listening on port: " << port << "\n"; - - try { - boost::shared_ptr p(new Poller()); - - Rdma::Listener a( - Rdma::ConnectionParams(16384, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(connected, p, _1), - connectionError, - disconnected, - connectionRequest); - - - SocketAddress sa("", port); - a.start(p, sa); - - // The poller loop blocks all signals so run in its own thread - Thread t(*p); - - ::pause(); - p->shutdown(); - t.join(); - } catch (Rdma::Exception& e) { - int err = e.getError(); - cerr << "Error: " << e.what() << "(" << err << ")\n"; - } -} diff --git a/qpid/cpp/src/qpid/sys/rdma/rdma_exception.h b/qpid/cpp/src/qpid/sys/rdma/rdma_exception.h deleted file mode 100644 index a3a289e38a..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/rdma_exception.h +++ /dev/null @@ -1,69 +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. - * - */ -#ifndef RDMA_EXCEPTION_H -#define RDMA_EXCEPTION_H - -#include - -#include -#include - -namespace Rdma { - static __thread char s[50]; - class Exception : public std::exception { - int err; - - public: - Exception(int e) : err(e) {} - int getError() { return err; } - const char* what() const throw() { - return ::strerror_r(err, s, 50); - } - }; - - inline void THROW_ERRNO() { - throw Rdma::Exception(errno); - } - - inline void CHECK(int rc) { - if (rc != 0) - throw Rdma::Exception((rc == -1) ? errno : rc >0 ? rc : -rc); - } - - inline int GETERR(int rc) { - return (rc == -1) ? errno : rc > 0 ? rc : -rc; - } - - inline void CHECK_IBV(int rc) { - if (rc != 0) - throw Rdma::Exception(rc); - } - - template - inline - T* CHECK_NULL(T* rc) { - if (rc == 0) - THROW_ERRNO(); - return rc; - } -} - -#endif // RDMA_EXCEPTION_H diff --git a/qpid/cpp/src/qpid/sys/rdma/rdma_factories.cpp b/qpid/cpp/src/qpid/sys/rdma/rdma_factories.cpp deleted file mode 100644 index a66f5b4035..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/rdma_factories.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/rdma/rdma_factories.h" - -#include "qpid/sys/rdma/rdma_exception.h" - - -namespace Rdma { - // Intentionally ignore return values for these functions - // - we can't do anything about then anyway - void acker(::rdma_cm_event* e) throw () { - if (e) (void) ::rdma_ack_cm_event(e); - } - - void destroyEChannel(::rdma_event_channel* c) throw () { - if (c) (void) ::rdma_destroy_event_channel(c); - } - - void destroyId(::rdma_cm_id* i) throw () { - if (i) (void) ::rdma_destroy_id(i); - } - - void deallocPd(::ibv_pd* p) throw () { - if (p) (void) ::ibv_dealloc_pd(p); - } - - void deregMr(::ibv_mr* mr) throw () { - if (mr) (void) ::ibv_dereg_mr(mr); - } - - void destroyCChannel(::ibv_comp_channel* c) throw () { - if (c) (void) ::ibv_destroy_comp_channel(c); - } - - void destroyCq(::ibv_cq* cq) throw () { - if (cq) (void) ::ibv_destroy_cq(cq); - } - - void destroyQp(::ibv_qp* qp) throw () { - if (qp) (void) ::ibv_destroy_qp(qp); - } - - boost::shared_ptr< ::rdma_cm_id > mkId(::rdma_cm_id* i) { - return boost::shared_ptr< ::rdma_cm_id >(i, destroyId); - } - - boost::shared_ptr< ::rdma_cm_event > mkEvent(::rdma_cm_event* e) { - return boost::shared_ptr< ::rdma_cm_event >(e, acker); - } - - boost::shared_ptr< ::ibv_qp > mkQp(::ibv_qp* qp) { - return boost::shared_ptr< ::ibv_qp > (qp, destroyQp); - } - - boost::shared_ptr< ::rdma_event_channel > mkEChannel() { - ::rdma_event_channel* c = CHECK_NULL(::rdma_create_event_channel()); - return boost::shared_ptr< ::rdma_event_channel >(c, destroyEChannel); - } - - boost::shared_ptr< ::rdma_cm_id > - mkId(::rdma_event_channel* ec, void* context, ::rdma_port_space ps) { - ::rdma_cm_id* i; - CHECK(::rdma_create_id(ec, &i, context, ps)); - return mkId(i); - } - - boost::shared_ptr< ::ibv_pd > allocPd(::ibv_context* c) { - ::ibv_pd* pd = CHECK_NULL(::ibv_alloc_pd(c)); - return boost::shared_ptr< ::ibv_pd >(pd, deallocPd); - } - - boost::shared_ptr< ::ibv_mr > regMr(::ibv_pd* pd, void* addr, size_t length, ::ibv_access_flags access) { - ::ibv_mr* mr = CHECK_NULL(::ibv_reg_mr(pd, addr, length, access)); - return boost::shared_ptr< ::ibv_mr >(mr, deregMr); - } - - boost::shared_ptr< ::ibv_comp_channel > mkCChannel(::ibv_context* c) { - ::ibv_comp_channel* cc = CHECK_NULL(::ibv_create_comp_channel(c)); - return boost::shared_ptr< ::ibv_comp_channel >(cc, destroyCChannel); - } - - boost::shared_ptr< ::ibv_cq > - mkCq(::ibv_context* c, int cqe, void* context, ::ibv_comp_channel* cc) { - ::ibv_cq* cq = CHECK_NULL(::ibv_create_cq(c, cqe, context, cc, 0)); - return boost::shared_ptr< ::ibv_cq >(cq, destroyCq); - } -} diff --git a/qpid/cpp/src/qpid/sys/rdma/rdma_factories.h b/qpid/cpp/src/qpid/sys/rdma/rdma_factories.h deleted file mode 100644 index bfca71fc7e..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/rdma_factories.h +++ /dev/null @@ -1,40 +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. - * - */ -#ifndef RDMA_FACTORIES_H -#define RDMA_FACTORIES_H - -#include - -#include - -namespace Rdma { - boost::shared_ptr< ::rdma_event_channel > mkEChannel(); - boost::shared_ptr< ::rdma_cm_id > mkId(::rdma_event_channel* ec, void* context, ::rdma_port_space ps); - boost::shared_ptr< ::rdma_cm_id > mkId(::rdma_cm_id* i); - boost::shared_ptr< ::rdma_cm_event > mkEvent(::rdma_cm_event* e); - boost::shared_ptr< ::ibv_qp > mkQp(::ibv_qp* qp); - boost::shared_ptr< ::ibv_pd > allocPd(::ibv_context* c); - boost::shared_ptr< ::ibv_mr > regMr(::ibv_pd* pd, void* addr, size_t length, ::ibv_access_flags access); - boost::shared_ptr< ::ibv_comp_channel > mkCChannel(::ibv_context* c); - boost::shared_ptr< ::ibv_cq > mkCq(::ibv_context* c, int cqe, void* context, ::ibv_comp_channel* cc); -} - -#endif // RDMA_FACTORIES_H diff --git a/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.cpp b/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.cpp deleted file mode 100644 index 39c7cc2ab4..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.cpp +++ /dev/null @@ -1,576 +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/sys/rdma/rdma_wrap.h" - -#include "qpid/sys/rdma/rdma_factories.h" -#include "qpid/sys/rdma/rdma_exception.h" - -#include "qpid/sys/posix/PrivatePosix.h" - -#include -#include - -#include -#include - -namespace Rdma { - const ::rdma_conn_param DEFAULT_CONNECT_PARAM = { - 0, // .private_data - 0, // .private_data_len - 4, // .responder_resources - 4, // .initiator_depth - 0, // .flow_control - 5, // .retry_count - 7 // .rnr_retry_count - }; - - // This is moderately inefficient so don't use in a critical path - int deviceCount() { - int count; - ::ibv_free_device_list(::ibv_get_device_list(&count)); - return count; - } - - Buffer::Buffer(uint32_t lkey, char* bytes, const int32_t byteCount, - const int32_t reserve) : - bufferSize(byteCount + reserve), reserved(reserve) - { - sge.addr = (uintptr_t) bytes; - sge.length = 0; - sge.lkey = lkey; - } - - QueuePairEvent::QueuePairEvent() : - dir(NONE) - {} - - QueuePairEvent::QueuePairEvent( - const ::ibv_wc& w, - boost::shared_ptr< ::ibv_cq > c, - QueueDirection d) : - cq(c), - wc(w), - dir(d) - { - assert(dir != NONE); - } - - QueuePairEvent::operator bool() const { - return dir != NONE; - } - - bool QueuePairEvent::immPresent() const { - return wc.wc_flags & IBV_WC_WITH_IMM; - } - - uint32_t QueuePairEvent::getImm() const { - return ntohl(wc.imm_data); - } - - QueueDirection QueuePairEvent::getDirection() const { - return dir; - } - - ::ibv_wc_opcode QueuePairEvent::getEventType() const { - return wc.opcode; - } - - ::ibv_wc_status QueuePairEvent::getEventStatus() const { - return wc.status; - } - - Buffer* QueuePairEvent::getBuffer() const { - Buffer* b = reinterpret_cast(wc.wr_id); - b->dataCount(wc.byte_len); - return b; - } - - QueuePair::QueuePair(boost::shared_ptr< ::rdma_cm_id > i) : - handle(new qpid::sys::IOHandle), - pd(allocPd(i->verbs)), - cchannel(mkCChannel(i->verbs)), - scq(mkCq(i->verbs, DEFAULT_CQ_ENTRIES, 0, cchannel.get())), - rcq(mkCq(i->verbs, DEFAULT_CQ_ENTRIES, 0, cchannel.get())), - outstandingSendEvents(0), - outstandingRecvEvents(0) - { - handle->fd = cchannel->fd; - - // Set cq context to this QueuePair object so we can find - // ourselves again - scq->cq_context = this; - rcq->cq_context = this; - - ::ibv_device_attr dev_attr; - CHECK(::ibv_query_device(i->verbs, &dev_attr)); - - ::ibv_qp_init_attr qp_attr = {}; - - // TODO: make a default struct for this - qp_attr.cap.max_send_wr = DEFAULT_WR_ENTRIES; - qp_attr.cap.max_send_sge = 1; - qp_attr.cap.max_recv_wr = DEFAULT_WR_ENTRIES; - qp_attr.cap.max_recv_sge = 1; - - qp_attr.send_cq = scq.get(); - qp_attr.recv_cq = rcq.get(); - qp_attr.qp_type = IBV_QPT_RC; - - CHECK(::rdma_create_qp(i.get(), pd.get(), &qp_attr)); - qp = mkQp(i->qp); - - // Set the qp context to this so we can find ourselves again - qp->qp_context = this; - } - - QueuePair::~QueuePair() { - // Reset back pointer in case someone else has the qp - qp->qp_context = 0; - - // Dispose queue pair before we ack events - qp.reset(); - - if (outstandingSendEvents > 0) - ::ibv_ack_cq_events(scq.get(), outstandingSendEvents); - if (outstandingRecvEvents > 0) - ::ibv_ack_cq_events(rcq.get(), outstandingRecvEvents); - - // Deallocate recv buffer memory - if (rmr) delete [] static_cast(rmr->addr); - - // Deallocate recv buffer memory - if (smr) delete [] static_cast(smr->addr); - - // The buffers vectors automatically deletes all the buffers we've allocated - } - - QueuePair::operator qpid::sys::IOHandle&() const - { - return *handle; - } - - // Create buffers to use for writing - void QueuePair::createSendBuffers(int sendBufferCount, int bufferSize, int reserved) - { - assert(!smr); - - // Round up buffersize to cacheline (64 bytes) - int dataLength = (bufferSize+reserved+63) & (~63); - - // Allocate memory block for all receive buffers - char* mem = new char [sendBufferCount * dataLength]; - smr = regMr(pd.get(), mem, sendBufferCount * dataLength, ::IBV_ACCESS_LOCAL_WRITE); - sendBuffers.reserve(sendBufferCount); - freeBuffers.reserve(sendBufferCount); - for (int i = 0; ilkey, &mem[i*dataLength], bufferSize, reserved)); - freeBuffers.push_back(i); - } - } - - Buffer* QueuePair::getSendBuffer() { - qpid::sys::ScopedLock l(bufferLock); - if (freeBuffers.empty()) - return 0; - int i = freeBuffers.back(); - freeBuffers.pop_back(); - assert(i >= 0 && i < int(sendBuffers.size())); - Buffer* b = &sendBuffers[i]; - b->dataCount(0); - return b; - } - - void QueuePair::returnSendBuffer(Buffer* b) { - qpid::sys::ScopedLock l(bufferLock); - int i = b - &sendBuffers[0]; - assert(i >= 0 && i < int(sendBuffers.size())); - freeBuffers.push_back(i); - } - - void QueuePair::allocateRecvBuffers(int recvBufferCount, int bufferSize) - { - assert(!rmr); - - // Round up buffersize to cacheline (64 bytes) - bufferSize = (bufferSize+63) & (~63); - - // Allocate memory block for all receive buffers - char* mem = new char [recvBufferCount * bufferSize]; - rmr = regMr(pd.get(), mem, recvBufferCount * bufferSize, ::IBV_ACCESS_LOCAL_WRITE); - recvBuffers.reserve(recvBufferCount); - for (int i = 0; ilkey, &mem[i*bufferSize], bufferSize)); - postRecv(&recvBuffers[i]); - } - } - - // Make channel non-blocking by making - // associated fd nonblocking - void QueuePair::nonblocking() { - ::fcntl(cchannel->fd, F_SETFL, O_NONBLOCK); - } - - // If we get EAGAIN because the channel has been set non blocking - // and we'd have to wait then return an empty event - QueuePair::intrusive_ptr QueuePair::getNextChannelEvent() { - // First find out which cq has the event - ::ibv_cq* cq; - void* ctx; - int rc = ::ibv_get_cq_event(cchannel.get(), &cq, &ctx); - if (rc == -1 && errno == EAGAIN) - return 0; - CHECK(rc); - - // Batch acknowledge the event - if (cq == scq.get()) { - if (++outstandingSendEvents > DEFAULT_CQ_ENTRIES / 2) { - ::ibv_ack_cq_events(cq, outstandingSendEvents); - outstandingSendEvents = 0; - } - } else if (cq == rcq.get()) { - if (++outstandingRecvEvents > DEFAULT_CQ_ENTRIES / 2) { - ::ibv_ack_cq_events(cq, outstandingRecvEvents); - outstandingRecvEvents = 0; - } - } - - return static_cast(ctx); - } - - QueuePairEvent QueuePair::getNextEvent() { - ::ibv_wc w; - if (::ibv_poll_cq(scq.get(), 1, &w) == 1) - return QueuePairEvent(w, scq, SEND); - else if (::ibv_poll_cq(rcq.get(), 1, &w) == 1) - return QueuePairEvent(w, rcq, RECV); - else - return QueuePairEvent(); - } - - void QueuePair::notifyRecv() { - CHECK_IBV(ibv_req_notify_cq(rcq.get(), 0)); - } - - void QueuePair::notifySend() { - CHECK_IBV(ibv_req_notify_cq(scq.get(), 0)); - } - - void QueuePair::postRecv(Buffer* buf) { - ::ibv_recv_wr rwr = {}; - - rwr.wr_id = reinterpret_cast(buf); - // We are given the whole buffer - buf->dataCount(buf->byteCount()); - rwr.sg_list = &buf->sge; - rwr.num_sge = 1; - - ::ibv_recv_wr* badrwr = 0; - CHECK(::ibv_post_recv(qp.get(), &rwr, &badrwr)); - if (badrwr) - throw std::logic_error("ibv_post_recv(): Bad rwr"); - } - - void QueuePair::postSend(Buffer* buf) { - ::ibv_send_wr swr = {}; - - swr.wr_id = reinterpret_cast(buf); - swr.opcode = IBV_WR_SEND; - swr.send_flags = IBV_SEND_SIGNALED; - swr.sg_list = &buf->sge; - swr.num_sge = 1; - - ::ibv_send_wr* badswr = 0; - CHECK(::ibv_post_send(qp.get(), &swr, &badswr)); - if (badswr) - throw std::logic_error("ibv_post_send(): Bad swr"); - } - - void QueuePair::postSend(uint32_t imm, Buffer* buf) { - ::ibv_send_wr swr = {}; - - swr.wr_id = reinterpret_cast(buf); - swr.imm_data = htonl(imm); - swr.opcode = IBV_WR_SEND_WITH_IMM; - swr.send_flags = IBV_SEND_SIGNALED; - swr.sg_list = &buf->sge; - swr.num_sge = 1; - - ::ibv_send_wr* badswr = 0; - CHECK(::ibv_post_send(qp.get(), &swr, &badswr)); - if (badswr) - throw std::logic_error("ibv_post_send(): Bad swr"); - } - - ConnectionEvent::ConnectionEvent(::rdma_cm_event* e) : - id((e->event != RDMA_CM_EVENT_CONNECT_REQUEST) ? - Connection::find(e->id) : new Connection(e->id)), - listen_id(Connection::find(e->listen_id)), - event(mkEvent(e)) - {} - - ConnectionEvent::operator bool() const { - return !!event; - } - - ::rdma_cm_event_type ConnectionEvent::getEventType() const { - return event->event; - } - - ::rdma_conn_param ConnectionEvent::getConnectionParam() const { - // It's badly documented, but it seems from the librdma source code that all the following - // event types have a valid param.conn - switch (event->event) { - case RDMA_CM_EVENT_CONNECT_REQUEST: - case RDMA_CM_EVENT_ESTABLISHED: - case RDMA_CM_EVENT_REJECTED: - case RDMA_CM_EVENT_DISCONNECTED: - case RDMA_CM_EVENT_CONNECT_ERROR: - return event->param.conn; - default: - ::rdma_conn_param p = {}; - return p; - } - } - - boost::intrusive_ptr ConnectionEvent::getConnection () const { - return id; - } - - boost::intrusive_ptr ConnectionEvent::getListenId() const { - return listen_id; - } - - // Wrap the passed in rdma_cm_id with a Connection - // this basically happens only on connection request - Connection::Connection(::rdma_cm_id* i) : - handle(new qpid::sys::IOHandle), - id(mkId(i)), - context(0) - { - handle->fd = id->channel->fd; - - // Just overwrite the previous context as it will - // have come from the listening connection - if (i) - i->context = this; - } - - Connection::Connection() : - handle(new qpid::sys::IOHandle), - channel(mkEChannel()), - id(mkId(channel.get(), this, RDMA_PS_TCP)), - context(0) - { - handle->fd = channel->fd; - } - - Connection::~Connection() { - // Reset the id context in case someone else has it - id->context = 0; - } - - Connection::operator qpid::sys::IOHandle&() const - { - return *handle; - } - - void Connection::ensureQueuePair() { - assert(id.get()); - - // Only allocate a queue pair if there isn't one already - if (qp) - return; - - qp = new QueuePair(id); - } - - Connection::intrusive_ptr Connection::make() { - return new Connection(); - } - - Connection::intrusive_ptr Connection::find(::rdma_cm_id* i) { - if (!i) - return 0; - Connection* id = static_cast< Connection* >(i->context); - if (!id) - throw std::logic_error("Couldn't find existing Connection"); - return id; - } - - // Make channel non-blocking by making - // associated fd nonblocking - void Connection::nonblocking() { - assert(id.get()); - ::fcntl(id->channel->fd, F_SETFL, O_NONBLOCK); - } - - // If we get EAGAIN because the channel has been set non blocking - // and we'd have to wait then return an empty event - ConnectionEvent Connection::getNextEvent() { - assert(id.get()); - ::rdma_cm_event* e; - int rc = ::rdma_get_cm_event(id->channel, &e); - if (GETERR(rc) == EAGAIN) - return ConnectionEvent(); - CHECK(rc); - return ConnectionEvent(e); - } - - void Connection::bind(const qpid::sys::SocketAddress& src_addr) const { - assert(id.get()); - CHECK(::rdma_bind_addr(id.get(), getAddrInfo(src_addr).ai_addr)); - } - - void Connection::listen(int backlog) const { - assert(id.get()); - CHECK(::rdma_listen(id.get(), backlog)); - } - - void Connection::resolve_addr( - const qpid::sys::SocketAddress& dst_addr, - int timeout_ms) const - { - assert(id.get()); - CHECK(::rdma_resolve_addr(id.get(), 0, getAddrInfo(dst_addr).ai_addr, timeout_ms)); - } - - void Connection::resolve_route(int timeout_ms) const { - assert(id.get()); - CHECK(::rdma_resolve_route(id.get(), timeout_ms)); - } - - void Connection::disconnect() const { - assert(id.get()); - int rc = ::rdma_disconnect(id.get()); - // iWarp doesn't let you disconnect a disconnected connection - // but Infiniband can do so it's okay to call rdma_disconnect() - // in response to a disconnect event, but we may get an error - if (GETERR(rc) == EINVAL) - return; - CHECK(rc); - } - - // TODO: Currently you can only connect with the default connection parameters - void Connection::connect(const void* data, size_t len) { - assert(id.get()); - // Need to have a queue pair before we can connect - ensureQueuePair(); - - ::rdma_conn_param p = DEFAULT_CONNECT_PARAM; - p.private_data = data; - p.private_data_len = len; - CHECK(::rdma_connect(id.get(), &p)); - } - - void Connection::connect() { - connect(0, 0); - } - - void Connection::accept(const ::rdma_conn_param& param, const void* data, size_t len) { - assert(id.get()); - // Need to have a queue pair before we can accept - ensureQueuePair(); - - ::rdma_conn_param p = param; - p.private_data = data; - p.private_data_len = len; - CHECK(::rdma_accept(id.get(), &p)); - } - - void Connection::accept(const ::rdma_conn_param& param) { - accept(param, 0, 0); - } - - void Connection::reject(const void* data, size_t len) const { - assert(id.get()); - CHECK(::rdma_reject(id.get(), data, len)); - } - - void Connection::reject() const { - assert(id.get()); - CHECK(::rdma_reject(id.get(), 0, 0)); - } - - QueuePair::intrusive_ptr Connection::getQueuePair() { - assert(id.get()); - - ensureQueuePair(); - - return qp; - } - - std::string Connection::getLocalName() const { - ::sockaddr* addr = ::rdma_get_local_addr(id.get()); - char hostName[NI_MAXHOST]; - char portName[NI_MAXSERV]; - CHECK_IBV(::getnameinfo( - addr, sizeof(::sockaddr_storage), - hostName, sizeof(hostName), - portName, sizeof(portName), - NI_NUMERICHOST | NI_NUMERICSERV)); - std::string r(hostName); - r += ":"; - r += portName; - return r; - } - - std::string Connection::getPeerName() const { - ::sockaddr* addr = ::rdma_get_peer_addr(id.get()); - char hostName[NI_MAXHOST]; - char portName[NI_MAXSERV]; - CHECK_IBV(::getnameinfo( - addr, sizeof(::sockaddr_storage), - hostName, sizeof(hostName), - portName, sizeof(portName), - NI_NUMERICHOST | NI_NUMERICSERV)); - std::string r(hostName); - r += ":"; - r += portName; - return r; - } -} - -std::ostream& operator<<(std::ostream& o, ::rdma_cm_event_type t) { -# define CHECK_TYPE(t) case t: o << #t; break; - switch(t) { - CHECK_TYPE(RDMA_CM_EVENT_ADDR_RESOLVED) - CHECK_TYPE(RDMA_CM_EVENT_ADDR_ERROR) - CHECK_TYPE(RDMA_CM_EVENT_ROUTE_RESOLVED) - CHECK_TYPE(RDMA_CM_EVENT_ROUTE_ERROR) - CHECK_TYPE(RDMA_CM_EVENT_CONNECT_REQUEST) - CHECK_TYPE(RDMA_CM_EVENT_CONNECT_RESPONSE) - CHECK_TYPE(RDMA_CM_EVENT_CONNECT_ERROR) - CHECK_TYPE(RDMA_CM_EVENT_UNREACHABLE) - CHECK_TYPE(RDMA_CM_EVENT_REJECTED) - CHECK_TYPE(RDMA_CM_EVENT_ESTABLISHED) - CHECK_TYPE(RDMA_CM_EVENT_DISCONNECTED) - CHECK_TYPE(RDMA_CM_EVENT_DEVICE_REMOVAL) - CHECK_TYPE(RDMA_CM_EVENT_MULTICAST_JOIN) - CHECK_TYPE(RDMA_CM_EVENT_MULTICAST_ERROR) - default: - o << "UNKNOWN_EVENT"; - } -# undef CHECK_TYPE - return o; -} diff --git a/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h b/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h deleted file mode 100644 index 5d9b681da8..0000000000 --- a/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h +++ /dev/null @@ -1,305 +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. - * - */ -#ifndef RDMA_WRAP_H -#define RDMA_WRAP_H - -#include - -#include "qpid/RefCounted.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Mutex.h" - -#include -#include -#include -#include - -#include - -namespace qpid { -namespace sys { - class SocketAddress; -}} - -namespace Rdma { - const int DEFAULT_TIMEOUT = 2000; // 2 secs - const int DEFAULT_BACKLOG = 100; - const int DEFAULT_CQ_ENTRIES = 256; - const int DEFAULT_WR_ENTRIES = 64; - extern const ::rdma_conn_param DEFAULT_CONNECT_PARAM; - - int deviceCount(); - - struct Buffer { - friend class QueuePair; - friend class QueuePairEvent; - - char* bytes() const; - uint32_t* words() const; - int32_t byteCount() const; - int32_t wordCount() const; - int32_t dataCount() const; - void dataCount(int32_t); - - private: - Buffer(uint32_t lkey, char* bytes, const int32_t byteCount, const int32_t reserve=0); - int32_t bufferSize; - int32_t reserved; // for framing header - ::ibv_sge sge; - }; - - inline char* Buffer::bytes() const { - return (char*) sge.addr; - } - - inline uint32_t* Buffer::words() const { - return (uint32_t*) sge.addr; - } - - /** return the number of bytes available for application data */ - inline int32_t Buffer::byteCount() const { - return bufferSize - reserved; - } - - /** return the number of words available for application data */ - inline int32_t Buffer::wordCount() const { - return (bufferSize - reserved) / sizeof(uint32_t); - } - - inline int32_t Buffer::dataCount() const { - return sge.length; - } - - inline void Buffer::dataCount(int32_t s) { - // catch any attempt to overflow a buffer - assert(s <= bufferSize + reserved); - sge.length = s; - } - - class Connection; - - enum QueueDirection { - NONE, - SEND, - RECV - }; - - class QueuePairEvent { - boost::shared_ptr< ::ibv_cq > cq; - ::ibv_wc wc; - QueueDirection dir; - - friend class QueuePair; - - QueuePairEvent(); - QueuePairEvent( - const ::ibv_wc& w, - boost::shared_ptr< ::ibv_cq > c, - QueueDirection d); - - public: - operator bool() const; - bool immPresent() const; - uint32_t getImm() const; - QueueDirection getDirection() const; - ::ibv_wc_opcode getEventType() const; - ::ibv_wc_status getEventStatus() const; - Buffer* getBuffer() const; - }; - - // Wrapper for a queue pair - this has the functionality for - // putting buffers on the receive queue and for sending buffers - // to the other end of the connection. - class QueuePair : public qpid::RefCounted { - friend class Connection; - - boost::scoped_ptr< qpid::sys::IOHandle > handle; - boost::shared_ptr< ::ibv_pd > pd; - boost::shared_ptr< ::ibv_mr > smr; - boost::shared_ptr< ::ibv_mr > rmr; - boost::shared_ptr< ::ibv_comp_channel > cchannel; - boost::shared_ptr< ::ibv_cq > scq; - boost::shared_ptr< ::ibv_cq > rcq; - boost::shared_ptr< ::ibv_qp > qp; - int outstandingSendEvents; - int outstandingRecvEvents; - std::vector sendBuffers; - std::vector recvBuffers; - qpid::sys::Mutex bufferLock; - std::vector freeBuffers; - - QueuePair(boost::shared_ptr< ::rdma_cm_id > id); - ~QueuePair(); - - public: - typedef boost::intrusive_ptr intrusive_ptr; - - operator qpid::sys::IOHandle&() const; - - // Create a buffers to use for writing - void createSendBuffers(int sendBufferCount, int dataSize, int headerSize); - - // Get a send buffer - Buffer* getSendBuffer(); - - // Return buffer to pool after use - void returnSendBuffer(Buffer* b); - - // Create and post recv buffers - void allocateRecvBuffers(int recvBufferCount, int bufferSize); - - // Make channel non-blocking by making - // associated fd nonblocking - void nonblocking(); - - // If we get EAGAIN because the channel has been set non blocking - // and we'd have to wait then return an empty event - QueuePair::intrusive_ptr getNextChannelEvent(); - - QueuePairEvent getNextEvent(); - - void postRecv(Buffer* buf); - void postSend(Buffer* buf); - void postSend(uint32_t imm, Buffer* buf); - void notifyRecv(); - void notifySend(); - }; - - class ConnectionEvent { - friend class Connection; - - // The order of the members is important as we have to acknowledge - // the event before destroying the ids on destruction - boost::intrusive_ptr id; - boost::intrusive_ptr listen_id; - boost::shared_ptr< ::rdma_cm_event > event; - - ConnectionEvent() {} - ConnectionEvent(::rdma_cm_event* e); - - // Default copy, assignment and destructor ok - public: - operator bool() const; - ::rdma_cm_event_type getEventType() const; - ::rdma_conn_param getConnectionParam() const; - boost::intrusive_ptr getConnection () const; - boost::intrusive_ptr getListenId() const; - }; - - // For the moment this is a fairly simple wrapper for rdma_cm_id. - // - // NB: It allocates a protection domain (pd) per connection which means that - // registered buffers can't be shared between different connections - // (this can only happen between connections on the same controller in any case, - // so needs careful management if used) - class Connection : public qpid::RefCounted { - boost::scoped_ptr< qpid::sys::IOHandle > handle; - boost::shared_ptr< ::rdma_event_channel > channel; - boost::shared_ptr< ::rdma_cm_id > id; - QueuePair::intrusive_ptr qp; - - void* context; - - friend class ConnectionEvent; - friend class QueuePair; - - // Wrap the passed in rdma_cm_id with a Connection - // this basically happens only on connection request - Connection(::rdma_cm_id* i); - Connection(); - ~Connection(); - - void ensureQueuePair(); - - public: - typedef boost::intrusive_ptr intrusive_ptr; - - operator qpid::sys::IOHandle&() const; - - static intrusive_ptr make(); - static intrusive_ptr find(::rdma_cm_id* i); - - template - void addContext(T* c) { - // Don't allow replacing context - if (!context) - context = c; - } - - void removeContext() { - context = 0; - } - - template - T* getContext() { - return static_cast(context); - } - - // Make channel non-blocking by making - // associated fd nonblocking - void nonblocking(); - - // If we get EAGAIN because the channel has been set non blocking - // and we'd have to wait then return an empty event - ConnectionEvent getNextEvent(); - - void bind(const qpid::sys::SocketAddress& src_addr) const; - void listen(int backlog = DEFAULT_BACKLOG) const; - void resolve_addr( - const qpid::sys::SocketAddress& dst_addr, - int timeout_ms = DEFAULT_TIMEOUT) const; - void resolve_route(int timeout_ms = DEFAULT_TIMEOUT) const; - void disconnect() const; - - // TODO: Currently you can only connect with the default connection parameters - void connect(const void* data, size_t len); - void connect(); - template - void connect(const T* data) { - connect(data, sizeof(T)); - } - - // TODO: Not sure how to default accept params - they come from the connection request - // event - void accept(const ::rdma_conn_param& param, const void* data, size_t len); - void accept(const ::rdma_conn_param& param); - template - void accept(const ::rdma_conn_param& param, const T* data) { - accept(param, data, sizeof(T)); - } - - void reject(const void* data, size_t len) const; - void reject() const; - template - void reject(const T* data) const { - reject(data, sizeof(T)); - } - - QueuePair::intrusive_ptr getQueuePair(); - std::string getLocalName() const; - std::string getPeerName() const; - std::string getFullName() const { return getLocalName()+"-"+getPeerName(); } - }; -} - -std::ostream& operator<<(std::ostream& o, ::rdma_cm_event_type t); - -#endif // RDMA_WRAP_H diff --git a/qpid/cpp/src/qpid/sys/regex.h b/qpid/cpp/src/qpid/sys/regex.h deleted file mode 100644 index 77de6a7f5c..0000000000 --- a/qpid/cpp/src/qpid/sys/regex.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef QPID_SYS_REGEX_H -#define QPID_SYS_REGEX_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. - * - */ - -#if defined(_POSIX_SOURCE) || defined(__unix__) -# include -# include -# include -#elif defined(_MSC_VER) -# include -#else -#error "No known regex implementation" -#endif - -// This is a very simple wrapper for Basic Regular Expression facilities either -// provided by POSIX or C++ tr1 -// -// Matching expressions are not supported and so the only useful operation is -// a simple boolean match indicator. - -namespace qpid { -namespace sys { - -#if defined(_POSIX_SOURCE) || defined(__unix__) - -class regex { - ::regex_t re; - -public: - regex(const std::string& s) { - int rc = ::regcomp(&re, s.c_str(), REG_NOSUB); - if (rc != 0) throw std::logic_error("Regular expression compilation error"); - } - - ~regex() { - ::regfree(&re); - } - - friend bool regex_match(const std::string& s, const regex& re); -}; - -inline bool regex_match(const std::string& s, const regex& re) { - return ::regexec(&(re.re), s.c_str(), 0, 0, 0)==0; -} - -#elif defined(_MSC_VER) - -class regex : public std::tr1::regex { -public: - regex(const std::string& s) : - std::tr1::regex(s, std::tr1::regex::basic) - {} -}; - -using std::tr1::regex_match; - -#else -#error "No known regex implementation" -#endif - -}} - - -#endif diff --git a/qpid/cpp/src/qpid/sys/solaris/ECFPoller.cpp b/qpid/cpp/src/qpid/sys/solaris/ECFPoller.cpp deleted file mode 100644 index 06d542c938..0000000000 --- a/qpid/cpp/src/qpid/sys/solaris/ECFPoller.cpp +++ /dev/null @@ -1,444 +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/log/Logger.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/DeletionManager.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - - -//TODO: Remove this -#include "qpid/sys/Dispatcher.h" - -namespace qpid { -namespace sys { - -// Deletion manager to handle deferring deletion of PollerHandles to when they definitely aren't being used -DeletionManager PollerHandleDeletionManager; - -// Instantiate (and define) class static for DeletionManager -template <> -DeletionManager::AllThreadsStatuses DeletionManager::allThreadsStatuses(0); - -class PollerHandlePrivate { - friend class Poller; - friend class PollerHandle; - - enum FDStat { - ABSENT, - MONITORED, - INACTIVE, - HUNGUP, - MONITORED_HUNGUP, - DELETED - }; - - int fd; - uint32_t events; - FDStat stat; - Mutex lock; - - PollerHandlePrivate(int f) : - fd(f), - events(0), - stat(ABSENT) { - } - - bool isActive() const { - return stat == MONITORED || stat == MONITORED_HUNGUP; - } - - void setActive() { - stat = (stat == HUNGUP) ? MONITORED_HUNGUP : MONITORED; - } - - bool isInactive() const { - return stat == INACTIVE || stat == HUNGUP; - } - - void setInactive() { - stat = INACTIVE; - } - - bool isIdle() const { - return stat == ABSENT; - } - - void setIdle() { - stat = ABSENT; - } - - bool isHungup() const { - return stat == MONITORED_HUNGUP || stat == HUNGUP; - } - - void setHungup() { - assert(stat == MONITORED); - stat = HUNGUP; - } - - bool isDeleted() const { - return stat == DELETED; - } - - void setDeleted() { - stat = DELETED; - } -}; - -PollerHandle::PollerHandle(const IOHandle& h) : - impl(new PollerHandlePrivate(toFd(h.impl))) -{} - -PollerHandle::~PollerHandle() { - { - ScopedLock l(impl->lock); - if (impl->isDeleted()) { - return; - } - if (impl->isActive()) { - impl->setDeleted(); - } - } - PollerHandleDeletionManager.markForDeletion(impl); -} - -/** - * Concrete implementation of Poller to use the Solaris Event Completion - * Framework interface - */ -class PollerPrivate { - friend class Poller; - - class InterruptHandle: public PollerHandle { - std::queue handles; - - void processEvent(Poller::EventType) { - PollerHandle* handle = handles.front(); - handles.pop(); - assert(handle); - - //Synthesise event - Poller::Event event(handle, Poller::INTERRUPTED); - - //Process synthesised event - event.process(); - } - - public: - InterruptHandle() : PollerHandle(DummyIOHandle) {} - - void addHandle(PollerHandle& h) { - handles.push(&h); - } - - PollerHandle *getHandle() { - PollerHandle* handle = handles.front(); - handles.pop(); - return handle; - } - - bool queuedHandles() { - return handles.size() > 0; - } - }; - - const int portId; - bool isShutdown; - InterruptHandle interruptHandle; - - static uint32_t directionToPollEvent(Poller::Direction dir) { - switch (dir) { - case Poller::INPUT: return POLLIN; - case Poller::OUTPUT: return POLLOUT; - case Poller::INOUT: return POLLIN | POLLOUT; - default: return 0; - } - } - - static Poller::EventType pollToDirection(uint32_t events) { - uint32_t e = events & (POLLIN | POLLOUT); - switch (e) { - case POLLIN: return Poller::READABLE; - case POLLOUT: return Poller::WRITABLE; - case POLLIN | POLLOUT: return Poller::READ_WRITABLE; - default: - return (events & (POLLHUP | POLLERR)) ? - Poller::DISCONNECTED : Poller::INVALID; - } - } - - PollerPrivate() : - portId(::port_create()), - isShutdown(false) { - QPID_POSIX_CHECK(portId); - QPID_LOG(trace, "port_create returned port Id: " << portId); - } - - ~PollerPrivate() { - } - - void interrupt() { - //Send an Alarm to the port - //We need to send a nonzero event mask, using POLLHUP, - //nevertheless the wait method will only look for a PORT_ALERT_SET - QPID_LOG(trace, "Sending a port_alert to " << portId); - QPID_POSIX_CHECK(::port_alert(portId, PORT_ALERT_SET, POLLHUP, - &static_cast(interruptHandle))); - } -}; - -void Poller::addFd(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - - uint32_t events = 0; - - if (eh.isIdle()) { - events = PollerPrivate::directionToPollEvent(dir); - } else { - assert(eh.isActive()); - events = eh.events | PollerPrivate::directionToPollEvent(dir); - } - - //port_associate can be used to add an association or modify an - //existing one - QPID_POSIX_CHECK(::port_associate(impl->portId, PORT_SOURCE_FD, (uintptr_t) eh.fd, events, &handle)); - eh.events = events; - eh.setActive(); - QPID_LOG(trace, "Poller::addFd(handle=" << &handle - << "[" << typeid(&handle).name() - << "], fd=" << eh.fd << ")"); -} - -void Poller::delFd(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(!eh.isIdle()); - int rc = ::port_dissociate(impl->portId, PORT_SOURCE_FD, (uintptr_t) eh.fd); - //Allow closing an invalid fd, allowing users to close fd before - //doing delFd() - if (rc == -1 && errno != EBADFD) { - QPID_POSIX_CHECK(rc); - } - eh.setIdle(); - QPID_LOG(trace, "Poller::delFd(handle=" << &handle - << ", fd=" << eh.fd << ")"); -} - -// modFd is equivalent to delFd followed by addFd -void Poller::modFd(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(!eh.isIdle()); - - eh.events = PollerPrivate::directionToPollEvent(dir); - - //If fd is already associated, events and user arguments are updated - //So, no need to check if fd is already associated - QPID_POSIX_CHECK(::port_associate(impl->portId, PORT_SOURCE_FD, (uintptr_t) eh.fd, eh.events, &handle)); - eh.setActive(); - QPID_LOG(trace, "Poller::modFd(handle=" << &handle - << ", fd=" << eh.fd << ")"); -} - -void Poller::rearmFd(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock l(eh.lock); - assert(eh.isInactive()); - - QPID_POSIX_CHECK(::port_associate(impl->portId, PORT_SOURCE_FD, (uintptr_t) eh.fd, eh.events, &handle)); - eh.setActive(); - QPID_LOG(trace, "Poller::rearmdFd(handle=" << &handle - << ", fd=" << eh.fd << ")"); -} - -void Poller::shutdown() { - //Allow sloppy code to shut us down more than once - if (impl->isShutdown) - return; - - impl->isShutdown = true; - impl->interrupt(); -} - -bool Poller::hasShutdown() -{ - return impl->isShutdown; -} - -bool Poller::interrupt(PollerHandle& handle) { - PollerPrivate::InterruptHandle& ih = impl->interruptHandle; - PollerHandlePrivate& eh = *static_cast(ih).impl; - ScopedLock l(eh.lock); - ih.addHandle(handle); - impl->interrupt(); - eh.setActive(); - return true; -} - -void Poller::run() { - // Make sure we can't be interrupted by signals at a bad time - ::sigset_t ss; - ::sigfillset(&ss); - ::pthread_sigmask(SIG_SETMASK, &ss, 0); - - do { - Event event = wait(); - - // If can read/write then dispatch appropriate callbacks - if (event.handle) { - event.process(); - } else { - // Handle shutdown - switch (event.type) { - case SHUTDOWN: - return; - default: - // This should be impossible - assert(false); - } - } - } while (true); -} - -Poller::Event Poller::wait(Duration timeout) { - timespec_t tout; - timespec_t* ptout = NULL; - port_event_t pe; - - AbsTime targetTimeout = (timeout == TIME_INFINITE) ? FAR_FUTURE : - AbsTime(now(), timeout); - - if (timeout != TIME_INFINITE) { - tout.tv_sec = 0; - tout.tv_nsec = timeout; - ptout = &tout; - } - - do { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - QPID_LOG(trace, "About to enter port_get on " << impl->portId - << ". Thread " << pthread_self() - << ", timeout=" << timeout); - - - int rc = ::port_get(impl->portId, &pe, ptout); - - QPID_LOG(trace, "port_get on " << impl->portId - << " returned " << rc); - - if (impl->isShutdown) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, SHUTDOWN); - } - - if (rc < 0) { - switch (errno) { - case EINTR: - continue; - case ETIME: - return Event(0, TIMEOUT); - default: - QPID_POSIX_CHECK(rc); - } - } else { - PollerHandle* handle = static_cast(pe.portev_user); - PollerHandlePrivate& eh = *handle->impl; - ScopedLock l(eh.lock); - - if (eh.isActive()) { - QPID_LOG(trace, "Handle is active"); - //We use alert mode to notify interrupts - if (pe.portev_source == PORT_SOURCE_ALERT && - handle == &impl->interruptHandle) { - QPID_LOG(trace, "Interrupt notified"); - - PollerHandle* wrappedHandle = impl->interruptHandle.getHandle(); - - if (impl->interruptHandle.queuedHandles()) { - impl->interrupt(); - eh.setActive(); - } else { - eh.setInactive(); - } - return Event(wrappedHandle, INTERRUPTED); - } - - if (pe.portev_source == PORT_SOURCE_FD) { - QPID_LOG(trace, "About to send handle: " << handle); - if (pe.portev_events & POLLHUP) { - if (eh.isHungup()) { - return Event(handle, DISCONNECTED); - } - eh.setHungup(); - } else { - eh.setInactive(); - } - QPID_LOG(trace, "Sending event (thread: " - << pthread_self() << ") for handle " << handle - << ", direction= " - << PollerPrivate::pollToDirection(pe.portev_events)); - return Event(handle, PollerPrivate::pollToDirection(pe.portev_events)); - } - } else if (eh.isDeleted()) { - //Remove the handle from the poller - int rc = ::port_dissociate(impl->portId, PORT_SOURCE_FD, - (uintptr_t) eh.fd); - if (rc == -1 && errno != EBADFD) { - QPID_POSIX_CHECK(rc); - } - } - } - - if (timeout == TIME_INFINITE) { - continue; - } - if (rc == 0 && now() > targetTimeout) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, TIMEOUT); - } - } while (true); -} - -// Concrete constructors -Poller::Poller() : - impl(new PollerPrivate()) -{} - -Poller::~Poller() { - delete impl; -} - -}} diff --git a/qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp b/qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp deleted file mode 100755 index 0e754e048b..0000000000 --- a/qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp +++ /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. - * - */ - -#include "qpid/sys/SystemInfo.h" - -#define BSD_COMP -#include -#include -#undef BDS_COMP - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -namespace qpid { -namespace sys { - -long SystemInfo::concurrency() { - return sysconf(_SC_NPROCESSORS_ONLN); -} - -bool SystemInfo::getLocalHostname(Address &address) { - char name[MAXHOSTNAMELEN]; - if (::gethostname(name, sizeof(name)) != 0) - return false; - address.host = name; - return true; -} - -static const string LOCALHOST("127.0.0.1"); -static const string TCP("tcp"); - -void SystemInfo::getSystemId(std::string &osName, - std::string &nodeName, - std::string &release, - std::string &version, - std::string &machine) { - struct utsname _uname; - if (uname (&_uname) == 0) { - osName = _uname.sysname; - nodeName = _uname.nodename; - release = _uname.release; - version = _uname.version; - machine = _uname.machine; - } -} - -uint32_t SystemInfo::getProcessId() -{ - return (uint32_t) ::getpid(); -} - -uint32_t SystemInfo::getParentProcessId() -{ - return (uint32_t) ::getppid(); -} - -string SystemInfo::getProcessName() -{ - psinfo processInfo; - char procfile[PATH_MAX]; - int fd; - string value; - - snprintf(procfile, PATH_MAX, "/proc/%d/psinfo", getProcessId()); - if ((fd = open(procfile, O_RDONLY)) >= 0) { - if (read(fd, (void *) &processInfo, sizeof(processInfo)) == sizeof(processInfo)) { - value = processInfo.pr_fname; - } - } - return value; -} - -// Always true. Only Windows has exception cases. -bool SystemInfo::threadSafeShutdown() -{ - return true; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp b/qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp deleted file mode 100644 index 731151caf1..0000000000 --- a/qpid/cpp/src/qpid/sys/ssl/SslSocket.cpp +++ /dev/null @@ -1,409 +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/sys/ssl/SslSocket.h" -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/ssl/check.h" -#include "qpid/sys/ssl/util.h" -#include "qpid/Exception.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/log/Statement.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace sys { -namespace ssl { - -namespace { -const std::string DOMAIN_SEPARATOR("@"); -const std::string DC_SEPARATOR("."); -const std::string DC("DC"); -const std::string DN_DELIMS(" ,="); - -std::string getDomainFromSubject(std::string subject) -{ - std::string::size_type last = subject.find_first_not_of(DN_DELIMS, 0); - std::string::size_type i = subject.find_first_of(DN_DELIMS, last); - - std::string domain; - bool nextTokenIsDC = false; - while (std::string::npos != i || std::string::npos != last) - { - std::string token = subject.substr(last, i - last); - if (nextTokenIsDC) { - if (domain.size()) domain += DC_SEPARATOR; - domain += token; - nextTokenIsDC = false; - } else if (token == DC) { - nextTokenIsDC = true; - } - last = subject.find_first_not_of(DN_DELIMS, i); - i = subject.find_first_of(DN_DELIMS, last); - } - return domain; -} - -struct LocalCertificateGetter -{ - LocalCertificateGetter(PRFileDesc* nssSocket) : socket(nssSocket) {} - CERTCertificate* operator()() const {return SSL_LocalCertificate(socket);} - PRFileDesc* socket; -}; -struct PeerCertificateGetter -{ - PeerCertificateGetter(PRFileDesc* nssSocket) : socket(nssSocket) {} - CERTCertificate* operator()() const {return SSL_PeerCertificate(socket);} - PRFileDesc* socket; -}; -template -std::string getAuthId(CertificateGetter certificateGetter) -{ - std::string authId; - CERTCertificate* cert = certificateGetter(); - if (cert) { - char *cn = CERT_GetCommonName(&(cert->subject)); - if (cn) { - authId = std::string(cn); - /* - * The NSS function CERT_GetDomainComponentName only returns - * the last component of the domain name, so we have to parse - * the subject manually to extract the full domain. - */ - std::string domain = getDomainFromSubject(cert->subjectName); - if (!domain.empty()) { - authId += DOMAIN_SEPARATOR; - authId += domain; - } - } - CERT_DestroyCertificate(cert); - } - return authId; -} -} - -SslSocket::SslSocket(const std::string& certName, bool clientAuth) : - nssSocket(0), certname(certName), prototype(0), hostnameVerification(true) -{ - //configure prototype socket: - prototype = SSL_ImportFD(0, PR_NewTCPSocket()); - - if (clientAuth) { - NSS_CHECK(SSL_OptionSet(prototype, SSL_REQUEST_CERTIFICATE, PR_TRUE)); - NSS_CHECK(SSL_OptionSet(prototype, SSL_REQUIRE_CERTIFICATE, PR_TRUE)); - } -} - -/** - * This form of the constructor is used with the server-side sockets - * returned from accept. Because we use posix accept rather than - * PR_Accept, we have to reset the handshake. - */ -SslSocket::SslSocket(int fd, PRFileDesc* model) : BSDSocket(fd), nssSocket(0), prototype(0) -{ - nssSocket = SSL_ImportFD(model, PR_ImportTCPSocket(fd)); - NSS_CHECK(SSL_ResetHandshake(nssSocket, PR_TRUE)); -} - -void SslSocket::ignoreHostnameVerificationFailure() -{ - hostnameVerification = false; -} - -void SslSocket::setNonblocking() const -{ - if (!nssSocket) { - BSDSocket::setNonblocking(); - return; - } - PRSocketOptionData option; - option.option = PR_SockOpt_Nonblocking; - option.value.non_blocking = true; - PR_SetSocketOption(nssSocket, &option); -} - -void SslSocket::setTcpNoDelay() const -{ - if (!nssSocket) { - BSDSocket::setTcpNoDelay(); - return; - } - PRSocketOptionData option; - option.option = PR_SockOpt_NoDelay; - option.value.no_delay = true; - PR_SetSocketOption(nssSocket, &option); -} - -void SslSocket::connect(const SocketAddress& addr) const -{ - BSDSocket::connect(addr); -} - -namespace { -SECStatus bad_certificate(void* arg, PRFileDesc* /*fd*/) { - switch (PR_GetError()) { - case SSL_ERROR_BAD_CERT_DOMAIN: - QPID_LOG(info, "Ignoring hostname verification failure for " << (const char*) arg); - return SECSuccess; - default: - return SECFailure; - } -} -} - -void SslSocket::finishConnect(const SocketAddress& addr) const -{ - nssSocket = SSL_ImportFD(0, PR_ImportTCPSocket(fd)); - - void* arg; - // Use the connection's cert-name if it has one; else use global cert-name - if (certname != "") { - arg = const_cast(certname.c_str()); - } else if (SslOptions::global.certName.empty()) { - arg = 0; - } else { - arg = const_cast(SslOptions::global.certName.c_str()); - } - NSS_CHECK(SSL_GetClientAuthDataHook(nssSocket, NSS_GetClientAuthData, arg)); - - url = addr.getHost(); - if (!hostnameVerification) { - NSS_CHECK(SSL_BadCertHook(nssSocket, bad_certificate, const_cast(url.data()))); - } - NSS_CHECK(SSL_SetURL(nssSocket, url.data())); - - NSS_CHECK(SSL_ResetHandshake(nssSocket, PR_FALSE)); - NSS_CHECK(SSL_ForceHandshake(nssSocket)); -} - -void SslSocket::close() const -{ - if (!nssSocket) { - BSDSocket::close(); - return; - } - if (fd > 0) { - PR_Close(nssSocket); - fd = -1; - } -} - -int SslSocket::listen(const SocketAddress& sa, int backlog) const -{ - //get certificate and key (is this the correct way?) - std::string cName( (certname == "") ? "localhost.localdomain" : certname); - CERTCertificate *cert = PK11_FindCertFromNickname(const_cast(cName.c_str()), 0); - if (!cert) throw Exception(QPID_MSG("Failed to load certificate '" << cName << "'")); - SECKEYPrivateKey *key = PK11_FindKeyByAnyCert(cert, 0); - if (!key) throw Exception(QPID_MSG("Failed to retrieve private key from certificate")); - NSS_CHECK(SSL_ConfigSecureServer(prototype, cert, key, NSS_FindCertKEAType(cert))); - SECKEY_DestroyPrivateKey(key); - CERT_DestroyCertificate(cert); - - return BSDSocket::listen(sa, backlog); -} - -Socket* SslSocket::accept() const -{ - QPID_LOG(trace, "Accepting SSL connection."); - int afd = ::accept(fd, 0, 0); - if ( afd >= 0) { - return new SslSocket(afd, prototype); - } else if (errno == EAGAIN) { - return 0; - } else { - throw QPID_POSIX_ERROR(errno); - } -} - -#define SSL_STREAM_MAX_WAIT_ms 20 -#define SSL_STREAM_MAX_RETRIES 2 - -static bool isSslStream(int afd) { - int retries = SSL_STREAM_MAX_RETRIES; - unsigned char buf[5] = {}; - - do { - struct pollfd fd = {afd, POLLIN, 0}; - - /* - * Note that this is blocking the accept thread, so connections that - * send no data can limit the rate at which we can accept new - * connections. - */ - if (::poll(&fd, 1, SSL_STREAM_MAX_WAIT_ms) > 0) { - errno = 0; - int result = recv(afd, buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT); - if (result == sizeof(buf)) { - break; - } - if (errno && errno != EAGAIN) { - int err = errno; - ::close(afd); - throw QPID_POSIX_ERROR(err); - } - } - } while (retries-- > 0); - - if (retries < 0) { - return false; - } - - /* - * SSLv2 Client Hello format - * http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.html - * - * Bytes 0-1: RECORD-LENGTH - * Byte 2: MSG-CLIENT-HELLO (1) - * Byte 3: CLIENT-VERSION-MSB - * Byte 4: CLIENT-VERSION-LSB - * - * Allowed versions: - * 2.0 - SSLv2 - * 3.0 - SSLv3 - * 3.1 - TLS 1.0 - * 3.2 - TLS 1.1 - * 3.3 - TLS 1.2 - * - * The version sent in the Client-Hello is the latest version supported by - * the client. NSS may send version 3.x in an SSLv2 header for - * maximum compatibility. - */ - bool isSSL2Handshake = buf[2] == 1 && // MSG-CLIENT-HELLO - ((buf[3] == 3 && buf[4] <= 3) || // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3) - (buf[3] == 2 && buf[4] == 0)); // SSL 2 - - /* - * SSLv3/TLS Client Hello format - * RFC 2246 - * - * Byte 0: ContentType (handshake - 22) - * Bytes 1-2: ProtocolVersion {major, minor} - * - * Allowed versions: - * 3.0 - SSLv3 - * 3.1 - TLS 1.0 - * 3.2 - TLS 1.1 - * 3.3 - TLS 1.2 - */ - bool isSSL3Handshake = buf[0] == 22 && // handshake - (buf[1] == 3 && buf[2] <= 3); // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3) - - return isSSL2Handshake || isSSL3Handshake; -} - -SslMuxSocket::SslMuxSocket(const std::string& certName, bool clientAuth) : - SslSocket(certName, clientAuth) -{ -} - -Socket* SslMuxSocket::accept() const -{ - int afd = ::accept(fd, 0, 0); - if (afd >= 0) { - QPID_LOG(trace, "Accepting connection with optional SSL wrapper."); - if (isSslStream(afd)) { - QPID_LOG(trace, "Accepted SSL connection."); - return new SslSocket(afd, prototype); - } else { - QPID_LOG(trace, "Accepted Plaintext connection."); - return new BSDSocket(afd); - } - } else if (errno == EAGAIN) { - return 0; - } else { - throw QPID_POSIX_ERROR(errno); - } -} - -std::string SslSocket::lastErrorCodeText() const -{ - return getErrorString(lastErrorCode); -} - -int SslSocket::read(void *buf, size_t count) const -{ - PRInt32 r = PR_Read(nssSocket, buf, count); - lastErrorCode = PR_GetError(); - return r; -} - -int SslSocket::write(const void *buf, size_t count) const -{ - PRInt32 r = PR_Write(nssSocket, buf, count); - lastErrorCode = PR_GetError(); - return r; -} - -void SslSocket::setCertName(const std::string& name) -{ - certname = name; -} - - -/** get the bit length of the current cipher's key */ -int SslSocket::getKeyLen() const -{ - int enabled = 0; - int keySize = 0; - SECStatus rc; - - rc = SSL_SecurityStatus( nssSocket, - &enabled, - NULL, - NULL, - &keySize, - NULL, NULL ); - if (rc == SECSuccess && enabled) { - return keySize; - } - return 0; -} - -std::string SslSocket::getPeerAuthId() const -{ - return getAuthId(PeerCertificateGetter(nssSocket)); -} - -std::string SslSocket::getLocalAuthId() const -{ - return getAuthId(LocalCertificateGetter(nssSocket)); -} - -}}} // namespace qpid::sys::ssl diff --git a/qpid/cpp/src/qpid/sys/ssl/SslSocket.h b/qpid/cpp/src/qpid/sys/ssl/SslSocket.h deleted file mode 100644 index 733a47aee5..0000000000 --- a/qpid/cpp/src/qpid/sys/ssl/SslSocket.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _sys_ssl_Socket_h -#define _sys_ssl_Socket_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/IOHandle.h" -#include "qpid/sys/posix/BSDSocket.h" -#include - -#include - -struct sockaddr; - -namespace qpid { -namespace sys { - -class Duration; - -namespace ssl { - -class SslSocket : public qpid::sys::BSDSocket -{ -public: - /** Create a socket wrapper for descriptor. - *@param certName name of certificate to use to identify the socket - */ - SslSocket(const std::string& certName = "", bool clientAuth = false); - - /** Proceed with connect inspite of hostname verifcation failures*/ - void ignoreHostnameVerificationFailure(); - - /** Set SSL cert-name. Allows the cert-name to be set per - * connection, overriding global cert-name settings from - * NSSInit().*/ - void setCertName(const std::string& certName); - - void setNonblocking() const; - void setTcpNoDelay() const; - - std::string lastErrorCodeText() const; - - void connect(const SocketAddress&) const; - void finishConnect(const SocketAddress&) const; - int listen(const SocketAddress&, int backlog = 10) const; - virtual Socket* accept() const; - int read(void *buf, size_t count) const; - int write(const void *buf, size_t count) const; - void close() const; - - int getKeyLen() const; - std::string getPeerAuthId() const; - std::string getLocalAuthId() const; - -protected: - mutable PRFileDesc* nssSocket; - std::string certname; - mutable std::string url; - - /** - * 'model' socket, with configuration to use when importing - * accepted sockets for use as ssl sockets. Set on listen(), used - * in accept to pass through to newly created socket instances. - */ - mutable PRFileDesc* prototype; - bool hostnameVerification; - - SslSocket(int fd, PRFileDesc* model); - friend class SslMuxSocket; // Needed for this constructor -}; - -class SslMuxSocket : public SslSocket -{ -public: - SslMuxSocket(const std::string& certName = "", bool clientAuth = false); - Socket* accept() const; -}; - -}}} -#endif /*!_sys_ssl_Socket_h*/ diff --git a/qpid/cpp/src/qpid/sys/ssl/check.cpp b/qpid/cpp/src/qpid/sys/ssl/check.cpp deleted file mode 100644 index 72a2e265bd..0000000000 --- a/qpid/cpp/src/qpid/sys/ssl/check.cpp +++ /dev/null @@ -1,85 +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/sys/ssl/check.h" -#include -#include -#include - -using boost::format; -using boost::str; - -namespace qpid { -namespace sys { -namespace ssl { - -ErrorString::ErrorString() : code(PR_GetError()), buffer(new char[PR_GetErrorTextLength()]), used(PR_GetErrorText(buffer)) {} - -ErrorString::~ErrorString() -{ - delete[] buffer; -} - -std::string ErrorString::getString() const -{ - std::string msg = std::string(buffer, used); - if (!used) { - //seems most of the NSPR/NSS errors don't have text set for - //them, add a few specific ones in here. (TODO: more complete - //list?): - return getErrorString(code); - } else { - return str(format("%1% [%2%]") % msg % code); - } -} - -std::string getErrorString(int code) -{ - std::string msg; - switch (code) { - case SSL_ERROR_EXPORT_ONLY_SERVER: msg = "Unable to communicate securely. Peer does not support high-grade encryption."; break; - case SSL_ERROR_US_ONLY_SERVER: msg = "Unable to communicate securely. Peer requires high-grade encryption which is not supported."; break; - case SSL_ERROR_NO_CYPHER_OVERLAP: msg = "Cannot communicate securely with peer: no common encryption algorithm(s)."; break; - case SSL_ERROR_NO_CERTIFICATE: msg = "Unable to find the certificate or key necessary for authentication."; break; - case SSL_ERROR_BAD_CERTIFICATE: msg = "Unable to communicate securely with peer: peers's certificate was rejected."; break; - case SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE: msg = "Unsupported certificate type."; break; - case SSL_ERROR_WRONG_CERTIFICATE: msg = "Client authentication failed: private key in key database does not correspond to public key in certificate database."; break; - case SSL_ERROR_BAD_CERT_DOMAIN: msg = "Unable to communicate securely with peer: requested domain name does not match the server's certificate."; break; - case SSL_ERROR_BAD_CERT_ALERT: msg = "SSL peer cannot verify your certificate."; break; - case SSL_ERROR_REVOKED_CERT_ALERT: msg = "SSL peer rejected your certificate as revoked."; break; - case SSL_ERROR_EXPIRED_CERT_ALERT: msg = "SSL peer rejected your certificate as expired."; break; - - case PR_DIRECTORY_LOOKUP_ERROR: msg = "A directory lookup on a network address has failed"; break; - case PR_CONNECT_RESET_ERROR: msg = "TCP connection reset by peer"; break; - case PR_END_OF_FILE_ERROR: msg = "Encountered end of file"; break; - case SEC_ERROR_EXPIRED_CERTIFICATE: msg = "Peer's certificate has expired"; break; - default: msg = (code < -6000) ? "NSS error" : "NSPR error"; break; - } - return str(format("%1% [%2%]") % msg % code); -} - -std::ostream& operator<<(std::ostream& out, const ErrorString& err) -{ - out << err.getString(); - return out; -} - - -}}} // namespace qpid::sys::ssl diff --git a/qpid/cpp/src/qpid/sys/ssl/check.h b/qpid/cpp/src/qpid/sys/ssl/check.h deleted file mode 100644 index 28d3c74ad0..0000000000 --- a/qpid/cpp/src/qpid/sys/ssl/check.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QPID_SYS_SSL_CHECK_H -#define QPID_SYS_SSL_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/Msg.h" - -#include -#include -#include -#include - -namespace qpid { -namespace sys { -namespace ssl { - -std::string getErrorString(int code); - -class ErrorString -{ - public: - ErrorString(); - ~ErrorString(); - std::string getString() const; - private: - const int code; - char* const buffer; - const size_t used; -}; - -std::ostream& operator<<(std::ostream& out, const ErrorString& err); - -}}} // namespace qpid::sys::ssl - - -#define NSS_CHECK(value) if (value != SECSuccess) { throw Exception(QPID_MSG("Failed: " << qpid::sys::ssl::ErrorString())); } -#define PR_CHECK(value) if (value != PR_SUCCESS) { throw Exception(QPID_MSG("Failed: " << qpid::sys::ssl::ErrorString())); } - -#endif /*!QPID_SYS_SSL_CHECK_H*/ diff --git a/qpid/cpp/src/qpid/sys/ssl/util.cpp b/qpid/cpp/src/qpid/sys/ssl/util.cpp deleted file mode 100644 index e527606fde..0000000000 --- a/qpid/cpp/src/qpid/sys/ssl/util.cpp +++ /dev/null @@ -1,132 +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/sys/ssl/util.h" -#include "qpid/sys/ssl/check.h" -#include "qpid/Exception.h" -#include "qpid/sys/SystemInfo.h" - -#include -#include -#include -#include -#include - -#include -#include - -namespace qpid { -namespace sys { -namespace ssl { - -static const std::string LOCALHOST("127.0.0.1"); - -std::string defaultCertName() -{ - Address address; - if (SystemInfo::getLocalHostname(address)) { - return address.host; - } else { - return LOCALHOST; - } -} - -SslOptions::SslOptions() : qpid::Options("SSL Settings"), - certName(defaultCertName()), - exportPolicy(false) -{ - addOptions() - ("ssl-use-export-policy", optValue(exportPolicy), "Use NSS export policy") - ("ssl-cert-password-file", optValue(certPasswordFile, "PATH"), "File containing password to use for accessing certificate database") - ("ssl-cert-db", optValue(certDbPath, "PATH"), "Path to directory containing certificate database") - ("ssl-cert-name", optValue(certName, "NAME"), "Name of the certificate to use"); -} - -SslOptions& SslOptions::operator=(const SslOptions& o) -{ - certDbPath = o.certDbPath; - certName = o.certName; - certPasswordFile = o.certPasswordFile; - exportPolicy = o.exportPolicy; - return *this; -} - -char* promptForPassword(PK11SlotInfo*, PRBool retry, void*) -{ - if (retry) return 0; - //TODO: something else? - return PL_strdup(getpass("Please enter the password for accessing the certificate database:")); -} - -SslOptions SslOptions::global; - -char* readPasswordFromFile(PK11SlotInfo*, PRBool retry, void*) -{ - const std::string& passwordFile = SslOptions::global.certPasswordFile; - if (retry || passwordFile.empty()) return 0; - std::ifstream file(passwordFile.c_str()); - if (!file) return 0; - - std::string password; - getline(file, password); - return PL_strdup(password.c_str()); -} - -void initNSS(const SslOptions& options, bool server) -{ - SslOptions::global = options; - if (options.certPasswordFile.empty()) { - PK11_SetPasswordFunc(promptForPassword); - } else { - PK11_SetPasswordFunc(readPasswordFromFile); - } - NSS_CHECK(NSS_Init(options.certDbPath.c_str())); - if (options.exportPolicy) { - NSS_CHECK(NSS_SetExportPolicy()); - } else { - NSS_CHECK(NSS_SetDomesticPolicy()); - } - if (server) { - //use defaults for all args, TODO: may want to make this configurable - SSL_ConfigServerSessionIDCache(0, 0, 0, 0); - } - - // disable SSLv2 and SSLv3 versions of the protocol - they are - // no longer considered secure - SSLVersionRange drange, srange; // default and supported ranges - const uint16_t tlsv1 = 0x0301; // Protocol version for TLSv1.0 - NSS_CHECK(SSL_VersionRangeGetDefault(ssl_variant_stream, &drange)); - NSS_CHECK(SSL_VersionRangeGetSupported(ssl_variant_stream, &srange)); - if (drange.min < tlsv1) { - drange.min = tlsv1; - NSS_CHECK(SSL_VersionRangeSetDefault(ssl_variant_stream, &drange)); - } - if (srange.max > drange.max) { - drange.max = srange.max; - NSS_CHECK(SSL_VersionRangeSetDefault(ssl_variant_stream, &drange)); - } -} - -void shutdownNSS() -{ - NSS_Shutdown(); -} - -}}} // namespace qpid::sys::ssl diff --git a/qpid/cpp/src/qpid/sys/ssl/util.h b/qpid/cpp/src/qpid/sys/ssl/util.h deleted file mode 100644 index f34adab7be..0000000000 --- a/qpid/cpp/src/qpid/sys/ssl/util.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_SYS_SSL_UTIL_H -#define QPID_SYS_SSL_UTIL_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/Options.h" -#include - -namespace qpid { -namespace sys { -namespace ssl { - -struct SslOptions : qpid::Options -{ - static SslOptions global; - - std::string certDbPath; - std::string certName; - std::string certPasswordFile; - bool exportPolicy; - - SslOptions(); - SslOptions& operator=(const SslOptions&); -}; - -void initNSS(const SslOptions& options, bool server = false); -void shutdownNSS(); - -}}} // namespace qpid::sys::ssl - -#endif /*!QPID_SYS_SSL_UTIL_H*/ diff --git a/qpid/cpp/src/qpid/sys/unordered_map.h b/qpid/cpp/src/qpid/sys/unordered_map.h deleted file mode 100644 index 1b27770804..0000000000 --- a/qpid/cpp/src/qpid/sys/unordered_map.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _sys_unordered_map_h -#define _sys_unordered_map_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. - * - */ - -// unordered_map include path is platform specific - -#if defined(_MSC_VER) || defined(_LIBCPP_VERSION) || __cplusplus >= 201103L -# include -#elif defined(__SUNPRO_CC) || defined(__IBMCPP__) -# include -#else -# include -#endif /* _MSC_VER */ -namespace qpid { -namespace sys { -#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L - using std::unordered_map; -#else - using std::tr1::unordered_map; -#endif -}} - - -#endif /* _sys_unordered_map_h */ diff --git a/qpid/cpp/src/qpid/sys/urlAdd.h b/qpid/cpp/src/qpid/sys/urlAdd.h deleted file mode 100644 index e78c5d586c..0000000000 --- a/qpid/cpp/src/qpid/sys/urlAdd.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_SYS_URLADD_H -#define QPID_SYS_URLADD_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 -#include -#include - -namespace qpid { -namespace sys { - -/** Add addr to url if it is not already present. */ -inline void urlAddAddress(Url& url, const Address& addr) { - if (std::find(url.begin(), url.end(), addr) == url.end()) url.push_back(addr); -} - -/** Add all addresses in more that are not already in url to url */ -inline void urlAddUrl(Url& url, const Url& more) { - for_each(more.begin(), more.end(), boost::bind(&urlAddAddress, boost::ref(url), _1)); -} - -/** Convert str to a Url and do urlAddUrl. */ -inline void urlAddString(Url& url, const std::string& str, const std::string& defaultProtocol) { - urlAddUrl(url, Url(str, defaultProtocol)); -} - -/** For each URL in a range, do urlAddUrl */ -template -void urlAddUrls(Url& url, UrlIterator i, UrlIterator j) { - for_each(i, j, boost::bind(&urlAddUrl, boost::ref(url), _1)); -} - -/** For each string in a range, do urlAddUrl(Url(string)) */ -template -void urlAddStrings(Url& url, StringIterator i, StringIterator j, - const std::string& defaultProtocol) { - for_each(i, j, boost::bind(&urlAddString, boost::ref(url), _1, defaultProtocol)); -} - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_URLADD_H*/ diff --git a/qpid/cpp/src/qpid/sys/uuid.h b/qpid/cpp/src/qpid/sys/uuid.h deleted file mode 100644 index 6c32c059c4..0000000000 --- a/qpid/cpp/src/qpid/sys/uuid.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _sys_uuid_h -#define _sys_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/types/ImportExport.h" - -#include "qpid/sys/IntegerTypes.h" - -namespace qpid { -namespace sys { - -const int UuidSize = 16; -typedef uint8_t uuid_t[UuidSize]; - -extern "C" -QPID_TYPES_EXTERN void uuid_generate (uint8_t out[UuidSize]); - -}} - -#endif /* _sys_uuid_h */ diff --git a/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp b/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp deleted file mode 100644 index a5b07ce448..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp +++ /dev/null @@ -1,713 +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/sys/windows/AsynchIoResult.h" -#include "qpid/sys/windows/IoHandlePrivate.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/windows/WinSocket.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/log/Statement.h" - -#include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/mingw32_compat.h" - -#include - -#include -#include -#include -#include - -#include -#include -#include "qpid/sys/windows/AsynchIO.h" - -namespace { - - typedef qpid::sys::ScopedLock QLock; - -/* - * The function pointers for AcceptEx and ConnectEx need to be looked up - * at run time. - */ -const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::IOHandle& io) { - SOCKET h = io.fd; - GUID guidAcceptEx = WSAID_ACCEPTEX; - DWORD dwBytes = 0; - LPFN_ACCEPTEX fnAcceptEx; - WSAIoctl(h, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &guidAcceptEx, - sizeof(guidAcceptEx), - &fnAcceptEx, - sizeof(fnAcceptEx), - &dwBytes, - NULL, - NULL); - if (fnAcceptEx == 0) - throw qpid::Exception(QPID_MSG("Failed to look up AcceptEx")); - return fnAcceptEx; -} - -} - -namespace qpid { -namespace sys { -namespace windows { - -/* - * Asynch Acceptor - * - */ -AsynchAcceptor::AsynchAcceptor(const Socket& s, Callback callback) - : acceptedCallback(callback), - socket(s), - wSocket(IOHandle(s).fd), - fnAcceptEx(lookUpAcceptEx(s)) { - - s.setNonblocking(); -} - -AsynchAcceptor::~AsynchAcceptor() -{ - socket.close(); -} - -void AsynchAcceptor::start(Poller::shared_ptr poller) { - PollerHandle ph = PollerHandle(socket); - poller->monitorHandle(ph, Poller::INPUT); - restart (); -} - -void AsynchAcceptor::restart(void) { - DWORD bytesReceived = 0; // Not used, needed for AcceptEx API - AsynchAcceptResult *result = new AsynchAcceptResult(acceptedCallback, - this, - socket); - BOOL status; - status = fnAcceptEx(wSocket, - IOHandle(*result->newSocket).fd, - result->addressBuffer, - 0, - AsynchAcceptResult::SOCKADDRMAXLEN, - AsynchAcceptResult::SOCKADDRMAXLEN, - &bytesReceived, - result->overlapped()); - QPID_WINDOWS_CHECK_ASYNC_START(status); -} - - -Socket* createSameTypeSocket(const Socket& sock) { - SOCKET socket = IOHandle(sock).fd; - // Socket currently has no actual socket attached - if (socket == INVALID_SOCKET) - return new WinSocket; - - ::sockaddr_storage sa; - ::socklen_t salen = sizeof(sa); - QPID_WINSOCK_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen)); - SOCKET s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM - if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError()); - return new WinSocket(s); -} - -AsynchAcceptResult::AsynchAcceptResult(AsynchAcceptor::Callback cb, - AsynchAcceptor *acceptor, - const Socket& lsocket) - : callback(cb), acceptor(acceptor), - listener(IOHandle(lsocket).fd), - newSocket(createSameTypeSocket(lsocket)) { -} - -void AsynchAcceptResult::success(size_t /*bytesTransferred*/) { - ::setsockopt (IOHandle(*newSocket).fd, - SOL_SOCKET, - SO_UPDATE_ACCEPT_CONTEXT, - (char*)&listener, - sizeof (listener)); - callback(*(newSocket.release())); - acceptor->restart (); - delete this; -} - -void AsynchAcceptResult::failure(int /*status*/) { - //if (status != WSA_OPERATION_ABORTED) - // Can there be anything else? ; - delete this; -} - -/* - * AsynchConnector does synchronous connects for now... to do asynch the - * IocpPoller will need some extension to register an event handle as a - * CONNECT-type "direction", the connect completion/result will need an - * event handle to associate with the connecting handle. But there's no - * time for that right now... - */ -AsynchConnector::AsynchConnector(const Socket& sock, - const std::string& hname, - const std::string& p, - ConnectedCallback connCb, - FailedCallback failCb) : - connCallback(connCb), failCallback(failCb), socket(sock), - hostname(hname), port(p) -{ -} - -void AsynchConnector::start(Poller::shared_ptr) -{ - try { - socket.connect(SocketAddress(hostname, port)); - socket.setNonblocking(); - connCallback(socket); - } catch(std::exception& e) { - if (failCallback) - failCallback(socket, -1, std::string(e.what())); - socket.close(); - } -} - -// This can never be called in the current windows code as connect -// is blocking and requestCallback only makes sense if connect is -// non-blocking with the results returned via a poller callback. -void AsynchConnector::requestCallback(RequestCallback rCb) -{ -} - -} // namespace windows - -AsynchAcceptor* AsynchAcceptor::create(const Socket& s, - Callback callback) -{ - return new windows::AsynchAcceptor(s, callback); -} - -AsynchConnector* qpid::sys::AsynchConnector::create(const Socket& s, - const std::string& hostname, - const std::string& port, - ConnectedCallback connCb, - FailedCallback failCb) -{ - return new windows::AsynchConnector(s, - hostname, - port, - connCb, - failCb); -} - - -/* - * Asynch reader/writer - */ - -namespace windows { - -// This is used to encapsulate pure callbacks into a handle -class CallbackHandle : public IOHandle { -public: - CallbackHandle(AsynchIoResult::Completer completeCb, - AsynchIO::RequestCallback reqCb = 0) : - IOHandle(INVALID_SOCKET, completeCb, reqCb) - {} -}; - -AsynchIO::AsynchIO(const Socket& s, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb, - BuffersEmptyCallback eCb, - IdleCallback iCb) : - - readCallback(rCb), - eofCallback(eofCb), - disCallback(disCb), - closedCallback(cCb), - emptyCallback(eCb), - idleCallback(iCb), - socket(s), - bufferCount(BufferCount), - opsInProgress(0), - writeInProgress(false), - readInProgress(false), - queuedDelete(false), - queuedClose(false), - working(false) { -} - -AsynchIO::~AsynchIO() { -} - -void AsynchIO::queueForDeletion() { - { - ScopedLock l(completionLock); - assert(!queuedDelete); - queuedDelete = true; - if (working || opsInProgress > 0) { - QPID_LOG(info, "Delete AsynchIO queued; ops in progress"); - // AsynchIOHandler calls this then deletes itself; don't do any more - // callbacks. - readCallback = 0; - eofCallback = 0; - disCallback = 0; - closedCallback = 0; - emptyCallback = 0; - idleCallback = 0; - return; - } - } - delete this; -} - -void AsynchIO::start(Poller::shared_ptr poller0) { - PollerHandle ph = PollerHandle(socket); - poller = poller0; - poller->monitorHandle(ph, Poller::INPUT); - if (writeQueue.size() > 0) // Already have data queued for write - notifyPendingWrite(); - startReading(); -} - -uint32_t AsynchIO::getBufferCount(void) { return bufferCount; } - -void AsynchIO::setBufferCount(uint32_t count) { bufferCount = count; } - - -void AsynchIO::createBuffers(uint32_t size) { - // Allocate all the buffer memory at once - bufferMemory.reset(new char[size*bufferCount]); - - // Create the Buffer structs in a vector - // And push into the buffer queue - buffers.reserve(bufferCount); - for (uint32_t i = 0; i < bufferCount; i++) { - buffers.push_back(BufferBase(&bufferMemory[i*size], size)); - queueReadBuffer(&buffers[i]); - } -} - -void AsynchIO::queueReadBuffer(AsynchIO::BufferBase* buff) { - assert(buff); - buff->dataStart = 0; - buff->dataCount = 0; - QLock l(bufferQueueLock); - bufferQueue.push_back(buff); -} - -void AsynchIO::unread(AsynchIO::BufferBase* buff) { - assert(buff); - buff->squish(); - QLock l(bufferQueueLock); - bufferQueue.push_front(buff); -} - -void AsynchIO::queueWrite(AsynchIO::BufferBase* buff) { - assert(buff); - QLock l(bufferQueueLock); - writeQueue.push_back(buff); - if (!writeInProgress) - notifyPendingWrite(); -} - -void AsynchIO::notifyPendingWrite() { - // This method is generally called from a processing thread; transfer - // work on this to an I/O thread. Much of the upper layer code assumes - // that all I/O-related things happen in an I/O thread. - if (poller == 0) // Not really going yet... - return; - - InterlockedIncrement(&opsInProgress); - PollerHandle ph(CallbackHandle(boost::bind(&AsynchIO::completion, this, _1))); - poller->monitorHandle(ph, Poller::OUTPUT); -} - -void AsynchIO::queueWriteClose() { - { - ScopedLock l(completionLock); - queuedClose = true; - if (working || writeInProgress) - // no need to summon an IO thread - return; - } - notifyPendingWrite(); -} - -bool AsynchIO::writeQueueEmpty() { - QLock l(bufferQueueLock); - return writeQueue.size() == 0; -} - -/* - * Initiate a read operation. AsynchIO::readComplete() will be - * called when the read is complete and data is available. - */ -void AsynchIO::startReading() { - if (queuedDelete || queuedClose) - return; - - // (Try to) get a buffer; look on the front since there may be an - // "unread" one there with data remaining from last time. - AsynchIO::BufferBase *buff = 0; - { - QLock l(bufferQueueLock); - - if (!bufferQueue.empty()) { - buff = bufferQueue.front(); - assert(buff); - bufferQueue.pop_front(); - } - else { - logNoBuffers("startReading"); - } - } - if (buff != 0) { - int readCount = buff->byteCount - buff->dataCount; - AsynchReadResult *result = - new AsynchReadResult(boost::bind(&AsynchIO::completion, this, _1), - buff, - readCount); - DWORD bytesReceived = 0, flags = 0; - InterlockedIncrement(&opsInProgress); - readInProgress = true; - int status = WSARecv(IOHandle(socket).fd, - const_cast(result->getWSABUF()), 1, - &bytesReceived, - &flags, - result->overlapped(), - 0); - if (status != 0) { - int error = WSAGetLastError(); - if (error != WSA_IO_PENDING) { - result->failure(error); - result = 0; // result is invalid here - return; - } - } - // On status 0 or WSA_IO_PENDING, completion will handle the rest. - } - else { - notifyBuffersEmpty(); - } - return; -} - -// Queue the specified callback for invocation from an I/O thread. -void AsynchIO::requestCallback(RequestCallback callback) { - // This method is generally called from a processing thread; transfer - // work on this to an I/O thread. Much of the upper layer code assumes - // that all I/O-related things happen in an I/O thread. - if (poller == 0) // Not really going yet... - return; - - InterlockedIncrement(&opsInProgress); - PollerHandle ph(CallbackHandle( - boost::bind(&AsynchIO::completion, this, _1), - callback)); - poller->monitorHandle(ph, Poller::INPUT); -} - -/** - * Return a queued buffer if there are enough to spare. - */ -AsynchIO::BufferBase* AsynchIO::getQueuedBuffer() { - QLock l(bufferQueueLock); - BufferBase* buff = bufferQueue.empty() ? 0 : bufferQueue.back(); - // An "unread" buffer is reserved for future read operations (which - // take from the front of the queue). - if (!buff || (buff->dataCount && bufferQueue.size() == 1)) { - if (buff) - logNoBuffers("getQueuedBuffer with unread data"); - else - logNoBuffers("getQueuedBuffer with empty queue"); - return 0; - } - assert(buff->dataCount == 0); - bufferQueue.pop_back(); - return buff; -} - -void AsynchIO::notifyEof(void) { - if (eofCallback) - eofCallback(*this); -} - -void AsynchIO::notifyDisconnect(void) { - if (disCallback) { - DisconnectCallback dcb = disCallback; - closedCallback = 0; - disCallback = 0; - dcb(*this); - // May have just been deleted. - return; - } -} - -void AsynchIO::notifyClosed(void) { - if (closedCallback) { - ClosedCallback ccb = closedCallback; - closedCallback = 0; - disCallback = 0; - ccb(*this, socket); - // May have just been deleted. - return; - } -} - -void AsynchIO::notifyBuffersEmpty(void) { - if (emptyCallback) - emptyCallback(*this); -} - -void AsynchIO::notifyIdle(void) { - if (idleCallback) - idleCallback(*this); -} - -/* - * Asynch reader/writer using overlapped I/O - */ - -void AsynchIO::startWrite(AsynchIO::BufferBase* buff) { - writeInProgress = true; - InterlockedIncrement(&opsInProgress); - AsynchWriteResult *result = - new AsynchWriteResult(boost::bind(&AsynchIO::completion, this, _1), - buff, - buff->dataCount); - DWORD bytesSent = 0; - int status = WSASend(IOHandle(socket).fd, - const_cast(result->getWSABUF()), 1, - &bytesSent, - 0, - result->overlapped(), - 0); - if (status != 0) { - int error = WSAGetLastError(); - if (error != WSA_IO_PENDING) { - result->failure(error); // Also decrements in-progress count - result = 0; // result is invalid here - return; - } - } - // On status 0 or WSA_IO_PENDING, completion will handle the rest. - return; -} - -/* - * Close the socket and callback to say we've done it - */ -void AsynchIO::close(void) { - socket.close(); - notifyClosed(); -} - -SecuritySettings AsynchIO::getSecuritySettings() { - SecuritySettings settings; - settings.ssf = socket.getKeyLen(); - settings.authid = socket.getPeerAuthId(); - return settings; -} - -void AsynchIO::readComplete(AsynchReadResult *result) { - int status = result->getStatus(); - size_t bytes = result->getTransferred(); - readInProgress = false; - if (status == 0 && bytes > 0) { - if (readCallback) - readCallback(*this, result->getBuff()); - startReading(); - } - else { - // No data read, so put the buffer back. It may be partially filled, - // so "unread" it back to the front of the queue. - unread(result->getBuff()); - if (queuedClose) { - return; // Expected from cancelRead() - } - notifyEof(); - if (status != 0) - { - notifyDisconnect(); - } - } -} - -/* - * NOTE - this completion is called for completed writes and also when - * a write is desired. The difference is in the buff - if a write is desired - * the buff is 0. - */ -void AsynchIO::writeComplete(AsynchWriteResult *result) { - int status = result->getStatus(); - size_t bytes = result->getTransferred(); - AsynchIO::BufferBase *buff = result->getBuff(); - if (buff != 0) { - writeInProgress = false; - if (status == 0 && bytes > 0) { - if (bytes < result->getRequested()) // Still more to go; resubmit - startWrite(buff); - else - queueReadBuffer(buff); // All done; back to the pool - } - else { - // An error... if it's a connection close, ignore it - it will be - // noticed and handled on a read completion any moment now. - // What to do with real error??? Save the Buffer? TBD. - queueReadBuffer(buff); // All done; back to the pool - } - } - - // If there are no writes outstanding, check for more writes to initiate - // (either queued or via idle). The opsInProgress count is handled in - // completion() - if (!writeInProgress) { - bool writing = false; - { - QLock l(bufferQueueLock); - if (writeQueue.size() > 0) { - buff = writeQueue.front(); - assert(buff); - writeQueue.pop_front(); - startWrite(buff); - writing = true; - } - } - if (!writing && !queuedClose) { - notifyIdle(); - } - } - return; -} - -void AsynchIO::completion(AsynchIoResult *result) { - bool closing = false; - bool deleting = false; - { - ScopedLock l(completionLock); - if (working) { - completionQueue.push(result); - return; - } - - // First thread in with something to do; note we're working then keep - // handling completions. - working = true; - while (result != 0) { - // New scope to unlock temporarily. - { - ScopedUnlock ul(completionLock); - AsynchReadResult *r = dynamic_cast(result); - if (r != 0) - readComplete(r); - else { - AsynchWriteResult *w = - dynamic_cast(result); - if (w != 0) - writeComplete(w); - else { - AsynchCallbackRequest *req = - dynamic_cast(result); - req->reqCallback(*this); - } - } - delete result; - result = 0; - InterlockedDecrement(&opsInProgress); - if (queuedClose && opsInProgress == 1 && readInProgress) - cancelRead(); - } - // Lock is held again. - if (completionQueue.empty()) - continue; - result = completionQueue.front(); - completionQueue.pop(); - } - working = false; - if (opsInProgress == 0) { - closing = queuedClose; - deleting = queuedDelete; - } - } - // Lock released; ok to close if ops are done and close requested. - // Layer above will call back to queueForDeletion() if it hasn't - // already been done. If it already has, go ahead and delete. - if (deleting) - delete this; - else if (closing) - // close() may cause a delete; don't trust 'this' on return - close(); -} - -/* - * NOTE - this method must be called in the same context as other completions, - * so that the resulting readComplete, and final AsynchIO::close() is serialized - * after this method returns. - */ -void AsynchIO::cancelRead() { - if (queuedDelete) - return; // socket already deleted - else { - ScopedLock l(completionLock);; - if (!completionQueue.empty()) - return; // process it; come back later if necessary - } - // Cancel outstanding read and force to completion. Otherwise, on a faulty - // physical link, the pending read can remain uncompleted indefinitely. - // Draining the pending read will result in the official close (and - // notifyClosed). CancelIoEX() is the natural choice, but not available in - // XP, so we make do with closesocket(). - socket.close(); -} - -/* - * Track down cause of unavailable buffer if it recurs: QPID-5033 - */ -void AsynchIO::logNoBuffers(const char *context) { - QPID_LOG(error, "No IO buffers available: " << context << - ". Debug data: " << bufferQueue.size() << - ' ' << writeQueue.size() << - ' ' << completionQueue.size() << - ' ' << opsInProgress << - ' ' << writeInProgress << - ' ' << readInProgress << - ' ' << working); -} - - -} // namespace windows - -AsynchIO* qpid::sys::AsynchIO::create(const Socket& s, - AsynchIO::ReadCallback rCb, - AsynchIO::EofCallback eofCb, - AsynchIO::DisconnectCallback disCb, - AsynchIO::ClosedCallback cCb, - AsynchIO::BuffersEmptyCallback eCb, - AsynchIO::IdleCallback iCb) -{ - return new qpid::sys::windows::AsynchIO(s, rCb, eofCb, disCb, cCb, eCb, iCb); -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/AsynchIO.h b/qpid/cpp/src/qpid/sys/windows/AsynchIO.h deleted file mode 100644 index a50864b561..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/AsynchIO.h +++ /dev/null @@ -1,235 +0,0 @@ -#ifndef _sys_windows_AsynchIO -#define _sys_windows_AsynchIO - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 "AsynchIoResult.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/Poller.h" -#include "qpid/CommonImportExport.h" -#include "qpid/sys/Mutex.h" -#include -#include -#include -#include -#include -#include - -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include -#include -#undef SECURITY_WIN32 - -namespace qpid { -namespace sys { -namespace windows { - -/* - * Asynch Acceptor - */ - -class AsynchAcceptor : public qpid::sys::AsynchAcceptor { - - friend class AsynchAcceptResult; - -public: - AsynchAcceptor(const Socket& s, AsynchAcceptor::Callback callback); - ~AsynchAcceptor(); - void start(Poller::shared_ptr poller); - -private: - void restart(void); - - AsynchAcceptor::Callback acceptedCallback; - const Socket& socket; - const SOCKET wSocket; - const LPFN_ACCEPTEX fnAcceptEx; -}; - - -class AsynchConnector : public qpid::sys::AsynchConnector { -private: - ConnectedCallback connCallback; - FailedCallback failCallback; - const Socket& socket; - const std::string hostname; - const std::string port; - -public: - AsynchConnector(const Socket& socket, - const std::string& hostname, - const std::string& port, - ConnectedCallback connCb, - FailedCallback failCb = 0); - void start(Poller::shared_ptr poller); - void requestCallback(RequestCallback rCb); -}; - -class AsynchIO : public qpid::sys::AsynchIO { - - friend class SslAsynchIO; - -public: - AsynchIO(const Socket& s, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0); - ~AsynchIO(); - - // Methods inherited from qpid::sys::AsynchIO - - /** - * Notify the object is should delete itself as soon as possible. - */ - virtual void queueForDeletion(); - - /// Take any actions needed to prepare for working with the poller. - virtual void start(Poller::shared_ptr poller); - virtual void createBuffers(uint32_t size); - virtual void queueReadBuffer(BufferBase* buff); - virtual void unread(BufferBase* buff); - virtual void queueWrite(BufferBase* buff); - virtual void notifyPendingWrite(); - virtual void queueWriteClose(); - virtual bool writeQueueEmpty(); - virtual void requestCallback(RequestCallback); - - /** - * getQueuedBuffer returns a buffer from the buffer queue, if one is - * available. - * - * @retval Pointer to BufferBase buffer; 0 if none is available. - */ - virtual BufferBase* getQueuedBuffer(); - - virtual SecuritySettings getSecuritySettings(void); - -private: - ReadCallback readCallback; - EofCallback eofCallback; - DisconnectCallback disCallback; - ClosedCallback closedCallback; - BuffersEmptyCallback emptyCallback; - IdleCallback idleCallback; - const Socket& socket; - Poller::shared_ptr poller; - uint32_t bufferCount; - - std::deque bufferQueue; - std::deque writeQueue; - /* The MSVC-supplied deque is not thread-safe; keep locks to serialize - * access to the buffer queue and write queue. - */ - Mutex bufferQueueLock; - std::vector buffers; - boost::shared_array bufferMemory; - - // Number of outstanding I/O operations. - volatile LONG opsInProgress; - // Is there a write in progress? - volatile bool writeInProgress; - // Or a read? - volatile bool readInProgress; - // Deletion requested, but there are callbacks in progress. - volatile bool queuedDelete; - // Socket close requested, but there are operations in progress. - volatile bool queuedClose; - -protected: - uint32_t getBufferCount(void); - void setBufferCount(uint32_t); - -private: - // Dispatch events that have completed. - void notifyEof(void); - void notifyDisconnect(void); - void notifyClosed(void); - void notifyBuffersEmpty(void); - void notifyIdle(void); - - /** - * Initiate a write of the specified buffer. There's no callback for - * write completion to the AsynchIO object. - */ - void startWrite(AsynchIO::BufferBase* buff); - - void close(void); - - /** - * startReading initiates reading, readComplete() is - * called when the read completes. - */ - void startReading(); - - /** - * readComplete is called when a read request is complete. - * - * @param result Results of the operation. - */ - void readComplete(AsynchReadResult *result); - - /** - * writeComplete is called when a write request is complete. - * - * @param result Results of the operation. - */ - void writeComplete(AsynchWriteResult *result); - - /** - * Queue of completions to run. This queue enforces the requirement - * from upper layers that only one thread at a time is allowed to act - * on any given connection. Once a thread is busy processing a completion - * on this object, other threads that dispatch completions queue the - * completions here for the in-progress thread to handle when done. - * Thus, any threads can dispatch a completion from the IocpPoller, but - * this class ensures that actual processing at the connection level is - * only on one thread at a time. - */ - std::queue completionQueue; - volatile bool working; - Mutex completionLock; - - /** - * Called when there's a completion to process. - */ - void completion(AsynchIoResult *result); - - /** - * Helper function to facilitate the close operation - */ - void cancelRead(); - - /** - * Log information about buffer depletion, which should never happen. - * See QPID-5033. - */ - void logNoBuffers(const char*); -}; - -}}} // namespace qpid::sys::windows - -#endif // _sys_windows_AsynchIO diff --git a/qpid/cpp/src/qpid/sys/windows/AsynchIoResult.h b/qpid/cpp/src/qpid/sys/windows/AsynchIoResult.h deleted file mode 100755 index 27e4c22138..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/AsynchIoResult.h +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef _windows_asynchIoResult_h -#define _windows_asynchIoResult_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/AsynchIO.h" -#include "qpid/sys/Socket.h" -#include -#include -#include - -namespace qpid { -namespace sys { -namespace windows { - -/* - * AsynchIoResult defines the class that receives the result of an - * asynchronous I/O operation, either send/recv or accept/connect. - * - * Operation factories should set one of these up before beginning the - * operation. Poller knows how to dispatch completion to this class. - * This class must be subclassed for needed operations; this class provides - * an interface only and cannot be instantiated. - * - * This class is tied to Windows; it inherits from OVERLAPPED so that the - * IocpPoller can cast OVERLAPPED pointers back to AsynchIoResult and call - * the completion handler. - */ -class AsynchResult : private OVERLAPPED { -public: - LPOVERLAPPED overlapped(void) { return this; } - static AsynchResult* from_overlapped(LPOVERLAPPED ol) { - return static_cast(ol); - } - virtual void success (size_t bytesTransferred) { - bytes = bytesTransferred; - status = 0; - complete(); - } - virtual void failure (int error) { - bytes = 0; - status = error; - complete(); - } - size_t getTransferred(void) const { return bytes; } - int getStatus(void) const { return status; } - -protected: - AsynchResult() : bytes(0), status(0) - { memset(overlapped(), 0, sizeof(OVERLAPPED)); } - ~AsynchResult() {} - virtual void complete(void) = 0; - - size_t bytes; - int status; -}; - -class AsynchAcceptor; - -class AsynchAcceptResult : public AsynchResult { - - friend class AsynchAcceptor; - -public: - AsynchAcceptResult(qpid::sys::AsynchAcceptor::Callback cb, - AsynchAcceptor *acceptor, - const qpid::sys::Socket& listener); - virtual void success (size_t bytesTransferred); - virtual void failure (int error); - -private: - virtual void complete(void) {} // No-op for this class. - - qpid::sys::AsynchAcceptor::Callback callback; - AsynchAcceptor *acceptor; - SOCKET listener; - std::auto_ptr newSocket; - - // AcceptEx needs a place to write the local and remote addresses - // when accepting the connection. Place those here; get enough for - // IPv6 addresses, even if the socket is IPv4. - enum { SOCKADDRMAXLEN = sizeof(sockaddr_in6) + 16, - SOCKADDRBUFLEN = 2 * SOCKADDRMAXLEN }; - char addressBuffer[SOCKADDRBUFLEN]; -}; - -class AsynchIoResult : public AsynchResult { -public: - typedef boost::function1 Completer; - - virtual ~AsynchIoResult() {} - qpid::sys::AsynchIO::BufferBase *getBuff(void) const { return iobuff; } - size_t getRequested(void) const { return requested; } - const WSABUF *getWSABUF(void) const { return &wsabuf; } - -protected: - void setBuff (qpid::sys::AsynchIO::BufferBase *buffer) { iobuff = buffer; } - -protected: - AsynchIoResult(Completer cb, - qpid::sys::AsynchIO::BufferBase *buff, size_t length) - : completionCallback(cb), iobuff(buff), requested(length) {} - - virtual void complete(void) = 0; - WSABUF wsabuf; - Completer completionCallback; - -private: - qpid::sys::AsynchIO::BufferBase *iobuff; - size_t requested; // Number of bytes in original I/O request -}; - -class AsynchReadResult : public AsynchIoResult { - - // complete() updates buffer then does completion callback. - virtual void complete(void) { - getBuff()->dataCount += bytes; - completionCallback(this); - } - -public: - AsynchReadResult(AsynchIoResult::Completer cb, - qpid::sys::AsynchIO::BufferBase *buff, - size_t length) - : AsynchIoResult(cb, buff, length) { - wsabuf.buf = buff->bytes + buff->dataCount; - wsabuf.len = length; - } -}; - -class AsynchWriteResult : public AsynchIoResult { - - // complete() updates buffer then does completion callback. - virtual void complete(void) { - qpid::sys::AsynchIO::BufferBase *b = getBuff(); - b->dataStart += bytes; - b->dataCount -= bytes; - completionCallback(this); - } - -public: - AsynchWriteResult(AsynchIoResult::Completer cb, - qpid::sys::AsynchIO::BufferBase *buff, - size_t length) - : AsynchIoResult(cb, buff, length) { - wsabuf.buf = buff ? buff->bytes : 0; - wsabuf.len = length; - } -}; - -class AsynchWriteWanted : public AsynchWriteResult { - - // complete() just does completion callback; no buffers used. - virtual void complete(void) { - completionCallback(this); - } - -public: - AsynchWriteWanted(AsynchIoResult::Completer cb) - : AsynchWriteResult(cb, 0, 0) { - wsabuf.buf = 0; - wsabuf.len = 0; - } -}; - -class AsynchCallbackRequest : public AsynchIoResult { - // complete() needs to simply call the completionCallback; no buffers. - virtual void complete(void) { - completionCallback(this); - } - -public: - AsynchCallbackRequest(AsynchIoResult::Completer cb, - qpid::sys::AsynchIO::RequestCallback reqCb) - : AsynchIoResult(cb, 0, 0), reqCallback(reqCb) { - wsabuf.buf = 0; - wsabuf.len = 0; - } - - qpid::sys::AsynchIO::RequestCallback reqCallback; -}; - -}}} // qpid::sys::windows - -#endif /*!_windows_asynchIoResult_h*/ diff --git a/qpid/cpp/src/qpid/sys/windows/Condition.h b/qpid/cpp/src/qpid/sys/windows/Condition.h deleted file mode 100755 index cd5aebbf09..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/Condition.h +++ /dev/null @@ -1,77 +0,0 @@ -#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 -#include -#include -#include -#include - -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/FileSysDir.cpp b/qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp deleted file mode 100644 index 5128f0f8d6..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * 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/FileSysDir.h" -#include "qpid/sys/StrError.h" -#include "qpid/Exception.h" - -#include -#include -#include -#include -#include -#include - - -namespace qpid { -namespace sys { - -bool FileSysDir::exists (void) const -{ - const char *cpath = dirPath.c_str (); - struct _stat s; - if (::_stat(cpath, &s)) { - if (errno == ENOENT) { - return false; - } - throw qpid::Exception (strError(errno) + - ": Can't check directory: " + dirPath); - } - if (s.st_mode & _S_IFDIR) - return true; - throw qpid::Exception(dirPath + " is not a directory"); -} - -void FileSysDir::mkdir(void) -{ - if (::_mkdir(dirPath.c_str()) == -1) - throw Exception ("Can't create directory: " + dirPath); -} - -void FileSysDir::forEachFile(Callback cb) const { - - WIN32_FIND_DATAA findFileData; - char szDir[MAX_PATH]; - size_t dirPathLength; - HANDLE hFind = INVALID_HANDLE_VALUE; - - // create dirPath+"\*" in szDir - StringCchLength (dirPath.c_str(), MAX_PATH, &dirPathLength); - - if (dirPathLength > (MAX_PATH - 3)) { - throw Exception ("Directory path is too long: " + dirPath); - } - - StringCchCopy(szDir, MAX_PATH, dirPath.c_str()); - StringCchCat(szDir, MAX_PATH, TEXT("\\*")); - - // Special work for first file - hFind = FindFirstFileA(szDir, &findFileData); - if (INVALID_HANDLE_VALUE == hFind) { - return; - } - - // process everything that isn't a directory - do { - if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - std::string fileName(dirPath); - fileName += "\\"; - fileName += findFileData.cFileName; - cb(fileName); - } - } while (FindNextFile(hFind, &findFileData) != 0); -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/IOHandle.cpp b/qpid/cpp/src/qpid/sys/windows/IOHandle.cpp deleted file mode 100755 index 19a1c44875..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/IOHandle.cpp +++ /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. - * - */ - -#include "qpid/sys/windows/IoHandlePrivate.h" -#include - -namespace qpid { -namespace sys { - - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/IoHandlePrivate.h b/qpid/cpp/src/qpid/sys/windows/IoHandlePrivate.h deleted file mode 100755 index 4529ad93ec..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/IoHandlePrivate.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _sys_windows_IoHandlePrivate_h -#define _sys_windows_IoHandlePrivate_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/AsynchIO.h" -#include "qpid/sys/windows/AsynchIoResult.h" -#include "qpid/CommonImportExport.h" - -#include - -namespace qpid { -namespace sys { - -// Private fd related implementation details -// There should be either a valid socket handle or a completer callback. -// Handle is used to associate with poller's iocp; completer is used to -// inject a completion that will very quickly trigger a callback to the -// completer from an I/O thread. If the callback mechanism is used, there -// can be a RequestCallback set - this carries the callback object through -// from AsynchIO::requestCallback() through to the I/O completion processing. -class IOHandle { -public: - IOHandle(SOCKET f = INVALID_SOCKET, - windows::AsynchIoResult::Completer cb = 0, - AsynchIO::RequestCallback reqCallback = 0) : - fd(f), - event(cb), - cbRequest(reqCallback) - {} - - SOCKET fd; - windows::AsynchIoResult::Completer event; - AsynchIO::RequestCallback cbRequest; -}; - -}} - -#endif /* _sys_windows_IoHandlePrivate_h */ diff --git a/qpid/cpp/src/qpid/sys/windows/IocpPoller.cpp b/qpid/cpp/src/qpid/sys/windows/IocpPoller.cpp deleted file mode 100755 index ecb33c5517..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/IocpPoller.cpp +++ /dev/null @@ -1,220 +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/sys/Poller.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/windows/AsynchIoResult.h" -#include "qpid/sys/windows/IoHandlePrivate.h" -#include "qpid/sys/windows/check.h" - -#include -#include - -#include -#include -#include - -namespace qpid { -namespace sys { - -class PollerHandlePrivate { - friend class Poller; - friend class PollerHandle; - - SOCKET fd; - windows::AsynchIoResult::Completer cb; - AsynchIO::RequestCallback cbRequest; - - PollerHandlePrivate(SOCKET f, - windows::AsynchIoResult::Completer cb0 = 0, - AsynchIO::RequestCallback rcb = 0) - : fd(f), cb(cb0), cbRequest(rcb) - { - } - -}; - -PollerHandle::PollerHandle(const IOHandle& h) : - impl(new PollerHandlePrivate(h.fd, h.event, h.cbRequest)) -{} - -PollerHandle::~PollerHandle() { - delete impl; -} - -/** - * Concrete implementation of Poller to use the Windows I/O Completion - * port (IOCP) facility. - */ -class PollerPrivate { - friend class Poller; - - const HANDLE iocp; - - // The number of threads running the event loop. - volatile LONG threadsRunning; - - // Shutdown request is handled by setting isShutdown and injecting a - // well-formed completion event into the iocp. - bool isShutdown; - - PollerPrivate() : - iocp(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)), - threadsRunning(0), - isShutdown(false) { - QPID_WINDOWS_CHECK_NULL(iocp); - } - - ~PollerPrivate() { - // It's probably okay to ignore any errors here as there can't be - // data loss - ::CloseHandle(iocp); - } -}; - -void Poller::shutdown() { - // Allow sloppy code to shut us down more than once. - if (impl->isShutdown) - return; - impl->isShutdown = true; - ULONG_PTR key = 1; // Tell wait() it's a shutdown, not I/O - PostQueuedCompletionStatus(impl->iocp, 0, key, 0); -} - -bool Poller::hasShutdown() -{ - return impl->isShutdown; -} - -bool Poller::interrupt(PollerHandle&) { - return false; // There's no concept of a registered handle. -} - -void Poller::run() { - while (!impl->isShutdown) { - Poller::Event event = this->wait(); - - // Handle shutdown - switch (event.type) { - case Poller::SHUTDOWN: - return; - break; - case Poller::INVALID: // On any type of success or fail completion - break; - default: - // This should be impossible - assert(false); - } - } -} - -void Poller::monitorHandle(PollerHandle& handle, Direction dir) { - HANDLE h = (HANDLE)(handle.impl->fd); - if (h != INVALID_HANDLE_VALUE) { - HANDLE iocpHandle = ::CreateIoCompletionPort (h, impl->iocp, 0, 0); - QPID_WINDOWS_CHECK_NULL(iocpHandle); - } - else { - // INPUT is used to request a callback; OUTPUT to request a write - assert(dir == Poller::INPUT || dir == Poller::OUTPUT); - - if (dir == Poller::OUTPUT) { - windows::AsynchWriteWanted *result = - new windows::AsynchWriteWanted(handle.impl->cb); - PostQueuedCompletionStatus(impl->iocp, 0, 0, result->overlapped()); - } - else { - windows::AsynchCallbackRequest *result = - new windows::AsynchCallbackRequest(handle.impl->cb, - handle.impl->cbRequest); - PostQueuedCompletionStatus(impl->iocp, 0, 0, result->overlapped()); - } - } -} - -// All no-ops... -void Poller::unmonitorHandle(PollerHandle& /*handle*/, Direction /*dir*/) {} -void Poller::registerHandle(PollerHandle& /*handle*/) {} -void Poller::unregisterHandle(PollerHandle& /*handle*/) {} - -Poller::Event Poller::wait(Duration timeout) { - DWORD timeoutMs = 0; - DWORD numTransferred = 0; - ULONG_PTR completionKey = 0; - OVERLAPPED *overlapped = 0; - windows::AsynchResult *result = 0; - - // Wait for either an I/O operation to finish (thus signaling the - // IOCP handle) or a shutdown request to be made (thus signaling the - // shutdown event). - if (timeout == TIME_INFINITE) - timeoutMs = INFINITE; - else - timeoutMs = static_cast(timeout / TIME_MSEC); - - InterlockedIncrement(&impl->threadsRunning); - bool goodOp = ::GetQueuedCompletionStatus (impl->iocp, - &numTransferred, - &completionKey, - &overlapped, - timeoutMs); - LONG remainingThreads = InterlockedDecrement(&impl->threadsRunning); - if (goodOp) { - // Dequeued a successful completion. If it's a posted packet from - // shutdown() the overlapped ptr is 0 and key is 1. Else downcast - // the OVERLAPPED pointer to an AsynchIoResult and call the - // completion handler. - if (overlapped == 0 && completionKey == 1) { - // If there are other threads still running this wait, re-post - // the completion. - if (remainingThreads > 0) - PostQueuedCompletionStatus(impl->iocp, 0, completionKey, 0); - return Event(0, SHUTDOWN); - } - - result = windows::AsynchResult::from_overlapped(overlapped); - result->success (static_cast(numTransferred)); - } - else { - if (overlapped != 0) { - // Dequeued a completion for a failed operation. Downcast back - // to the result object and inform it that the operation failed. - DWORD status = ::GetLastError(); - result = windows::AsynchResult::from_overlapped(overlapped); - result->failure (static_cast(status)); - } - } - return Event(0, INVALID); // TODO - this may need to be changed. - -} - -// Concrete constructors -Poller::Poller() : - impl(new PollerPrivate()) -{} - -Poller::~Poller() { - delete impl; -} - -}} diff --git a/qpid/cpp/src/qpid/sys/windows/LockFile.cpp b/qpid/cpp/src/qpid/sys/windows/LockFile.cpp deleted file mode 100755 index 048c2d5b18..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/LockFile.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * 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/LockFile.h" -#include "qpid/sys/windows/check.h" - -#include - -namespace qpid { -namespace sys { - -class LockFilePrivate { - friend class LockFile; - - HANDLE fd; - -public: - LockFilePrivate(HANDLE f) : fd(f) {} -}; - -LockFile::LockFile(const std::string& path_, bool create) - : path(path_), created(create) { - - HANDLE h = ::CreateFile(path.c_str(), - create ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ, - FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, - 0, /* Default security */ - create ? OPEN_ALWAYS : OPEN_EXISTING, - FILE_FLAG_DELETE_ON_CLOSE, /* Delete file when closed */ - NULL); - if (h == INVALID_HANDLE_VALUE) - throw qpid::Exception(path + ": " + qpid::sys::strError(GetLastError())); - - // Lock up to 4Gb - if (!::LockFile(h, 0, 0, 0xffffffff, 0)) - throw qpid::Exception(path + ": " + qpid::sys::strError(GetLastError())); - impl.reset(new LockFilePrivate(h)); -} - -LockFile::~LockFile() { - if (impl) { - if (impl->fd != INVALID_HANDLE_VALUE) { - ::UnlockFile(impl->fd, 0, 0, 0xffffffff, 0); - ::CloseHandle(impl->fd); - } - } -} - -}} /* namespace qpid::sys */ diff --git a/qpid/cpp/src/qpid/sys/windows/MemoryMappedFile.cpp b/qpid/cpp/src/qpid/sys/windows/MemoryMappedFile.cpp deleted file mode 100644 index 60b3df7da6..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/MemoryMappedFile.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/MemoryMappedFile.h" - -namespace qpid { -namespace sys { -class MemoryMappedFilePrivate {}; - -MemoryMappedFile::MemoryMappedFile() : state(0) {} -MemoryMappedFile::~MemoryMappedFile() {} - -void MemoryMappedFile::open(const std::string& /*name*/, const std::string& /*directory*/) -{ -} -void MemoryMappedFile::close() -{ -} -size_t MemoryMappedFile::getPageSize() -{ - return 0; -} -char* MemoryMappedFile::map(size_t /*offset*/, size_t /*size*/) -{ - return 0; -} -void MemoryMappedFile::unmap(char* /*region*/, size_t /*size*/) -{ -} -void MemoryMappedFile::flush(char* /*region*/, size_t /*size*/) -{ -} -void MemoryMappedFile::expand(size_t /*offset*/) -{ -} -bool MemoryMappedFile::isSupported() -{ - return false; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/Mutex.h b/qpid/cpp/src/qpid/sys/windows/Mutex.h deleted file mode 100755 index 5dcc69e836..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/Mutex.h +++ /dev/null @@ -1,188 +0,0 @@ -#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 -#if (BOOST_VERSION < 103500) -#error The Windows port requires Boost version 1.35.0 or later -#endif - -#include -#include -#include -#include -#include - -namespace qpid { -namespace sys { - -class Condition; - -/** - * Mutex lock. - */ -class Mutex : private boost::noncopyable { - friend class Condition; - -public: - typedef ::qpid::sys::ScopedLock ScopedLock; - typedef ::qpid::sys::ScopedUnlock 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 ScopedRlock; - typedef ::qpid::sys::ScopedWlock 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 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 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/Path.cpp b/qpid/cpp/src/qpid/sys/windows/Path.cpp deleted file mode 100644 index 1cb4521fde..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/Path.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * 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/Path.h" -#include "qpid/sys/StrError.h" -#include "qpid/Exception.h" - -#include -#include -#include -#include -#include -#include - - -namespace qpid { -namespace sys { - -const std::string Path::separator("\\"); - -namespace { -// Return true for success, false for ENOENT, throw otherwise. -bool getStat(const std::string& path, struct _stat& s) { - if (::_stat(path.c_str(), &s)) { - if (errno == ENOENT) return false; - throw qpid::Exception("cannot stat: " + path + ": " + strError(errno)); - } - return true; -} - -bool isFlag(const std::string& path, unsigned long flag) { - struct _stat s; - return getStat(path, s) && (s.st_mode & flag); -} -} - -bool Path::exists () const { - struct _stat s; - return getStat(path, s); -} - -bool Path::isFile() const { return isFlag(path, _S_IFREG); } -bool Path::isDirectory() const { return isFlag(path, _S_IFDIR); } - -bool Path::isAbsolute() const { - return (path.size() > 0 && (path[0] == separator[0] || path[0] == '/')) - || (path.size() > 1 && (isalpha(path[0]) && path[1] == ':')); -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/PipeHandle.cpp b/qpid/cpp/src/qpid/sys/windows/PipeHandle.cpp deleted file mode 100755 index 062458ae5f..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/PipeHandle.cpp +++ /dev/null @@ -1,101 +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/sys/PipeHandle.h" -#include "qpid/sys/windows/check.h" -#include - -namespace qpid { -namespace sys { - -PipeHandle::PipeHandle(bool nonBlocking) { - - SOCKET listener, pair[2]; - struct sockaddr_in addr; - int err; - int addrlen = sizeof(addr); - pair[0] = pair[1] = INVALID_SOCKET; - if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = 0; - - err = bind(listener, (const struct sockaddr*) &addr, sizeof(addr)); - if (err == SOCKET_ERROR) { - err = WSAGetLastError(); - closesocket(listener); - throw QPID_WINDOWS_ERROR(err); - } - - err = getsockname(listener, (struct sockaddr*) &addr, &addrlen); - if (err == SOCKET_ERROR) { - err = WSAGetLastError(); - closesocket(listener); - throw QPID_WINDOWS_ERROR(err); - } - - try { - if (listen(listener, 1) == SOCKET_ERROR) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - if ((pair[0] = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - if (connect(pair[0], (const struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - if ((pair[1] = accept(listener, NULL, NULL)) == INVALID_SOCKET) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - - closesocket(listener); - writeFd = pair[0]; - readFd = pair[1]; - } - catch (...) { - closesocket(listener); - if (pair[0] != INVALID_SOCKET) - closesocket(pair[0]); - throw; - } - - // Set the socket to non-blocking - if (nonBlocking) { - unsigned long nonblock = 1; - ioctlsocket(readFd, FIONBIO, &nonblock); - } -} - -PipeHandle::~PipeHandle() { - closesocket(readFd); - closesocket(writeFd); -} - -int PipeHandle::read(void* buf, size_t bufSize) { - return ::recv(readFd, (char *)buf, bufSize, 0); -} - -int PipeHandle::write(const void* buf, size_t bufSize) { - return ::send(writeFd, (const char *)buf, bufSize, 0); -} - -int PipeHandle::getReadHandle() { - return readFd; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/PollableCondition.cpp b/qpid/cpp/src/qpid/sys/windows/PollableCondition.cpp deleted file mode 100644 index 3e2a5fb36c..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/PollableCondition.cpp +++ /dev/null @@ -1,114 +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/sys/PollableCondition.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/windows/AsynchIoResult.h" -#include "qpid/sys/windows/IoHandlePrivate.h" - -#include -#include - -namespace qpid { -namespace sys { - -// PollableConditionPrivate will reuse the IocpPoller's ability to queue -// a completion to the IOCP and have it dispatched to the completer callback -// noted in the IOHandlePrivate when the request is queued. The -// AsynchCallbackRequest object is not really used - we already have the -// desired callback for the user of PollableCondition. -class PollableConditionPrivate : private IOHandle { - friend class PollableCondition; - -private: - PollableConditionPrivate(const sys::PollableCondition::Callback& cb, - sys::PollableCondition& parent, - const boost::shared_ptr& poller); - ~PollableConditionPrivate(); - - void poke(); - void dispatch(windows::AsynchIoResult *result); - -private: - PollableCondition::Callback cb; - PollableCondition& parent; - boost::shared_ptr poller; - LONG isSet; - LONG isDispatching; -}; - -PollableConditionPrivate::PollableConditionPrivate(const sys::PollableCondition::Callback& cb, - sys::PollableCondition& parent, - const boost::shared_ptr& poller) - : IOHandle(INVALID_SOCKET, boost::bind(&PollableConditionPrivate::dispatch, this, _1)), - cb(cb), parent(parent), poller(poller), isSet(0), isDispatching(0) -{ -} - -PollableConditionPrivate::~PollableConditionPrivate() -{ -} - -void PollableConditionPrivate::poke() -{ - // monitorHandle will queue a completion for the IOCP; when it's handled, a - // poller thread will call back to dispatch() below. - PollerHandle ph(*this); - poller->monitorHandle(ph, Poller::INPUT); -} - -void PollableConditionPrivate::dispatch(windows::AsynchIoResult *result) -{ - delete result; // Poller::monitorHandle() allocates this - // If isDispatching is already set, just return. Else, enter. - if (::InterlockedCompareExchange(&isDispatching, 1, 0) == 1) - return; - cb(parent); - LONG oops = ::InterlockedDecrement(&isDispatching); // Result must be 0 - assert(!oops); - if (isSet) - poke(); -} - - /* PollableCondition */ - -PollableCondition::PollableCondition(const Callback& cb, - const boost::shared_ptr& poller) - : impl(new PollableConditionPrivate(cb, *this, poller)) -{ -} - -PollableCondition::~PollableCondition() -{ - delete impl; -} - -void PollableCondition::set() { - // Add one to the set count and poke it to provoke a callback - ::InterlockedIncrement(&impl->isSet); - impl->poke(); -} - -void PollableCondition::clear() { - ::InterlockedExchange(&impl->isSet, 0); -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/QpidDllMain.h b/qpid/cpp/src/qpid/sys/windows/QpidDllMain.h deleted file mode 100644 index 74eaf0256a..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/QpidDllMain.h +++ /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. - * - */ - -/* - * Include this file once in each DLL that relies on SystemInfo.h: - * threadSafeShutdown(). Note that Thread.cpp has a more elaborate - * DllMain, that also provides this functionality separately. - * - * Teardown is in the reverse order of the DLL dependencies used - * during the load phase. The calls to DllMain and the static - * destructors are from the same thread, so no locking is necessary - * and there is no downside to an invocation of DllMain by multiple - * Qpid DLLs. - */ - -#ifdef _DLL - -#include -#include - -namespace qpid { -namespace sys { -namespace windows { - -QPID_IMPORT bool processExiting; -QPID_IMPORT bool libraryUnloading; - -}}} // namespace qpid::sys::SystemInfo - - -BOOL APIENTRY DllMain(HMODULE hm, DWORD reason, LPVOID reserved) { - switch (reason) { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - - case DLL_PROCESS_DETACH: - // Remember how the process is terminating this DLL. - if (reserved != NULL) { - qpid::sys::windows::processExiting = true; - // Danger: all threading suspect, including indirect use of malloc or locks. - // Think twice before adding more functionality here. - return TRUE; - } - else { - qpid::sys::windows::libraryUnloading = true; - } - break; - } - return TRUE; -} - - -#endif diff --git a/qpid/cpp/src/qpid/sys/windows/Shlib.cpp b/qpid/cpp/src/qpid/sys/windows/Shlib.cpp deleted file mode 100644 index ba18747eb4..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/Shlib.cpp +++ /dev/null @@ -1,54 +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/sys/Shlib.h" -#include "qpid/Exception.h" -#include "qpid/sys/windows/check.h" -#include - -namespace qpid { -namespace sys { - -void Shlib::load(const char* name) { - HMODULE h = LoadLibrary(name); - if (h == NULL) { - throw QPID_WINDOWS_ERROR(GetLastError()); - } - handle = static_cast(h); -} - -void Shlib::unload() { - if (handle) { - if (FreeLibrary(static_cast(handle)) == 0) { - throw QPID_WINDOWS_ERROR(GetLastError()); - } - handle = 0; - } -} - -void* Shlib::getSymbol(const char* name) { - // Double cast avoids warning about casting function pointer to object - void *sym = reinterpret_cast(reinterpret_cast(GetProcAddress(static_cast(handle), name))); - if (sym == NULL) - throw QPID_WINDOWS_ERROR(GetLastError()); - return sym; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp b/qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp deleted file mode 100644 index b0903752c6..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp +++ /dev/null @@ -1,346 +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/sys/SocketAddress.h" - -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/log/Logger.h" - -// Ensure we get all of winsock2.h -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - -#include -#include -#include - -namespace qpid { -namespace sys { - -SocketAddress::SocketAddress(const std::string& host0, const std::string& port0) : - host(host0), - port(port0), - addrInfo(0), - currentAddrInfo(0) -{ -} - -SocketAddress::SocketAddress(const SocketAddress& sa) : - host(sa.host), - port(sa.port), - addrInfo(0), - currentAddrInfo(0) -{ -} - -SocketAddress& SocketAddress::operator=(const SocketAddress& sa) -{ - SocketAddress temp(sa); - - std::swap(temp, *this); - return *this; -} - -SocketAddress::~SocketAddress() -{ - if (addrInfo) { - ::freeaddrinfo(addrInfo); - } -} - -std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen, bool dispNameOnly, bool hideDecoration) -{ - char servName[NI_MAXSERV]; - char dispName[NI_MAXHOST]; - if (int rc=::getnameinfo(addr, addrlen, - dispName, sizeof(dispName), - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw qpid::Exception(QPID_MSG(gai_strerror(rc))); - std::string s; - switch (addr->sa_family) { - case AF_INET: s += dispName; break; - case AF_INET6: - if (!hideDecoration) { - s += "["; s += dispName; s+= "]"; - } else { - s += dispName; - } - break; - default: throw Exception(QPID_MSG("Unexpected socket type")); - } - if (!dispNameOnly) { - s += ":"; - s += servName; - } - return s; -} - -uint16_t SocketAddress::getPort(::sockaddr const * const addr) -{ - switch (addr->sa_family) { - case AF_INET: return ntohs(((::sockaddr_in*)addr)->sin_port); - case AF_INET6: return ntohs(((::sockaddr_in6*)addr)->sin6_port); - default:throw Exception(QPID_MSG("Unexpected socket type")); - } -} - -std::string SocketAddress::asString(bool numeric, bool dispNameOnly, bool hideDecoration) const -{ - if (!numeric) - return host + ":" + port; - // Canonicalise into numeric id - const ::addrinfo& ai = getAddrInfo(*this); - - return asString(ai.ai_addr, ai.ai_addrlen, dispNameOnly, hideDecoration); -} - -std::string SocketAddress::getHost() const -{ - return host; -} - -/** - * Return true if this SocketAddress is IPv4 or IPv6 - */ -bool SocketAddress::isIp() const -{ - const ::addrinfo& ai = getAddrInfo(*this); - return ai.ai_family == AF_INET || ai.ai_family == AF_INET6; -} - -/** - * this represents the low address of an ACL address range. - * Given rangeHi that represents the high address, - * return a string showing the numeric comparisons that the - * inRange checks will do for address pair. - */ -std::string SocketAddress::comparisonDetails(const SocketAddress& rangeHi) const -{ - std::ostringstream os; - SocketAddress thisSa(*this); - SocketAddress rangeHiSa(rangeHi); - (void) getAddrInfo(thisSa); - (void) getAddrInfo(rangeHiSa); - os << "(" << thisSa.asString(true, true, false) << - "," << rangeHiSa.asString(true, true, false) << ")"; - while (thisSa.nextAddress()) { - if (!rangeHiSa.nextAddress()) { - throw(Exception(QPID_MSG("Comparison iteration fails: " + (*this).asString() + - rangeHi.asString()))); - } - os << ",(" << thisSa.asString(true, true, false) << - "," << rangeHiSa.asString(true, true, false) << ")"; - } - if (rangeHiSa.nextAddress()) { - throw(Exception(QPID_MSG("Comparison iteration fails: " + (*this).asString() + - rangeHi.asString()))); - } - std::string result = os.str(); - return result; -} - -/** - * For ACL address matching make sure that the two addresses, *this - * which is the low address and hiPeer which is the high address, are - * both numeric ip addresses of the same family and that hi > *this. - * - * Note that if the addresses resolve to more than one struct addrinfo - * then this and the hiPeer must be equal. This avoids having to do - * difficult range checks where the this and hiPeer both resolve to - * multiple IPv4 or IPv6 addresses. - * - * This check is run at acl file load time and not at run tme. - */ -bool SocketAddress::isComparable(const SocketAddress& hiPeer) const { - try { - // May only compare if this socket is IPv4 or IPv6 - SocketAddress lo(*this); - const ::addrinfo& peerLoInfo = getAddrInfo(lo); - if (!(peerLoInfo.ai_family == AF_INET || peerLoInfo.ai_family == AF_INET6)) { - return false; - } - try { - // May only compare if peer socket is same family - SocketAddress hi(hiPeer); - const ::addrinfo& peerHiInfo = getAddrInfo(hi); - if (peerLoInfo.ai_family != peerHiInfo.ai_family) { - return false; - } - // Host names that resolve to lists are allowed if they are equal. - // For example: localhost, or fjord.lab.example.com - if ((*this).asString() == hiPeer.asString()) { - return true; - } - // May only compare if this and peer resolve to single address. - if (lo.nextAddress() || hi.nextAddress()) { - return false; - } - // Make sure that the lo/hi relationship is ok - int res; - if (!compareAddresses(peerLoInfo, peerHiInfo, res) || res < 0) { - return false; - } - return true; - } catch (Exception) { - // failed to resolve hi - return false; - } - } catch (Exception) { - // failed to resolve lo - return false; - } -} - -/** - * *this SocketAddress was created from the numeric IP address of a - * connecting host. - * The lo and hi addresses are the limit checks from the ACL file. - * Return true if this address is in range of any of the address pairs - * in the limit check range. - * - * This check is executed on every incoming connection. - */ -bool SocketAddress::inRange(const SocketAddress& lo, - const SocketAddress& hi) const -{ - (*this).firstAddress(); - lo.firstAddress(); - hi.firstAddress(); - const ::addrinfo& thisInfo = getAddrInfo(*this); - const ::addrinfo& loInfo = getAddrInfo(lo); - const ::addrinfo& hiInfo = getAddrInfo(hi); - if (inRange(thisInfo, loInfo, hiInfo)) { - return true; - } - while (lo.nextAddress()) { - if (!hi.nextAddress()) { - assert (false); - throw(Exception(QPID_MSG("Comparison iteration fails: " + - lo.asString() + hi.asString()))); - } - const ::addrinfo& loInfo = getAddrInfo(lo); - const ::addrinfo& hiInfo = getAddrInfo(hi); - if (inRange(thisInfo, loInfo, hiInfo)) { - return true; - } - } - return false; -} - -/** - * *this SocketAddress was created from the numeric IP address of a - * connecting host. - * The lo and hi addresses are one binary address pair from a range - * given in an ACL file. - * Return true if this binary address is '>= lo' and '<= hi'. - */ -bool SocketAddress::inRange(const ::addrinfo& thisInfo, - const ::addrinfo& lo, - const ::addrinfo& hi) const -{ - int resLo; - int resHi; - if (!compareAddresses(lo, thisInfo, resLo)) { - return false; - } - if (!compareAddresses(hi, thisInfo, resHi)) { - return false; - } - if (resLo < 0) { - return false; - } - if (resHi > 0) { - return false; - } - return true; -} - -/** - * Compare this address against two binary low/high addresses. - * return true with result holding the comparison. - */ -bool SocketAddress::compareAddresses(const struct addrinfo& lo, - const struct addrinfo& hi, - int& result) const -{ - if (lo.ai_family != hi.ai_family) { - return false; - } - if (lo.ai_family == AF_INET) { - struct sockaddr_in* sin4lo = (struct sockaddr_in*)lo.ai_addr; - struct sockaddr_in* sin4hi = (struct sockaddr_in*)hi.ai_addr; - result = memcmp(&sin4hi->sin_addr, &sin4lo->sin_addr, sizeof(in_addr)); - } else if (lo.ai_family == AF_INET6) { - struct sockaddr_in6* sin6lo = (struct sockaddr_in6*)lo.ai_addr; - struct sockaddr_in6* sin6hi = (struct sockaddr_in6*)hi.ai_addr; - result = memcmp(&sin6hi->sin6_addr, &sin6lo->sin6_addr, sizeof(in6_addr)); - } else { - assert (false); - return false; - } - return true; -} - -void SocketAddress::firstAddress() const { - if (addrInfo) { - currentAddrInfo = addrInfo; - } else { - (void) getAddrInfo(*this); - } -} - -bool SocketAddress::nextAddress() const { - bool r = currentAddrInfo->ai_next != 0; - if (r) - currentAddrInfo = currentAddrInfo->ai_next; - return r; -} - -const ::addrinfo& getAddrInfo(const SocketAddress& sa) -{ - if (!sa.addrInfo) { - ::addrinfo hints; - ::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for - hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6 - hints.ai_socktype = SOCK_STREAM; - - const char* node = 0; - if (sa.host.empty()) { - hints.ai_flags |= AI_PASSIVE; - } else { - node = sa.host.c_str(); - } - const char* service = sa.port.empty() ? "0" : sa.port.c_str(); - - int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo); - if (n != 0) - throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n))); - sa.currentAddrInfo = sa.addrInfo; - } - - return *sa.currentAddrInfo; -} - -}} diff --git a/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp b/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp deleted file mode 100644 index 29f673c156..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp +++ /dev/null @@ -1,735 +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 "SslAsynchIO.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/log/Statement.h" - -#include "qpid/sys/windows/check.h" - -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include -#include -#undef SECURITY_WIN32 - -#include -#include -#include "AsynchIO.h" - -namespace qpid { -namespace sys { -namespace windows { - -namespace { - - /* - * To make the SSL encryption more efficient, set up a new BufferBase - * that leaves room for the SSL header to be prepended and the SSL - * trailer to be appended. - * - * This works by accepting a properly formed BufferBase, remembering it, - * and resetting the members of this struct to reflect the reserved - * header and trailer areas. It's only needed for giving buffers up to - * the frame layer for writing into. - */ - struct SslIoBuff : public qpid::sys::AsynchIO::BufferBase { - qpid::sys::AsynchIO::BufferBase* aioBuff; - - SslIoBuff (qpid::sys::AsynchIO::BufferBase *base, - const SecPkgContext_StreamSizes &sizes) - : qpid::sys::AsynchIO::BufferBase(&base->bytes[sizes.cbHeader], - std::min(base->byteCount - sizes.cbHeader - sizes.cbTrailer, - sizes.cbMaximumMessage)), - aioBuff(base) - {} - - ~SslIoBuff() {} - }; -} - -SslAsynchIO::SslAsynchIO(const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb, - BuffersEmptyCallback eCb, - IdleCallback iCb, - NegotiateDoneCallback nCb) : - credHandle(hCred), - aio(0), - state(Negotiating), - readCallback(rCb), - idleCallback(iCb), - negotiateDoneCallback(nCb), - queuedDelete(false), - queuedClose(false), - reapCheckPending(false), - started(false), - leftoverPlaintext(0) -{ - SecInvalidateHandle(&ctxtHandle); - peerAddress = s.getPeerAddress(); - aio = qpid::sys::AsynchIO::create(s, - boost::bind(&SslAsynchIO::sslDataIn, this, _1, _2), - eofCb, - disCb, - cCb, - eCb, - boost::bind(&SslAsynchIO::idle, this, _1)); -} - -SslAsynchIO::~SslAsynchIO() { - leftoverPlaintext = 0; -} - -void SslAsynchIO::queueForDeletion() { - // Called exactly once, always on the IO completion thread. - bool authenticated = (state != Negotiating); - state = ShuttingDown; - if (authenticated) { - // Tell SChannel we are done. - DWORD shutdown = SCHANNEL_SHUTDOWN; - SecBuffer shutBuff; - shutBuff.cbBuffer = sizeof(DWORD); - shutBuff.BufferType = SECBUFFER_TOKEN; - shutBuff.pvBuffer = &shutdown; - SecBufferDesc desc; - desc.ulVersion = SECBUFFER_VERSION; - desc.cBuffers = 1; - desc.pBuffers = &shutBuff; - ::ApplyControlToken(&ctxtHandle, &desc); - negotiateStep(0); - } - - queueWriteClose(); - queuedDelete = true; - - // This method effectively disconnects the layer above; pass it on the - // AsynchIO and delete. - aio->queueForDeletion(); - - if (!reapCheckPending) - delete(this); -} - -void SslAsynchIO::start(qpid::sys::Poller::shared_ptr poller) { - aio->start(poller); - started = true; - startNegotiate(); -} - -void SslAsynchIO::createBuffers(uint32_t size) { - // Reserve an extra buffer to hold unread plaintext or trailing encrypted input. - windows::AsynchIO *waio = dynamic_cast(aio); - waio->setBufferCount(waio->getBufferCount() + 1); - aio->createBuffers(size); -} - -void SslAsynchIO::queueReadBuffer(AsynchIO::BufferBase* buff) { - aio->queueReadBuffer(buff); -} - -void SslAsynchIO::unread(AsynchIO::BufferBase* buff) { - // This is plaintext data being given back for more. Since it's already - // decrypted, don't give it back to the aio layer; keep it to append - // any new data for the upper layer. - assert(buff); - buff->squish(); - assert(leftoverPlaintext == 0); - leftoverPlaintext = buff; -} - -void SslAsynchIO::queueWrite(AsynchIO::BufferBase* buff) { - // @@TODO: Need to delay the write if the session is renegotiating. - - // Should not have gotten here without an SslIoBuff. This assert is - // primarily to catch any stray cases where write is called with a buffer - // not obtained via getQueuedBuffer. - SslIoBuff *sslBuff = dynamic_cast(buff); - assert(sslBuff != 0); - - // Encrypt and hand off to the io layer. Remember that the upper layer's - // encoding was working on, and adjusting counts for, the SslIoBuff. - // Update the count of the original BufferBase before handing off to - // the I/O layer. - buff = sslBuff->aioBuff; - SecBuffer buffs[4]; - buffs[0].cbBuffer = schSizes.cbHeader; - buffs[0].BufferType = SECBUFFER_STREAM_HEADER; - buffs[0].pvBuffer = buff->bytes; // This space was left by SslIoBuff - buffs[1].cbBuffer = sslBuff->dataCount; - buffs[1].BufferType = SECBUFFER_DATA; - buffs[1].pvBuffer = sslBuff->bytes; - buffs[2].cbBuffer = schSizes.cbTrailer; - buffs[2].BufferType = SECBUFFER_STREAM_TRAILER; - buffs[2].pvBuffer = &sslBuff->bytes[sslBuff->dataCount]; - buffs[3].cbBuffer = 0; - buffs[3].BufferType = SECBUFFER_EMPTY; - buffs[3].pvBuffer = 0; - SecBufferDesc buffDesc; - buffDesc.ulVersion = SECBUFFER_VERSION; - buffDesc.cBuffers = 4; - buffDesc.pBuffers = buffs; - SECURITY_STATUS status = ::EncryptMessage(&ctxtHandle, 0, &buffDesc, 0); - - // EncryptMessage encrypts the data in place. The header and trailer - // areas were left previously and must now be included in the updated - // count of bytes to write to the peer. - delete sslBuff; - buff->dataCount = buffs[0].cbBuffer + buffs[1].cbBuffer + buffs[2].cbBuffer; - aio->queueWrite(buff); -} - -void SslAsynchIO::notifyPendingWrite() { - aio->notifyPendingWrite(); -} - -void SslAsynchIO::queueWriteClose() { - qpid::sys::Mutex::ScopedLock l(lock); - if (queuedClose) - return; - queuedClose = true; - if (started) { - reapCheckPending = true; - // Move tear down logic to an IO thread. - aio->requestCallback(boost::bind(&SslAsynchIO::reapCheck, this)); - } - aio->queueWriteClose(); -} - -void SslAsynchIO::reapCheck() { - // Serialized check in the IO thread whether to self-delete. - reapCheckPending = false; - if (queuedDelete) - delete(this); -} - -bool SslAsynchIO::writeQueueEmpty() { - return aio->writeQueueEmpty(); -} - -// Queue the specified callback for invocation from an I/O thread. -void SslAsynchIO::requestCallback(RequestCallback callback) { - aio->requestCallback(callback); -} - -/** - * Return a queued buffer read to put new data in for writing. - * This method ALWAYS returns a SslIoBuff reflecting a BufferBase from - * the aio layer that has header and trailer space reserved. - */ -AsynchIO::BufferBase* SslAsynchIO::getQueuedBuffer() { - SslIoBuff *sslBuff = 0; - BufferBase* buff = aio->getQueuedBuffer(); - if (buff == 0) - return 0; - - sslBuff = new SslIoBuff(buff, schSizes); - return sslBuff; -} - -SecuritySettings SslAsynchIO::getSecuritySettings() { - SecPkgContext_KeyInfo info; - memset(&info, 0, sizeof(info)); - ::QueryContextAttributes(&ctxtHandle, SECPKG_ATTR_KEY_INFO, &info); - - SecuritySettings settings; - settings.ssf = info.KeySize; - settings.authid = std::string(); - return settings; -} - -void SslAsynchIO::negotiationDone() { - switch(state) { - case Negotiating: - ::QueryContextAttributes(&ctxtHandle, - SECPKG_ATTR_STREAM_SIZES, - &schSizes); - state = Running; - if (negotiateDoneCallback) - negotiateDoneCallback(SEC_E_OK); - break; - case Redo: - state = Running; - break; - case ShuttingDown: - break; - default: - assert(0); - } -} - -void SslAsynchIO::negotiationFailed(SECURITY_STATUS status) { - QPID_LOG(notice, "SSL negotiation failed to " << peerAddress << ": " << - qpid::sys::strError(status)); - if (negotiateDoneCallback) - negotiateDoneCallback(status); - else - queueWriteClose(); -} - -void SslAsynchIO::sslDataIn(qpid::sys::AsynchIO& a, BufferBase *buff) { - if (state == ShuttingDown) { - return; - } - if (state != Running) { - negotiateStep(buff); - return; - } - - // Decrypt one block; if there's legit data, pass it on through. - // However, it's also possible that the peer hasn't supplied enough - // data yet, or the session needs to be renegotiated, or the session - // is ending. - SecBuffer recvBuffs[4]; - recvBuffs[0].cbBuffer = buff->dataCount; - recvBuffs[0].BufferType = SECBUFFER_DATA; - recvBuffs[0].pvBuffer = &buff->bytes[buff->dataStart]; - recvBuffs[1].BufferType = SECBUFFER_EMPTY; - recvBuffs[2].BufferType = SECBUFFER_EMPTY; - recvBuffs[3].BufferType = SECBUFFER_EMPTY; - SecBufferDesc buffDesc; - buffDesc.ulVersion = SECBUFFER_VERSION; - buffDesc.cBuffers = 4; - buffDesc.pBuffers = recvBuffs; - SECURITY_STATUS status = ::DecryptMessage(&ctxtHandle, &buffDesc, 0, NULL); - if (status != SEC_E_OK) { - if (status == SEC_E_INCOMPLETE_MESSAGE) { - // Give the partially filled buffer back and get more data - a.unread(buff); - } - else { - // Don't need this any more... - a.queueReadBuffer(buff); - - if (status == SEC_I_RENEGOTIATE) { - state = Redo; - negotiateStep(0); - } - else if (status == SEC_I_CONTEXT_EXPIRED) { - queueWriteClose(); - } - else { - throw QPID_WINDOWS_ERROR(status); - } - } - return; - } - - // All decrypted and verified... continue with AMQP. The recvBuffs have - // been set up by DecryptMessage to demarcate the SSL header, data, and - // trailer, as well as any extra data left over. Walk through and find - // that info, adjusting the buff data accordingly to reflect only the - // actual decrypted data. - // If there's extra data, copy that out to a new buffer and run through - // this method again. - char *extraBytes = 0; - int32_t extraLength = 0; - BufferBase *extraBuff = 0; - for (int i = 0; i < 4; i++) { - switch (recvBuffs[i].BufferType) { - case SECBUFFER_STREAM_HEADER: - buff->dataStart += recvBuffs[i].cbBuffer; - // Fall through - also don't count these bytes as data - case SECBUFFER_STREAM_TRAILER: - buff->dataCount -= recvBuffs[i].cbBuffer; - break; - case SECBUFFER_EXTRA: - extraBytes = (char *) recvBuffs[i].pvBuffer; - extraLength = recvBuffs[i].cbBuffer; - break; - default: - break; - } - } - - // Since we've already taken (possibly) all the available bytes from the - // aio layer, need to be sure that everything that's processable is - // processed before returning back to aio. It could be that any - // leftoverPlaintext data plus new buff data won't fit in one buffer, so - // need to keep going around the input processing loop until either - // all the bytes are gone, or there's less than a full frame remaining - // (so we can count on more bytes being on the way via aio). - do { - BufferBase *temp = 0; - // See if there was partial data left over from last time. If so, append this new - // data to that and release the current buff back to aio. Assume that - // leftoverPlaintext was squished so the data starts at 0. - if (leftoverPlaintext != 0) { - // There is leftover data; append all the new data that will fit. - int32_t count = buff->dataCount; - if (count) { - if (leftoverPlaintext->dataCount + count > leftoverPlaintext->byteCount) - count = (leftoverPlaintext->byteCount - leftoverPlaintext->dataCount); - ::memmove(&leftoverPlaintext->bytes[leftoverPlaintext->dataCount], - &buff->bytes[buff->dataStart], count); - leftoverPlaintext->dataCount += count; - buff->dataCount -= count; - buff->dataStart += count; - // Prepare to pass the buffer up. Beware that the read callback - // may do an unread(), so move the leftoverPlaintext pointer - // out of the way. It also may release the buffer back to aio, - // so in either event, the pointer passed to the callback is not - // valid on return. - temp = leftoverPlaintext; - leftoverPlaintext = 0; - } - else { - // All decrypted data used up, decrypt some more or get more from the aio - if (extraLength) { - buff->dataStart = extraBytes - buff->bytes; - buff->dataCount = extraLength; - sslDataIn(a, buff); - return; - } - else { - a.queueReadBuffer(buff); - return; - } - } - } - else { - // Use buff, but first offload data not yet encrypted - if (extraLength) { - // Very important to get this buffer from the downstream aio. - // The ones constructed from the local getQueuedBuffer() are - // restricted size for encrypting. However, data coming up from - // TCP may have a bunch of SSL segments coalesced and be much - // larger than the maximum single SSL segment. - extraBuff = a.getQueuedBuffer(); - if (0 == extraBuff) { - // No leftoverPlaintext, so a spare buffer should be available - throw QPID_WINDOWS_ERROR(WSAENOBUFS); - } - memmove(extraBuff->bytes, extraBytes, extraLength); - extraBuff->dataCount = extraLength; - extraLength = 0; - } - temp = buff; - buff = 0; - } - if (readCallback) { - // The callback guard here is to prevent an upcall from deleting - // this out from under us via queueForDeletion(). - readCallback(*this, temp); - } - else - a.queueReadBuffer(temp); // What else can we do with this??? - } while (buff != 0); - - // Ok, the current decrypted data is done. If there was any extra data, - // go back and handle that. - if (extraBuff != 0) { - sslDataIn(a, extraBuff); - } -} - -void SslAsynchIO::idle(qpid::sys::AsynchIO&) { - // Don't relay idle indication to layer above until SSL session is up. - if (state == Running) { - state = Running; - if (idleCallback) - idleCallback(*this); - } -} - -/**************************************************/ - -namespace { - -bool unsafeNegotiatedTlsVersion(CtxtHandle &ctxtHandle) { - // See if SChannel ultimately negotiated <= SSL3, perhaps due to - // global registry settings. - SecPkgContext_ConnectionInfo info; - ::QueryContextAttributes(&ctxtHandle, SECPKG_ATTR_CONNECTION_INFO, &info); - // Ascending bit patterns denote newer SSL/TLS protocol versions - return (info.dwProtocol < SP_PROT_TLS1_SERVER) ? true : false; -} - -} // namespace - -/**************************************************/ - -ClientSslAsynchIO::ClientSslAsynchIO(const std::string& brokerHost, - const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb, - BuffersEmptyCallback eCb, - IdleCallback iCb, - NegotiateDoneCallback nCb) : - SslAsynchIO(s, hCred, rCb, eofCb, disCb, cCb, eCb, iCb, nCb), - serverHost(brokerHost), clientCertRequested(false) -{ -} - -void ClientSslAsynchIO::startNegotiate() { - // SEC_CHAR is non-const, so do all the typing here. - SEC_CHAR *host = const_cast(serverHost.c_str()); - - // Need a buffer to receive the token to send to the server. - BufferBase *buff = aio->getQueuedBuffer(); - ULONG ctxtRequested = ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS; - ULONG ctxtAttrs; - // sendBuffs gets information to forward to the peer. - SecBuffer sendBuffs[2]; - sendBuffs[0].cbBuffer = buff->byteCount; - sendBuffs[0].BufferType = SECBUFFER_TOKEN; - sendBuffs[0].pvBuffer = buff->bytes; - sendBuffs[1].cbBuffer = 0; - sendBuffs[1].BufferType = SECBUFFER_EMPTY; - sendBuffs[1].pvBuffer = 0; - SecBufferDesc sendBuffDesc; - sendBuffDesc.ulVersion = SECBUFFER_VERSION; - sendBuffDesc.cBuffers = 2; - sendBuffDesc.pBuffers = sendBuffs; - SECURITY_STATUS status = ::InitializeSecurityContext(&credHandle, - NULL, - host, - ctxtRequested, - 0, - 0, - NULL, - 0, - &ctxtHandle, - &sendBuffDesc, - &ctxtAttrs, - NULL); - - if (status == SEC_I_CONTINUE_NEEDED) { - buff->dataCount = sendBuffs[0].cbBuffer; - aio->queueWrite(buff); - } -} - -void ClientSslAsynchIO::negotiateStep(BufferBase* buff) { - // SEC_CHAR is non-const, so do all the typing here. - SEC_CHAR *host = const_cast(serverHost.c_str()); - ULONG ctxtRequested = ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS; - ULONG ctxtAttrs; - - // tokenBuffs describe the buffer that's coming in. It should have - // a token from the SSL server. - SecBuffer tokenBuffs[2]; - tokenBuffs[0].cbBuffer = buff ? buff->dataCount : 0; - tokenBuffs[0].BufferType = SECBUFFER_TOKEN; - tokenBuffs[0].pvBuffer = buff ? buff->bytes : 0; - tokenBuffs[1].cbBuffer = 0; - tokenBuffs[1].BufferType = SECBUFFER_EMPTY; - tokenBuffs[1].pvBuffer = 0; - SecBufferDesc tokenBuffDesc; - tokenBuffDesc.ulVersion = SECBUFFER_VERSION; - tokenBuffDesc.cBuffers = 2; - tokenBuffDesc.pBuffers = tokenBuffs; - - // Need a buffer to receive any token to send back to the server. - BufferBase *sendbuff = aio->getQueuedBuffer(); - // sendBuffs gets information to forward to the peer. - SecBuffer sendBuffs[2]; - sendBuffs[0].cbBuffer = sendbuff->byteCount; - sendBuffs[0].BufferType = SECBUFFER_TOKEN; - sendBuffs[0].pvBuffer = sendbuff->bytes; - sendBuffs[1].cbBuffer = 0; - sendBuffs[1].BufferType = SECBUFFER_EMPTY; - sendBuffs[1].pvBuffer = 0; - SecBufferDesc sendBuffDesc; - sendBuffDesc.ulVersion = SECBUFFER_VERSION; - sendBuffDesc.cBuffers = 2; - sendBuffDesc.pBuffers = sendBuffs; - - SECURITY_STATUS status = ::InitializeSecurityContext(&credHandle, - &ctxtHandle, - host, - ctxtRequested, - 0, - 0, - &tokenBuffDesc, - 0, - NULL, - &sendBuffDesc, - &ctxtAttrs, - NULL); - - if (status == SEC_E_INCOMPLETE_MESSAGE) { - // Not enough - get more data from the server then try again. - aio->unread(buff); - aio->queueReadBuffer(sendbuff); // Don't need this one for now... - return; - } - // Done with the buffer that came in... - if (buff) - aio->queueReadBuffer(buff); - if (status == SEC_I_CONTINUE_NEEDED) { - // check if server has requested a client certificate - if (!clientCertRequested) { - SecPkgContext_IssuerListInfoEx caList; - memset(&caList, 0, sizeof(caList)); - ::QueryContextAttributes(&ctxtHandle, SECPKG_ATTR_ISSUER_LIST_EX, &caList); - if (caList.cIssuers > 0) - clientCertRequested = true; - if (caList.aIssuers) - ::FreeContextBuffer(caList.aIssuers); - } - - sendbuff->dataCount = sendBuffs[0].cbBuffer; - aio->queueWrite(sendbuff); - return; - } - // Nothing to send back to the server... - aio->queueReadBuffer(sendbuff); - - if (status == SEC_E_OK && unsafeNegotiatedTlsVersion(ctxtHandle)) { - // Refuse a connection that negotiates to less than TLS 1.0. - QPID_LOG(notice, "client SSL negotiation to unsafe protocol version."); - status = SEC_E_UNSUPPORTED_FUNCTION; - } - - // SEC_I_CONTEXT_EXPIRED means session stop complete; SEC_E_OK can be - // either session stop or negotiation done (session up). - if (status == SEC_E_OK || status == SEC_I_CONTEXT_EXPIRED) - negotiationDone(); - else { - if (clientCertRequested && status == SEC_E_CERT_UNKNOWN) - // ISC_REQ_USE_SUPPLIED_CREDS makes us reponsible for this case - // (no client cert). Map it to its counterpart: - status = SEC_E_INCOMPLETE_CREDENTIALS; - negotiationFailed(status); - } -} - -/*************************************************/ - -ServerSslAsynchIO::ServerSslAsynchIO(bool clientMustAuthenticate, - const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb, - BuffersEmptyCallback eCb, - IdleCallback iCb, - NegotiateDoneCallback nCb) : - SslAsynchIO(s, hCred, rCb, eofCb, disCb, cCb, eCb, iCb, nCb), - clientAuth(clientMustAuthenticate) -{ -} - -void ServerSslAsynchIO::startNegotiate() { - // Nothing... need the client to send a token first. -} - -void ServerSslAsynchIO::negotiateStep(BufferBase* buff) { - ULONG ctxtRequested = ASC_REQ_STREAM; - if (clientAuth) - ctxtRequested |= ASC_REQ_MUTUAL_AUTH; - ULONG ctxtAttrs; - - // tokenBuffs describe the buffer that's coming in. It should have - // a token from the SSL server except if shutting down or renegotiating. - SecBuffer tokenBuffs[2]; - tokenBuffs[0].cbBuffer = buff ? buff->dataCount : 0; - tokenBuffs[0].BufferType = SECBUFFER_TOKEN; - tokenBuffs[0].pvBuffer = buff ? buff->bytes : 0; - tokenBuffs[1].cbBuffer = 0; - tokenBuffs[1].BufferType = SECBUFFER_EMPTY; - tokenBuffs[1].pvBuffer = 0; - SecBufferDesc tokenBuffDesc; - tokenBuffDesc.ulVersion = SECBUFFER_VERSION; - tokenBuffDesc.cBuffers = 2; - tokenBuffDesc.pBuffers = tokenBuffs; - - // Need a buffer to receive any token to send back to the server. - BufferBase *sendbuff = aio->getQueuedBuffer(); - // sendBuffs gets information to forward to the peer. - SecBuffer sendBuffs[2]; - sendBuffs[0].cbBuffer = sendbuff->byteCount; - sendBuffs[0].BufferType = SECBUFFER_TOKEN; - sendBuffs[0].pvBuffer = sendbuff->bytes; - sendBuffs[1].cbBuffer = 0; - sendBuffs[1].BufferType = SECBUFFER_EMPTY; - sendBuffs[1].pvBuffer = 0; - SecBufferDesc sendBuffDesc; - sendBuffDesc.ulVersion = SECBUFFER_VERSION; - sendBuffDesc.cBuffers = 2; - sendBuffDesc.pBuffers = sendBuffs; - PCtxtHandle ctxtHandlePtr = (SecIsValidHandle(&ctxtHandle)) ? &ctxtHandle : 0; - SECURITY_STATUS status = ::AcceptSecurityContext(&credHandle, - ctxtHandlePtr, - &tokenBuffDesc, - ctxtRequested, - 0, - &ctxtHandle, - &sendBuffDesc, - &ctxtAttrs, - NULL); - if (status == SEC_E_INCOMPLETE_MESSAGE) { - // Not enough - get more data from the server then try again. - if (buff) - aio->unread(buff); - aio->queueReadBuffer(sendbuff); // Don't need this one for now... - return; - } - // Done with the buffer that came in... - if (buff) - aio->queueReadBuffer(buff); - if (status == SEC_I_CONTINUE_NEEDED) { - sendbuff->dataCount = sendBuffs[0].cbBuffer; - aio->queueWrite(sendbuff); - return; - } - // There may have been a token generated; if so, send it to the client. - if (sendBuffs[0].cbBuffer > 0 && state != ShuttingDown) { - sendbuff->dataCount = sendBuffs[0].cbBuffer; - aio->queueWrite(sendbuff); - } - else - // Nothing to send back to the server... - aio->queueReadBuffer(sendbuff); - - if (status == SEC_E_OK && unsafeNegotiatedTlsVersion(ctxtHandle)) { - // Refuse a connection that negotiates to less than TLS 1.0. - QPID_LOG(notice, "server SSL negotiation to unsafe protocol version."); - status = SEC_E_UNSUPPORTED_FUNCTION; - } - - // SEC_I_CONTEXT_EXPIRED means session stop complete; SEC_E_OK can be - // either session stop or negotiation done (session up). - if (status == SEC_E_OK || status == SEC_I_CONTEXT_EXPIRED) { - if (clientAuth) - QPID_LOG(warning, "DID WE CHECK FOR CLIENT AUTH???"); - - negotiationDone(); - } - else { - negotiationFailed(status); - } -} - -}}} // namespace qpid::sys::windows diff --git a/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h b/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h deleted file mode 100644 index 3d00e1c429..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef _sys_windows_SslAsynchIO -#define _sys_windows_SslAsynchIO - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/AsynchIO.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/Poller.h" -#include "qpid/CommonImportExport.h" -#include "qpid/sys/Mutex.h" -#include -#include -#include -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include -#include -#undef SECURITY_WIN32 - -namespace qpid { -namespace sys { -namespace windows { - -/* - * SSL/Schannel shim between the frame-handling and AsynchIO layers. - * SslAsynchIO creates a regular AsynchIO object to handle I/O and this class - * gets involved for SSL negotiations and encrypt/decrypt. The details of - * how this all works are invisible to the layers on either side. The only - * change from normal AsynchIO usage is that there's an extra callback - * from SslAsynchIO to indicate that the initial session negotiation is - * complete. - * - * The details of session negotiation are different for client and server - * SSL roles. These differences are handled by deriving separate client - * and server role classes. - */ -class SslAsynchIO : public qpid::sys::AsynchIO { -public: - typedef boost::function1 NegotiateDoneCallback; - - SslAsynchIO(const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0, - NegotiateDoneCallback nCb = 0); - ~SslAsynchIO(); - - virtual void queueForDeletion(); - - virtual void start(qpid::sys::Poller::shared_ptr poller); - virtual void createBuffers(uint32_t size); - virtual void queueReadBuffer(BufferBase* buff); - virtual void unread(BufferBase* buff); - virtual void queueWrite(BufferBase* buff); - virtual void notifyPendingWrite(); - virtual void queueWriteClose(); - virtual bool writeQueueEmpty(); - virtual void requestCallback(RequestCallback); - virtual BufferBase* getQueuedBuffer(); - virtual SecuritySettings getSecuritySettings(void); - -protected: - CredHandle credHandle; - - // AsynchIO layer below that's actually doing the I/O - qpid::sys::AsynchIO *aio; - Mutex lock; - - // Track what the state of the SSL session is. Have to know when it's - // time to notify the upper layer that the session is up, and also to - // know when it's not legit to pass data through to either side. - enum { Negotiating, Running, Redo, ShuttingDown } state; - CtxtHandle ctxtHandle; - TimeStamp credExpiry; - - // Client- and server-side SSL subclasses implement these to do the - // proper negotiation steps. negotiateStep() is called with a buffer - // just received from the peer. - virtual void startNegotiate() = 0; - virtual void negotiateStep(BufferBase *buff) = 0; - - // The negotiating steps call one of these when it's finalized: - void negotiationDone(); - void negotiationFailed(SECURITY_STATUS status); - -private: - // These are callbacks from AsynchIO to here. - void sslDataIn(qpid::sys::AsynchIO& a, BufferBase *buff); - void idle(qpid::sys::AsynchIO&); - void reapCheck(); - - // These callbacks are to the layer above. - ReadCallback readCallback; - IdleCallback idleCallback; - NegotiateDoneCallback negotiateDoneCallback; - - volatile bool queuedDelete; - volatile bool queuedClose; - volatile bool reapCheckPending; - bool started; - - // Address of peer, in case it's needed for logging. - std::string peerAddress; - - // Partial buffer of decrypted plaintext given back by the layer above. - AsynchIO::BufferBase *leftoverPlaintext; - - SecPkgContext_StreamSizes schSizes; -}; - -/* - * SSL/Schannel client-side shim between the frame-handling and AsynchIO - * layers. - */ -class ClientSslAsynchIO : public SslAsynchIO { -public: - // Args same as for SslIoShim, with the addition of brokerHost which is - // the expected SSL name of the server. - QPID_COMMON_EXTERN ClientSslAsynchIO(const std::string& brokerHost, - const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0, - NegotiateDoneCallback nCb = 0); - -private: - std::string serverHost; - bool clientCertRequested; - - // Client- and server-side SSL subclasses implement these to do the - // proper negotiation steps. negotiateStep() is called with a buffer - // just received from the peer. - void startNegotiate(); - void negotiateStep(BufferBase *buff); -}; -/* - * SSL/Schannel server-side shim between the frame-handling and AsynchIO - * layers. - */ -class ServerSslAsynchIO : public SslAsynchIO { -public: - QPID_COMMON_EXTERN ServerSslAsynchIO(bool clientMustAuthenticate, - const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0, - NegotiateDoneCallback nCb = 0); - -private: - bool clientAuth; - - // Client- and server-side SSL subclasses implement these to do the - // proper negotiation steps. negotiateStep() is called with a buffer - // just received from the peer. - void startNegotiate(); - void negotiateStep(BufferBase *buff); -}; - -}}} // namespace qpid::sys::windows - -#endif // _sys_windows_SslAsynchIO diff --git a/qpid/cpp/src/qpid/sys/windows/SslCredential.cpp b/qpid/cpp/src/qpid/sys/windows/SslCredential.cpp deleted file mode 100644 index de8f10b0e9..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/SslCredential.cpp +++ /dev/null @@ -1,279 +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 -#include -#include "qpid/Msg.h" -#include "qpid/log/Logger.h" -#include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/util.h" -#include "qpid/sys/windows/SslCredential.h" - - -namespace qpid { -namespace sys { -namespace windows { - - -SslCredential::SslCredential() : certStore(0), cert(0), hostnameVerification(true) -{ - SecInvalidateHandle(&credHandle); - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS; -} - -SslCredential::~SslCredential() -{ - if (SecIsValidHandle(&credHandle)) - ::FreeCredentialsHandle(&credHandle); - if (cert) - ::CertFreeCertificateContext(cert); - if (certStore) - ::CertCloseStore(certStore, CERT_CLOSE_STORE_FORCE_FLAG); -} - -bool SslCredential::load(const std::string& certName) -{ - cert = findCertificate(certName); - if (cert != NULL) { - // assign the certificate into the credentials - cred.paCred = &cert; - cred.cCreds = 1; - } - if (!hostnameVerification) - cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_OUTBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - &credExpiry); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - - return (cert != NULL); -} - -CredHandle SslCredential::handle() -{ - return credHandle; -} - -std::string SslCredential::error() -{ - // Certificate needed after all. Return main error and log additional context - if (!loadError.logMessage.empty()) - QPID_LOG(warning, loadError.logMessage); - return loadError.error; -} - -void SslCredential::ignoreHostnameVerificationFailure(){ - hostnameVerification = false; -} - -void SslCredential::loadPrivCertStore() -{ - // Get a handle to the system store or pkcs#12 file - qpid::sys::ssl::SslOptions& opts = qpid::sys::ssl::SslOptions::global; - if (opts.certFilename.empty()) { - // opening a system store, names are not case sensitive - std::string store = opts.certStore.empty() ? "my" : opts.certStore; - std::transform(store.begin(), store.end(), store.begin(), ::tolower); - // map confusing GUI name to actual registry store name - if (store == "personal") - store = "my"; - certStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL, - CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG | - CERT_SYSTEM_STORE_CURRENT_USER, store.c_str()); - if (!certStore) { - HRESULT status = GetLastError(); - loadError.set(Msg() << "Could not open system certificate store: " << store, status); - return; - } - QPID_LOG(debug, "SslConnector using certifcates from system store: " << store); - } else { - // opening the store from file and populating it with a private key - HANDLE certFileHandle = NULL; - certFileHandle = CreateFile(opts.certFilename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (INVALID_HANDLE_VALUE == certFileHandle) { - HRESULT status = GetLastError(); - loadError.set(Msg() << "Failed to open the file holding the private key: " << opts.certFilename, status); - return; - } - std::vector certEncoded; - DWORD certEncodedSize = 0L; - const DWORD fileSize = GetFileSize(certFileHandle, NULL); - if (INVALID_FILE_SIZE != fileSize) { - certEncoded.resize(fileSize); - bool result = false; - result = ReadFile(certFileHandle, &certEncoded[0], - fileSize, - &certEncodedSize, - NULL); - if (!result) { - // the read failed, return the error as an HRESULT - HRESULT status = GetLastError(); - CloseHandle(certFileHandle); - loadError.set(Msg() << "Reading the private key from file failed " << opts.certFilename, status); - return; - } - } - else { - HRESULT status = GetLastError(); - loadError.set(Msg() << "Unable to read the certificate file " << opts.certFilename, status); - return; - } - CloseHandle(certFileHandle); - - CRYPT_DATA_BLOB blobData; - blobData.cbData = certEncodedSize; - blobData.pbData = &certEncoded[0]; - - // get passwd from file and convert to null terminated wchar_t (Windows UCS2) - std::string passwd = getPasswd(opts.certPasswordFile); - if (loadError.pending()) - return; - int pwlen = passwd.length(); - std::vector pwUCS2(pwlen + 1, L'\0'); - int nwc = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, passwd.data(), pwlen, &pwUCS2[0], pwlen); - if (!nwc) { - HRESULT status = GetLastError(); - loadError.set("Error converting password from UTF8", status); - return; - } - - certStore = PFXImportCertStore(&blobData, &pwUCS2[0], 0); - if (certStore == NULL) { - HRESULT status = GetLastError(); - loadError.set("Failed to open the certificate store", status); - return; - } - QPID_LOG(debug, "SslConnector using certificate from pkcs#12 file: " << opts.certFilename); - } -} - - -PCCERT_CONTEXT SslCredential::findCertificate(const std::string& name) -{ - loadPrivCertStore(); - if (loadError.pending()) - return NULL; - - // search for the certificate by Friendly Name - PCCERT_CONTEXT tmpctx = NULL; - while (tmpctx = CertEnumCertificatesInStore(certStore, tmpctx)) { - DWORD len = CertGetNameString(tmpctx, CERT_NAME_FRIENDLY_DISPLAY_TYPE, - 0, NULL, NULL, 0); - if (len == 1) - continue; - std::vector ctxname(len); - CertGetNameString(tmpctx, CERT_NAME_FRIENDLY_DISPLAY_TYPE, - 0, NULL, &ctxname[0], len); - bool found = !name.compare(&ctxname[0]); - if (found) - break; - } - - // verify whether some certificate has been found - if (tmpctx == NULL) { - loadError.set(Msg() << "Client SSL/TLS certificate not found in the certificate store for name " << name, - "client certificate not found"); - } - return tmpctx; -} - - -std::string SslCredential::getPasswd(const std::string& filename) -{ - std::string passwd; - if (filename == "") - return passwd; - - HANDLE pwfHandle = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - - if (INVALID_HANDLE_VALUE == pwfHandle) { - HRESULT status = GetLastError(); - loadError.set(Msg() << "Failed to open the password file: " << filename, status); - return passwd; - } - - const DWORD fileSize = GetFileSize(pwfHandle, NULL); - if (fileSize == INVALID_FILE_SIZE) { - CloseHandle(pwfHandle); - loadError.set("", "Cannot read password file"); - return passwd; - } - - std::vector pwbuf; - pwbuf.resize(fileSize); - DWORD nbytes = 0; - if (!ReadFile(pwfHandle, &pwbuf[0], fileSize, &nbytes, NULL)) { - HRESULT status = GetLastError(); - CloseHandle(pwfHandle); - loadError.set("Error reading password file", status); - return passwd; - } - CloseHandle(pwfHandle); - - if (nbytes == 0) - return passwd; - - while (nbytes) { - if ((pwbuf[nbytes-1] == 012) || (pwbuf[nbytes-1] == 015)) - nbytes--; - else - break; - } - - if (nbytes) - passwd.assign(&pwbuf[0], nbytes); - - return passwd; -} - -void SslCredential::SavedError::set(const std::string &lm, const std::string es) { - logMessage = lm; - error = es; -} - -void SslCredential::SavedError::set(const std::string &lm, int status) { - logMessage = lm; - error = qpid::sys::strError(status); -} - -void SslCredential::SavedError::clear() { - logMessage.clear(); - error.clear(); -} - -bool SslCredential::SavedError::pending() { - return !logMessage.empty() || !error.empty(); -} - -}}} diff --git a/qpid/cpp/src/qpid/sys/windows/SslCredential.h b/qpid/cpp/src/qpid/sys/windows/SslCredential.h deleted file mode 100644 index 25d174a2fa..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/SslCredential.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _sys_SslCredential -#define _sys_SslCredential -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/CommonImportExport.h" - -#include -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include -#include -#undef SECURITY_WIN32 - -namespace qpid { -namespace sys { -namespace windows { - -/* - * Manage certificate data structures for SChannel. - * - * Note on client certificates: The Posix/NSS implementation performs a lazy - * client certificate search part way through the ssl handshake if the server - * requests one. Here, it is not known in advance if the server will - * request the certificate so the certificate is pre-loaded (even if never - * used). To match the Linux behavior, client certificate load problems are - * remembered and reported later if appropriate, but do not prevent the - * connection attempt. - */ - -class SslCredential { -public: - QPID_COMMON_EXTERN SslCredential(); - QPID_COMMON_EXTERN ~SslCredential(); - QPID_COMMON_EXTERN bool load(const std::string& certName); - QPID_COMMON_EXTERN CredHandle handle(); - QPID_COMMON_EXTERN std::string error(); - /** Proceed with connect inspite of hostname verifcation failures*/ - QPID_COMMON_EXTERN void ignoreHostnameVerificationFailure(); - -private: - struct SavedError { - std::string logMessage; - std::string error; - void set(const std::string &lm, const std::string es); - void set(const std::string &lm, int status); - void clear(); - bool pending(); - }; - - HCERTSTORE certStore; - PCCERT_CONTEXT cert; - SCHANNEL_CRED cred; - CredHandle credHandle; - TimeStamp credExpiry; - SavedError loadError; - bool hostnameVerification; - - PCCERT_CONTEXT findCertificate(const std::string& name); - void loadPrivCertStore(); - std::string getPasswd(const std::string& filename); -}; - -}}} - -#endif // _sys_SslCredential diff --git a/qpid/cpp/src/qpid/sys/windows/StrError.cpp b/qpid/cpp/src/qpid/sys/windows/StrError.cpp deleted file mode 100755 index 546d399d16..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/StrError.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 "qpid/sys/StrError.h" -#include -#include -#include - -namespace qpid { -namespace sys { - -std::string strError(int err) { - const size_t bufsize = 512; - char buf[bufsize]; - buf[0] = 0; - if (0 == FormatMessage (FORMAT_MESSAGE_MAX_WIDTH_MASK - | FORMAT_MESSAGE_FROM_SYSTEM, - 0, - err, - 0, // Default language - buf, - bufsize, - 0)) - { -#ifdef _MSC_VER - strerror_s(buf, bufsize, err); -#else - return std::string(strerror(err)); -#endif - } - return std::string(buf); -} - -}} diff --git a/qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp b/qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp deleted file mode 100755 index fb58d53b81..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/SystemInfo.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. - * - */ - -/* GetNativeSystemInfo call requires _WIN32_WINNT 0x0501 or higher */ -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -#endif - -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" - -#include -#include -#include -#include -#include - -#ifndef HOST_NAME_MAX -# define HOST_NAME_MAX 256 -#endif - -namespace qpid { -namespace sys { - -long SystemInfo::concurrency() { - SYSTEM_INFO sys_info; - ::GetSystemInfo (&sys_info); - long activeProcessors = 0; - DWORD_PTR mask = sys_info.dwActiveProcessorMask; - while (mask != 0) { - if (mask & 1) - ++activeProcessors; - mask >>= 1; - } - return activeProcessors; -} - -bool SystemInfo::getLocalHostname (Address &address) { - char name[HOST_NAME_MAX]; - if (::gethostname(name, sizeof(name)) != 0) { - errno = WSAGetLastError(); - return false; - } - address.host = name; - return true; -} - -static const std::string LOCALHOST("127.0.0.1"); -static const std::string TCP("tcp"); - -// Null function which always fails to find an network interface name -bool SystemInfo::getInterfaceAddresses(const std::string&, std::vector&) -{ - return false; -} - -void SystemInfo::getSystemId (std::string &osName, - std::string &nodeName, - std::string &release, - std::string &version, - std::string &machine) -{ - osName = "Microsoft Windows"; - - char node[MAX_COMPUTERNAME_LENGTH + 1]; - DWORD nodelen = MAX_COMPUTERNAME_LENGTH + 1; - GetComputerName (node, &nodelen); - nodeName = node; - - OSVERSIONINFOEX vinfo; - vinfo.dwOSVersionInfoSize = sizeof(vinfo); - GetVersionEx ((OSVERSIONINFO *)&vinfo); - - SYSTEM_INFO sinfo; - GetNativeSystemInfo(&sinfo); - - switch(vinfo.dwMajorVersion) { - case 5: - switch(vinfo.dwMinorVersion) { - case 0: - release ="2000"; - break; - case 1: - release = "XP"; - break; - case 2: - if (sinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || - sinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) - release = "XP-64"; - else - release = "Server 2003"; - break; - default: - release = "Windows"; - } - break; - case 6: - if (vinfo.wProductType == VER_NT_SERVER) - release = "Server 2008"; - else - release = "Vista"; - break; - default: - release = "Microsoft Windows"; - } - version = vinfo.szCSDVersion; - - switch(sinfo.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_AMD64: - machine = "x86-64"; - break; - case PROCESSOR_ARCHITECTURE_IA64: - machine = "IA64"; - break; - case PROCESSOR_ARCHITECTURE_INTEL: - machine = "x86"; - break; - default: - machine = "unknown"; - break; - } -} - -uint32_t SystemInfo::getProcessId() -{ - return static_cast(::GetCurrentProcessId()); -} - -uint32_t SystemInfo::getParentProcessId() -{ - // Only want info for the current process, so ask for something specific. - // The module info won't be used here but it keeps the snapshot limited to - // the current process so a search through all processes is not needed. - HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); - if (snap == INVALID_HANDLE_VALUE) - return 0; - PROCESSENTRY32 entry; - entry.dwSize = sizeof(entry); - if (!Process32First(snap, &entry)) - entry.th32ParentProcessID = 0; - CloseHandle(snap); - return static_cast(entry.th32ParentProcessID); -} - -std::string SystemInfo::getProcessName() -{ - std::string name; - - // Only want info for the current process, so ask for something specific. - // The module info won't be used here but it keeps the snapshot limited to - // the current process so a search through all processes is not needed. - HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); - if (snap == INVALID_HANDLE_VALUE) - return name; - PROCESSENTRY32 entry; - entry.dwSize = sizeof(entry); - if (!Process32First(snap, &entry)) - entry.szExeFile[0] = '\0'; - CloseHandle(snap); - name = entry.szExeFile; - return name; -} - - -#ifdef _DLL -namespace windows { -// set from one or more Qpid DLLs: i.e. in DllMain with DLL_PROCESS_DETACH -QPID_EXPORT bool processExiting = false; -QPID_EXPORT bool libraryUnloading = false; -} -#endif - -bool SystemInfo::threadSafeShutdown() -{ -#ifdef _DLL - if (!windows::processExiting && !windows::libraryUnloading) { - // called before exit() or FreeLibrary(), or by a DLL without - // a participating DllMain. - QPID_LOG(warning, "invalid query for shutdown state"); - throw qpid::Exception(QPID_MSG("Unable to determine shutdown state.")); - } - return !windows::processExiting; -#else - // Not a DLL: shutdown can only be by exit() or return from main(). - return false; -#endif -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/Thread.cpp b/qpid/cpp/src/qpid/sys/windows/Thread.cpp deleted file mode 100755 index 8034680664..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/Thread.cpp +++ /dev/null @@ -1,340 +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. - * - */ - -// Ensure definition of OpenThread in mingw -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/windows/check.h" -#include "qpid/sys/SystemInfo.h" - -#include -#include - -/* - * This implementation distinguishes between two types of thread: Qpid - * threads (based on qpid::sys::Runnable) and the rest. It provides a - * join() that will not deadlock against the Windows loader lock for - * Qpid threads. - * - * System thread identifiers are unique per Windows thread; thread - * handles are not. Thread identifiers can be recycled, but keeping a - * handle open against the thread prevents recycling as long as - * shared_ptr references to a ThreadPrivate structure remain. - * - * There is a 1-1 relationship between Qpid threads and their - * ThreadPrivate structure. Non-Qpid threads do not need to find the - * qpidThreadDone handle, so there may be a 1-many relationship for - * them. - * - * TLS storage is used for a lockless solution for static library - * builds. The special case of LoadLibrary/FreeLibrary requires - * additional synchronization variables and resource cleanup in - * DllMain. _DLL marks the dynamic case. - */ - -namespace qpid { -namespace sys { - -class ThreadPrivate { -public: - friend class Thread; - friend unsigned __stdcall runThreadPrivate(void*); - typedef boost::shared_ptr shared_ptr; - ~ThreadPrivate(); - -private: - unsigned threadId; - HANDLE threadHandle; - HANDLE initCompleted; - HANDLE qpidThreadDone; - Runnable* runnable; - shared_ptr keepAlive; - - ThreadPrivate() : threadId(GetCurrentThreadId()), initCompleted(NULL), - qpidThreadDone(NULL), runnable(NULL) { - threadHandle = OpenThread (SYNCHRONIZE, FALSE, threadId); - QPID_WINDOWS_CHECK_CRT_NZ(threadHandle); - } - - ThreadPrivate(Runnable* r) : threadHandle(NULL), initCompleted(NULL), - qpidThreadDone(NULL), runnable(r) {} - - void start(shared_ptr& p); - static shared_ptr createThread(Runnable* r); -}; - -}} // namespace qpid::sys - - -namespace { -using namespace qpid::sys; - -#ifdef _DLL -class ScopedCriticalSection -{ - public: - ScopedCriticalSection(CRITICAL_SECTION& cs) : criticalSection(cs) { EnterCriticalSection(&criticalSection); } - ~ScopedCriticalSection() { LeaveCriticalSection(&criticalSection); } - private: - CRITICAL_SECTION& criticalSection; -}; - -CRITICAL_SECTION threadLock; -long runningThreads = 0; -HANDLE threadsDone; -bool terminating = false; -#endif - - -DWORD volatile tlsIndex = TLS_OUT_OF_INDEXES; - -DWORD getTlsIndex() { - if (tlsIndex != TLS_OUT_OF_INDEXES) - return tlsIndex; // already set - - DWORD trialIndex = TlsAlloc(); - QPID_WINDOWS_CHECK_NOT(trialIndex, TLS_OUT_OF_INDEXES); // No OS resource - - // only one thread gets to set the value - DWORD actualIndex = (DWORD) InterlockedCompareExchange((LONG volatile *) &tlsIndex, (LONG) trialIndex, (LONG) TLS_OUT_OF_INDEXES); - if (actualIndex == TLS_OUT_OF_INDEXES) - return trialIndex; // we won the race - else { - TlsFree(trialIndex); - return actualIndex; - } -} - -} // namespace - -namespace qpid { -namespace sys { - -unsigned __stdcall runThreadPrivate(void* p) -{ - ThreadPrivate* threadPrivate = static_cast(p); - TlsSetValue(getTlsIndex(), threadPrivate); - - WaitForSingleObject (threadPrivate->initCompleted, INFINITE); - CloseHandle (threadPrivate->initCompleted); - threadPrivate->initCompleted = NULL; - - try { - threadPrivate->runnable->run(); - } catch (...) { - // not our concern - } - - SetEvent (threadPrivate->qpidThreadDone); // allow join() - threadPrivate->keepAlive.reset(); // may run ThreadPrivate destructor - -#ifdef _DLL - { - ScopedCriticalSection l(threadLock); - if (--runningThreads == 0) - SetEvent(threadsDone); - } -#endif - return 0; -} - - -ThreadPrivate::shared_ptr ThreadPrivate::createThread(Runnable* runnable) { - ThreadPrivate::shared_ptr tp(new ThreadPrivate(runnable)); - tp->start(tp); - return tp; -} - -void ThreadPrivate::start(ThreadPrivate::shared_ptr& tp) { - getTlsIndex(); // fail here if OS problem, not in new thread - - initCompleted = CreateEvent (NULL, TRUE, FALSE, NULL); - QPID_WINDOWS_CHECK_CRT_NZ(initCompleted); - qpidThreadDone = CreateEvent (NULL, TRUE, FALSE, NULL); - QPID_WINDOWS_CHECK_CRT_NZ(qpidThreadDone); - -#ifdef _DLL - { - ScopedCriticalSection l(threadLock); - if (terminating) - throw qpid::Exception(QPID_MSG("creating thread after exit/FreeLibrary")); - runningThreads++; - } -#endif - - uintptr_t h = _beginthreadex(0, - 0, - runThreadPrivate, - (void *)this, - 0, - &threadId); - -#ifdef _DLL - if (h == NULL) { - ScopedCriticalSection l(threadLock); - if (--runningThreads == 0) - SetEvent(threadsDone); - } -#endif - - QPID_WINDOWS_CHECK_CRT_NZ(h); - - // Success - keepAlive = tp; - threadHandle = reinterpret_cast(h); - SetEvent (initCompleted); -} - -ThreadPrivate::~ThreadPrivate() { - if (threadHandle) - CloseHandle (threadHandle); - if (initCompleted) - CloseHandle (initCompleted); - if (qpidThreadDone) - CloseHandle (qpidThreadDone); -} - - -Thread::Thread() {} - -Thread::Thread(Runnable* runnable) : impl(ThreadPrivate::createThread(runnable)) {} - -Thread::Thread(Runnable& runnable) : impl(ThreadPrivate::createThread(&runnable)) {} - -Thread::operator bool() { - return !!impl; -} - -bool Thread::operator==(const Thread& t) const { - if (!impl || !t.impl) - return false; - return impl->threadId == t.impl->threadId; -} - -bool Thread::operator!=(const Thread& t) const { - return !(*this==t); -} - -void Thread::join() { - if (impl) { - DWORD status; - if (impl->runnable) { - HANDLE handles[2] = {impl->qpidThreadDone, impl->threadHandle}; - // wait for either. threadHandle not signalled if loader - // lock held (FreeLibrary). qpidThreadDone not signalled - // if thread terminated by exit(). - status = WaitForMultipleObjects (2, handles, false, INFINITE); - } - else - status = WaitForSingleObject (impl->threadHandle, INFINITE); - QPID_WINDOWS_CHECK_NOT(status, WAIT_FAILED); - } -} - -unsigned long Thread::logId() { - return GetCurrentThreadId(); -} - -/* static */ -Thread Thread::current() { - ThreadPrivate* tlsValue = (ThreadPrivate *) TlsGetValue(getTlsIndex()); - Thread t; - if (tlsValue != NULL) { - // called from within Runnable->run(), so keepAlive has positive use count - t.impl = tlsValue->keepAlive; - } - else - t.impl.reset(new ThreadPrivate()); - return t; -} - -}} // namespace qpid::sys - - -#ifdef _DLL - -namespace qpid { -namespace sys { -namespace windows { - -extern bool processExiting; -extern bool libraryUnloading; - -}}} // namespace qpid::sys::SystemInfo - -// DllMain: called possibly many times in a process lifetime if dll -// loaded and freed repeatedly. Be mindful of Windows loader lock -// and other DllMain restrictions. - -BOOL APIENTRY DllMain(HMODULE hm, DWORD reason, LPVOID reserved) { - switch (reason) { - case DLL_PROCESS_ATTACH: - InitializeCriticalSection(&threadLock); - threadsDone = CreateEvent(NULL, TRUE, FALSE, NULL); - break; - - case DLL_PROCESS_DETACH: - terminating = true; - if (reserved != NULL) { - // process exit(): threads are stopped arbitrarily and - // possibly in an inconsistent state. Not even threadLock - // can be trusted. All static destructors for this unit - // are pending and face the same unsafe environment. - // Any resources this unit knows about will be released as - // part of process tear down by the OS. Accordingly, skip - // any clean up tasks. - qpid::sys::windows::processExiting = true; - return TRUE; - } - else { - // FreeLibrary(): threads are still running and we are - // encouraged to clean up to avoid leaks. Mostly we just - // want any straggler threads to finish and notify - // threadsDone as the last thing they do. - qpid::sys::windows::libraryUnloading = true; - while (1) { - { - ScopedCriticalSection l(threadLock); - if (runningThreads == 0) - break; - ResetEvent(threadsDone); - } - WaitForSingleObject(threadsDone, INFINITE); - } - if (tlsIndex != TLS_OUT_OF_INDEXES) - TlsFree(getTlsIndex()); - CloseHandle(threadsDone); - DeleteCriticalSection(&threadLock); - } - break; - - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - } - return TRUE; -} - -#endif diff --git a/qpid/cpp/src/qpid/sys/windows/Time.cpp b/qpid/cpp/src/qpid/sys/windows/Time.cpp deleted file mode 100644 index 4169ef1f0a..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/Time.cpp +++ /dev/null @@ -1,217 +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/sys/Time.h" -#include -#include -#include -#include -#include -#include - -using namespace boost::posix_time; - -namespace { - -// High-res timing support. This will display times since program start, -// more or less. Keep track of the start value and the conversion factor to -// seconds. -bool timeInitialized = false; -LARGE_INTEGER start_hpc; -double hpc_freq = 1.0; - -double start_time; - -/// Static constant to remove time skew between FILETIME and POSIX -/// time. POSIX and Win32 use different epochs (Jan. 1, 1970 v.s. -/// Jan. 1, 1601). The following constant defines the difference -/// in 100ns ticks. -const DWORDLONG FILETIME_to_timval_skew = 0x19db1ded53e8000; - -} - -namespace qpid { -namespace sys { - -AbsTime::AbsTime(const AbsTime& t, const Duration& d) { - if (d == Duration::max()) { - timepoint = ptime(max_date_time); - } - else { - time_duration td = microseconds(d.nanosecs / 1000); - timepoint = t.timepoint + td; - } -} - -AbsTime AbsTime::FarFuture() { - AbsTime ff; - ptime maxd(max_date_time); - ff.timepoint = maxd; - return ff; -} - -AbsTime AbsTime::Zero() { - AbsTime time_epoch; - time_epoch.timepoint = boost::posix_time::from_time_t(0); - return time_epoch; -} - -AbsTime AbsTime::epoch() { - AbsTime time_epoch; - time_epoch.timepoint = boost::posix_time::from_time_t(0); - return time_epoch; -} - -AbsTime AbsTime::now() { - AbsTime time_now; - time_now.timepoint = boost::get_system_time(); - return time_now; -} - -Duration Duration::FromEpoch() { - time_duration d = boost::get_system_time() - boost::posix_time::from_time_t(0); - return d.total_nanoseconds(); -} - -Duration::Duration(const AbsTime& start, const AbsTime& finish) { - time_duration d = finish.timepoint - start.timepoint; - nanosecs = d.total_nanoseconds(); -} - -std::ostream& operator<<(std::ostream& o, const Duration& d) { - if (d >= TIME_SEC) return o << (double(d)/TIME_SEC) << "s"; - if (d >= TIME_MSEC) return o << (double(d)/TIME_MSEC) << "ms"; - if (d >= TIME_USEC) return o << (double(d)/TIME_USEC) << "us"; - return o << int64_t(d) << "ns"; -} - -std::istream& operator>>(std::istream& i, Duration& d) { - // Don't throw, let the istream throw if it's configured to do so. - double number; - i >> number; - if (i.fail()) return i; - - if (i.eof() || std::isspace(i.peek())) // No suffix - d = number*TIME_SEC; - else { - std::string suffix; - i >> suffix; - if (i.fail()) return i; - if (suffix.compare("s") == 0) d = number*TIME_SEC; - else if (suffix.compare("ms") == 0) d = number*TIME_MSEC; - else if (suffix.compare("us") == 0) d = number*TIME_USEC; - else if (suffix.compare("ns") == 0) d = number*TIME_NSEC; - else i.setstate(std::ios::failbit); - } - return i; -} - -std::ostream& operator<<(std::ostream& o, const AbsTime& t) { - std::string time_string = to_simple_string(t.timepoint); - return o << time_string; -} - - -void sleep(int secs) { - ::Sleep(secs * 1000); -} - -void usleep(uint64_t usecs) { - DWORD msecs = usecs / 1000; - if (msecs == 0) - msecs = 1; - ::Sleep(msecs); -} - -void outputFormattedNow(std::ostream& o) { - ::time_t rawtime; - ::tm timeinfo; - char time_string[100]; - - ::time( &rawtime ); -#ifdef _MSC_VER - ::localtime_s(&timeinfo, &rawtime); -#else - timeinfo = *(::localtime(&rawtime)); -#endif - ::strftime(time_string, 100, - "%Y-%m-%d %H:%M:%S", - &timeinfo); - o << time_string << " "; -} - -void outputHiresNow(std::ostream& o) { - ::time_t tv_sec; - ::tm timeinfo; - char time_string[100]; - - if (!timeInitialized) { - // To start, get the current time from FILETIME which includes - // sub-second resolution. However, since FILETIME is updated a bit - // "bumpy" every 15 msec or so, future time displays will be the - // starting FILETIME plus a delta based on the high-resolution - // performance counter. - FILETIME file_time; - ULARGE_INTEGER start_usec; - ::GetSystemTimeAsFileTime(&file_time); // This is in 100ns units - start_usec.LowPart = file_time.dwLowDateTime; - start_usec.HighPart = file_time.dwHighDateTime; - start_usec.QuadPart -= FILETIME_to_timval_skew; - start_usec.QuadPart /= 10; // Convert 100ns to usec - tv_sec = (time_t)(start_usec.QuadPart / (1000 * 1000)); - long tv_usec = (long)(start_usec.QuadPart % (1000 * 1000)); - start_time = static_cast(tv_sec); - start_time += tv_usec / 1000000.0; - - start_hpc.QuadPart = 0; - LARGE_INTEGER iFreq; - iFreq.QuadPart = 1; - QueryPerformanceCounter(&start_hpc); - QueryPerformanceFrequency(&iFreq); - hpc_freq = static_cast(iFreq.QuadPart); - timeInitialized = true; - } - LARGE_INTEGER hpc_now; - hpc_now.QuadPart = 0; - QueryPerformanceCounter(&hpc_now); - hpc_now.QuadPart -= start_hpc.QuadPart; - if (hpc_now.QuadPart < 0) - hpc_now.QuadPart = 0; - double now = static_cast(hpc_now.QuadPart); - now /= hpc_freq; // now is seconds after this - double fnow = start_time + now; - double usec, sec; - usec = modf(fnow, &sec); - tv_sec = static_cast(sec); -#ifdef _MSC_VER - ::localtime_s(&timeinfo, &tv_sec); -#else - timeinfo = *(::localtime(&tv_sec)); -#endif - ::strftime(time_string, 100, - "%Y-%m-%d %H:%M:%S", - &timeinfo); - // No way to set "max field width" to cleanly output the double usec so - // convert it back to integral number of usecs and print that. - unsigned long i_usec = usec * 1000 * 1000; - o << time_string << "." << std::setw(6) << std::setfill('0') << i_usec << " "; -} -}} diff --git a/qpid/cpp/src/qpid/sys/windows/Time.h b/qpid/cpp/src/qpid/sys/windows/Time.h deleted file mode 100644 index 2987b1c8b2..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/Time.h +++ /dev/null @@ -1,36 +0,0 @@ -#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 - -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/WinSocket.cpp b/qpid/cpp/src/qpid/sys/windows/WinSocket.cpp deleted file mode 100644 index aada990c11..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/WinSocket.cpp +++ /dev/null @@ -1,286 +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/sys/windows/WinSocket.h" - -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/IoHandlePrivate.h" -#include "qpid/sys/SystemInfo.h" - -namespace qpid { -namespace sys { - -// Need to initialize WinSock. Ideally, this would be a singleton or embedded -// in some one-time initialization function. I tried boost singleton and could -// not get it to compile (and others located in google had the same problem). -// So, this simple static with an interlocked increment will do for known -// use cases at this time. Since this will only shut down winsock at process -// termination, there may be some problems with client programs that also -// expect to load and unload winsock, but we'll see... -// If someone does get an easy-to-use singleton sometime, converting to it -// may be preferable. - -namespace { - -static LONG volatile initialized = 0; - -class WinSockSetup { - // : public boost::details::pool::singleton_default { - -public: - WinSockSetup() { - LONG timesEntered = InterlockedIncrement(&initialized); - if (timesEntered > 1) - return; - err = 0; - WORD wVersionRequested; - WSADATA wsaData; - - /* Request WinSock 2.2 */ - wVersionRequested = MAKEWORD(2, 2); - err = WSAStartup(wVersionRequested, &wsaData); - } - - ~WinSockSetup() { - if (SystemInfo::threadSafeShutdown()) - WSACleanup(); - } - -public: - int error(void) const { return err; } - -protected: - DWORD err; -}; - -static WinSockSetup setup; - -std::string getName(SOCKET fd, bool local) -{ - ::sockaddr_storage name_s; // big enough for any socket address - ::sockaddr* name = (::sockaddr*)&name_s; - ::socklen_t namelen = sizeof(name_s); - - if (local) { - QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen)); - } else { - QPID_WINSOCK_CHECK(::getpeername(fd, name, &namelen)); - } - - return SocketAddress::asString(name, namelen); -} - -uint16_t getLocalPort(int fd) -{ - ::sockaddr_storage name_s; // big enough for any socket address - ::sockaddr* name = (::sockaddr*)&name_s; - ::socklen_t namelen = sizeof(name_s); - - QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen)); - - return SocketAddress::getPort(name); -} -} // namespace - -WinSocket::WinSocket() : - handle(new IOHandle), - nonblocking(false), - nodelay(false) -{} - -Socket* createSocket() -{ - return new WinSocket; -} - -WinSocket::WinSocket(SOCKET fd) : - handle(new IOHandle(fd)), - nonblocking(false), - nodelay(false) -{} - -WinSocket::operator const IOHandle&() const -{ - return *handle; -} - -void WinSocket::createSocket(const SocketAddress& sa) const -{ - SOCKET& socket = handle->fd; - if (socket != INVALID_SOCKET) WinSocket::close(); - - SOCKET s = ::socket (getAddrInfo(sa).ai_family, - getAddrInfo(sa).ai_socktype, - 0); - if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError()); - socket = s; - - try { - if (nonblocking) setNonblocking(); - if (nodelay) setTcpNoDelay(); - } catch (std::exception&) { - ::closesocket(s); - socket = INVALID_SOCKET; - throw; - } -} - -void WinSocket::setNonblocking() const { - u_long nonblock = 1; - QPID_WINSOCK_CHECK(ioctlsocket(handle->fd, FIONBIO, &nonblock)); -} - -void -WinSocket::connect(const SocketAddress& addr) const -{ - peername = addr.asString(false); - - createSocket(addr); - - const SOCKET& socket = handle->fd; - int err; - WSASetLastError(0); - if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) != 0) && - ((err = ::WSAGetLastError()) != WSAEWOULDBLOCK)) - throw qpid::Exception(QPID_MSG(strError(err) << ": " << peername)); -} - -void -WinSocket::finishConnect(const SocketAddress&) const -{ -} - -void -WinSocket::close() const -{ - SOCKET& socket = handle->fd; - if (socket == INVALID_SOCKET) return; - QPID_WINSOCK_CHECK(closesocket(socket)); - socket = INVALID_SOCKET; -} - - -int WinSocket::write(const void *buf, size_t count) const -{ - const SOCKET& socket = handle->fd; - int sent = ::send(socket, (const char *)buf, count, 0); - if (sent == SOCKET_ERROR) - return -1; - return sent; -} - -int WinSocket::read(void *buf, size_t count) const -{ - const SOCKET& socket = handle->fd; - int received = ::recv(socket, (char *)buf, count, 0); - if (received == SOCKET_ERROR) - return -1; - return received; -} - -int WinSocket::listen(const SocketAddress& addr, int backlog) const -{ - createSocket(addr); - - const SOCKET& socket = handle->fd; - BOOL yes=1; - QPID_WINSOCK_CHECK(setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&yes, sizeof(yes))); - - if (::bind(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) == SOCKET_ERROR) - throw Exception(QPID_MSG("Can't bind to " << addr.asString() << ": " << strError(WSAGetLastError()))); - if (::listen(socket, backlog) == SOCKET_ERROR) - throw Exception(QPID_MSG("Can't listen on " <fd, 0, 0); - if (afd != INVALID_SOCKET) - return new WinSocket(afd); - else if (WSAGetLastError() == EAGAIN) - return 0; - else throw QPID_WINDOWS_ERROR(WSAGetLastError()); -} - -std::string WinSocket::getPeerAddress() const -{ - if (peername.empty()) { - peername = getName(handle->fd, false); - } - return peername; -} - -std::string WinSocket::getLocalAddress() const -{ - if (localname.empty()) { - localname = getName(handle->fd, true); - } - return localname; -} - -int WinSocket::getError() const -{ - int result; - socklen_t rSize = sizeof (result); - - QPID_WINSOCK_CHECK(::getsockopt(handle->fd, SOL_SOCKET, SO_ERROR, (char *)&result, &rSize)); - return result; -} - -// TODO: I don't think this can ever be called! -std::string WinSocket::lastErrorCodeText() const -{ - return strError(::WSAGetLastError()); -} -void WinSocket::setTcpNoDelay() const -{ - SOCKET& socket = handle->fd; - nodelay = true; - if (socket != INVALID_SOCKET) { - int flag = 1; - int result = setsockopt(handle->fd, - IPPROTO_TCP, - TCP_NODELAY, - (char *)&flag, - sizeof(flag)); - QPID_WINSOCK_CHECK(result); - } -} - -int WinSocket::getKeyLen() const -{ - return 0; -} - -std::string WinSocket::getPeerAuthId() const -{ - return std::string(); -} - -std::string WinSocket::getLocalAuthId() const -{ - return "dummy"; -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/src/qpid/sys/windows/WinSocket.h b/qpid/cpp/src/qpid/sys/windows/WinSocket.h deleted file mode 100644 index 619c14437e..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/WinSocket.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef QPID_SYS_WINDOWS_BSDSOCKET_H -#define QPID_SYS_WINDOWS_BSDSOCKET_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/Socket.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/CommonImportExport.h" -#include - -#include - -// Ensure we get all of winsock2.h -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - -#include - -namespace qpid { -namespace sys { - -namespace windows { -Socket* createSameTypeSocket(const Socket&); -} - -class Duration; -class IOHandle; -class SocketAddress; - -class QPID_COMMON_CLASS_EXTERN WinSocket : public Socket -{ -public: - /** Create a socket wrapper for descriptor. */ - QPID_COMMON_EXTERN WinSocket(); - - QPID_COMMON_EXTERN operator const IOHandle&() const; - - /** Set socket non blocking */ - QPID_COMMON_EXTERN virtual void setNonblocking() const; - - QPID_COMMON_EXTERN virtual void setTcpNoDelay() const; - - QPID_COMMON_EXTERN virtual void connect(const SocketAddress&) const; - QPID_COMMON_EXTERN virtual void finishConnect(const SocketAddress&) const; - - QPID_COMMON_EXTERN virtual void close() const; - - /** Bind to a port and start listening. - *@return The bound port number - */ - QPID_COMMON_EXTERN virtual int listen(const SocketAddress&, int backlog = 10) const; - - /** - * Returns an address (host and port) for the remote end of the - * socket - */ - QPID_COMMON_EXTERN std::string getPeerAddress() const; - /** - * Returns an address (host and port) for the local end of the - * socket - */ - QPID_COMMON_EXTERN std::string getLocalAddress() const; - - /** - * Returns the error code stored in the socket. This may be used - * to determine the result of a non-blocking connect. - */ - QPID_COMMON_EXTERN int getError() const; - - QPID_COMMON_EXTERN std::string lastErrorCodeText() const; - - /** Accept a connection from a socket that is already listening - * and has an incoming connection - */ - QPID_COMMON_EXTERN virtual Socket* accept() const; - - // TODO The following are raw operations, maybe they need better wrapping? - QPID_COMMON_EXTERN virtual int read(void *buf, size_t count) const; - QPID_COMMON_EXTERN virtual int write(const void *buf, size_t count) const; - - QPID_COMMON_EXTERN int getKeyLen() const; - QPID_COMMON_EXTERN std::string getPeerAuthId() const; - QPID_COMMON_EXTERN std::string getLocalAuthId() const; - -protected: - /** Create socket */ - void createSocket(const SocketAddress&) const; - - mutable boost::scoped_ptr handle; - mutable std::string localname; - mutable std::string peername; - mutable bool nonblocking; - mutable bool nodelay; - - /** Construct socket with existing handle */ - friend Socket* qpid::sys::windows::createSameTypeSocket(const Socket&); - WinSocket(SOCKET fd); -}; - -}} -#endif /*!QPID_SYS_WINDOWS_BSDSOCKET_H*/ diff --git a/qpid/cpp/src/qpid/sys/windows/check.h b/qpid/cpp/src/qpid/sys/windows/check.h deleted file mode 100755 index 2a8e439bed..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/check.h +++ /dev/null @@ -1,49 +0,0 @@ -#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/sys/windows/mingw32_compat.h b/qpid/cpp/src/qpid/sys/windows/mingw32_compat.h deleted file mode 100644 index 51f613cc25..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/mingw32_compat.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _sys_windows_mingw32_compat -#define _sys_windows_mingw32_compat -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 WIN32 -#ifndef _MSC_VER - -// -// The following definitions for extension function GUIDs and signatures are taken from -// MswSock.h in the Windows32 SDK. These rightfully belong in the mingw32 version of -// mswsock.h, but are not included presently. -// - -#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} -typedef BOOL (PASCAL *LPFN_ACCEPTEX)(SOCKET,SOCKET,PVOID,DWORD,DWORD,DWORD,LPDWORD,LPOVERLAPPED); - -#endif -#endif - -#endif diff --git a/qpid/cpp/src/qpid/sys/windows/util.cpp b/qpid/cpp/src/qpid/sys/windows/util.cpp deleted file mode 100644 index 75aef26c35..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/util.cpp +++ /dev/null @@ -1,70 +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/sys/windows/util.h" -#include "qpid/Exception.h" -#include "qpid/sys/SystemInfo.h" - -#include -#include - -namespace qpid { -namespace sys { -namespace ssl { - -static const std::string LOCALHOST("127.0.0.1"); - -std::string defaultCertName() -{ - Address address; - if (SystemInfo::getLocalHostname(address)) { - return address.host; - } else { - return LOCALHOST; - } -} - -SslOptions::SslOptions() : qpid::Options("SSL Settings"), - certName(defaultCertName()) -{ - addOptions() - ("ssl-cert-password-file", optValue(certPasswordFile, "PATH"), "File containing password to use for accessing certificates") - ("ssl-cert-store", optValue(certStore, "NAME"), "Windows certificate store containing the certificate") - ("ssl-cert-Filename", optValue(certFilename, "PATH"), "Path to PKCS#12 file containing the certificate") - ("ssl-cert-name", optValue(certName, "NAME"), "Friendly Name of the certificate to use"); -} - -SslOptions& SslOptions::operator=(const SslOptions& o) -{ - certStore = o.certStore; - certName = o.certName; - certPasswordFile = o.certPasswordFile; - certFilename = o.certFilename; - - return *this; -} - -SslOptions SslOptions::global; - -void initWinSsl(const SslOptions& options, bool) -{ - SslOptions::global = options; -} -}}} // namespace qpid::sys::ssl diff --git a/qpid/cpp/src/qpid/sys/windows/util.h b/qpid/cpp/src/qpid/sys/windows/util.h deleted file mode 100644 index 2855a90955..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/util.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_SYS_SSL_UTIL_H -#define QPID_SYS_SSL_UTIL_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/Options.h" -#include - -namespace qpid { -namespace sys { -namespace ssl { - -struct SslOptions : qpid::Options -{ - QPID_COMMON_EXTERN static SslOptions global; - - std::string certStore; - std::string certName; - std::string certPasswordFile; - std::string certFilename; - - QPID_COMMON_EXTERN SslOptions(); - QPID_COMMON_EXTERN SslOptions& operator=(const SslOptions&); -}; - -QPID_COMMON_EXTERN void initWinSsl(const SslOptions& options, bool server = false); - -}}} // namespace qpid::sys::ssl - -#endif /*!QPID_SYS_SSL_UTIL_H*/ diff --git a/qpid/cpp/src/qpid/sys/windows/uuid.cpp b/qpid/cpp/src/qpid/sys/windows/uuid.cpp deleted file mode 100644 index 4ff75ca627..0000000000 --- a/qpid/cpp/src/qpid/sys/windows/uuid.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/* - * UUIDs and GUIDs (both RFC 4122) differ on byte positions of the - * internal representation. This matters when encoding to the wire - * and adhering to versioning info. Microsoft APIs used here operate - * on GUIDs even if the name implies UUIDs. AMQP expects the UUID 128 - * bit format which is used here unless otherwise noted. - */ - -#include -#ifdef uuid_t /* Done in rpcdce.h */ -# undef uuid_t -#endif - -#include "qpid/sys/uuid.h" - -#include - -namespace { -inline void iswap (char *p1, char *p2) { - char t = *p1; - *p1 = *p2; - *p2 = t; -} - -void toUuid (const UUID *guid, uint8_t uuid[qpid::sys::UuidSize]) { - // copy then swap bytes - memcpy ((char *) uuid, (char *) guid, qpid::sys::UuidSize); - char *p = (char *) uuid; - iswap (p, p+3); - iswap (p+1, p+2); - iswap (p+4, p+5); - iswap (p+6, p+7); -} - -} // namespace - -namespace qpid { -namespace sys { - -void uuid_generate (uint8_t out[qpid::sys::UuidSize]) { - UUID guid; - UuidCreate (&guid); - // Version 4 GUID, convert to UUID - toUuid (&guid, out); -} - -}} diff --git a/qpid/cpp/src/qpid/types/Exception.cpp b/qpid/cpp/src/qpid/types/Exception.cpp deleted file mode 100644 index 71390e6abd..0000000000 --- a/qpid/cpp/src/qpid/types/Exception.cpp +++ /dev/null @@ -1,30 +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/types/Exception.h" - -namespace qpid { -namespace types { - -Exception::Exception(const std::string& msg) throw() : message(msg) {} -Exception::~Exception() throw() {} -const char* Exception::what() const throw() { return message.c_str(); } - -}} // namespace qpid::types diff --git a/qpid/cpp/src/qpid/types/Uuid.cpp b/qpid/cpp/src/qpid/types/Uuid.cpp deleted file mode 100644 index c0e38e1da5..0000000000 --- a/qpid/cpp/src/qpid/types/Uuid.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/types/Uuid.h" -#include "qpid/sys/uuid.h" -#include "qpid/sys/IntegerTypes.h" -#include -#include -#include -#include -#include - -namespace qpid { -namespace types { - -using namespace std; - -const size_t Uuid::SIZE=16; -static const int UNPARSED_SIZE=36; - -Uuid::Uuid(bool unique) -{ - if (unique) { - generate(); - } else { - clear(); - } -} - -Uuid::Uuid(const Uuid& other) -{ - ::memcpy(bytes, other.bytes, Uuid::SIZE); -} - -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; - ::memcpy(bytes, other.bytes, Uuid::SIZE); - return *this; -} - -void Uuid::generate() -{ - sys::uuid_generate(bytes); -} - -void Uuid::clear() -{ - ::memset(bytes, 0, Uuid::SIZE); -} - -bool Uuid::isNull() const -{ - static Uuid nullUuid; - return *this == nullUuid; -} - -Uuid::operator bool() const { return !isNull(); } -bool Uuid::operator!() const { return isNull(); } - -size_t Uuid::size() const { return SIZE; } - -const unsigned char* Uuid::data() const -{ - return bytes; -} - -bool operator==(const Uuid& a, const Uuid& b) -{ - return ::memcmp(a.bytes, b.bytes, Uuid::SIZE) == 0; -} - -bool operator!=(const Uuid& a, const Uuid& b) -{ - return !(a == b); -} - -bool operator<(const Uuid& a, const Uuid& b) -{ - return ::memcmp(a.bytes, b.bytes, Uuid::SIZE) < 0; -} - -bool operator>(const Uuid& a, const Uuid& b) -{ - return ::memcmp(a.bytes, b.bytes, Uuid::SIZE) > 0; -} - -bool operator<=(const Uuid& a, const Uuid& b) -{ - return ::memcmp(a.bytes, b.bytes, Uuid::SIZE) <= 0; -} - -bool operator>=(const Uuid& a, const Uuid& b) -{ - return ::memcmp(a.bytes, b.bytes, Uuid::SIZE) >= 0; -} - -ostream& operator<<(ostream& out, Uuid uuid) -{ - const uint8_t* bytes = uuid.bytes; - - ios_base::fmtflags f = out.flags(); - out << hex << setfill('0') - << setw(2) << int(bytes[0]) - << setw(2) << int(bytes[1]) - << setw(2) << int(bytes[2]) - << setw(2) << int(bytes[3]) - << "-" - << setw(2) << int(bytes[4]) - << setw(2) << int(bytes[5]) - << "-" - << setw(2) << int(bytes[6]) - << setw(2) << int(bytes[7]) - << "-" - << setw(2) << int(bytes[8]) - << setw(2) << int(bytes[9]) - << "-" - << setw(2) << int(bytes[10]) - << setw(2) << int(bytes[11]) - << setw(2) << int(bytes[12]) - << setw(2) << int(bytes[13]) - << setw(2) << int(bytes[14]) - << setw(2) << int(bytes[15]); - out.flags(f); - return out; -} - -istream& operator>>(istream& in, Uuid& uuid) -{ - unsigned bytes[16]; - char unparsed[UNPARSED_SIZE + 1] = {0}; - - istream::sentry s(in); - if ( !s ) return in; - - in.get(unparsed, UNPARSED_SIZE+1); - - // Check if we read enough characters - if ( in.gcount()!=UNPARSED_SIZE ) { - in.setstate(ios::failbit); - return in; - } - int r = ::sscanf(unparsed, "%2x%2x%2x%2x-" - "%2x%2x-" - "%2x%2x-" - "%2x%2x-" - "%2x%2x%2x%2x%2x%2x", - &bytes[0], &bytes[1], &bytes[2], &bytes[3], - &bytes[4], &bytes[5], - &bytes[6], &bytes[7], - &bytes[8], &bytes[9], - &bytes[10], &bytes[11], &bytes[12], &bytes[13], &bytes[14], &bytes[15] - ); - // Check if we got enough converted input - if ( r!=int(Uuid::SIZE) ) { - in.setstate(ios::failbit); - return in; - } - - for (unsigned i=0; i<16; ++i) { - uuid.bytes[i] = bytes[i]; - } - return in; -} - -std::string Uuid::str() const -{ - std::ostringstream os; - os << *this; - return os.str(); -} - -size_t Uuid::hash() const { - std::size_t seed = 0; - for(size_t i = 0; i < SIZE; ++i) - seed ^= static_cast(bytes[i]) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - return seed; -} - - -}} // namespace qpid::types diff --git a/qpid/cpp/src/qpid/types/Variant.cpp b/qpid/cpp/src/qpid/types/Variant.cpp deleted file mode 100644 index 26dbe0c91e..0000000000 --- a/qpid/cpp/src/qpid/types/Variant.cpp +++ /dev/null @@ -1,962 +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/types/Variant.h" -#include "qpid/log/Statement.h" -#include "encodings.h" -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace types { - -namespace { -const std::string EMPTY; -const std::string PREFIX("invalid conversion: "); -} - -InvalidConversion::InvalidConversion(const std::string& msg) : Exception(PREFIX + msg) {} -InvalidConversion::~InvalidConversion() throw() {} - -class VariantImpl -{ - public: - VariantImpl(); - void reset(); - void set(bool); - void set(uint8_t); - void set(uint16_t); - void set(uint32_t); - void set(uint64_t); - void set(int8_t); - void set(int16_t); - void set(int32_t); - void set(int64_t); - void set(float); - void set(double); - void set(const std::string&, const std::string& encoding=std::string()); - void set(const Variant::Map&); - void set(const Variant::List&); - void set(const Uuid&); - void set(const Variant&); - ~VariantImpl(); - - VariantType getType() const; - - bool asBool() const; - uint8_t asUint8() const; - uint16_t asUint16() const; - uint32_t asUint32() const; - uint64_t asUint64() const; - int8_t asInt8() const; - int16_t asInt16() const; - int32_t asInt32() const; - int64_t asInt64() const; - float asFloat() const; - double asDouble() const; - std::string asString() const; - Uuid asUuid() const; - - const Variant::Map& asMap() const; - Variant::Map& asMap(); - const Variant::List& asList() const; - Variant::List& asList(); - - const std::string& getString() const; - std::string& getString(); - - void setEncoding(const std::string&); - const std::string& getEncoding() const; - - bool isEqualTo(VariantImpl&) const; - bool isEquivalentTo(VariantImpl&) const; - - Variant::List descriptors; // Optional descriptors for described value. - - private: - VariantType type; - union { - bool b; - uint8_t ui8; - uint16_t ui16; - uint32_t ui32; - uint64_t ui64; - int8_t i8; - int16_t i16; - int32_t i32; - int64_t i64; - float f; - double d; - Uuid* uuid; - Variant::Map* map; - Variant::List* list; - std::string* string; - } value; - std::string encoding; // Optional encoding for variable length data. - - template T convertFromString() const - { - const std::string& s = *value.string; - - try { - // Extra shenanigans to work around negative zero - // conversion error in older GCC libs. - if ( s[0] != '-' ) { - return boost::lexical_cast(s); - } else { - T r = boost::lexical_cast(s.substr(1)); - if (std::numeric_limits::is_signed) { - return -r; - } else { - if (r==0) return 0; - } - } - } catch(const boost::bad_lexical_cast&) { - } - throw InvalidConversion(QPID_MSG("Cannot convert " << s)); - } - -}; - -VariantImpl::VariantImpl() : type(VAR_VOID) {} - -void VariantImpl::set(bool b) { reset(); type = VAR_BOOL; value.b = b; } -void VariantImpl::set(uint8_t i) { reset(); type = VAR_UINT8; value.ui8 = i; } -void VariantImpl::set(uint16_t i) { reset(); type = VAR_UINT16; value.ui16 = i; } -void VariantImpl::set(uint32_t i) { reset(); type = VAR_UINT32; value.ui32 = i; } -void VariantImpl::set(uint64_t i) { reset(); type = VAR_UINT64; value.ui64 = i; } -void VariantImpl::set(int8_t i) { reset(); type = VAR_INT8; value.i8 = i; } -void VariantImpl::set(int16_t i) { reset(); type = VAR_INT16; value.i16 = i; } -void VariantImpl::set(int32_t i) { reset(); type = VAR_INT32; value.i32 = i; } -void VariantImpl::set(int64_t i) { reset(); type = VAR_INT64; value.i64 = i; } -void VariantImpl::set(float f) { reset(); type = VAR_FLOAT; value.f = f; } -void VariantImpl::set(double d) { reset(); type = VAR_DOUBLE; value.d = d; } -void VariantImpl::set(const std::string& s, const std::string& e) { reset(); type = VAR_STRING; encoding = e; value.string = new std::string(s); } - -void VariantImpl::set(const Variant::Map& m) { - reset(); - type = VAR_MAP; - value.map = new Variant::Map(m); -} - -void VariantImpl::set(const Variant::List& l) { reset(); type = VAR_LIST; value.list = new Variant::List(l); } - -void VariantImpl::set(const Uuid& u) { reset(); type = VAR_UUID; value.uuid = new Uuid(u); } - -VariantImpl::~VariantImpl() { reset(); } - -void VariantImpl::reset() { - switch (type) { - case VAR_STRING: - delete value.string; - break; - case VAR_MAP: - delete value.map; - break; - case VAR_LIST: - delete value.list; - break; - case VAR_UUID: - delete value.uuid; - break; - default: - break; - } - type = VAR_VOID; -} - -VariantType VariantImpl::getType() const { return type; } - -namespace { - -bool same_char(char a, char b) -{ - return toupper(a) == toupper(b); -} - -bool caseInsensitiveMatch(const std::string& a, const std::string& b) -{ - return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), &same_char); -} - -const std::string TRUE_STRING("True"); -const std::string FALSE_STRING("False"); - -bool toBool(const std::string& s) -{ - if (caseInsensitiveMatch(s, TRUE_STRING)) return true; - if (caseInsensitiveMatch(s, FALSE_STRING)) return false; - try { return boost::lexical_cast(s); } catch(const boost::bad_lexical_cast&) {} - throw InvalidConversion(QPID_MSG("Cannot convert " << s << " to bool")); -} - -template std::string toString(const T& t) -{ - std::stringstream out; - out << t; - return out.str(); -} - -template bool equal(const T& a, const T& b) -{ - return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); -} - -} - -bool VariantImpl::asBool() const -{ - switch(type) { - case VAR_VOID: return false; - case VAR_BOOL: return value.b; - case VAR_UINT8: return value.ui8; - case VAR_UINT16: return value.ui16; - case VAR_UINT32: return value.ui32; - case VAR_UINT64: return value.ui64; - case VAR_INT8: return value.i8; - case VAR_INT16: return value.i16; - case VAR_INT32: return value.i32; - case VAR_INT64: return value.i64; - case VAR_STRING: return toBool(*value.string); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_BOOL))); - } -} -uint8_t VariantImpl::asUint8() const -{ - switch(type) { - case VAR_UINT8: return value.ui8; - case VAR_UINT16: - if (value.ui16 <= 0x00ff) - return uint8_t(value.ui16); - break; - case VAR_UINT32: - if (value.ui32 <= 0x000000ff) - return uint8_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= 0x00000000000000ff) - return uint8_t(value.ui64); - break; - case VAR_INT8: - if (value.i8 >= 0) - return uint8_t(value.i8); - break; - case VAR_INT16: - if (value.i16 >= 0 && value.i16 <= 0x00ff) - return uint8_t(value.i16); - break; - case VAR_INT32: - if (value.i32 >= 0 && value.i32 <= 0x000000ff) - return uint8_t(value.i32); - break; - case VAR_INT64: - if (value.i64 >= 0 && value.i64 <= 0x00000000000000ff) - return uint8_t(value.i64); - break; - case VAR_STRING: return convertFromString(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT8))); -} -uint16_t VariantImpl::asUint16() const -{ - switch(type) { - case VAR_UINT8: return value.ui8; - case VAR_UINT16: return value.ui16; - case VAR_UINT32: - if (value.ui32 <= 0x0000ffff) - return uint16_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= 0x000000000000ffff) - return uint16_t(value.ui64); - break; - case VAR_INT8: - if (value.i8 >= 0) - return uint16_t(value.i8); - break; - case VAR_INT16: - if (value.i16 >= 0) - return uint16_t(value.i16); - break; - case VAR_INT32: - if (value.i32 >= 0 && value.i32 <= 0x0000ffff) - return uint16_t(value.i32); - break; - case VAR_INT64: - if (value.i64 >= 0 && value.i64 <= 0x000000000000ffff) - return uint16_t(value.i64); - break; - case VAR_STRING: return convertFromString(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT16))); -} -uint32_t VariantImpl::asUint32() const -{ - switch(type) { - case VAR_UINT8: return value.ui8; - case VAR_UINT16: return value.ui16; - case VAR_UINT32: return value.ui32; - case VAR_UINT64: - if (value.ui64 <= 0x00000000ffffffff) - return uint32_t(value.ui64); - break; - case VAR_INT8: - if (value.i8 >= 0) - return uint32_t(value.i8); - break; - case VAR_INT16: - if (value.i16 >= 0) - return uint32_t(value.i16); - break; - case VAR_INT32: - if (value.i32 >= 0) - return uint32_t(value.i32); - break; - case VAR_INT64: - if (value.i64 >= 0 && value.i64 <= 0x00000000ffffffff) - return uint32_t(value.i64); - break; - case VAR_STRING: return convertFromString(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT32))); -} -uint64_t VariantImpl::asUint64() const -{ - switch(type) { - case VAR_UINT8: return value.ui8; - case VAR_UINT16: return value.ui16; - case VAR_UINT32: return value.ui32; - case VAR_UINT64: return value.ui64; - case VAR_INT8: - if (value.i8 >= 0) - return uint64_t(value.i8); - break; - case VAR_INT16: - if (value.i16 >= 0) - return uint64_t(value.i16); - break; - case VAR_INT32: - if (value.i32 >= 0) - return uint64_t(value.i32); - break; - case VAR_INT64: - if (value.i64 >= 0) - return uint64_t(value.i64); - break; - case VAR_STRING: return convertFromString(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT64))); -} - -int8_t VariantImpl::asInt8() const -{ - switch(type) { - case VAR_INT8: return value.i8; - case VAR_INT16: - if ((value.i16 >= std::numeric_limits::min()) && (value.i16 <= std::numeric_limits::max())) - return int8_t(value.i16); - break; - case VAR_INT32: - if ((value.i32 >= std::numeric_limits::min()) && (value.i32 <= std::numeric_limits::max())) - return int8_t(value.i32); - break; - case VAR_INT64: - if ((value.i64 >= std::numeric_limits::min()) && (value.i64 <= std::numeric_limits::max())) - return int8_t(value.i64); - break; - case VAR_UINT8: - if (value.ui8 <= std::numeric_limits::max()) - return int8_t(value.ui8); - break; - case VAR_UINT16: - if (value.ui16 <= std::numeric_limits::max()) - return int8_t(value.ui16); - break; - case VAR_UINT32: - if (value.ui32 <= (uint32_t) std::numeric_limits::max()) - return int8_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= (uint64_t) std::numeric_limits::max()) - return int8_t(value.ui64); - break; - case VAR_STRING: return convertFromString(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT8))); -} -int16_t VariantImpl::asInt16() const -{ - switch(type) { - case VAR_INT8: return value.i8; - case VAR_INT16: return value.i16; - case VAR_INT32: - if ((value.i32 >= std::numeric_limits::min()) && (value.i32 <= std::numeric_limits::max())) - return int16_t(value.i32); - break; - case VAR_INT64: - if ((value.i64 >= std::numeric_limits::min()) && (value.i64 <= std::numeric_limits::max())) - return int16_t(value.i64); - break; - case VAR_UINT8: return int16_t(value.ui8); - case VAR_UINT16: - if (value.ui16 <= std::numeric_limits::max()) - return int16_t(value.ui16); - break; - case VAR_UINT32: - if (value.ui32 <= (uint32_t) std::numeric_limits::max()) - return int16_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= (uint64_t) std::numeric_limits::max()) - return int16_t(value.ui64); - break; - case VAR_STRING: return convertFromString(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT16))); -} -int32_t VariantImpl::asInt32() const -{ - switch(type) { - case VAR_INT8: return value.i8; - case VAR_INT16: return value.i16; - case VAR_INT32: return value.i32; - case VAR_INT64: - if ((value.i64 >= std::numeric_limits::min()) && (value.i64 <= std::numeric_limits::max())) - return int32_t(value.i64); - break; - case VAR_UINT8: return int32_t(value.ui8); - case VAR_UINT16: return int32_t(value.ui16); - case VAR_UINT32: - if (value.ui32 <= (uint32_t) std::numeric_limits::max()) - return int32_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= (uint64_t) std::numeric_limits::max()) - return int32_t(value.ui64); - break; - case VAR_STRING: return convertFromString(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT32))); -} -int64_t VariantImpl::asInt64() const -{ - switch(type) { - case VAR_INT8: return value.i8; - case VAR_INT16: return value.i16; - case VAR_INT32: return value.i32; - case VAR_INT64: return value.i64; - case VAR_UINT8: return int64_t(value.ui8); - case VAR_UINT16: return int64_t(value.ui16); - case VAR_UINT32: return int64_t(value.ui32); - case VAR_UINT64: - if (value.ui64 <= (uint64_t) std::numeric_limits::max()) - return int64_t(value.ui64); - break; - case VAR_STRING: return convertFromString(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT64))); -} -float VariantImpl::asFloat() const -{ - switch(type) { - case VAR_FLOAT: return value.f; - case VAR_STRING: return convertFromString(); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_FLOAT))); - } -} -double VariantImpl::asDouble() const -{ - switch(type) { - case VAR_FLOAT: return value.f; - case VAR_DOUBLE: return value.d; - case VAR_STRING: return convertFromString(); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_DOUBLE))); - } -} -std::string VariantImpl::asString() const -{ - switch(type) { - case VAR_VOID: return EMPTY; - case VAR_BOOL: return value.b ? TRUE_STRING : FALSE_STRING; - case VAR_UINT8: return boost::lexical_cast((int) value.ui8); - case VAR_UINT16: return boost::lexical_cast(value.ui16); - case VAR_UINT32: return boost::lexical_cast(value.ui32); - case VAR_UINT64: return boost::lexical_cast(value.ui64); - case VAR_INT8: return boost::lexical_cast((int) value.i8); - case VAR_INT16: return boost::lexical_cast(value.i16); - case VAR_INT32: return boost::lexical_cast(value.i32); - case VAR_INT64: return boost::lexical_cast(value.i64); - case VAR_DOUBLE: return boost::lexical_cast(value.d); - case VAR_FLOAT: return boost::lexical_cast(value.f); - case VAR_STRING: return *value.string; - case VAR_UUID: return value.uuid->str(); - case VAR_LIST: return toString(asList()); - case VAR_MAP: return toString(asMap()); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_STRING))); - } -} -Uuid VariantImpl::asUuid() const -{ - switch(type) { - case VAR_UUID: return *value.uuid; - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UUID))); - } -} - -bool VariantImpl::isEqualTo(VariantImpl& other) const -{ - if (type == other.type) { - switch(type) { - case VAR_VOID: return true; - case VAR_BOOL: return value.b == other.value.b; - case VAR_UINT8: return value.ui8 == other.value.ui8; - case VAR_UINT16: return value.ui16 == other.value.ui16; - case VAR_UINT32: return value.ui32 == other.value.ui32; - case VAR_UINT64: return value.ui64 == other.value.ui64; - case VAR_INT8: return value.i8 == other.value.i8; - case VAR_INT16: return value.i16 == other.value.i16; - case VAR_INT32: return value.i32 == other.value.i32; - case VAR_INT64: return value.i64 == other.value.i64; - case VAR_DOUBLE: return value.d == other.value.d; - case VAR_FLOAT: return value.f == other.value.f; - case VAR_STRING: return *value.string == *other.value.string; - case VAR_UUID: return *value.uuid == *other.value.uuid; - case VAR_LIST: return equal(asList(), other.asList()); - case VAR_MAP: return equal(asMap(), other.asMap()); - } - } - return false; -} - -const Variant::Map& VariantImpl::asMap() const -{ - switch(type) { - case VAR_MAP: return *value.map; - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_MAP))); - } -} - -Variant::Map& VariantImpl::asMap() -{ - switch(type) { - case VAR_MAP: return *value.map; - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_MAP))); - } -} - -const Variant::List& VariantImpl::asList() const -{ - switch(type) { - case VAR_LIST: return *value.list; - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_LIST))); - } -} - -Variant::List& VariantImpl::asList() -{ - switch(type) { - case VAR_LIST: return *value.list; - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_LIST))); - } -} - -std::string& VariantImpl::getString() -{ - switch(type) { - case VAR_STRING: return *value.string; - default: throw InvalidConversion(QPID_MSG("Variant is not a string; use asString() if conversion is required.")); - } -} - -const std::string& VariantImpl::getString() const -{ - switch(type) { - case VAR_STRING: return *value.string; - default: throw InvalidConversion(QPID_MSG("Variant is not a string; use asString() if conversion is required.")); - } -} - -void VariantImpl::setEncoding(const std::string& s) { encoding = s; } -const std::string& VariantImpl::getEncoding() const { return encoding; } - -std::string getTypeName(VariantType type) -{ - switch (type) { - case VAR_VOID: return "void"; - case VAR_BOOL: return "bool"; - case VAR_UINT8: return "uint8"; - case VAR_UINT16: return "uint16"; - case VAR_UINT32: return "uint32"; - case VAR_UINT64: return "uint64"; - case VAR_INT8: return "int8"; - case VAR_INT16: return "int16"; - case VAR_INT32: return "int32"; - case VAR_INT64: return "int64"; - case VAR_FLOAT: return "float"; - case VAR_DOUBLE: return "double"; - case VAR_STRING: return "string"; - case VAR_MAP: return "map"; - case VAR_LIST: return "list"; - case VAR_UUID: return "uuid"; - } - return "";//should never happen -} - -bool isIntegerType(VariantType type) -{ - switch (type) { - case VAR_BOOL: - case VAR_UINT8: - case VAR_UINT16: - case VAR_UINT32: - case VAR_UINT64: - case VAR_INT8: - case VAR_INT16: - case VAR_INT32: - case VAR_INT64: - return true; - default: - return false; - } -} - -void VariantImpl::set(const Variant& v) -{ - switch (v.getType()) { - case VAR_BOOL: set(v.asBool()); break; - case VAR_UINT8: set(v.asUint8()); break; - case VAR_UINT16: set(v.asUint16()); break; - case VAR_UINT32: set(v.asUint32()); break; - case VAR_UINT64: set(v.asUint64()); break; - case VAR_INT8: set(v.asInt8()); break; - case VAR_INT16: set(v.asInt16()); break; - case VAR_INT32: set(v.asInt32()); break; - case VAR_INT64: set(v.asInt64()); break; - case VAR_FLOAT: set(v.asFloat()); break; - case VAR_DOUBLE: set(v.asDouble()); break; - case VAR_STRING: set(v.asString(), v.getEncoding()); break; - case VAR_MAP: set(v.asMap()); break; - case VAR_LIST: set(v.asList()); break; - case VAR_UUID: set(v.asUuid()); break; - default: reset(); - } - encoding = v.getEncoding(); - descriptors = v.getDescriptors(); -} - -Variant::Variant() : impl(0) {} -Variant::Variant(bool b) : impl(new VariantImpl()) { impl->set(b); } -Variant::Variant(uint8_t i) : impl(new VariantImpl()) { impl->set(i); } -Variant::Variant(uint16_t i) : impl(new VariantImpl()) { impl->set(i); } -Variant::Variant(uint32_t i) : impl(new VariantImpl()) { impl->set(i); } -Variant::Variant(uint64_t i) : impl(new VariantImpl()) { impl->set(i); } -Variant::Variant(int8_t i) : impl(new VariantImpl()) { impl->set(i); } -Variant::Variant(int16_t i) : impl(new VariantImpl()) { impl->set(i); } -Variant::Variant(int32_t i) : impl(new VariantImpl()) { impl->set(i); } -Variant::Variant(int64_t i) : impl(new VariantImpl()) { impl->set(i); } -Variant::Variant(float f) : impl(new VariantImpl()) { impl->set(f); } -Variant::Variant(double d) : impl(new VariantImpl()) { impl->set(d); } -Variant::Variant(const std::string& s) : impl(new VariantImpl()) { impl->set(s); } -Variant::Variant(const std::string& s, const std::string& encoding) : impl(new VariantImpl()) { impl->set(s, encoding); } -Variant::Variant(const char* s) : impl(new VariantImpl()) { impl->set(std::string(s)); } -Variant::Variant(const char* s, const char* encoding) : impl(new VariantImpl()) { impl->set(std::string(s), std::string(encoding)); } -Variant::Variant(const Map& m) : impl(new VariantImpl()) { impl->set(m); } -Variant::Variant(const List& l) : impl(new VariantImpl()) { impl->set(l); } -Variant::Variant(const Variant& v) : impl(new VariantImpl()) { impl->set(v); } -Variant::Variant(const Uuid& u) : impl(new VariantImpl()) { impl->set(u); } - -Variant::~Variant() { if (impl) delete impl; } - -void Variant::reset() -{ - if (impl) delete impl; - impl = 0; -} - -namespace { -VariantImpl* assure(VariantImpl*& ptr) { - if (!ptr) ptr = new VariantImpl(); - return ptr; -} -} - -Variant& Variant::operator=(bool b) -{ - assure(impl)->set(b); - return *this; -} - -Variant& Variant::operator=(uint8_t i) -{ - assure(impl)->set(i); - return *this; -} -Variant& Variant::operator=(uint16_t i) -{ - assure(impl)->set(i); - return *this; -} -Variant& Variant::operator=(uint32_t i) -{ - assure(impl)->set(i); - return *this; -} -Variant& Variant::operator=(uint64_t i) -{ - assure(impl)->set(i); - return *this; -} - -Variant& Variant::operator=(int8_t i) -{ - assure(impl)->set(i); - return *this; -} -Variant& Variant::operator=(int16_t i) -{ - assure(impl)->set(i); - return *this; -} -Variant& Variant::operator=(int32_t i) -{ - assure(impl)->set(i); - return *this; -} -Variant& Variant::operator=(int64_t i) -{ - assure(impl)->set(i); - return *this; -} - -Variant& Variant::operator=(float f) -{ - assure(impl)->set(f); - return *this; -} -Variant& Variant::operator=(double d) -{ - assure(impl)->set(d); - return *this; -} - -Variant& Variant::operator=(const std::string& s) -{ - assure(impl)->set(s); - return *this; -} - -Variant& Variant::operator=(const char* s) -{ - assure(impl)->set(std::string(s)); - return *this; -} - -Variant& Variant::operator=(const Uuid& u) -{ - assure(impl)->set(u); - return *this; -} - -Variant& Variant::operator=(const Map& m) -{ - assure(impl)->set(m); - return *this; -} - -Variant& Variant::operator=(const List& l) -{ - assure(impl)->set(l); - return *this; -} - -Variant& Variant::operator=(const Variant& v) -{ - assure(impl)->set(v); - return *this; -} - -Variant& Variant::parse(const std::string& s) -{ - operator=(s); - try { - return operator=(asInt64()); - } catch (const InvalidConversion&) {} - try { - return operator=(asUint64()); - } catch (const InvalidConversion&) {} - try { - return operator=(asDouble()); - } catch (const InvalidConversion&) {} - try { - return operator=(asBool()); - } catch (const InvalidConversion&) {} - setEncoding(qpid::types::encodings::UTF8); - return *this; -} - - -VariantType Variant::getType() const { return impl ? impl->getType() : VAR_VOID; } -bool Variant::isVoid() const { return getType() == VAR_VOID; } -bool Variant::asBool() const { return impl && impl->asBool(); } -uint8_t Variant::asUint8() const { return impl ? impl->asUint8() : 0; } -uint16_t Variant::asUint16() const { return impl ? impl->asUint16() : 0; } -uint32_t Variant::asUint32() const { return impl ? impl->asUint32() : 0; } -uint64_t Variant::asUint64() const { return impl ? impl->asUint64() : 0; } -int8_t Variant::asInt8() const { return impl ? impl->asInt8() : 0; } -int16_t Variant::asInt16() const { return impl ? impl->asInt16() : 0; } -int32_t Variant::asInt32() const { return impl ? impl->asInt32(): 0; } -int64_t Variant::asInt64() const { return impl ? impl->asInt64() : 0; } -float Variant::asFloat() const { return impl ? impl->asFloat() : 0; } -double Variant::asDouble() const { return impl ? impl->asDouble() : 0; } -std::string Variant::asString() const { return impl ? impl->asString() : EMPTY; } -Uuid Variant::asUuid() const { return impl ? impl->asUuid() : Uuid(); } -const Variant::Map& Variant::asMap() const { if (!impl) throw InvalidConversion("Can't convert VOID to MAP"); return impl->asMap(); } -Variant::Map& Variant::asMap() { if (!impl) throw InvalidConversion("Can't convert VOID to MAP"); return impl->asMap(); } -const Variant::List& Variant::asList() const { if (!impl) throw InvalidConversion("Can't convert VOID to LIST"); return impl->asList(); } -Variant::List& Variant::asList() { if (!impl) throw InvalidConversion("Can't convert VOID to LIST"); return impl->asList(); } -const std::string& Variant::getString() const { if (!impl) throw InvalidConversion("Can't convert VOID to STRING"); return impl->getString(); } -std::string& Variant::getString() { if (!impl) throw InvalidConversion("Can't convert VOID to STRING"); return impl->getString(); } -void Variant::setEncoding(const std::string& s) { - assure(impl)->setEncoding(s); -} -const std::string& Variant::getEncoding() const { return impl ? impl->getEncoding() : EMPTY; } - -Variant::operator bool() const { return asBool(); } -Variant::operator uint8_t() const { return asUint8(); } -Variant::operator uint16_t() const { return asUint16(); } -Variant::operator uint32_t() const { return asUint32(); } -Variant::operator uint64_t() const { return asUint64(); } -Variant::operator int8_t() const { return asInt8(); } -Variant::operator int16_t() const { return asInt16(); } -Variant::operator int32_t() const { return asInt32(); } -Variant::operator int64_t() const { return asInt64(); } -Variant::operator float() const { return asFloat(); } -Variant::operator double() const { return asDouble(); } -Variant::operator std::string() const { return asString(); } -Variant::operator Uuid() const { return asUuid(); } - -std::ostream& operator<<(std::ostream& out, const Variant::Map& map) -{ - out << "{"; - for (Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) { - if (i != map.begin()) out << ", "; - out << i->first << ":" << i->second; - } - out << "}"; - return out; -} - -std::ostream& operator<<(std::ostream& out, const Variant::List& list) -{ - out << "["; - for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { - if (i != list.begin()) out << ", "; - out << *i; - } - out << "]"; - return out; -} - -std::ostream& operator<<(std::ostream& out, const Variant& value) -{ - // Print the descriptors - const Variant::List& descriptors = value.getDescriptors(); - for (Variant::List::const_iterator i = descriptors.begin(); i != descriptors.end(); ++i) - out << "@" << *i << " "; - - // Print the value - switch (value.getType()) { - case VAR_MAP: - out << value.asMap(); - break; - case VAR_LIST: - out << value.asList(); - break; - case VAR_VOID: - out << ""; - break; - default: - out << value.asString(); - break; - } - return out; -} - -bool operator==(const Variant& a, const Variant& b) -{ - return a.isEqualTo(b); -} - -bool operator!=(const Variant& a, const Variant& b) { return !(a == b); } - -bool Variant::isEqualTo(const Variant& other) const -{ - if (isVoid() && other.isVoid()) return true; - if (isVoid() || other.isVoid()) return false; - return impl && impl->isEqualTo(*other.impl); -} - -bool Variant::isDescribed() const { - return impl && !impl->descriptors.empty(); -} - -Variant::List& Variant::getDescriptors() { - return assure(impl)->descriptors; -} - -const Variant::List& Variant::getDescriptors() const { - return assure(impl)->descriptors; -} - -Variant Variant::getDescriptor() const { - if (getDescriptors().size() > 0) return getDescriptors().front(); - else return Variant(); -} - -void Variant::setDescriptor(const Variant& descriptor) { - getDescriptors().clear(); - getDescriptors().push_back(descriptor); -} - -Variant Variant::described(const Variant& descriptor, const Variant& value) { - Variant described(value); - described.setDescriptor(descriptor); - return described; -} - -Variant Variant::described(const Variant& descriptor, const List& value) { - Variant described(value); - described.setDescriptor(descriptor); - return described; -} - -}} // namespace qpid::types diff --git a/qpid/cpp/src/qpid/types/encodings.h b/qpid/cpp/src/qpid/types/encodings.h deleted file mode 100644 index 571e8607aa..0000000000 --- a/qpid/cpp/src/qpid/types/encodings.h +++ /dev/null @@ -1,35 +0,0 @@ -#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 deleted file mode 100644 index ffe9a66656..0000000000 --- a/qpid/cpp/src/qpid/xml/XmlExchange.cpp +++ /dev/null @@ -1,474 +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 "config.h" - -#include "qpid/xml/XmlExchange.h" - -#include "qpid/amqp/CharSequence.h" -#include "qpid/broker/DeliverableMessage.h" - -#include "qpid/log/Statement.h" -#include "qpid/broker/FedOps.h" -#include "qpid/amqp/MapHandler.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" - -#include "qpid/Plugin.h" - -#include -#include - -#ifdef XQ_EFFECTIVE_BOOLEAN_VALUE_HPP -#include -#endif - -#include - -#include -#include - -#include -#include -#include -#include -#include - -using namespace qpid::framing; -using namespace qpid::sys; -using qpid::management::Manageable; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -namespace { -const char* DUMMY("dummy"); -} -class XmlNullResolver : public XERCES_CPP_NAMESPACE::XMLEntityResolver -{ - public: - XERCES_CPP_NAMESPACE::InputSource* resolveEntity(XERCES_CPP_NAMESPACE::XMLResourceIdentifier* xmlri) - { - if (xmlri->getResourceIdentifierType() == XERCES_CPP_NAMESPACE::XMLResourceIdentifier::ExternalEntity) { - return new XERCES_CPP_NAMESPACE::MemBufInputSource(0, 0, DUMMY); - } else { - return 0; - } - } -}; - - -XQilla XmlBinding::xqilla; - -XmlBinding::XmlBinding(const std::string& key, const Queue::shared_ptr queue, const std::string& _fedOrigin, Exchange* parent, - const ::qpid::framing::FieldTable& _arguments, const std::string& queryText ) - : Binding(key, queue, parent, _arguments), - xquery(), - parse_message_content(true), - fedOrigin(_fedOrigin) -{ - startManagement(); - - QPID_LOG(trace, "Creating binding with query: " << queryText ); - - try { - Query q(xqilla.parse(X(queryText.c_str()))); - xquery = q; - - QPID_LOG(trace, "Bound successfully with query: " << queryText ); - - parse_message_content = false; - - if (xquery->getQueryBody()->getStaticAnalysis().areContextFlagsUsed()) { - parse_message_content = true; - } - else { - GlobalVariables &vars = const_cast(xquery->getVariables()); - for (GlobalVariables::iterator it = vars.begin(); it != vars.end(); ++it) { - if ((*it)->getStaticAnalysis().areContextFlagsUsed()) { - parse_message_content = true; - break; - } - } - } - } - catch (XQException& e) { - throw InternalErrorException(QPID_MSG("Could not parse xquery:"+ queryText)); - } - catch (...) { - throw InternalErrorException(QPID_MSG("Unexpected error - Could not parse xquery:"+ queryText)); - } -} - - -XmlExchange::XmlExchange(const std::string& _name, Manageable* _parent, Broker* b) : Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -XmlExchange::XmlExchange(const std::string& _name, bool _durable, bool autodelete, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, autodelete, _args, _parent, b), resolver(new XmlNullResolver) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool XmlExchange::bind(Queue::shared_ptr queue, const std::string& bindingKey, const FieldTable* args) -{ - - // Federation uses bind for unbind and reorigin comands as well as for binds. - // - // Both federated and local binds are done in this method. Other - // federated requests are done by calling the relevent methods. - - std::string fedOp; - std::string fedTags; - std::string fedOrigin; - - if (args) - fedOp = args->getAsString(qpidFedOp); - if (! fedOp.empty()) { - fedTags = args->getAsString(qpidFedTags); - fedOrigin = args->getAsString(qpidFedOrigin); - } - - if (fedOp == fedOpUnbind) { - return fedUnbind(fedOrigin, fedTags, queue, bindingKey, args); - } - else if (fedOp == fedOpReorigin) { - fedReorigin(); - return true; - } - - // OK, looks like we're really going to bind - - else if (fedOp.empty() || fedOp == fedOpBind) { - - std::string queryText = args->getAsString("xquery"); - - RWlock::ScopedWlock l(lock); - - XmlBinding::vector& bindings(bindingsMap[bindingKey]); - XmlBinding::vector::ConstPtr p = bindings.snapshot(); - - if (!p || std::find_if(p->begin(), p->end(), MatchQueueAndOrigin(queue, fedOrigin)) == p->end()) { - - XmlBinding::shared_ptr binding(new XmlBinding (bindingKey, queue, fedOrigin, this, *args, queryText)); - bindings.add(binding); - - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - return false; - } - } - else { - QPID_LOG(warning, "Unknown Federation Op: " << fedOp); - } - - routeIVE(); - propagateFedOp(bindingKey, fedTags, fedOp, fedOrigin, args); - - return true; -} - -bool XmlExchange::unbind(Queue::shared_ptr queue, const std::string& bindingKey, const FieldTable* args) -{ - RWlock::ScopedWlock l(lock); - return unbindLH(queue, bindingKey, args); -} - -bool XmlExchange::unbindLH(Queue::shared_ptr queue, const std::string& bindingKey, const FieldTable* args) -{ - /* - * When called directly, no qpidFedOrigin argument will be - * present. When called from federation, it will be present. - * - * This is a bit of a hack - the binding needs the origin, but - * this interface, as originally defined, would not supply one. - * - * Note: caller must hold Wlock - */ - std::string fedOrigin; - if (args) fedOrigin = args->getAsString(qpidFedOrigin); - - if (bindingsMap[bindingKey].remove_if(MatchQueueAndOrigin(queue, fedOrigin))) { - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - if (bindingsMap[bindingKey].empty()) bindingsMap.erase(bindingKey); - if (bindingsMap.empty()) checkAutodelete(); - return true; - } else { - return false; - } -} - -namespace { -class DefineExternals : public qpid::amqp::MapHandler -{ - public: - DefineExternals(DynamicContext* c) : context(c) { assert(context); } - void handleBool(const qpid::amqp::CharSequence& key, bool value) { process(std::string(key.data, key.size), (int) value); } - void handleUint8(const qpid::amqp::CharSequence& key, uint8_t value) { process(std::string(key.data, key.size), (int) value); } - void handleUint16(const qpid::amqp::CharSequence& key, uint16_t value) { process(std::string(key.data, key.size), (int) value); } - void handleUint32(const qpid::amqp::CharSequence& key, uint32_t value) { process(std::string(key.data, key.size), (int) value); } - void handleUint64(const qpid::amqp::CharSequence& key, uint64_t value) { process(std::string(key.data, key.size), (int) value); } - void handleInt8(const qpid::amqp::CharSequence& key, int8_t value) { process(std::string(key.data, key.size), (int) value); } - void handleInt16(const qpid::amqp::CharSequence& key, int16_t value) { process(std::string(key.data, key.size), (int) value); } - void handleInt32(const qpid::amqp::CharSequence& key, int32_t value) { process(std::string(key.data, key.size), (int) value); } - void handleInt64(const qpid::amqp::CharSequence& key, int64_t value) { process(std::string(key.data, key.size), (int) value); } - void handleFloat(const qpid::amqp::CharSequence& key, float value) { process(std::string(key.data, key.size), value); } - void handleDouble(const qpid::amqp::CharSequence& key, double value) { process(std::string(key.data, key.size), value); } - void handleString(const qpid::amqp::CharSequence& key, const qpid::amqp::CharSequence& value, const qpid::amqp::CharSequence& /*encoding*/) - { - process(std::string(key.data, key.size), std::string(value.data, value.size)); - } - void handleVoid(const qpid::amqp::CharSequence&) {} - private: - void process(const std::string& key, double value) - { - QPID_LOG(trace, "XmlExchange, external variable (double): " << key << " = " << value); - Item::Ptr item = context->getItemFactory()->createDouble(value, context); - context->setExternalVariable(X(key.c_str()), item); - } - void process(const std::string& key, int value) - { - QPID_LOG(trace, "XmlExchange, external variable (int):" << key << " = " << value); - Item::Ptr item = context->getItemFactory()->createInteger(value, context); - context->setExternalVariable(X(key.c_str()), item); - } - void process(const std::string& key, const std::string& value) - { - QPID_LOG(trace, "XmlExchange, external variable (string):" << key << " = " << value); - Item::Ptr item = context->getItemFactory()->createString(X(value.c_str()), context); - context->setExternalVariable(X(key.c_str()), item); - } - - DynamicContext* context; -}; - -} - -bool XmlExchange::matches(Query& query, Deliverable& msg, bool parse_message_content) -{ - std::string msgContent; - - try { - QPID_LOG(trace, "matches: query is [" << UTF8(query->getQueryText()) << "]"); - - boost::scoped_ptr context(query->createDynamicContext()); - if (!context.get()) { - throw InternalErrorException(QPID_MSG("Query context looks munged ...")); - } - - if (parse_message_content) { - - if (resolver) context->setXMLEntityResolver(resolver.get()); - msgContent = msg.getMessage().getContent(); - - QPID_LOG(trace, "matches: message content is [" << msgContent << "]"); - - XERCES_CPP_NAMESPACE::MemBufInputSource xml((const XMLByte*) msgContent.c_str(), - msgContent.length(), "input" ); - - // This will parse the document using either Xerces or FastXDM, depending - // on your XQilla configuration. FastXDM can be as much as 10x faster. - - Sequence seq(context->parseDocument(xml)); - - if(!seq.isEmpty() && seq.first()->isNode()) { - context->setContextItem(seq.first()); - context->setContextPosition(1); - context->setContextSize(1); - } - } - - DefineExternals f(context.get()); - msg.getMessage().processProperties(f); - - Result result = query->execute(context.get()); -#ifdef XQ_EFFECTIVE_BOOLEAN_VALUE_HPP - Item::Ptr first_ = result->next(context.get()); - Item::Ptr second_ = result->next(context.get()); - return XQEffectiveBooleanValue::get(first_, second_, context.get(), 0); -#else - return result->getEffectiveBooleanValue(context.get(), 0); -#endif - } - catch (XQException& e) { - QPID_LOG(warning, "Could not parse XML content (or message headers):" << msgContent); - } - catch (...) { - QPID_LOG(warning, "Unexpected error routing message: " << msgContent); - } - return 0; -} - -// Future optimization: If any query in a binding for a given routing key requires -// message content, parse the message once, and use that parsed form for all bindings. -// -// Future optimization: XQilla does not currently do document projection for data -// accessed via the context item. If there is a single query for a given routing key, -// and it accesses document data, this could be a big win. -// -// Document projection often is not a win if you have multiple queries on the same data. -// But for very large messages, if all these queries are on the first part of the data, -// it could still be a big win. - -void XmlExchange::route(Deliverable& msg) -{ - const std::string& routingKey = msg.getMessage().getRoutingKey(); - PreRoute pr(msg, this); - try { - XmlBinding::vector::ConstPtr p; - BindingList b(new std::vector >); - { - RWlock::ScopedRlock l(lock); - p = bindingsMap[routingKey].snapshot(); - } - - if (p.get()) { - for (std::vector::const_iterator i = p->begin(); i != p->end(); i++) { - if (matches((*i)->xquery, msg, (*i)->parse_message_content)) { - b->push_back(*i); - } - } - } - // else allow stats to be counted, even for non-matched messages - doRoute(msg, b); - } catch (...) { - QPID_LOG(warning, "XMLExchange " << getName() << ": exception routing message with query " << routingKey); - } -} - - -bool XmlExchange::isBound(Queue::shared_ptr queue, const std::string* const bindingKey, const FieldTable* const) -{ - RWlock::ScopedRlock l(lock); - if (bindingKey) { - XmlBindingsMap::iterator i = bindingsMap.find(*bindingKey); - - if (i == bindingsMap.end()) - return false; - if (!queue) - return true; - XmlBinding::vector::ConstPtr p = i->second.snapshot(); - return p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end(); - } else if (!queue) { - //if no queue or routing key is specified, just report whether any bindings exist - return bindingsMap.size() > 0; - } else { - for (XmlBindingsMap::iterator i = bindingsMap.begin(); i != bindingsMap.end(); i++) { - XmlBinding::vector::ConstPtr p = i->second.snapshot(); - if (p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end()) return true; - } - return false; - } - -} - -XmlExchange::~XmlExchange() -{ - if (mgmtExchange != 0) - mgmtExchange->debugStats("destroying"); - bindingsMap.clear(); -} - -void XmlExchange::propagateFedOp(const std::string& bindingKey, const std::string& fedTags, const std::string& fedOp, const std::string& fedOrigin, const qpid::framing::FieldTable* args) -{ - FieldTable nonFedArgs; - - if (args) { - for (qpid::framing::FieldTable::ValueMap::const_iterator i=args->begin(); i != args->end(); ++i) { - const std::string& name(i->first); - if (name != qpidFedOp && - name != qpidFedTags && - name != qpidFedOrigin) { - nonFedArgs.insert((*i)); - } - } - } - - FieldTable* propArgs = (nonFedArgs.count() > 0 ? &nonFedArgs : 0); - Exchange::propagateFedOp(bindingKey, fedTags, fedOp, fedOrigin, propArgs); -} - -bool XmlExchange::fedUnbind(const std::string& fedOrigin, const std::string& fedTags, Queue::shared_ptr queue, const std::string& bindingKey, const FieldTable* args) -{ - RWlock::ScopedWlock l(lock); - - if (unbindLH(queue, bindingKey, args)) { - propagateFedOp(bindingKey, fedTags, fedOpUnbind, fedOrigin); - return true; - } - return false; -} - -void XmlExchange::fedReorigin() -{ - std::vector keys2prop; - { - RWlock::ScopedRlock l(lock); - for (XmlBindingsMap::iterator i = bindingsMap.begin(); i != bindingsMap.end(); ++i) { - XmlBinding::vector::ConstPtr p = i->second.snapshot(); - if (std::find_if(p->begin(), p->end(), MatchOrigin(std::string())) != p->end()) { - keys2prop.push_back(i->first); - } - } - } /* lock dropped */ - for (std::vector::const_iterator key = keys2prop.begin(); - key != keys2prop.end(); key++) { - propagateFedOp( *key, std::string(), fedOpBind, std::string()); - } -} - - -XmlExchange::MatchOrigin::MatchOrigin(const std::string& _origin) : origin(_origin) {} - -bool XmlExchange::MatchOrigin::operator()(XmlBinding::shared_ptr b) -{ - return b->fedOrigin == origin; -} - - -XmlExchange::MatchQueueAndOrigin::MatchQueueAndOrigin(Queue::shared_ptr _queue, const std::string& _origin) : queue(_queue), origin(_origin) {} - -bool XmlExchange::MatchQueueAndOrigin::operator()(XmlBinding::shared_ptr b) -{ - return b->queue == queue and b->fedOrigin == origin; -} - - -const std::string XmlExchange::typeName("xml"); - -bool XmlExchange::hasBindings() -{ - RWlock::ScopedRlock l(lock); - return !bindingsMap.empty(); -} -} -} diff --git a/qpid/cpp/src/qpid/xml/XmlExchange.h b/qpid/cpp/src/qpid/xml/XmlExchange.h deleted file mode 100644 index 4115f3d530..0000000000 --- a/qpid/cpp/src/qpid/xml/XmlExchange.h +++ /dev/null @@ -1,124 +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. - * - */ -#ifndef _XmlExchange_ -#define _XmlExchange_ - -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/sys/Monitor.h" -#include "qpid/broker/Queue.h" - -#include - -#include - -#include -#include -#include - -namespace qpid { -namespace broker { - -class Broker; - -typedef boost::shared_ptr Query; - -struct XmlBinding : public Exchange::Binding { - - static XQilla xqilla; - - typedef boost::shared_ptr shared_ptr; - typedef qpid::sys::CopyOnWriteArray vector; - - Query xquery; - bool parse_message_content; - const std::string fedOrigin; // empty for local bindings - - XmlBinding(const std::string& key, const Queue::shared_ptr queue, const std::string& fedOrigin, Exchange* parent, - const ::qpid::framing::FieldTable& _arguments, const std::string& ); - -}; - -class XmlNullResolver; - -class XmlExchange : public virtual Exchange { - - typedef std::map XmlBindingsMap; - XmlBindingsMap bindingsMap; - - qpid::sys::RWlock lock; - boost::shared_ptr resolver; - - bool matches(Query& query, Deliverable& msg, bool parse_message_content); - - public: - static const std::string typeName; - - XmlExchange(const std::string& name, management::Manageable* parent = 0, Broker* broker = 0); - XmlExchange(const std::string& _name, bool _durable, bool autodelete, - const qpid::framing::FieldTable& _args, management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - virtual bool bind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual void route(Deliverable& msg); - - virtual bool isBound(Queue::shared_ptr queue, const std::string* const routingKey, const qpid::framing::FieldTable* const args); - - virtual void propagateFedOp(const std::string& bindingKey, const std::string& fedTags, const std::string& fedOp, const std::string& fedOrigin, const qpid::framing::FieldTable* args=0); - - virtual bool fedUnbind(const std::string& fedOrigin, const std::string& fedTags, Queue::shared_ptr queue, const std::string& bindingKey, const qpid::framing::FieldTable* args); - - virtual void fedReorigin(); - - virtual bool supportsDynamicBinding() { return true; } - - virtual ~XmlExchange(); - - struct MatchOrigin { - const std::string origin; - MatchOrigin(const std::string& origin); - bool operator()(XmlBinding::shared_ptr b); - }; - - struct MatchQueueAndOrigin { - const Queue::shared_ptr queue; - const std::string origin; - MatchQueueAndOrigin(Queue::shared_ptr queue, const std::string& origin); - bool operator()(XmlBinding::shared_ptr b); - }; - - protected: - bool hasBindings(); - private: - bool unbindLH(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); -}; - - -} -} - - -#endif diff --git a/qpid/cpp/src/qpid/xml/XmlExchangePlugin.cpp b/qpid/cpp/src/qpid/xml/XmlExchangePlugin.cpp deleted file mode 100644 index 02f0110faf..0000000000 --- a/qpid/cpp/src/qpid/xml/XmlExchangePlugin.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * - * 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 -#include "qpid/acl/Acl.h" -#include "qpid/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/log/Statement.h" - -#include -#include - -#include "qpid/xml/XmlExchange.h" - -namespace qpid { -namespace broker { // ACL uses the acl namespace here - should I? - -using namespace std; -class Broker; - -Exchange::shared_ptr create(const std::string& name, bool durable, - bool autodelete, - const framing::FieldTable& args, - management::Manageable* parent, - Broker* broker) -{ - Exchange::shared_ptr e(new XmlExchange(name, durable, autodelete, args, parent, broker)); - return e; -} - - -class XmlExchangePlugin : public Plugin -{ -public: - void earlyInitialize(Plugin::Target& target); - void initialize(Plugin::Target& target); -}; - - -void XmlExchangePlugin::earlyInitialize(Plugin::Target& target) -{ - Broker* broker = dynamic_cast(&target); - if (broker) { - broker->getExchanges().registerType(XmlExchange::typeName, &create); - QPID_LOG(info, "Registered xml exchange"); - } -} - -void XmlExchangePlugin::initialize(Target&) {} - - -static XmlExchangePlugin matchingPlugin; - - -}} // namespace qpid::acl diff --git a/qpid/cpp/src/qpidd.cpp b/qpid/cpp/src/qpidd.cpp deleted file mode 100644 index e17dea3164..0000000000 --- a/qpid/cpp/src/qpidd.cpp +++ /dev/null @@ -1,115 +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 "./qpidd.h" -#include "qpid/Plugin.h" -#include "qpid/Version.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Statement.h" - -#include -#include -using namespace std; - -namespace qpid { -namespace broker { - -auto_ptr options; - -// Broker real entry; various system-invoked entrypoints call here. -int run_broker(int argc, char *argv[], bool hidden) -{ - try - { - BootstrapOptions bootOptions(argv[0]); - string defaultPath (bootOptions.module.loadDir); - - // --version causes print and exit - if (bootOptions.findArg(argc, argv, "version")) { - cout << "qpidd (" << qpid::product << ") version " - << qpid::version << endl; - return 0; - } - - // --help sets a flag so that its presence is known despite - // subsequent parse problems. - bool helpArgSeen = bootOptions.findArg(argc, argv, "help"); - - // Parse only the common, load, and log options to see which - // modules need to be loaded. Once the modules are loaded, - // the command line will be re-parsed with all of the - // module-supplied options. - try { - bootOptions.parse (argc, argv, bootOptions.common.config, true); - if (hidden) - bootOptions.log.sinkOptions->detached(); - qpid::log::Logger::instance().configure(bootOptions.log); - } catch (const std::exception& e) { - if (helpArgSeen) { - // provide help even when parsing fails - bootOptions.usage(); - } - // Couldn't configure logging so write the message direct to stderr. - cerr << endl << "Unexpected error: " << e.what() << endl; - return 1; - } - - for (vector::iterator iter = bootOptions.module.load.begin(); - iter != bootOptions.module.load.end(); - iter++) - qpid::tryShlib (*iter); - - if (!bootOptions.module.noLoad) { - bool isDefault = defaultPath == bootOptions.module.loadDir; - qpid::loadModuleDir (bootOptions.module.loadDir, isDefault); - } - - // Parse options. In the second pass, do not allow unknown options. - // All the modules have been added now, so any unknown options - // should be flagged as errors. - try { - options.reset(new QpiddOptions(argv[0])); - options->parse(argc, argv, options->common.config, false); - } catch (const std::exception& /*e*/) { - if (helpArgSeen) { - // provide help even when parsing fails - options->usage(); - } - throw; - } - - // Options that just print information. - if (helpArgSeen) { - options->usage(); - return 0; - } - - // Everything else is driven by the platform-specific broker - // logic. - QpiddBroker broker; - return broker.execute(options.get()); - } - catch(const exception& e) { - QPID_LOG(critical, "Unexpected error: " << e.what()); - } - return 1; -} -}} diff --git a/qpid/cpp/src/qpidd.h b/qpid/cpp/src/qpidd.h deleted file mode 100644 index 38328139c3..0000000000 --- a/qpid/cpp/src/qpidd.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_H -#define QPID_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/Modules.h" -#include "qpid/Options.h" -#include "qpid/broker/BrokerOptions.h" -#include "qpid/log/Options.h" - -#include - -namespace qpid { -namespace broker { - -// BootstrapOptions is a minimal subset of options used for a pre-parse -// of the command line to discover which plugin modules need to be loaded. -// The pre-parse is necessary because plugin modules may supply their own -// set of options. CommonOptions is needed to properly support loading -// from a configuration file. -struct BootstrapOptions : public qpid::Options { - qpid::CommonOptions common; - qpid::ModuleOptions module; - qpid::log::Options log; - - BootstrapOptions(const char *argv0); - void usage() const; -}; - -// Each platform derives an options struct from QpiddOptionsPrivate, adding -// platform-specific option types. QpiddOptions needs to allocation one of -// these derived structs from its constructor. -struct QpiddOptions; -struct QpiddOptionsPrivate { - QpiddOptions *options; - QpiddOptionsPrivate(QpiddOptions *parent) : options(parent) {} - virtual ~QpiddOptionsPrivate() {} -protected: - QpiddOptionsPrivate() {} -}; - -struct QpiddOptions : public qpid::Options { - qpid::CommonOptions common; - qpid::ModuleOptions module; - qpid::broker::BrokerOptions broker; - qpid::log::Options log; - std::auto_ptr platform; - - QpiddOptions(const char *argv0); - void usage() const; -}; - -class QpiddBroker { -public: - int execute (QpiddOptions *options); -}; - -// Broker real entry; various system-invoked entrypoints call here. -int run_broker(int argc, char *argv[], bool hidden = false); - -}} -#endif /*!QPID_H*/ diff --git a/qpid/cpp/src/rdma.cmake b/qpid/cpp/src/rdma.cmake deleted file mode 100644 index 07fac5cdc8..0000000000 --- a/qpid/cpp/src/rdma.cmake +++ /dev/null @@ -1,117 +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. -# -# -# RDMA (Remote DMA) wrapper CMake fragment, to be included in CMakeLists.txt -# - -# Optional RDMA support. Requires ibverbs and rdma_cm. - -include(CheckIncludeFiles) -include(CheckLibraryExists) - -CHECK_LIBRARY_EXISTS (ibverbs ibv_create_qp "" HAVE_IBVERBS) -CHECK_LIBRARY_EXISTS (rdmacm rdma_create_id "" HAVE_RDMACM) -CHECK_INCLUDE_FILES (infiniband/verbs.h HAVE_IBVERBS_H) -CHECK_INCLUDE_FILES (rdma/rdma_cma.h HAVE_RDMACM_H) - -set (rdma_default ${rdma_force}) -if (HAVE_IBVERBS AND HAVE_IBVERBS_H) - if (HAVE_RDMACM AND HAVE_RDMACM_H) - set (rdma_default ON) - endif (HAVE_RDMACM AND HAVE_RDMACM_H) -endif (HAVE_IBVERBS AND HAVE_IBVERBS_H) - -option(BUILD_RDMA "Build with support for Remote DMA protocols" ${rdma_default}) -if (BUILD_RDMA) - if (NOT HAVE_IBVERBS) - message(FATAL_ERROR "libibverbs not found, required for RDMA support") - endif (NOT HAVE_IBVERBS) - if (NOT HAVE_RDMACM) - message(FATAL_ERROR "librdmacm not found, required for RDMA support") - endif (NOT HAVE_RDMACM) - if (NOT HAVE_IBVERBS_H) - message(FATAL_ERROR "ibverbs headers not found, required for RDMA support") - endif (NOT HAVE_IBVERBS_H) - if (NOT HAVE_RDMACM_H) - message(FATAL_ERROR "rdmacm headers not found, required for RDMA support") - endif (NOT HAVE_RDMACM_H) - - set (rdma_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 - ) - - add_library (rdmawrap SHARED ${rdma_SOURCES}) - target_link_libraries (rdmawrap qpidcommon rdmacm ibverbs) - set_target_properties (rdmawrap PROPERTIES - VERSION ${rdmawrap_version} - SOVERSION ${rdmawrap_version_major}) - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(rdmawrap PROPERTIES - COMPILE_FLAGS -Wno-missing-field-initializers) - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS rdmawrap - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_COMMON}) - - add_library (rdma MODULE qpid/sys/RdmaIOPlugin.cpp) - target_link_libraries (rdma qpidbroker qpidcommon rdmawrap) - set_target_properties (rdma PROPERTIES - PREFIX "") - - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(rdma PROPERTIES - COMPILE_FLAGS -Wno-missing-field-initializers) - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS rdma - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - - add_library (rdmaconnector MODULE qpid/client/RdmaConnector.cpp) - target_link_libraries (rdmaconnector qpidclient qpidcommon rdmawrap) - set_target_properties (rdmaconnector PROPERTIES - PREFIX "") - - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(rdmaconnector PROPERTIES - COMPILE_FLAGS -Wno-missing-field-initializers) - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS rdmaconnector - DESTINATION ${QPIDC_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_CLIENT}) - - # RDMA test/sample programs - add_executable (RdmaServer qpid/sys/rdma/RdmaServer.cpp) - target_link_libraries (RdmaServer rdmawrap qpidcommon) - add_executable (RdmaClient qpid/sys/rdma/RdmaClient.cpp) - target_link_libraries (RdmaClient rdmawrap qpidcommon) - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(RdmaClient PROPERTIES - COMPILE_FLAGS -Wno-missing-field-initializers) - endif (CMAKE_COMPILER_IS_GNUCXX) - -endif (BUILD_RDMA) diff --git a/qpid/cpp/src/tests/.valgrind.supp b/qpid/cpp/src/tests/.valgrind.supp deleted file mode 100644 index d881c73743..0000000000 --- a/qpid/cpp/src/tests/.valgrind.supp +++ /dev/null @@ -1,242 +0,0 @@ -{ - Leak in TCPConnector: https://bugzilla.redhat.com/show_bug.cgi?id=520600 - Memcheck:Leak - fun:_vgrZU_libcZdsoZa_calloc - fun:_dl_allocate_tls - fun:* - fun:* - fun:* - fun:_ZN4qpid6client12TCPConnector7connectERKSsi -} - -{ - Leak in TCPConnector: https://bugzilla.redhat.com/show_bug.cgi?id=520600 - Memcheck:Leak - fun:_vgrZU_libcZdsoZa_calloc - fun:_dl_allocate_tls - fun:* - fun:* - fun:_ZN4qpid6client12TCPConnector7connectERKSsi -} - -{ - Reported on FC5 and RHEL5 when md5 sasl libs are installed - Memcheck:Leak - fun:* - fun:_dl_map_object_from_fd - fun:_dl_map_object - fun:openaux - fun:_dl_catch_error - fun:_dl_map_object_deps - fun:dl_open_worker - fun:_dl_catch_error - fun:_dl_open - fun:dlopen_doit - fun:_dl_catch_error - fun:_dlerror_run - fun:* - fun:_sasl_get_plugin - fun:_sasl_load_plugins - fun:sasl_client_init -} - -{ - Uninitialised value problem in _dl_relocate (F7, F8) - Memcheck:Cond - fun:_dl_relocate_object - fun:*dl_* -} - -{ - False "possibly leaked" in boost program_options - global std::string var. - Memcheck:Leak - fun:_Znwj - fun:_ZNSs4_Rep9_S_createEjjRKSaIcE - obj:/usr/lib/libstdc++.so.6.0.8 - fun:_ZNSsC1EPKcRKSaIcE - obj:/usr/lib/libboost_program_options.so.1.33.1 -} - -{ - INVESTIGATE - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:pthread_create@@GLIBC_2.2.5 - fun:_ZN4qpid6client9Connector4initEv - fun:_ZN4qpid6client14ConnectionImpl4openERKSsiS3_S3_S3_ -} - -{ - INVESTIGATE - Memcheck:Param - write(buf) - obj:/lib64/tls/libc-2.3.4.so - fun:_ZNK4qpid3sys6Socket5writeEPKvm - fun:_ZN4qpid3sys8AsynchIO9writeableERNS0_14DispatchHandleE -} - -{ - "Conditional jump or move depends on uninitialised value(s)" from Xerces parser - Memcheck:Cond - fun:_ZN11xercesc_2_717XMLUTF8Transcoder13transcodeFromEPKhjPtjRjPh - fun:_ZN11xercesc_2_79XMLReader14xcodeMoreCharsEPtPhj - fun:_ZN11xercesc_2_79XMLReader17refreshCharBufferEv -} - -{ - INVESTIGATE - Memcheck:Param - socketcall.sendto(msg) - fun:send - fun:get_mapping - fun:__nscd_get_map_ref - fun:nscd_gethst_r - fun:__nscd_gethostbyname_r - fun:gethostbyname_r@@GLIBC_2.2.5 - fun:gethostbyname - fun:_ZNK4qpid3sys6Socket7connectERKSsi -} - -{ - INVESTIGATE - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:pthread_create@@GLIBC_2.2.5 - fun:_ZN4qpid6broker5Timer5startEv - fun:_ZN4qpid6broker5TimerC1Ev - fun:_ZN4qpid6broker10DtxManagerC1Ev - fun:_ZN4qpid6broker6BrokerC1ERKNS1_7OptionsE - fun:_ZN4qpid6broker6Broker6createERKNS1_7OptionsE - fun:_ZN20ClientSessionFixtureC1Ev - fun:_Z14testQueueQueryv - fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor8functionEv - obj:/usr/lib64/libboost_unit_test_framework.so.1.32.0 - fun:_ZN5boost17execution_monitor7executeEbi - fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor21execute_and_translateEPNS0_9test_caseEMS3_FvvEi - fun:_ZN5boost9unit_test9test_case3runEv - fun:_ZN5boost9unit_test10test_suite6do_runEv - fun:_ZN5boost9unit_test9test_case3runEv - fun:main -} - -{ - INVESTIGATE - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:pthread_create@@GLIBC_2.2.5 - fun:_ZN4qpid6client9Connector4initEv -} - -{ - MICK -- FIX - Memcheck:Leak - fun:_Znam - fun:_ZN4qpid7Options5parseEiPPcRKSsb -} - -{ - MICK -- FIX - Memcheck:Leak - fun:malloc - fun:strdup - fun:_ZN4qpid7Options5parseEiPPcRKSsb -} - -{ - Known leak in boost.thread 1.33.1. Wildcards for 64/32 bit diffs. - Memcheck:Leak - fun:* - obj:/usr/*/libboost_thread.so.1.33.1 - fun:_ZN5boost6detail3tss3setEPv -} - -{ - Shows up on RHEL5: believed benign - Memcheck:Cond - fun:__strcpy_chk - fun:_sasl_load_plugins - fun:sasl_client_init -} - -{ - Seems like a use after delete issue in boost unit_test - Memcheck:Addr8 - fun:_ZN5boost9unit_test14framework_implD1Ev - fun:exit - fun:(below main) -} - -{ - Seems like a use after delete issue in boost unit_test - Memcheck:Addr4 - fun:_ZN5boost9unit_test14framework_implD1Ev - fun:exit - fun:(below main) -} - -{ - Leak reported in acl_tests - Memcheck:Cond - fun:_ZN4qpid3acl9AclReader16loadDecisionData* - fun:_ZN4qpid3acl9AclReader4read* - fun:_ZN4qpid3acl3Acl11readAclFile* - ... -} - -{ - Leak reported in acl_tests and queue_redirect_tests - Memcheck:Leak - fun:_Znwm - ... - fun:_ZN4qpid6broker14QueueFlowLimit11createLimit* - ... -} - -{ - Leak reported in python_tests - Memcheck:Leak - fun:_Znwm - ... - fun:_M_get_node - fun:_M_create_node - ... -} - -{ - Leak reported in python_tests - Memcheck:Leak - fun:_Znwm - fun:_ZN4qpid6broker5Queue18scheduleAutoDeleteEb - ... -} - -{ - Leak reported in linearstore_python_tests - Memcheck:Leak - fun:_Znwm - fun:_ZN4qpid11linearstore7journal20EmptyFilePoolManager15insertPartition* - fun:_ZN4qpid11linearstore7journal20EmptyFilePoolManager17findEfpPartitionsEv - ... -} - -{ - Leak reported in acl_tests and python_tests - Memcheck:Leak - fun:_Znwm - ... - fun:_ZN4qpid6broker12QueueFactory6create* - fun:_ZN4qpid6broker13QueueRegistry7declare* - fun:_ZN4qpid6broker6Broker11createQueue* - ... -} - -{ - Leak reported in acl_tests - Memcheck:Leak - fun:_Znwm - fun:_ZNSs4_Rep9_S_createEmmRKSaIcE - ... -} diff --git a/qpid/cpp/src/tests/AccumulatedAckTest.cpp b/qpid/cpp/src/tests/AccumulatedAckTest.cpp deleted file mode 100644 index c736a519d2..0000000000 --- a/qpid/cpp/src/tests/AccumulatedAckTest.cpp +++ /dev/null @@ -1,237 +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/framing/AccumulatedAck.h" -#include "unit_test.h" -#include -#include - -using std::list; -using namespace qpid::framing; - - -namespace qpid { -namespace tests { - -bool covers(const AccumulatedAck& ack, int i) -{ - return ack.covers(SequenceNumber(i)); -} - -void update(AccumulatedAck& ack, int start, int end) -{ - ack.update(SequenceNumber(start), SequenceNumber(end)); -} - -QPID_AUTO_TEST_SUITE(AccumulatedAckTestSuite) - -QPID_AUTO_TEST_CASE(testGeneral) -{ - AccumulatedAck ack(0); - ack.clear(); - update(ack, 3,3); - update(ack, 7,7); - update(ack, 9,9); - update(ack, 1,2); - update(ack, 4,5); - update(ack, 6,6); - - for(int i = 1; i <= 7; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(covers(ack, 9)); - - BOOST_CHECK(!covers(ack, 8)); - BOOST_CHECK(!covers(ack, 10)); - - ack.consolidate(); - - for(int i = 1; i <= 7; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(covers(ack, 9)); - - BOOST_CHECK(!covers(ack, 8)); - BOOST_CHECK(!covers(ack, 10)); -} - -QPID_AUTO_TEST_CASE(testCovers) -{ - AccumulatedAck ack(5); - update(ack, 7, 7); - update(ack, 9, 9); - - BOOST_CHECK(covers(ack, 1)); - BOOST_CHECK(covers(ack, 2)); - BOOST_CHECK(covers(ack, 3)); - BOOST_CHECK(covers(ack, 4)); - BOOST_CHECK(covers(ack, 5)); - BOOST_CHECK(covers(ack, 7)); - BOOST_CHECK(covers(ack, 9)); - - BOOST_CHECK(!covers(ack, 6)); - BOOST_CHECK(!covers(ack, 8)); - BOOST_CHECK(!covers(ack, 10)); -} - -QPID_AUTO_TEST_CASE(testUpdateFromCompletionData) -{ - AccumulatedAck ack(0); - SequenceNumber mark(2); - SequenceNumberSet ranges; - ranges.addRange(SequenceNumber(5), SequenceNumber(8)); - ranges.addRange(SequenceNumber(10), SequenceNumber(15)); - ranges.addRange(SequenceNumber(9), SequenceNumber(9)); - ranges.addRange(SequenceNumber(3), SequenceNumber(4)); - - ack.update(mark, ranges); - - for(int i = 0; i <= 15; i++) { - BOOST_CHECK(covers(ack, i)); - } - BOOST_CHECK(!covers(ack, 16)); - BOOST_CHECK_EQUAL((uint32_t) 15, ack.mark.getValue()); -} - -QPID_AUTO_TEST_CASE(testCase1) -{ - AccumulatedAck ack(3); - update(ack, 1,2); - for(int i = 1; i <= 3; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(!covers(ack, 4)); -} - -QPID_AUTO_TEST_CASE(testCase2) -{ - AccumulatedAck ack(3); - update(ack, 3,6); - for(int i = 1; i <= 6; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(!covers(ack, 7)); -} - -QPID_AUTO_TEST_CASE(testCase3) -{ - AccumulatedAck ack(3); - update(ack, 4,6); - for(int i = 1; i <= 6; i++) { - BOOST_CHECK(covers(ack, i)); - } - BOOST_CHECK(!covers(ack, 7)); -} - -QPID_AUTO_TEST_CASE(testCase4) -{ - AccumulatedAck ack(3); - update(ack, 5,6); - for(int i = 1; i <= 6; i++) { - if (i == 4) BOOST_CHECK(!covers(ack, i)); - else BOOST_CHECK(covers(ack, i)); - } - BOOST_CHECK(!covers(ack, 7)); -} - -QPID_AUTO_TEST_CASE(testConsolidation1) -{ - AccumulatedAck ack(3); - update(ack, 7,7); - BOOST_CHECK_EQUAL((uint32_t) 3, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 8,9); - BOOST_CHECK_EQUAL((uint32_t) 3, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 1,2); - BOOST_CHECK_EQUAL((uint32_t) 3, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 4,5); - BOOST_CHECK_EQUAL((uint32_t) 5, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 6,6); - BOOST_CHECK_EQUAL((uint32_t) 9, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 0, ack.ranges.size()); - - for(int i = 1; i <= 9; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(!covers(ack, 10)); -} - -QPID_AUTO_TEST_CASE(testConsolidation2) -{ - AccumulatedAck ack(0); - update(ack, 10,12); - BOOST_CHECK_EQUAL((uint32_t) 0, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 7,9); - BOOST_CHECK_EQUAL((uint32_t) 0, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - BOOST_CHECK_EQUAL((uint32_t) 7, ack.ranges.front().start.getValue()); - BOOST_CHECK_EQUAL((uint32_t) 12, ack.ranges.front().end.getValue()); - - update(ack, 5,7); - BOOST_CHECK_EQUAL((uint32_t) 0, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - BOOST_CHECK_EQUAL((uint32_t) 5, ack.ranges.front().start.getValue()); - BOOST_CHECK_EQUAL((uint32_t) 12, ack.ranges.front().end.getValue()); - - update(ack, 3,4); - BOOST_CHECK_EQUAL((uint32_t) 0, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - BOOST_CHECK_EQUAL((uint32_t) 3, ack.ranges.front().start.getValue()); - BOOST_CHECK_EQUAL((uint32_t) 12, ack.ranges.front().end.getValue()); - - update(ack, 1,2); - BOOST_CHECK_EQUAL((uint32_t) 12, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 0, ack.ranges.size()); - - for(int i = 1; i <= 12; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(!covers(ack, 13)); -} - -QPID_AUTO_TEST_CASE(testConsolidation3) -{ - AccumulatedAck ack(0); - update(ack, 10,12); - update(ack, 6,7); - update(ack, 3,4); - update(ack, 1,15); - BOOST_CHECK_EQUAL((uint32_t) 15, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 0, ack.ranges.size()); -} - -QPID_AUTO_TEST_CASE(testConsolidation4) -{ - AccumulatedAck ack(0); - ack.update(SequenceNumber(0), SequenceNumber(2)); - ack.update(SequenceNumber(5), SequenceNumber(8)); - ack.update(SequenceNumber(10), SequenceNumber(15)); - ack.update(SequenceNumber(9), SequenceNumber(9)); - ack.update(SequenceNumber(3), SequenceNumber(4)); - - for(int i = 0; i <= 15; i++) { - BOOST_CHECK(covers(ack, i)); - } - BOOST_CHECK(!covers(ack, 16)); - BOOST_CHECK_EQUAL((uint32_t) 15, ack.mark.getValue()); -} - -QPID_AUTO_TEST_SUITE_END() - - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Acl.cpp b/qpid/cpp/src/tests/Acl.cpp deleted file mode 100644 index 9c3de0de62..0000000000 --- a/qpid/cpp/src/tests/Acl.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * Copyright (c) 2014 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 "unit_test.h" -#include "test_tools.h" -#include "qpid/acl/AclLexer.h" -#include - -using namespace std; -using namespace qpid; -using namespace qpid::acl; -using namespace boost::assign; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(AclTestSuite) - -#define OBJ_ENUMS(e, s) \ - BOOST_CHECK_EQUAL(AclHelper::getObjectTypeStr((e)),(s)); \ - BOOST_CHECK_EQUAL(AclHelper::getObjectType((s)),(e)) - -QPID_AUTO_TEST_CASE(TestLexerObjectEnums) { - BOOST_CHECK_EQUAL(OBJECTSIZE, 7); - OBJ_ENUMS(OBJ_QUEUE, "queue"); - OBJ_ENUMS(OBJ_EXCHANGE, "exchange"); - OBJ_ENUMS(OBJ_BROKER, "broker"); - OBJ_ENUMS(OBJ_LINK, "link"); - OBJ_ENUMS(OBJ_METHOD, "method"); - OBJ_ENUMS(OBJ_QUERY, "query"); - OBJ_ENUMS(OBJ_CONNECTION, "connection"); - int maxLen = 0; - for (int i=0; i maxLen) - maxLen = thisLen; - } - BOOST_CHECK_EQUAL(maxLen, acl::OBJECTTYPE_STR_WIDTH); -} - -#define ACT_ENUMS(e, s) \ - BOOST_CHECK_EQUAL(AclHelper::getActionStr((e)),(s)); \ - BOOST_CHECK_EQUAL(AclHelper::getAction((s)),(e)) - -QPID_AUTO_TEST_CASE(TestLexerActionEnums) { - BOOST_CHECK_EQUAL(ACTIONSIZE, 12); - ACT_ENUMS(ACT_CONSUME, "consume"); - ACT_ENUMS(ACT_PUBLISH, "publish"); - ACT_ENUMS(ACT_CREATE, "create"); - ACT_ENUMS(ACT_ACCESS, "access"); - ACT_ENUMS(ACT_BIND, "bind"); - ACT_ENUMS(ACT_UNBIND, "unbind"); - ACT_ENUMS(ACT_DELETE, "delete"); - ACT_ENUMS(ACT_PURGE, "purge"); - ACT_ENUMS(ACT_UPDATE, "update"); - ACT_ENUMS(ACT_MOVE, "move"); - ACT_ENUMS(ACT_REDIRECT, "redirect"); - ACT_ENUMS(ACT_REROUTE, "reroute"); - int maxLen = 0; - for (int i=0; i maxLen) - maxLen = thisLen; - } - BOOST_CHECK_EQUAL(maxLen, acl::ACTION_STR_WIDTH); -} - -#define PROP_ENUMS(e, s) \ - BOOST_CHECK_EQUAL(AclHelper::getPropertyStr((e)),(s)); \ - BOOST_CHECK_EQUAL(AclHelper::getProperty((s)),(e)) - -QPID_AUTO_TEST_CASE(TestLexerPropertyEnums) { - BOOST_CHECK_EQUAL(PROPERTYSIZE, 21); - PROP_ENUMS(PROP_NAME, "name"); - PROP_ENUMS(PROP_DURABLE, "durable"); - PROP_ENUMS(PROP_OWNER, "owner"); - PROP_ENUMS(PROP_ROUTINGKEY, "routingkey"); - PROP_ENUMS(PROP_AUTODELETE, "autodelete"); - PROP_ENUMS(PROP_EXCLUSIVE, "exclusive"); - PROP_ENUMS(PROP_TYPE, "type"); - PROP_ENUMS(PROP_ALTERNATE, "alternate"); - PROP_ENUMS(PROP_QUEUENAME, "queuename"); - PROP_ENUMS(PROP_EXCHANGENAME, "exchangename"); - PROP_ENUMS(PROP_SCHEMAPACKAGE, "schemapackage"); - PROP_ENUMS(PROP_SCHEMACLASS, "schemaclass"); - PROP_ENUMS(PROP_POLICYTYPE, "policytype"); - PROP_ENUMS(PROP_PAGING, "paging"); - PROP_ENUMS(PROP_HOST, "host"); - PROP_ENUMS(PROP_MAXPAGES, "maxpages"); - PROP_ENUMS(PROP_MAXPAGEFACTOR, "maxpagefactor"); - PROP_ENUMS(PROP_MAXQUEUESIZE, "maxqueuesize"); - PROP_ENUMS(PROP_MAXQUEUECOUNT, "maxqueuecount"); - PROP_ENUMS(PROP_MAXFILESIZE, "maxfilesize"); - PROP_ENUMS(PROP_MAXFILECOUNT, "maxfilecount"); - -} - -#define SPECPROP_ENUMS(e, s) \ - BOOST_CHECK_EQUAL(AclHelper::getPropertyStr((e)),(s)); \ - BOOST_CHECK_EQUAL(AclHelper::getSpecProperty((s)),(e)) - -QPID_AUTO_TEST_CASE(TestLexerSpecPropertyEnums) { - BOOST_CHECK_EQUAL(SPECPROPSIZE, 27); - SPECPROP_ENUMS(SPECPROP_NAME, "name"); - SPECPROP_ENUMS(SPECPROP_DURABLE, "durable"); - SPECPROP_ENUMS(SPECPROP_OWNER, "owner"); - SPECPROP_ENUMS(SPECPROP_ROUTINGKEY, "routingkey"); - SPECPROP_ENUMS(SPECPROP_AUTODELETE, "autodelete"); - SPECPROP_ENUMS(SPECPROP_EXCLUSIVE, "exclusive"); - SPECPROP_ENUMS(SPECPROP_TYPE, "type"); - SPECPROP_ENUMS(SPECPROP_ALTERNATE, "alternate"); - SPECPROP_ENUMS(SPECPROP_QUEUENAME, "queuename"); - SPECPROP_ENUMS(SPECPROP_EXCHANGENAME, "exchangename"); - SPECPROP_ENUMS(SPECPROP_SCHEMAPACKAGE, "schemapackage"); - SPECPROP_ENUMS(SPECPROP_SCHEMACLASS, "schemaclass"); - SPECPROP_ENUMS(SPECPROP_POLICYTYPE, "policytype"); - SPECPROP_ENUMS(SPECPROP_PAGING, "paging"); - SPECPROP_ENUMS(SPECPROP_HOST, "host"); - SPECPROP_ENUMS(SPECPROP_MAXQUEUESIZELOWERLIMIT, "queuemaxsizelowerlimit"); - SPECPROP_ENUMS(SPECPROP_MAXQUEUESIZEUPPERLIMIT, "queuemaxsizeupperlimit"); - SPECPROP_ENUMS(SPECPROP_MAXQUEUECOUNTLOWERLIMIT, "queuemaxcountlowerlimit"); - SPECPROP_ENUMS(SPECPROP_MAXQUEUECOUNTUPPERLIMIT, "queuemaxcountupperlimit"); - SPECPROP_ENUMS(SPECPROP_MAXFILESIZELOWERLIMIT, "filemaxsizelowerlimit"); - SPECPROP_ENUMS(SPECPROP_MAXFILESIZEUPPERLIMIT, "filemaxsizeupperlimit"); - SPECPROP_ENUMS(SPECPROP_MAXFILECOUNTLOWERLIMIT, "filemaxcountlowerlimit"); - SPECPROP_ENUMS(SPECPROP_MAXFILECOUNTUPPERLIMIT, "filemaxcountupperlimit"); - SPECPROP_ENUMS(SPECPROP_MAXPAGESLOWERLIMIT, "pageslowerlimit"); - SPECPROP_ENUMS(SPECPROP_MAXPAGESUPPERLIMIT, "pagesupperlimit"); - SPECPROP_ENUMS(SPECPROP_MAXPAGEFACTORLOWERLIMIT, "pagefactorlowerlimit"); - SPECPROP_ENUMS(SPECPROP_MAXPAGEFACTORUPPERLIMIT, "pagefactorupperlimit"); - - BOOST_CHECK_EQUAL(AclHelper::getSpecProperty("maxqueuesize"), SPECPROP_MAXQUEUESIZEUPPERLIMIT); - BOOST_CHECK_EQUAL(AclHelper::getSpecProperty("maxqueuecount"), SPECPROP_MAXQUEUECOUNTUPPERLIMIT); -} - -#define RESULT_ENUMS(e, s) \ - BOOST_CHECK_EQUAL(AclHelper::getAclResultStr((e)),(s)); \ - BOOST_CHECK_EQUAL(AclHelper::getAclResult((s)),(e)) - -QPID_AUTO_TEST_CASE(TestLexerResultEnums) { - BOOST_CHECK_EQUAL(RESULTSIZE, 4); - RESULT_ENUMS(ALLOW, "allow"); - RESULT_ENUMS(ALLOWLOG, "allow-log"); - RESULT_ENUMS(DENY, "deny"); - RESULT_ENUMS(DENYLOG, "deny-log"); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/AclHost.cpp b/qpid/cpp/src/tests/AclHost.cpp deleted file mode 100644 index 7d60c5a63d..0000000000 --- a/qpid/cpp/src/tests/AclHost.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * Copyright (c) 2014 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 "unit_test.h" -#include "test_tools.h" -#include "qpid/AclHost.h" -#include "qpid/sys/SocketAddress.h" -#include - -using namespace std; -using namespace qpid; -using namespace boost::assign; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(AclHostTestSuite) - -#define ACLURL_CHECK_INVALID(STR) BOOST_CHECK_THROW(AclHost(STR), AclHost::Invalid) - -#define SENSE_IP_VERSIONS() \ - bool haveIPv4(true); \ - try { \ - sys::SocketAddress sa("1.1.1.1", ""); \ - sa.firstAddress(); \ -} catch (qpid::Exception) { \ - haveIPv4 = false; \ -} \ - bool haveIPv6(true); \ - try { \ - sys::SocketAddress sa("::1", ""); \ - sa.firstAddress(); \ -} catch (qpid::Exception) { \ - haveIPv6 = false; \ -} \ -(void) haveIPv4; \ -(void) haveIPv6; - -QPID_AUTO_TEST_CASE(TestParseTcpIPv4) { - SENSE_IP_VERSIONS(); - if (haveIPv4) { - BOOST_CHECK_EQUAL(AclHost("1.1.1.1").str(), "(1.1.1.1,1.1.1.1)"); - BOOST_CHECK_EQUAL(AclHost("1.1.1.1,2.2.2.2").str(), "(1.1.1.1,2.2.2.2)"); - } -} - -QPID_AUTO_TEST_CASE(TestParseTcpIPv6) { - SENSE_IP_VERSIONS(); - if (haveIPv6) { - BOOST_CHECK_EQUAL(AclHost("[::1]").str(), "([::1],[::1])"); - BOOST_CHECK_EQUAL(AclHost("[::1],::5").str(), "([::1],[::5])"); - } -} - -QPID_AUTO_TEST_CASE(TestParseAll) { - SENSE_IP_VERSIONS(); - if (haveIPv4 || haveIPv6) { - BOOST_CHECK_EQUAL(AclHost("").str(), "(all)"); - } -} - -QPID_AUTO_TEST_CASE(TestInvalidMixedIpFamilies) { - SENSE_IP_VERSIONS(); - if (haveIPv4 && haveIPv6) { - ACLURL_CHECK_INVALID("1.1.1.1,[::1]"); - ACLURL_CHECK_INVALID("[::1],1.1.1.1"); - } -} - -QPID_AUTO_TEST_CASE(TestMalformedIPv4) { - SENSE_IP_VERSIONS(); - if (haveIPv4) { - ACLURL_CHECK_INVALID("1.1.1.1.1"); - ACLURL_CHECK_INVALID("1.1.1.777"); - ACLURL_CHECK_INVALID("1.1.1.1abcd"); - ACLURL_CHECK_INVALID("1.1.1.*"); - } -} - -QPID_AUTO_TEST_CASE(TestRangeWithInvertedSizeOrder) { - SENSE_IP_VERSIONS(); - if (haveIPv4) { - ACLURL_CHECK_INVALID("1.1.1.100,1.1.1.1"); - } - if (haveIPv6) { - ACLURL_CHECK_INVALID("[FF::1],[::1]"); - } -} - -QPID_AUTO_TEST_CASE(TestSingleHostResolvesMultipleAddresses) { - SENSE_IP_VERSIONS(); - AclHost XX("localhost"); -} - -QPID_AUTO_TEST_CASE(TestMatchSingleAddresses) { - SENSE_IP_VERSIONS(); - if (haveIPv4) { - AclHost host1("1.1.1.1"); - BOOST_CHECK(host1.match("1.1.1.1") == true); - BOOST_CHECK(host1.match("1.2.1.1") == false); - } - if (haveIPv6) { - AclHost host2("FF::1"); - BOOST_CHECK(host2.match("00FF:0000::1") == true); - } -} - -QPID_AUTO_TEST_CASE(TestMatchIPv4Range) { - SENSE_IP_VERSIONS(); - if (haveIPv4) { - AclHost host1("192.168.0.0,192.168.255.255"); - BOOST_CHECK(host1.match("128.1.1.1") == false); - BOOST_CHECK(host1.match("192.167.255.255") == false); - BOOST_CHECK(host1.match("192.168.0.0") == true); - BOOST_CHECK(host1.match("192.168.0.1") == true); - BOOST_CHECK(host1.match("192.168.1.0") == true); - BOOST_CHECK(host1.match("192.168.255.254") == true); - BOOST_CHECK(host1.match("192.168.255.255") == true); - BOOST_CHECK(host1.match("192.169.0.0") == false); - if (haveIPv6) { - BOOST_CHECK(host1.match("::1") == false); - } - } -} - -QPID_AUTO_TEST_CASE(TestMatchIPv6Range) { - SENSE_IP_VERSIONS(); - if (haveIPv6) { - AclHost host1("::10,::1:0"); - BOOST_CHECK(host1.match("::1") == false); - BOOST_CHECK(host1.match("::f") == false); - BOOST_CHECK(host1.match("::10") == true); - BOOST_CHECK(host1.match("::11") == true); - BOOST_CHECK(host1.match("::ffff") == true); - BOOST_CHECK(host1.match("::1:0") == true); - BOOST_CHECK(host1.match("::1:1") == false); - if (haveIPv4) { - BOOST_CHECK(host1.match("192.169.0.0") == false); - } - AclHost host2("[fc00::],[fc00::ff]"); - BOOST_CHECK(host2.match("fc00::") == true); - BOOST_CHECK(host2.match("fc00::1") == true); - BOOST_CHECK(host2.match("fc00::ff") == true); - BOOST_CHECK(host2.match("fc00::100") == false); - - } -} -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Address.cpp b/qpid/cpp/src/tests/Address.cpp deleted file mode 100644 index 0fd3585958..0000000000 --- a/qpid/cpp/src/tests/Address.cpp +++ /dev/null @@ -1,135 +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 -#include "qpid/messaging/Address.h" -#include "qpid/types/Variant.h" - -#include "unit_test.h" - -using namespace qpid::messaging; -using namespace qpid::types; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(AddressSuite) - -QPID_AUTO_TEST_CASE(testParseNameOnly) -{ - Address address("my-topic"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); -} - -QPID_AUTO_TEST_CASE(testParseSubject) -{ - Address address("my-topic/my-subject"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - BOOST_CHECK_EQUAL(std::string("my-subject"), address.getSubject()); -} - -QPID_AUTO_TEST_CASE(testParseOptions) -{ - Address address("my-topic; {a:bc, x:101, y:'a string'}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - - BOOST_CHECK_EQUAL(std::string("bc"), address.getOptions()["a"]); - BOOST_CHECK_EQUAL(101, static_cast(address.getOptions()["x"])); - BOOST_CHECK_EQUAL(std::string("a string"), address.getOptions()["y"]); - - // Test asString() and asInt64() once here - - BOOST_CHECK_EQUAL(std::string("bc"), address.getOptions()["a"].asString()); - BOOST_CHECK_EQUAL(static_cast(101), address.getOptions()["x"].asInt64()); - BOOST_CHECK_EQUAL(std::string("a string"), address.getOptions()["y"].asString()); -} - -QPID_AUTO_TEST_CASE(testParseSubjectAndOptions) -{ - Address address("my-topic/my-subject; {a:bc, x:101, y:'a string'}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - BOOST_CHECK_EQUAL(std::string("my-subject"), address.getSubject()); - - BOOST_CHECK_EQUAL(std::string("bc"), address.getOptions()["a"]); - BOOST_CHECK_EQUAL(101, static_cast(address.getOptions()["x"])); - BOOST_CHECK_EQUAL(std::string("a string"), address.getOptions()["y"]); -} - -QPID_AUTO_TEST_CASE(testParseNestedOptions) -{ - Address address("my-topic; {a:{p:202, q:'another string'}, x:101, y:'a string'}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - BOOST_CHECK_EQUAL(202, static_cast(address.getOptions()["a"].asMap()["p"])); - BOOST_CHECK_EQUAL(std::string("another string"), address.getOptions()["a"].asMap()["q"]); - BOOST_CHECK_EQUAL(std::string("a string"), address.getOptions()["y"]); -} - -QPID_AUTO_TEST_CASE(testParseOptionsWithList) -{ - Address address("my-topic; {a:[202, 'another string'], x:101}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - Variant::List& list = address.getOptions()["a"].asList(); - Variant::List::const_iterator i = list.begin(); - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL((uint16_t) 202, i->asInt64()); - BOOST_CHECK(++i != list.end()); - BOOST_CHECK_EQUAL(std::string("another string"), i->asString()); - BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64()); -} - -QPID_AUTO_TEST_CASE(testParseOptionsWithEmptyList) -{ - Address address("my-topic; {a:[], x:101}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - Variant::List& list = address.getOptions()["a"].asList(); - BOOST_CHECK_EQUAL(list.size(), (size_t) 0); - BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64()); -} - -QPID_AUTO_TEST_CASE(testParseOptionsWithEmptyMap) -{ - Address address("my-topic; {a:{}, x:101}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - Variant::Map& map = address.getOptions()["a"].asMap(); - BOOST_CHECK_EQUAL(map.size(), (size_t) 0); - BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64()); -} - -QPID_AUTO_TEST_CASE(testParseQuotedNameAndSubject) -{ - Address address("'my topic with / in it'/'my subject with ; in it'"); - BOOST_CHECK_EQUAL(std::string("my topic with / in it"), address.getName()); - BOOST_CHECK_EQUAL(std::string("my subject with ; in it"), address.getSubject()); -} - -QPID_AUTO_TEST_CASE(testParseOptionsWithEmptyStringAsValue) -{ - Address address("my-topic; {a:'', x:101}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - Variant a = address.getOptions()["a"]; - BOOST_CHECK_EQUAL(VAR_STRING, a.getType()); - std::string aVal = a; - BOOST_CHECK(aVal.size() == 0); - BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} diff --git a/qpid/cpp/src/tests/Array.cpp b/qpid/cpp/src/tests/Array.cpp deleted file mode 100644 index 8ce7615162..0000000000 --- a/qpid/cpp/src/tests/Array.cpp +++ /dev/null @@ -1,84 +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 -#include -#include "qpid/framing/Array.h" -#include "qpid/framing/FieldValue.h" - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ArrayTestSuite) - -using namespace qpid::framing; - -void populate(std::vector& data, int count = 10) -{ - for (int i = 0; i < count; i++) { - std::stringstream out; - out << "item-" << i; - data.push_back(out.str()); - } -} - -QPID_AUTO_TEST_CASE(testEncodeDecode) -{ - std::vector data; - populate(data); - - Array a(data); - - char buff[200]; - Buffer wbuffer(buff, 200); - a.encode(wbuffer); - - Array b; - Buffer rbuffer(buff, 200); - b.decode(rbuffer); - BOOST_CHECK_EQUAL(a, b); - - std::vector data2; - std::transform(b.begin(), b.end(), std::back_inserter(data2), Array::get); - //BOOST_CHECK_EQUAL(data, data2); - BOOST_CHECK(data == data2); -} - -QPID_AUTO_TEST_CASE(testArrayAssignment) -{ - std::vector data; - populate(data); - Array b; - { - Array a(data); - b = a; - BOOST_CHECK_EQUAL(a, b); - } - std::vector data2; - std::transform(b.begin(), b.end(), std::back_inserter(data2), Array::get); - //BOOST_CHECK_EQUAL(data, data2); - BOOST_CHECK(data == data2); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/AsyncCompletion.cpp b/qpid/cpp/src/tests/AsyncCompletion.cpp deleted file mode 100644 index dc43f10156..0000000000 --- a/qpid/cpp/src/tests/AsyncCompletion.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * 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 "unit_test.h" -#include "test_tools.h" -#include "BrokerFixture.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/QueueQueryResult.h" -#include "qpid/client/TypedResult.h" - -using namespace std; -using namespace qpid; -using namespace client; -using namespace framing; - -namespace qpid { namespace broker { -class TransactionContext; -class PersistableQueue; -}} - -using broker::PersistableMessage; -using broker::NullMessageStore; -using broker::TransactionContext; -using broker::PersistableQueue; -using sys::TIME_SEC; -using boost::intrusive_ptr; - -/** @file - * Unit tests for async completion. - * Using a dummy store, verify that the broker indicates async completion of - * message enqueues at the correct time. - */ - -namespace qpid { -namespace tests { - -class AsyncCompletionMessageStore : public NullMessageStore { - public: - sys::BlockingQueue > enqueued; - - AsyncCompletionMessageStore() : NullMessageStore() {} - ~AsyncCompletionMessageStore(){} - - void enqueue(TransactionContext*, - const boost::intrusive_ptr& msg, - const PersistableQueue& ) - { - enqueued.push(msg); - } -}; - -QPID_AUTO_TEST_SUITE(AsyncCompletionTestSuite) - -/** - * Send a sync after a bunch of incomplete messages, verify the sync completes - * only when all the messages are complete. - */ -QPID_AUTO_TEST_CASE(testWaitTillComplete) { - SessionFixture fix; - AsyncCompletionMessageStore* store = new AsyncCompletionMessageStore; - boost::shared_ptr p; - p.reset(store); - fix.broker->setStore(p); - AsyncSession s = fix.session; - - static const int count = 3; - - s.queueDeclare("q", arg::durable=true); - Completion transfers[count]; - for (int i = 0; i < count; ++i) { - Message msg(boost::lexical_cast(i), "q"); - msg.getDeliveryProperties().setDeliveryMode(PERSISTENT); - transfers[i] = s.messageTransfer(arg::content=msg); - } - - // Get hold of the broker-side messages. - typedef vector > BrokerMessages; - BrokerMessages enqueued; - for (int j = 0; j < count; ++j) - enqueued.push_back(store->enqueued.pop(TIME_SEC)); - - // Send a sync, make sure it does not complete till all messages are complete. - // In reverse order for fun. - Completion sync = s.executionSync(arg::sync=true); - for (int k = count-1; k >= 0; --k) { - BOOST_CHECK(!transfers[k].isComplete()); // Should not be complete yet. - BOOST_CHECK(!sync.isComplete()); // Should not be complete yet. - enqueued[k]->enqueueComplete(); - } - sync.wait(); // Should complete now, all messages are completed. -} - -/** - * Send a sync after all messages are complete, verify it completes immediately. - */ -QPID_AUTO_TEST_CASE(testSyncAfterComplete) { - SessionFixture fix; - AsyncCompletionMessageStore* store = new AsyncCompletionMessageStore; - boost::shared_ptr p; - p.reset(store); - fix.broker->setStore(p); - AsyncSession s = fix.session; - - static const int count = 3; - - s.queueDeclare("q", arg::durable=true); - // Transfer and complete all the messages - for (int i = 0; i < count; ++i) { - Message msg(boost::lexical_cast(i), "q"); - msg.getDeliveryProperties().setDeliveryMode(PERSISTENT); - Completion transfer = s.messageTransfer(arg::content=msg, arg::sync=true); - intrusive_ptr enqueued = store->enqueued.pop(TIME_SEC); - enqueued->enqueueComplete(); - transfer.wait(); - } - // Send a sync, make sure it completes immediately - Completion sync = s.executionSync(arg::sync=true); - sync.wait(); // Should complete now, all messages are completed. -} - -QPID_AUTO_TEST_CASE(testGetResult) { - SessionFixture fix; - AsyncSession s = fix.session; - - s.queueDeclare("q", arg::durable=true); - TypedResult tr = s.queueQuery("q"); - QueueQueryResult qq = tr.get(); - BOOST_CHECK_EQUAL(qq.getQueue(), "q"); - BOOST_CHECK_EQUAL(qq.getMessageCount(), 0U); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/AtomicValue.cpp b/qpid/cpp/src/tests/AtomicValue.cpp deleted file mode 100644 index d855d993a7..0000000000 --- a/qpid/cpp/src/tests/AtomicValue.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * 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 "unit_test.h" -#include "test_tools.h" -#include "qpid/sys/AtomicValue.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(AtomicValueTestSuite) - -QPID_AUTO_TEST_CASE(test) { - qpid::sys::AtomicValue x(0); - BOOST_CHECK_EQUAL(++x, 1); - BOOST_CHECK_EQUAL(--x,0); - BOOST_CHECK_EQUAL(x+=5,5); - BOOST_CHECK_EQUAL(x-=10,-5); - BOOST_CHECK_EQUAL(x.fetchAndAdd(7), -5); - BOOST_CHECK_EQUAL(x.get(),2); - BOOST_CHECK_EQUAL(x.fetchAndSub(3), 2); - BOOST_CHECK_EQUAL(x.get(),-1); - - BOOST_CHECK_EQUAL(x.valueCompareAndSwap(-1,10), -1); - BOOST_CHECK_EQUAL(x.get(), 10); - BOOST_CHECK_EQUAL(x.valueCompareAndSwap(5, 6), 10); - BOOST_CHECK_EQUAL(x.get(), 10); - - BOOST_CHECK(!x.boolCompareAndSwap(5, 6)); - BOOST_CHECK_EQUAL(x.get(), 10); - BOOST_CHECK(x.boolCompareAndSwap(10, 6)); - BOOST_CHECK_EQUAL(x.get(), 6); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Blob.cpp b/qpid/cpp/src/tests/Blob.cpp deleted file mode 100644 index 9878d92fe4..0000000000 --- a/qpid/cpp/src/tests/Blob.cpp +++ /dev/null @@ -1,21 +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. - * - */ - diff --git a/qpid/cpp/src/tests/BrokerFixture.h b/qpid/cpp/src/tests/BrokerFixture.h deleted file mode 100644 index 474b9d747f..0000000000 --- a/qpid/cpp/src/tests/BrokerFixture.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef TESTS_BROKERFIXTURE_H -#define TESTS_BROKERFIXTURE_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/Broker.h" -#include "qpid/broker/BrokerOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/LocalQueue.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/sys/Thread.h" -#include - -namespace qpid { -namespace tests { - -/** - * A fixture with an in-process broker. - */ -struct BrokerFixture : private boost::noncopyable { - typedef qpid::broker::Broker Broker; - typedef boost::intrusive_ptr BrokerPtr; - typedef qpid::broker::BrokerOptions BrokerOptions; - typedef std::vector Args; - - BrokerPtr broker; - BrokerOptions opts; - uint16_t port; - qpid::sys::Thread brokerThread; - - BrokerFixture(const Args& args=Args(), const BrokerOptions& opts0=BrokerOptions(), - bool isExternalPort_=false, uint16_t externalPort_=0) : - opts(opts0) - { - init(args, isExternalPort_, externalPort_); - } - - BrokerFixture(const BrokerOptions& opts0, - bool isExternalPort_=false, uint16_t externalPort_=0) : - opts(opts0) - { - init(Args(), 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, 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; - logOpts.selectors.clear(); - logOpts.deselectors.clear(); - 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"); - opts.workerThreads=1; - opts.dataDir=""; - opts.auth=false; - - // Argument parsing - if (args.size() > 0) { - std::vector argv(args.size()); - for (size_t i = 0; iaccept(); - if (isExternalPort) port = externalPort; - else port = broker->getPort(qpid::broker::Broker::TCP_TRANSPORT); - brokerThread = qpid::sys::Thread(*broker); - }; -}; - -/** Connection that opens in its constructor */ -struct LocalConnection : public qpid::client::Connection { - LocalConnection(uint16_t port) { open("localhost", port); } - LocalConnection(const qpid::client::ConnectionSettings& s) { open(s); } - ~LocalConnection() { close(); } -}; - -/** Convenience class to create and open a connection and session - * and some related useful objects. - */ -template -struct ClientT { - ConnectionType connection; - SessionType session; - qpid::client::SubscriptionManager subs; - qpid::client::LocalQueue lq; - std::string name; - - ClientT(uint16_t port, const std::string& name_=std::string(), int timeout=0) - : connection(port), session(connection.newSession(name_,timeout)), subs(session), name(name_) {} - ClientT(const qpid::client::ConnectionSettings& settings, const std::string& name_=std::string(), int timeout=0) - : connection(settings), session(connection.newSession(name_, timeout)), subs(session), name(name_) {} - - ~ClientT() { close(); } - void close() { session.close(); connection.close(); } -}; - -typedef ClientT<> Client; - -/** - * A BrokerFixture and ready-connected BrokerFixture::Client all in one. - */ -template -struct SessionFixtureT : BrokerFixture, ClientT { - - SessionFixtureT(const BrokerOptions& opts=BrokerOptions()) : - BrokerFixture(BrokerFixture::Args(), opts), - ClientT(getPort()) - {} - -}; - -typedef SessionFixtureT SessionFixture; - -}} // namespace qpid::tests - -#endif /*!TESTS_BROKERFIXTURE_H*/ diff --git a/qpid/cpp/src/tests/BrokerMgmtAgent.cpp b/qpid/cpp/src/tests/BrokerMgmtAgent.cpp deleted file mode 100644 index bad7e768a6..0000000000 --- a/qpid/cpp/src/tests/BrokerMgmtAgent.cpp +++ /dev/null @@ -1,387 +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 "unit_test.h" -#include "MessagingFixture.h" -#include "qpid/management/Buffer.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/messaging/Message.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" - -#include "qmf/org/apache/qpid/broker/mgmt/test/TestObject.h" - -#include - - -using qpid::management::Mutex; -using qpid::management::Manageable; -using qpid::management::Buffer; -using namespace qpid::messaging; -using namespace qpid::types; - - - -namespace qpid { -namespace tests { - -namespace _qmf = qmf::org::apache::qpid::broker::mgmt::test; -namespace { - -typedef boost::shared_ptr<_qmf::TestObject> TestObjectPtr; -typedef std::vector TestObjectVector; - -// Instantiates a broker and its internal management agent. Provides -// factories for constructing Receivers for object indication messages. -// -class AgentFixture -{ - MessagingFixture *mFix; - - public: - AgentFixture( unsigned int pubInterval=10, - bool qmfV2=false, - 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); - - _qmf::TestObject::registerSelf(getBrokerAgent()); - }; - ~AgentFixture() - { - delete mFix; - }; - ::qpid::management::ManagementAgent *getBrokerAgent() { return mFix->broker->getManagementAgent(); } - Receiver createV1DataIndRcvr( const std::string package, const std::string klass ) - { - return mFix->session.createReceiver(std::string("kqueue; {create: always, delete: always, " - "node: {type: queue, " - "x-bindings: [{exchange: qpid.management, " - "key: 'console.obj.1.0.") - + package + std::string(".") + klass - + std::string("'}]}}")); - }; - Receiver createV2DataIndRcvr( const std::string package, const std::string klass ) - { - std::string p(package); - std::replace(p.begin(), p.end(), '.', '_'); - std::string k(klass); - std::replace(k.begin(), k.end(), '.', '_'); - - return mFix->session.createReceiver(std::string("kqueue; {create: always, delete: always, " - "node: {type: queue, " - "x-bindings: [{exchange: qmf.default.topic, " - "key: 'agent.ind.data.") - + p + std::string(".") + k - + std::string("'}]}}")); - }; -}; - - -// A "management object" that supports the TestObject -// -class TestManageable : public qpid::management::Manageable -{ - management::ManagementObject::shared_ptr mgmtObj; - const std::string key; - public: - TestManageable(management::ManagementAgent *agent, std::string _key) - : key(_key) - { - _qmf::TestObject::shared_ptr tmp(new _qmf::TestObject(agent, this)); - - // seed it with some default values... - tmp->set_string1(key); - tmp->set_bool1(true); - qpid::types::Variant::Map vMap; - vMap["one"] = qpid::types::Variant(1); - vMap["two"] = qpid::types::Variant("two"); - vMap["three"] = qpid::types::Variant("whatever"); - tmp->set_map1(vMap); - - mgmtObj = tmp; - }; - ~TestManageable() { mgmtObj.reset(); } - management::ManagementObject::shared_ptr GetManagementObject() const { return mgmtObj; }; - static void validateTestObjectProperties(_qmf::TestObject& to) - { - // verify the default values are as expected. We don't check 'string1', - // as it is the object key, and is unique for each object (no default value). - BOOST_CHECK(to.get_bool1() == true); - BOOST_CHECK(to.get_map1().size() == 3); - qpid::types::Variant::Map mappy = to.get_map1(); - BOOST_CHECK(1 == (unsigned int)mappy["one"]); - BOOST_CHECK(mappy["two"].asString() == std::string("two")); - BOOST_CHECK(mappy["three"].asString() == std::string("whatever")); - }; -}; - - -// decode a V1 Content Indication message -// -void decodeV1ObjectUpdates(const Message& inMsg, TestObjectVector& objs, const size_t objLen) -{ - const size_t MAX_BUFFER_SIZE=65536; - char tmp[MAX_BUFFER_SIZE]; - - objs.clear(); - - BOOST_CHECK(inMsg.getContent().size() <= MAX_BUFFER_SIZE); - - ::memcpy(tmp, inMsg.getContent().data(), inMsg.getContent().size()); - Buffer buf(tmp, inMsg.getContent().size()); - - while (buf.available() > 8) { // 8 == qmf v1 header size - BOOST_CHECK_EQUAL(buf.getOctet(), 'A'); - BOOST_CHECK_EQUAL(buf.getOctet(), 'M'); - BOOST_CHECK_EQUAL(buf.getOctet(), '2'); - BOOST_CHECK_EQUAL(buf.getOctet(), 'c'); // opcode == content indication - // @@todo: kag: how do we skip 'i' entries??? - buf.getLong(); // ignore sequence - - std::string str1; // decode content body as string - buf.getRawData(str1, objLen); - - TestObjectPtr fake(new _qmf::TestObject(0,0)); - fake->readProperties( str1 ); - objs.push_back(fake); - } -} - - -// decode a V2 Content Indication message -// -void decodeV2ObjectUpdates(const qpid::messaging::Message& inMsg, TestObjectVector& objs) -{ - objs.clear(); - - BOOST_CHECK_EQUAL(inMsg.getContentType(), std::string("amqp/list")); - - const ::qpid::types::Variant::Map& m = inMsg.getProperties(); - Variant::Map::const_iterator iter = m.find(std::string("qmf.opcode")); - BOOST_CHECK(iter != m.end()); - BOOST_CHECK_EQUAL(iter->second.asString(), std::string("_data_indication")); - - Variant::List vList; - ::qpid::amqp_0_10::ListCodec::decode(inMsg.getContent(), vList); - - for (Variant::List::iterator lIter = vList.begin(); lIter != vList.end(); lIter++) { - TestObjectPtr fake(new _qmf::TestObject(0,0)); - fake->readTimestamps(lIter->asMap()); - fake->mapDecodeValues((lIter->asMap())["_values"].asMap()); - objs.push_back(fake); - } -} -} - -QPID_AUTO_TEST_SUITE(BrokerMgmtAgent) - -// verify that an object that is added to the broker's management database is -// published correctly. Furthermore, verify that it is published once after -// it has been deleted. -// -QPID_AUTO_TEST_CASE(v1ObjPublish) -{ - AgentFixture* fix = new AgentFixture(3); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - // create a manageable test object - TestManageable *tm = new TestManageable(agent, std::string("obj1")); - uint32_t objLen = tm->GetManagementObject()->writePropertiesSize(); - - Receiver r1 = fix->createV1DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - - agent->addObject(tm->GetManagementObject(), 1); - - // wait for the object to be published - Message m1; - BOOST_CHECK(r1.fetch(m1, Duration::SECOND * 6)); - - TestObjectVector objs; - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - BOOST_CHECK(0 == mappy["_delete_ts"].asUint64()); // not deleted - } - - // destroy the object - - tm->GetManagementObject()->resourceDestroy(); - - // wait for the deleted object to be published - - bool isDeleted = false; - while (!isDeleted && r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) - isDeleted = true; - } - } - - BOOST_CHECK(isDeleted); - - r1.close(); - delete fix; - delete tm; -} - -// Repeat the previous test, but with V2-based object support -// -QPID_AUTO_TEST_CASE(v2ObjPublish) -{ - AgentFixture* fix = new AgentFixture(3, true); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - TestManageable *tm = new TestManageable(agent, std::string("obj2")); - - Receiver r1 = fix->createV2DataIndRcvr(tm->GetManagementObject()->getPackageName(), "#"); - - agent->addObject(tm->GetManagementObject(), "testobj-1"); - - // wait for the object to be published - Message m1; - BOOST_CHECK(r1.fetch(m1, Duration::SECOND * 6)); - - TestObjectVector objs; - decodeV2ObjectUpdates(m1, objs); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - BOOST_CHECK(0 == mappy["_delete_ts"].asUint64()); - } - - // destroy the object - - tm->GetManagementObject()->resourceDestroy(); - - // wait for the deleted object to be published - - bool isDeleted = false; - while (!isDeleted && r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV2ObjectUpdates(m1, objs); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) - isDeleted = true; - } - } - - BOOST_CHECK(isDeleted); - - r1.close(); - delete fix; - delete tm; -} - -// See QPID-2997 -QPID_AUTO_TEST_CASE(v2RapidRestoreObj) -{ - AgentFixture* fix = new AgentFixture(3, true); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - // two objects, same ObjID - TestManageable *tm1 = new TestManageable(agent, std::string("obj2")); - TestManageable *tm2 = new TestManageable(agent, std::string("obj2")); - - Receiver r1 = fix->createV2DataIndRcvr(tm1->GetManagementObject()->getPackageName(), "#"); - - // add, then immediately delete and re-add a copy of the object - agent->addObject(tm1->GetManagementObject(), "testobj-1"); - tm1->GetManagementObject()->resourceDestroy(); - agent->addObject(tm2->GetManagementObject(), "testobj-1"); - - // expect: a delete notification, then an update notification - TestObjectVector objs; - bool isDeleted = false; - bool isAdvertised = false; - size_t count = 0; - Message m1; - while (r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV2ObjectUpdates(m1, objs); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - count++; - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) { - isDeleted = true; - BOOST_CHECK(isAdvertised == false); // delete must be first - } else { - isAdvertised = true; - BOOST_CHECK(isDeleted == true); // delete must be first - } - } - } - - BOOST_CHECK(isDeleted); - BOOST_CHECK(isAdvertised); - BOOST_CHECK(count == 2); - - r1.close(); - delete fix; - delete tm1; - delete tm2; -} - -QPID_AUTO_TEST_SUITE_END() -} -} - - diff --git a/qpid/cpp/src/tests/BrokerMgmtAgent.xml b/qpid/cpp/src/tests/BrokerMgmtAgent.xml deleted file mode 100644 index 202b8debf3..0000000000 --- a/qpid/cpp/src/tests/BrokerMgmtAgent.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - A test object defined for the BrokerMgmtAgent unit test. - - - - - - - - - diff --git a/qpid/cpp/src/tests/BrokerOptions.cpp b/qpid/cpp/src/tests/BrokerOptions.cpp deleted file mode 100644 index b36d96916a..0000000000 --- a/qpid/cpp/src/tests/BrokerOptions.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * 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. - * - */ - -/** Unit tests for various broker configuration options **/ - -#include "unit_test.h" -#include "test_tools.h" -#include "MessagingFixture.h" - -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Session.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(BrokerOptionsTestSuite) - -using namespace qpid::broker; -using namespace qpid::messaging; -using namespace qpid::types; -using namespace qpid; - -QPID_AUTO_TEST_CASE(testDisabledTimestamp) -{ - // by default, there should be no timestamp added by the broker - MessagingFixture fix; - - Sender sender = fix.session.createSender("test-q; {create:always, delete:sender}"); - messaging::Message msg("hi"); - sender.send(msg); - - Receiver receiver = fix.session.createReceiver("test-q"); - messaging::Message in; - BOOST_CHECK(receiver.fetch(in, Duration::IMMEDIATE)); - Variant::Map props = in.getProperties(); - BOOST_CHECK(props.find("x-amqp-0-10.timestamp") == props.end()); -} - -QPID_AUTO_TEST_CASE(testEnabledTimestamp) -{ - // when enabled, the 0.10 timestamp is added by the broker - Broker::Options opts; - opts.timestampRcvMsgs = true; - MessagingFixture fix(opts, true); - - Sender sender = fix.session.createSender("test-q; {create:always, delete:sender}"); - messaging::Message msg("one"); - sender.send(msg); - - Receiver receiver = fix.session.createReceiver("test-q"); - messaging::Message in; - BOOST_CHECK(receiver.fetch(in, Duration::IMMEDIATE)); - Variant::Map props = in.getProperties(); - BOOST_CHECK(props.find("x-amqp-0-10.timestamp") != props.end()); - BOOST_CHECK(props["x-amqp-0-10.timestamp"]); -} - -QPID_AUTO_TEST_SUITE_END() - -}} diff --git a/qpid/cpp/src/tests/CMakeLists.txt b/qpid/cpp/src/tests/CMakeLists.txt deleted file mode 100644 index d69d2874c4..0000000000 --- a/qpid/cpp/src/tests/CMakeLists.txt +++ /dev/null @@ -1,323 +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. -# - -# Make sure that everything get built before the tests -# Need to create a var with all the necessary top level targets - -# If we're linking Boost for DLLs, turn that on for the unit test too. -if (QPID_LINK_BOOST_DYNAMIC) - add_definitions(-DBOOST_TEST_DYN_LINK) -endif (QPID_LINK_BOOST_DYNAMIC) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - -# Using the Boost DLLs triggers warning 4275 on Visual Studio (non -# dll-interface class used as base for dll-interface class). This is -# ok, so suppress the warning. -# -# Also, boost lengthy names trigger warning 4503, decorated name -# length exceeded and using getenv() triggers insecure CRT warnings -# which we can silence in the test environment. -if (MSVC) - add_definitions(/wd4275 /wd4503 /D_CRT_SECURE_NO_WARNINGS) -endif (MSVC) - -# If we're using GCC allow variadic macros (even though they're c99 not c++01) -if (CMAKE_COMPILER_IS_GNUCXX) - add_definitions(-Wno-variadic-macros) -endif (CMAKE_COMPILER_IS_GNUCXX) - -# Windows uses some process-startup calls to ensure that errors, etc. don't -# result in error boxes being thrown up. Since it's expected that most test -# runs will be in scripts, the default is to force these outputs to stderr -# instead of windows. If you want to remove this code, build without the -# QPID_WINDOWS_DEFAULT_TEST_OUTPUTS ON. -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - option(QPID_WINDOWS_DEFAULT_TEST_OUTPUTS "Use default error-handling on Windows tests" OFF) - if (NOT QPID_WINDOWS_DEFAULT_TEST_OUTPUTS) - set(platform_test_additions windows/DisableWin32ErrorWindows.cpp) - endif (NOT QPID_WINDOWS_DEFAULT_TEST_OUTPUTS) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -# Some generally useful utilities that just happen to be built in the test area -add_executable(qpid-receive qpid-receive.cpp Statistics.cpp ${platform_test_additions}) -target_link_libraries(qpid-receive qpidmessaging qpidtypes qpidcommon) - -add_executable(qpid-send qpid-send.cpp Statistics.cpp ${platform_test_additions}) -target_link_libraries(qpid-send qpidmessaging qpidtypes qpidcommon) - -install(TARGETS qpid-receive qpid-send RUNTIME DESTINATION ${QPID_INSTALL_BINDIR}) - -add_executable(qpid-perftest qpid-perftest.cpp ${platform_test_additions}) -target_link_libraries(qpid-perftest qpidclient qpidcommon ${Boost_PROGRAM_OPTIONS_LIBRARY}) - -add_executable(qpid-latency-test qpid-latency-test.cpp ${platform_test_additions}) -target_link_libraries(qpid-latency-test qpidclient qpidcommon) - -add_executable(qpid-client-test qpid-client-test.cpp ${platform_test_additions}) -target_link_libraries(qpid-client-test qpidclient qpidcommon) - -add_executable(qpid-ping qpid-ping.cpp ${platform_test_additions}) -target_link_libraries(qpid-ping qpidmessaging qpidtypes qpidcommon) - -add_executable(qpid-topic-listener qpid-topic-listener.cpp ${platform_test_additions}) -target_link_libraries(qpid-topic-listener qpidclient qpidcommon) - -add_executable(qpid-topic-publisher qpid-topic-publisher.cpp ${platform_test_additions}) -target_link_libraries(qpid-topic-publisher qpidclient qpidcommon) - -add_executable(receiver receiver.cpp ${platform_test_additions}) -target_link_libraries(receiver qpidclient qpidcommon) - -# This is bizarre - using both messaging and client libraries -add_executable(sender sender.cpp Statistics.cpp ${platform_test_additions}) -target_link_libraries(sender qpidmessaging qpidtypes qpidclient qpidcommon) - -add_executable(qpid-txtest qpid-txtest.cpp ${platform_test_additions}) -target_link_libraries(qpid-txtest qpidclient qpidcommon qpidtypes) - -add_executable(qpid-txtest2 qpid-txtest2.cpp ${platform_test_additions}) -target_link_libraries(qpid-txtest2 qpidmessaging qpidtypes qpidcommon) - -install(TARGETS - qpid-perftest qpid-latency-test qpid-client-test - qpid-ping - qpid-topic-listener qpid-topic-publisher receiver sender - qpid-txtest qpid-txtest2 - RUNTIME DESTINATION ${QPID_INSTALL_TESTDIR}) - -# Only build test code if testing is turned on -if (BUILD_TESTING) - -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - # Windows - - set(ENV{OUTDIR} ${EXECUTABLE_OUTPUT_PATH}) - - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/env.ps1.in - ${CMAKE_CURRENT_BINARY_DIR}/env.ps1 @ONLY) -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - # Posix - - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/env.sh.in - ${CMAKE_CURRENT_BINARY_DIR}/env.sh @ONLY) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/check_dependencies.py.in - ${CMAKE_CURRENT_BINARY_DIR}/check_dependencies.py @ONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/env.py.in - ${CMAKE_CURRENT_BINARY_DIR}/env.py @ONLY) - -file(COPY . - DESTINATION . - PATTERN "*.cmake" EXCLUDE - PATTERN "*.in" EXCLUDE - PATTERN "*.c" EXCLUDE - PATTERN "*.h" EXCLUDE - PATTERN "*.cpp" EXCLUDE) - -if (BUILD_TESTING_UNITTESTS) - -# 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 run -# ccmake and set unit_tests_to_build to the set you want to build. - -# Like this to work with cmake 2.4 on Unix -set(qpid_test_boost_libs - ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${Boost_SYSTEM_LIBRARY}) - -set(all_unit_tests - AccumulatedAckTest - Acl - AclHost - Array - AsyncCompletion - AtomicValue - ClientMessage - ClientMessageTest - ClientSessionTest - DeliveryRecordTest - DtxWorkRecordTest - exception_test - ExchangeTest - FieldTable - FieldValue - FrameDecoder - FramingTest - HeadersExchangeTest - HeaderTest - InlineAllocator - InlineVector - logging - ManagementTest - MessageReplayTracker - MessageTest - MessagingLogger - MessagingSessionTests - PollableCondition - ProxyTest - QueueDepth - QueueFlowLimitTest - QueueOptionsTest - QueuePolicyTest - QueueRegistryTest - QueueTest - RangeSet - RefCounted - RetryList - Selector - SequenceNumberTest - SequenceSet - SessionState - Shlib - StringUtils - SystemInfo - TimerTest - TopicExchangeTest - TxBufferTest - TransactionObserverTest - Url - Uuid - Variant - ${xml_tests}) - -set(unit_tests_to_build "" CACHE STRING "Which unit tests to build") -mark_as_advanced(unit_tests_to_build) - -# If no unit_test specifically set then use all unit tests -if (unit_tests_to_build) - set(actual_unit_tests ${unit_tests_to_build}) -else() - set(actual_unit_tests ${all_unit_tests}) -endif() - -add_executable (unit_test unit_test - ${actual_unit_tests} ${platform_test_additions}) -target_link_libraries (unit_test - ${qpid_test_boost_libs} - qpidmessaging qpidtypes qpidbroker qpidclient qpidcommon) - -endif (BUILD_TESTING_UNITTESTS) - -add_library(shlibtest MODULE shlibtest.cpp) - -if (BUILD_SASL) - add_custom_command(OUTPUT sasl_config/qpidd.conf sasl_config/qpidd.sasldb - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/sasl_test_setup.sh) - - add_custom_target(sasl_config ALL - DEPENDS sasl_config/qpidd.conf sasl_config/qpidd.sasldb) -endif (BUILD_SASL) - -# Other test programs - -add_executable(echotest echotest.cpp ${platform_test_additions}) -target_link_libraries(echotest qpidclient qpidcommon) - -add_executable(publish publish.cpp ${platform_test_additions}) -target_link_libraries(publish qpidclient qpidcommon) - -add_executable(consume consume.cpp ${platform_test_additions}) -target_link_libraries(consume qpidclient qpidcommon) - -add_executable(header_test header_test.cpp ${platform_test_additions}) -target_link_libraries(header_test qpidclient qpidcommon) - -add_executable(declare_queues declare_queues.cpp ${platform_test_additions}) -target_link_libraries(declare_queues qpidclient qpidcommon) - -add_executable(replaying_sender replaying_sender.cpp ${platform_test_additions}) -target_link_libraries(replaying_sender qpidclient qpidcommon) - -add_executable(resuming_receiver resuming_receiver.cpp ${platform_test_additions}) -target_link_libraries(resuming_receiver qpidclient qpidcommon) - -add_executable(txshift txshift.cpp ${platform_test_additions}) -target_link_libraries(txshift qpidclient qpidcommon) - -add_executable(txjob txjob.cpp ${platform_test_additions}) -target_link_libraries(txjob qpidclient qpidcommon) - -add_executable(datagen datagen.cpp ${platform_test_additions}) -target_link_libraries(datagen qpidclient qpidcommon) - -add_executable(msg_group_test msg_group_test.cpp ${platform_test_additions}) -target_link_libraries(msg_group_test qpidmessaging qpidtypes qpidcommon) - -add_executable(ha_test_max_queues ha_test_max_queues.cpp ${platform_test_additions}) -target_link_libraries(ha_test_max_queues qpidclient qpidcommon) - -add_library(test_store MODULE test_store.cpp) -target_link_libraries(test_store qpidbroker qpidcommon) -set_target_properties(test_store PROPERTIES PREFIX "" COMPILE_DEFINITIONS _IN_QPID_BROKER) - -add_library(dlclose_noop MODULE dlclose_noop.c) - -if (BUILD_SASL) - add_executable(sasl_version sasl_version.cpp ${platform_test_additions}) -endif (BUILD_SASL) - -# Cross-platform tests - -add_test(NAME unit_tests COMMAND ${PYTHON_EXECUTABLE} run_unit_tests) - -add_test(NAME acl_tests COMMAND ${PYTHON_EXECUTABLE} run_acl_tests) -add_test(NAME cli_tests COMMAND ${PYTHON_EXECUTABLE} run_cli_tests) -add_test(NAME client_tests COMMAND ${PYTHON_EXECUTABLE} run_client_tests) -add_test(NAME federation_tests COMMAND ${PYTHON_EXECUTABLE} run_federation_tests) -add_test(NAME flow_control_tests COMMAND ${PYTHON_EXECUTABLE} run_flow_control_tests) -add_test(NAME msg_group_tests COMMAND ${PYTHON_EXECUTABLE} run_msg_group_tests) -add_test(NAME performance_tests COMMAND ${PYTHON_EXECUTABLE} run_performance_tests) -add_test(NAME python_tests COMMAND ${PYTHON_EXECUTABLE} run_python_tests) -add_test(NAME queue_redirect_tests COMMAND ${PYTHON_EXECUTABLE} run_queue_redirect_tests) -add_test(NAME qmf_tests COMMAND ${PYTHON_EXECUTABLE} run_qmf_tests) -add_test(NAME transaction_tests COMMAND ${PYTHON_EXECUTABLE} run_transaction_tests) - -if (BUILD_AMQP) - add_test(NAME idle_timeout_tests COMMAND ${PYTHON_EXECUTABLE} run_idle_timeout_tests) - add_test(NAME interlink_tests COMMAND ${PYTHON_EXECUTABLE} run_interlink_tests) - add_test(NAME interop_tests COMMAND ${PYTHON_EXECUTABLE} run_interop_tests) -endif (BUILD_AMQP) - -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - # Windows-only tests - - add_test(NAME windows_store_tests COMMAND ${PYTHON_EXECUTABLE} run_windows_store_tests) -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - # Posix-only tests - - add_test(NAME ha_tests COMMAND ${PYTHON_EXECUTABLE} run_ha_tests) - add_test(NAME ipv6_tests COMMAND run_ipv6_tests) # Also pretty simple to convert - add_test(NAME logging_tests COMMAND run_logging_tests) # Pretty simple to convert - add_test(NAME paged_queue_tests COMMAND run_paged_queue_tests) - add_test(NAME ring_queue_tests COMMAND run_ring_queue_tests) - add_test(NAME topic_tests COMMAND run_topic_tests) - - if (BUILD_SASL) - add_test(NAME sasl_tests COMMAND run_sasl_tests) - - if (BUILD_SSL) - add_test(NAME ssl_tests COMMAND run_ssl_tests) - endif (BUILD_SSL) - endif (BUILD_SASL) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -endif (BUILD_TESTING) diff --git a/qpid/cpp/src/tests/ClientMessage.cpp b/qpid/cpp/src/tests/ClientMessage.cpp deleted file mode 100644 index 994c46552c..0000000000 --- a/qpid/cpp/src/tests/ClientMessage.cpp +++ /dev/null @@ -1,46 +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 -#include "qpid/messaging/Message.h" - -#include "unit_test.h" - -using namespace qpid::messaging; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ClientMessageSuite) - -QPID_AUTO_TEST_CASE(testCopyConstructor) -{ - Message m("my-data"); - m.setSubject("my-subject"); - m.getProperties()["a"] = "ABC"; - Message c(m); - BOOST_CHECK_EQUAL(m.getContent(), c.getContent()); - BOOST_CHECK_EQUAL(m.getSubject(), c.getSubject()); - BOOST_CHECK_EQUAL(m.getProperties()["a"], c.getProperties()["a"]); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/ClientMessageTest.cpp b/qpid/cpp/src/tests/ClientMessageTest.cpp deleted file mode 100644 index f925f1c234..0000000000 --- a/qpid/cpp/src/tests/ClientMessageTest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * 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 Unit tests for the client::Message class. */ - -#include "unit_test.h" -#include "qpid/client/Message.h" - -using namespace qpid::client; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ClientMessageTestSuite) - -QPID_AUTO_TEST_CASE(MessageCopyAssign) { - // Verify that message has normal copy semantics. - Message m("foo"); - BOOST_CHECK_EQUAL("foo", m.getData()); - Message c(m); - BOOST_CHECK_EQUAL("foo", c.getData()); - Message a; - BOOST_CHECK_EQUAL("", a.getData()); - a = m; - BOOST_CHECK_EQUAL("foo", a.getData()); - a.setData("a"); - BOOST_CHECK_EQUAL("a", a.getData()); - c.setData("c"); - BOOST_CHECK_EQUAL("c", c.getData()); - BOOST_CHECK_EQUAL("foo", m.getData()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/ClientSessionTest.cpp b/qpid/cpp/src/tests/ClientSessionTest.cpp deleted file mode 100644 index f35524c0c0..0000000000 --- a/qpid/cpp/src/tests/ClientSessionTest.cpp +++ /dev/null @@ -1,663 +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 "unit_test.h" -#include "test_tools.h" -#include "BrokerFixture.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Time.h" -#include "qpid/client/Session.h" -#include "qpid/client/Message.h" -#include "qpid/framing/reply_exceptions.h" - -#include -#include -#include -#include -#include - -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ClientSessionTest) - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid; -using qpid::sys::Monitor; -using qpid::sys::Thread; -using qpid::sys::TIME_SEC; -using qpid::broker::BrokerOptions; -using std::string; -using std::cout; -using std::endl; - - -struct DummyListener : public sys::Runnable, public MessageListener { - std::vector messages; - string name; - uint expected; - SubscriptionManager submgr; - - DummyListener(Session& session, const string& n, uint ex) : - name(n), expected(ex), submgr(session) {} - - void run() - { - submgr.subscribe(*this, name); - submgr.run(); - } - - void received(Message& msg) - { - messages.push_back(msg); - if (--expected == 0) { - submgr.stop(); - } - } -}; - -struct SimpleListener : public MessageListener -{ - Monitor lock; - std::vector messages; - - void received(Message& msg) - { - Monitor::ScopedLock l(lock); - messages.push_back(msg); - lock.notifyAll(); - } - - void waitFor(const uint n) - { - Monitor::ScopedLock l(lock); - while (messages.size() < n) { - lock.wait(); - } - } -}; - -struct ClientSessionFixture : public SessionFixture -{ - ClientSessionFixture(const BrokerOptions& opts = BrokerOptions()) : SessionFixture(opts) { - session.queueDeclare(arg::queue="my-queue"); - } -}; - -QPID_AUTO_TEST_CASE(testQueueQuery) { - ClientSessionFixture fix; - fix.session = fix.connection.newSession(); - fix.session.queueDeclare(arg::queue="q", arg::alternateExchange="amq.fanout", - arg::exclusive=true, arg::autoDelete=true); - QueueQueryResult result = fix.session.queueQuery("q"); - BOOST_CHECK_EQUAL(false, result.getDurable()); - BOOST_CHECK_EQUAL(true, result.getExclusive()); - BOOST_CHECK_EQUAL("amq.fanout", result.getAlternateExchange()); -} - -QPID_AUTO_TEST_CASE(testDispatcher) -{ - ClientSessionFixture fix; - fix.session =fix.connection.newSession(); - size_t count = 100; - for (size_t i = 0; i < count; ++i) - fix.session.messageTransfer(arg::content=Message(boost::lexical_cast(i), "my-queue")); - DummyListener listener(fix.session, "my-queue", count); - listener.run(); - BOOST_CHECK_EQUAL(count, listener.messages.size()); - for (size_t i = 0; i < count; ++i) - BOOST_CHECK_EQUAL(boost::lexical_cast(i), listener.messages[i].getData()); -} - -QPID_AUTO_TEST_CASE(testDispatcherThread) -{ - ClientSessionFixture fix; - fix.session =fix.connection.newSession(); - size_t count = 10; - DummyListener listener(fix.session, "my-queue", count); - sys::Thread t(listener); - for (size_t i = 0; i < count; ++i) { - fix.session.messageTransfer(arg::content=Message(boost::lexical_cast(i), "my-queue")); - } - t.join(); - BOOST_CHECK_EQUAL(count, listener.messages.size()); - for (size_t i = 0; i < count; ++i) - BOOST_CHECK_EQUAL(boost::lexical_cast(i), listener.messages[i].getData()); -} - -QPID_AUTO_TEST_CASE(testUseSuspendedError) -{ - ClientSessionFixture fix; - fix.session.timeout(60); - fix.session.suspend(); - try { - fix.session.exchangeQuery(arg::exchange="amq.fanout"); - BOOST_FAIL("Expected session suspended exception"); - } catch(const NotAttachedException&) {} -} - -QPID_AUTO_TEST_CASE(testSendToSelf) { - ClientSessionFixture fix; - SimpleListener mylistener; - fix.session.queueDeclare(arg::queue="myq", arg::exclusive=true, arg::autoDelete=true); - fix.subs.subscribe(mylistener, "myq"); - sys::Thread runner(fix.subs);//start dispatcher thread - string data("msg"); - Message msg(data, "myq"); - const uint count=10; - for (uint i = 0; i < count; ++i) { - fix.session.messageTransfer(arg::content=msg); - } - mylistener.waitFor(count); - fix.subs.cancel("myq"); - fix.subs.stop(); - runner.join(); - fix.session.close(); - BOOST_CHECK_EQUAL(mylistener.messages.size(), count); - for (uint j = 0; j < count; ++j) { - BOOST_CHECK_EQUAL(mylistener.messages[j].getData(), data); - } -} - -QPID_AUTO_TEST_CASE(testLocalQueue) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="lq", arg::exclusive=true, arg::autoDelete=true); - LocalQueue lq; - fix.subs.subscribe(lq, "lq", FlowControl(2, FlowControl::UNLIMITED, false)); - fix.session.messageTransfer(arg::content=Message("foo0", "lq")); - fix.session.messageTransfer(arg::content=Message("foo1", "lq")); - fix.session.messageTransfer(arg::content=Message("foo2", "lq")); - BOOST_CHECK_EQUAL("foo0", lq.pop().getData()); - BOOST_CHECK_EQUAL("foo1", lq.pop().getData()); - BOOST_CHECK(lq.empty()); // Credit exhausted. - fix.subs.getSubscription("lq").setFlowControl(FlowControl::unlimited()); - BOOST_CHECK_EQUAL("foo2", lq.pop().getData()); -} - -struct DelayedTransfer : sys::Runnable -{ - ClientSessionFixture& fixture; - - DelayedTransfer(ClientSessionFixture& f) : fixture(f) {} - - void run() - { - qpid::sys::sleep(1); - fixture.session.messageTransfer(arg::content=Message("foo2", "getq")); - } -}; - -QPID_AUTO_TEST_CASE(testGet) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="getq", arg::exclusive=true, arg::autoDelete=true); - fix.session.messageTransfer(arg::content=Message("foo0", "getq")); - fix.session.messageTransfer(arg::content=Message("foo1", "getq")); - Message got; - BOOST_CHECK(fix.subs.get(got, "getq", TIME_SEC)); - BOOST_CHECK_EQUAL("foo0", got.getData()); - BOOST_CHECK(fix.subs.get(got, "getq", TIME_SEC)); - BOOST_CHECK_EQUAL("foo1", got.getData()); - BOOST_CHECK(!fix.subs.get(got, "getq")); - DelayedTransfer sender(fix); - Thread t(sender); - //test timed get where message shows up after a short delay - BOOST_CHECK(fix.subs.get(got, "getq", 5*TIME_SEC)); - BOOST_CHECK_EQUAL("foo2", got.getData()); - t.join(); -} - -QPID_AUTO_TEST_CASE(testOpenFailure) { - BrokerFixture b; - Connection c; - string host("unknowable-host"); - try { - c.open(host); - } catch (const Exception&) { - BOOST_CHECK(!c.isOpen()); - } - b.open(c); - BOOST_CHECK(c.isOpen()); - c.close(); - BOOST_CHECK(!c.isOpen()); -} - -QPID_AUTO_TEST_CASE(testPeriodicExpiration) { - BrokerOptions opts; - opts.queueCleanInterval = 1*TIME_SEC; - opts.queueFlowStopRatio = 0; - opts.queueFlowResumeRatio = 0; - ClientSessionFixture fix(opts); - FieldTable args; - args.setInt("qpid.max_count",10); - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - - for (uint i = 0; i < 10; i++) { - Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - if (i % 2) m.getDeliveryProperties().setTtl(500); - fix.session.messageTransfer(arg::content=m); - } - - BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 10u); - qpid::sys::sleep(2); - BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 5u); - fix.session.messageTransfer(arg::content=Message("Message_11", "my-queue"));//ensure policy is also updated -} - -QPID_AUTO_TEST_CASE(testExpirationOnPop) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - for (uint i = 0; i < 10; i++) { - Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - if (i % 2) m.getDeliveryProperties().setTtl(200); - fix.session.messageTransfer(arg::content=m); - } - - qpid::sys::usleep(300* 1000); - - for (uint i = 0; i < 10; i++) { - if (i % 2) continue; - Message m; - BOOST_CHECK(fix.subs.get(m, "my-queue", TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData()); - } -} - -QPID_AUTO_TEST_CASE(testRelease) { - ClientSessionFixture fix; - - const uint count=10; - for (uint i = 0; i < count; i++) { - Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - fix.session.messageTransfer(arg::content=m); - } - - fix.subs.setAutoStop(false); - fix.subs.start(); - SubscriptionSettings settings; - settings.autoAck = 0; - - SimpleListener l1; - Subscription s1 = fix.subs.subscribe(l1, "my-queue", settings); - l1.waitFor(count); - s1.cancel(); - - for (uint i = 0; i < count; i++) { - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), l1.messages[i].getData()); - } - s1.release(s1.getUnaccepted()); - - //check that released messages are redelivered - settings.autoAck = 1; - SimpleListener l2; - Subscription s2 = fix.subs.subscribe(l2, "my-queue", settings); - l2.waitFor(count); - for (uint i = 0; i < count; i++) { - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), l2.messages[i].getData()); - } - - fix.subs.stop(); - fix.subs.wait(); - fix.session.close(); -} - -QPID_AUTO_TEST_CASE(testCompleteOnAccept) { - ClientSessionFixture fix; - const uint count = 8; - const uint chunk = 4; - for (uint i = 0; i < count; i++) { - Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - fix.session.messageTransfer(arg::content=m); - } - - SubscriptionSettings settings; - settings.autoAck = 0; - settings.completionMode = COMPLETE_ON_ACCEPT; - settings.flowControl = FlowControl::messageWindow(chunk); - - LocalQueue q; - Subscription s = fix.subs.subscribe(q, "my-queue", settings); - fix.session.messageFlush(arg::destination=s.getName()); - SequenceSet accepted; - for (uint i = 0; i < chunk; i++) { - Message m; - BOOST_CHECK(q.get(m)); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData()); - accepted.add(m.getId()); - } - Message m; - BOOST_CHECK(!q.get(m)); - - s.accept(accepted); - //need to reallocate credit as we have flushed it all out - s.setFlowControl(FlowControl::messageWindow(chunk)); - fix.session.messageFlush(arg::destination=s.getName()); - accepted.clear(); - - for (uint i = chunk; i < count; i++) { - Message m; - BOOST_CHECK(q.get(m)); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData()); - accepted.add(m.getId()); - } - fix.session.messageAccept(accepted); -} - -namespace -{ -struct Publisher : qpid::sys::Runnable -{ - AsyncSession session; - Message message; - uint count; - Thread thread; - - Publisher(Connection& con, Message m, uint c) : session(con.newSession()), message(m), count(c) {} - - void start() - { - thread = Thread(*this); - } - - void join() - { - thread.join(); - } - - void run() - { - for (uint i = 0; i < count; i++) { - session.messageTransfer(arg::content=message); - } - session.sync(); - session.close(); - } -}; -} - -QPID_AUTO_TEST_CASE(testConcurrentSenders) -{ - //Ensure concurrent publishing sessions on a connection don't - //cause assertions, deadlocks or other undesirables: - BrokerFixture fix; - Connection connection; - ConnectionSettings settings; - settings.maxFrameSize = 1024; - settings.port = fix.broker->getPort(qpid::broker::Broker::TCP_TRANSPORT); - connection.open(settings); - AsyncSession session = connection.newSession(); - Message message(string(512, 'X')); - - boost::ptr_vector publishers; - for (size_t i = 0; i < 5; i++) { - publishers.push_back(new Publisher(connection, message, 100)); - } - std::for_each(publishers.begin(), publishers.end(), boost::bind(&Publisher::start, _1)); - std::for_each(publishers.begin(), publishers.end(), boost::bind(&Publisher::join, _1)); - connection.close(); -} - - -QPID_AUTO_TEST_CASE(testExclusiveSubscribe) -{ - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="myq", arg::exclusive=true, arg::autoDelete=true); - SubscriptionSettings settings; - settings.exclusive = true; - LocalQueue q; - fix.subs.subscribe(q, "myq", settings, "first"); - //attempt to create new subscriber should fail - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(fix.subs.subscribe(q, "myq", "second"), ResourceLockedException); - ; - -} - -QPID_AUTO_TEST_CASE(testExclusiveBinding) { - FieldTable options; - options.setString("qpid.exclusive-binding", "anything"); - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="queue-1", arg::exclusive=true, arg::autoDelete=true); - fix.session.queueDeclare(arg::queue="queue-2", arg::exclusive=true, arg::autoDelete=true); - fix.session.exchangeBind(arg::exchange="amq.direct", arg::queue="queue-1", arg::bindingKey="my-key", arg::arguments=options); - fix.session.messageTransfer(arg::destination="amq.direct", arg::content=Message("message1", "my-key")); - fix.session.exchangeBind(arg::exchange="amq.direct", arg::queue="queue-2", arg::bindingKey="my-key", arg::arguments=options); - fix.session.messageTransfer(arg::destination="amq.direct", arg::content=Message("message2", "my-key")); - - Message got; - BOOST_CHECK(fix.subs.get(got, "queue-1")); - BOOST_CHECK_EQUAL("message1", got.getData()); - BOOST_CHECK(!fix.subs.get(got, "queue-1")); - - BOOST_CHECK(fix.subs.get(got, "queue-2")); - BOOST_CHECK_EQUAL("message2", got.getData()); - BOOST_CHECK(!fix.subs.get(got, "queue-2")); -} - -QPID_AUTO_TEST_CASE(testResubscribeWithLocalQueue) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="some-queue", arg::exclusive=true, arg::autoDelete=true); - LocalQueue p, q; - fix.subs.subscribe(p, "some-queue"); - fix.subs.cancel("some-queue"); - fix.subs.subscribe(q, "some-queue"); - - fix.session.messageTransfer(arg::content=Message("some-data", "some-queue")); - fix.session.messageFlush(arg::destination="some-queue"); - - Message got; - BOOST_CHECK(!p.get(got)); - - BOOST_CHECK(q.get(got)); - BOOST_CHECK_EQUAL("some-data", got.getData()); - BOOST_CHECK(!q.get(got)); -} - -QPID_AUTO_TEST_CASE(testReliableDispatch) { - ClientSessionFixture fix; - std::string queue("a-queue"); - fix.session.queueDeclare(arg::queue=queue, arg::autoDelete=true); - - ConnectionSettings settings; - settings.port = fix.broker->getPort(qpid::broker::Broker::TCP_TRANSPORT); - - Connection c1; - c1.open(settings); - Session s1 = c1.newSession(); - SubscriptionManager subs1(s1); - LocalQueue q1; - subs1.subscribe(q1, queue, FlowControl());//first subscriber has no credit - - Connection c2; - c2.open(settings); - Session s2 = c2.newSession(); - SubscriptionManager subs2(s2); - LocalQueue q2; - subs2.subscribe(q2, queue);//second subscriber has credit - - fix.session.messageTransfer(arg::content=Message("my-message", queue)); - - //check that the second consumer gets the message - Message got; - BOOST_CHECK(q2.get(got, 1*TIME_SEC)); - BOOST_CHECK_EQUAL("my-message", got.getData()); - - c1.close(); - c2.close(); -} - -QPID_AUTO_TEST_CASE(testSessionCloseOnInvalidSession) { - Session session; - session.close(); -} - -QPID_AUTO_TEST_CASE(testLVQVariedSize) { - ClientSessionFixture fix; - std::string queue("my-lvq"); - QueueOptions args; - args.setOrdering(LVQ_NO_BROWSE); - fix.session.queueDeclare(arg::queue=queue, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - - std::string key; - args.getLVQKey(key); - - for (size_t i = 0; i < 10; i++) { - std::ostringstream data; - size_t size = 100 - ((i % 10) * 10); - data << std::string(size, 'x'); - - Message m(data.str(), queue); - m.getHeaders().setString(key, "abc"); - fix.session.messageTransfer(arg::content=m); - } -} - -QPID_AUTO_TEST_CASE(testSessionManagerSetFlowControl) { - ClientSessionFixture fix; - std::string name("dummy"); - LocalQueue queue; - SubscriptionSettings settings; - settings.flowControl = FlowControl(); - fix.session.queueDeclare(arg::queue=name, arg::exclusive=true, arg::autoDelete=true); - fix.subs.subscribe(queue, name, settings); - fix.session.messageTransfer(arg::content=Message("my-message", name)); - fix.subs.setFlowControl(name, 1, FlowControl::UNLIMITED, false); - fix.session.messageFlush(name); - Message got; - BOOST_CHECK(queue.get(got, 0)); - BOOST_CHECK_EQUAL("my-message", got.getData()); -} - -QPID_AUTO_TEST_CASE(testGetThenSubscribe) { - ClientSessionFixture fix; - std::string name("myqueue"); - fix.session.queueDeclare(arg::queue=name, arg::exclusive=true, arg::autoDelete=true); - fix.session.messageTransfer(arg::content=Message("one", name)); - fix.session.messageTransfer(arg::content=Message("two", name)); - Message got; - BOOST_CHECK(fix.subs.get(got, name)); - BOOST_CHECK_EQUAL("one", got.getData()); - - DummyListener listener(fix.session, name, 1); - listener.run(); - BOOST_CHECK_EQUAL(1u, listener.messages.size()); - if (!listener.messages.empty()) { - BOOST_CHECK_EQUAL("two", listener.messages[0].getData()); - } -} - -QPID_AUTO_TEST_CASE(testSessionIsValid) { - ClientSessionFixture fix; - BOOST_CHECK(fix.session.isValid()); - Session session; - BOOST_CHECK(!session.isValid()); -} - -QPID_AUTO_TEST_CASE(testExpirationNotAltered) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - Message m("my-message", "my-queue"); - m.getDeliveryProperties().setTtl(60000); - m.getDeliveryProperties().setExpiration(12345); - fix.session.messageTransfer(arg::content=m); - Message got; - BOOST_CHECK(fix.subs.get(got, "my-queue")); - BOOST_CHECK_EQUAL("my-message", got.getData()); - BOOST_CHECK_EQUAL(12345u, got.getDeliveryProperties().getExpiration()); -} - -QPID_AUTO_TEST_CASE(testGetConnectionFromSession) { - ClientSessionFixture fix; - FieldTable options; - options.setInt("no-local", 1); - fix.session.queueDeclare(arg::queue="a", arg::exclusive=true, arg::autoDelete=true, arg::arguments=options); - fix.session.queueDeclare(arg::queue="b", arg::exclusive=true, arg::autoDelete=true); - - Connection c = fix.session.getConnection(); - Session s = c.newSession(); - //If this new session was created as expected on the same connection as - //fix.session, then the no-local behaviour means that queue 'a' - //will not enqueue messages from this new session but queue 'b' - //will. - s.messageTransfer(arg::content=Message("a", "a")); - s.messageTransfer(arg::content=Message("b", "b")); - - Message got; - BOOST_CHECK(fix.subs.get(got, "b")); - BOOST_CHECK_EQUAL("b", got.getData()); - BOOST_CHECK(!fix.subs.get(got, "a")); -} - - -QPID_AUTO_TEST_CASE(testQueueDeleted) -{ - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue"); - LocalQueue queue; - fix.subs.subscribe(queue, "my-queue"); - - ScopedSuppressLogging sl; - fix.session.queueDelete(arg::queue="my-queue"); - BOOST_CHECK_THROW(queue.get(1*qpid::sys::TIME_SEC), qpid::framing::ResourceDeletedException); -} - -QPID_AUTO_TEST_CASE(testTtl) -{ - const uint64_t ms = 1000ULL; // convert sec to ms - const uint64_t us = 1000ULL * 1000ULL; // convert sec to us - - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="ttl-test", arg::exclusive=true, arg::autoDelete=true); - Message msg1 = Message("AAA", "ttl-test"); - uint64_t ttl = 2 * ms; // 2 sec - msg1.getDeliveryProperties().setTtl(ttl); - Connection c = fix.session.getConnection(); - Session s = c.newSession(); - s.messageTransfer(arg::content=msg1); - - Message msg2 = Message("BBB", "ttl-test"); - ttl = 10 * ms; // 10 sec - msg2.getDeliveryProperties().setTtl(ttl); - s.messageTransfer(arg::content=msg2); - - qpid::sys::usleep(5 * us); // 5 sec - - // Message "AAA" should be expired and never be delivered - // Check "BBB" has ttl somewhere between 1 and 5 secs - Message got; - BOOST_CHECK(fix.subs.get(got, "ttl-test")); - BOOST_CHECK_EQUAL("BBB", got.getData()); - BOOST_CHECK(got.getDeliveryProperties().getTtl() > 1 * ms); - BOOST_CHECK(got.getDeliveryProperties().getTtl() < ttl - (5 * ms)); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/ConnectionOptions.h b/qpid/cpp/src/tests/ConnectionOptions.h deleted file mode 100644 index fe945e9ddd..0000000000 --- a/qpid/cpp/src/tests/ConnectionOptions.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_CLIENT_CONNECTIONOPTIONS_H -#define QPID_CLIENT_CONNECTIONOPTIONS_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/ConnectionSettings.h" -#include "qpid/Options.h" - -namespace qpid { - -/** - * Options parser for ConnectionOptions. - */ -struct ConnectionOptions : public qpid::Options, - public qpid::client::ConnectionSettings -{ - ConnectionOptions() : qpid::Options("Connection Settings") - { - using namespace qpid; - addOptions() - ("broker,b", optValue(host, "HOST"), "Broker host to connect to") - ("port,p", optValue(port, "PORT"), "Broker port to connect to") - ("protocol,P", optValue(protocol, "tcp|ssl|rdma"), "Protocol to use for broker connection") - ("virtualhost,v", optValue(virtualhost, "VHOST"), "virtual host") - ("username", optValue(username, "USER"), "user name for broker log in.") - ("password", optValue(password, "PASSWORD"), "password for broker log in.") - ("mechanism", optValue(mechanism, "MECH"), "SASL mechanism to use when authenticating.") - ("locale", optValue(locale, "LOCALE"), "locale to use.") - ("max-channels", optValue(maxChannels, "N"), "the maximum number of channels the client requires.") - ("heartbeat", optValue(heartbeat, "N"), "Desired heartbeat interval in seconds.") - ("max-frame-size", optValue(maxFrameSize, "N"), "the maximum frame size to request.") - ("bounds-multiplier", optValue(bounds, "N"), - "bound size of write queue (as a multiple of the max frame size).") - ("tcp-nodelay", optValue(tcpNoDelay), "Turn on tcp-nodelay") - ("service", optValue(service, "SERVICE-NAME"), "SASL service name.") - ("min-ssf", optValue(minSsf, "N"), "Minimum acceptable strength for SASL security layer") - ("max-ssf", optValue(maxSsf, "N"), "Maximum acceptable strength for SASL security layer"); - } -}; - -} // namespace qpid - -#endif /*!QPID_CLIENT_CONNECTIONOPTIONS_H*/ diff --git a/qpid/cpp/src/tests/DeliveryRecordTest.cpp b/qpid/cpp/src/tests/DeliveryRecordTest.cpp deleted file mode 100644 index 37b3095f81..0000000000 --- a/qpid/cpp/src/tests/DeliveryRecordTest.cpp +++ /dev/null @@ -1,67 +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/broker/DeliveryRecord.h" -#include "qpid/broker/Queue.h" -#include "unit_test.h" -#include -#include -#include - -using namespace qpid::broker; -using namespace qpid::sys; -using namespace qpid::framing; -using boost::dynamic_pointer_cast; -using std::list; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(DeliveryRecordTestSuite) - -QPID_AUTO_TEST_CASE(testSort) -{ - list ids; - ids.push_back(SequenceNumber(6)); - ids.push_back(SequenceNumber(2)); - ids.push_back(SequenceNumber(4)); - ids.push_back(SequenceNumber(5)); - ids.push_back(SequenceNumber(1)); - ids.push_back(SequenceNumber(3)); - - list records; - for (list::iterator i = ids.begin(); i != ids.end(); i++) { - DeliveryRecord r(QueueCursor(CONSUMER), framing::SequenceNumber(), SequenceNumber(), Queue::shared_ptr(), "tag", Consumer::shared_ptr(), false, false, false); - r.setId(*i); - records.push_back(r); - } - records.sort(); - - SequenceNumber expected(0); - for (list::iterator i = records.begin(); i != records.end(); i++) { - BOOST_CHECK(i->getId() == ++expected); - } -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/DispatcherTest.cpp b/qpid/cpp/src/tests/DispatcherTest.cpp deleted file mode 100644 index 7312fe8d2e..0000000000 --- a/qpid/cpp/src/tests/DispatcherTest.cpp +++ /dev/null @@ -1,240 +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/sys/Poller.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/sys/Thread.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace std; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -int writeALot(int fd, const string& s) { - int bytesWritten = 0; - do { - errno = 0; - int lastWrite = ::write(fd, s.c_str(), s.size()); - if ( lastWrite >= 0) { - bytesWritten += lastWrite; - } - } while (errno != EAGAIN); - return bytesWritten; -} - -int readALot(int fd) { - int bytesRead = 0; - char buf[10240]; - - do { - errno = 0; - int lastRead = ::read(fd, buf, sizeof(buf)); - if ( lastRead >= 0) { - bytesRead += lastRead; - } - } while (errno != EAGAIN); - return bytesRead; -} - -int64_t writtenBytes = 0; -int64_t readBytes = 0; - -void writer(DispatchHandle& h, int fd, const string& s) { - writtenBytes += writeALot(fd, s); - h.rewatch(); -} - -void reader(DispatchHandle& h, int fd) { - readBytes += readALot(fd); - h.rewatch(); -} - -void rInterrupt(DispatchHandle&) { - cerr << "R"; -} - -void wInterrupt(DispatchHandle&) { - cerr << "W"; -} - -DispatchHandle::Callback rcb = rInterrupt; -DispatchHandle::Callback wcb = wInterrupt; - -DispatchHandleRef *volatile rh = 0; -DispatchHandleRef *volatile wh = 0; - -volatile bool stopWait = false; -volatile bool phase1finished = false; - -timer_t timer; - -void stop_handler(int /*signo*/, siginfo_t* /*info*/, void* /*context*/) { - stopWait = true; -} - -void timer_handler(int /*signo*/, siginfo_t* /*info*/, void* /*context*/) { - static int count = 0; - if (count++ < 10) { - rh->call(rcb); - wh->call(wcb); - } else { - phase1finished = true; - assert(::timer_delete(timer) == 0); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int /*argc*/, char** /*argv*/) -{ - // Create poller - Poller::shared_ptr poller(new Poller); - - // Create dispatcher thread - Thread dt(*poller); - Thread dt1(*poller); - Thread dt2(*poller); - Thread dt3(*poller); - - // Setup sender and receiver - int sv[2]; - int rc = ::socketpair(AF_UNIX, SOCK_STREAM, 0, sv); - assert(rc >= 0); - - // Set non-blocking - rc = ::fcntl(sv[0], F_SETFL, O_NONBLOCK); - assert(rc >= 0); - - rc = ::fcntl(sv[1], F_SETFL, O_NONBLOCK); - assert(rc >= 0); - - // Make up a large string - string testString = "This is only a test ... 1,2,3,4,5,6,7,8,9,10;"; - for (int i = 0; i < 8; i++) - testString += testString; - - IOHandle f0(sv[0]); - IOHandle f1(sv[1]); - - rh = new DispatchHandleRef(f0, boost::bind(reader, _1, sv[0]), 0, 0); - wh = new DispatchHandleRef(f1, 0, boost::bind(writer, _1, sv[1], testString), 0); - - rh->startWatch(poller); - wh->startWatch(poller); - - // Set up a regular itimer interupt - // We assume that this thread will handle the signals whilst sleeping - // as the Poller threads have signal handling blocked - - // Signal handling - struct ::sigaction sa; - sa.sa_sigaction = timer_handler; - sa.sa_flags = SA_RESTART | SA_SIGINFO; - ::sigemptyset(&sa.sa_mask); - rc = ::sigaction(SIGRTMIN, &sa,0); - assert(rc == 0); - - ::sigevent se; - ::memset(&se, 0, sizeof(se)); // Clear to make valgrind happy (this *is* the neatest way to do this portably - sigh) - se.sigev_notify = SIGEV_SIGNAL; - se.sigev_signo = SIGRTMIN; - rc = ::timer_create(CLOCK_REALTIME, &se, &timer); - assert(rc == 0); - - itimerspec ts = { - /*.it_value = */ {2, 0}, // s, ns - /*.it_interval = */ {2, 0}}; // s, ns - - rc = ::timer_settime(timer, 0, &ts, 0); - assert(rc == 0); - - // wait - while (!phase1finished) { - ::sleep(1); - } - - // Now test deleting/creating DispatchHandles in tight loop, so that we are likely to still be using the - // attached PollerHandles after deleting the DispatchHandle - DispatchHandleRef* t = wh; - wh = 0; - delete t; - t = rh; - rh = 0; - delete t; - - sa.sa_sigaction = stop_handler; - rc = ::sigaction(SIGRTMIN, &sa,0); - assert(rc == 0); - - itimerspec nts = { - /*.it_value = */ {30, 0}, // s, ns - /*.it_interval = */ {30, 0}}; // s, ns - - rc = ::timer_create(CLOCK_REALTIME, &se, &timer); - assert(rc == 0); - rc = ::timer_settime(timer, 0, &nts, 0); - assert(rc == 0); - - DispatchHandleRef* rh1; - DispatchHandleRef* wh1; - - struct timespec w = {0, 1000000}; - while (!stopWait) { - rh1 = new DispatchHandleRef(f0, boost::bind(reader, _1, sv[0]), 0, 0); - wh1 = new DispatchHandleRef(f1, 0, boost::bind(writer, _1, sv[1], testString), 0); - rh1->startWatch(poller); - wh1->startWatch(poller); - - ::nanosleep(&w, 0); - - delete wh1; - delete rh1; - } - - rc = ::timer_delete(timer); - assert(rc == 0); - - poller->shutdown(); - dt.join(); - dt1.join(); - dt2.join(); - dt3.join(); - - cout << "\nWrote: " << writtenBytes << "\n"; - cout << "Read: " << readBytes << "\n"; - - return 0; -} diff --git a/qpid/cpp/src/tests/DtxWorkRecordTest.cpp b/qpid/cpp/src/tests/DtxWorkRecordTest.cpp deleted file mode 100644 index bcb3fc14a1..0000000000 --- a/qpid/cpp/src/tests/DtxWorkRecordTest.cpp +++ /dev/null @@ -1,193 +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/broker/DtxWorkRecord.h" -#include "unit_test.h" -#include -#include -#include "TxMocks.h" - -using namespace qpid::broker; -using boost::static_pointer_cast; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(DtxWorkRecordTestSuite) - -QPID_AUTO_TEST_CASE(testOnePhaseCommit){ - MockTransactionalStore store; - store.expectBegin().expectCommit(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectCommit(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare().expectCommit(); - - boost::intrusive_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast(opA)); - bufferA->markEnded(); - boost::intrusive_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast(opB)); - bufferB->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - - work.commit(true); - - store.check(); - BOOST_CHECK(store.isCommitted()); - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_CASE(testFailOnOnePhaseCommit){ - MockTransactionalStore store; - store.expectBegin().expectAbort(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectRollback(); - - boost::intrusive_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast(opA)); - bufferA->markEnded(); - boost::intrusive_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast(opB)); - bufferB->markEnded(); - boost::intrusive_ptr bufferC(new DtxBuffer()); - bufferC->enlist(static_pointer_cast(opC)); - bufferC->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - work.add(bufferC); - - work.commit(true); - - BOOST_CHECK(store.isAborted()); - store.check(); - - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testTwoPhaseCommit){ - MockTransactionalStore store; - store.expectBegin2PC().expectPrepare().expectCommit(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectCommit(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare().expectCommit(); - - boost::intrusive_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast(opA)); - bufferA->markEnded(); - boost::intrusive_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast(opB)); - bufferB->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - - BOOST_CHECK(work.prepare()); - BOOST_CHECK(store.isPrepared()); - work.commit(false); - store.check(); - BOOST_CHECK(store.isCommitted()); - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_CASE(testFailOnTwoPhaseCommit){ - MockTransactionalStore store; - store.expectBegin2PC().expectAbort(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectRollback(); - - boost::intrusive_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast(opA)); - bufferA->markEnded(); - boost::intrusive_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast(opB)); - bufferB->markEnded(); - boost::intrusive_ptr bufferC(new DtxBuffer()); - bufferC->enlist(static_pointer_cast(opC)); - bufferC->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - work.add(bufferC); - - BOOST_CHECK(!work.prepare()); - BOOST_CHECK(store.isAborted()); - store.check(); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testRollback){ - MockTransactionalStore store; - store.expectBegin2PC().expectPrepare().expectAbort(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare().expectRollback(); - - boost::intrusive_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast(opA)); - bufferA->markEnded(); - boost::intrusive_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast(opB)); - bufferB->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - - BOOST_CHECK(work.prepare()); - BOOST_CHECK(store.isPrepared()); - work.rollback(); - store.check(); - BOOST_CHECK(store.isAborted()); - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/ExchangeTest.cpp b/qpid/cpp/src/tests/ExchangeTest.cpp deleted file mode 100644 index df0684e832..0000000000 --- a/qpid/cpp/src/tests/ExchangeTest.cpp +++ /dev/null @@ -1,267 +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/Exception.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/framing/reply_exceptions.h" -#include "unit_test.h" -#include -#include "MessageUtils.h" - -using std::string; - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -using namespace qpid; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ExchangeTestSuite) - -QPID_AUTO_TEST_CASE(testMe) -{ - Queue::shared_ptr queue(new Queue("queue", true)); - Queue::shared_ptr queue2(new Queue("queue2", true)); - - TopicExchange topic("topic"); - topic.bind(queue, "abc", 0); - topic.bind(queue2, "abc", 0); - - DirectExchange direct("direct"); - direct.bind(queue, "abc", 0); - direct.bind(queue2, "abc", 0); - - queue.reset(); - queue2.reset(); - - DeliverableMessage msg(MessageUtils::createMessage("exchange", "abc"), 0); - topic.route(msg); - direct.route(msg); -} - -QPID_AUTO_TEST_CASE(testIsBound) -{ - Queue::shared_ptr a(new Queue("a", true)); - Queue::shared_ptr b(new Queue("b", true)); - Queue::shared_ptr c(new Queue("c", true)); - Queue::shared_ptr d(new Queue("d", true)); - - string k1("abc"); - string k2("def"); - string k3("xyz"); - - FanOutExchange fanout("fanout"); - BOOST_CHECK(fanout.bind(a, "", 0)); - BOOST_CHECK(fanout.bind(b, "", 0)); - BOOST_CHECK(fanout.bind(c, "", 0)); - - BOOST_CHECK(fanout.isBound(a, 0, 0)); - BOOST_CHECK(fanout.isBound(b, 0, 0)); - BOOST_CHECK(fanout.isBound(c, 0, 0)); - BOOST_CHECK(!fanout.isBound(d, 0, 0)); - - DirectExchange direct("direct"); - BOOST_CHECK(direct.bind(a, k1, 0)); - BOOST_CHECK(direct.bind(a, k3, 0)); - BOOST_CHECK(direct.bind(b, k2, 0)); - BOOST_CHECK(direct.bind(c, k1, 0)); - - BOOST_CHECK(direct.isBound(a, 0, 0)); - BOOST_CHECK(direct.isBound(a, &k1, 0)); - BOOST_CHECK(direct.isBound(a, &k3, 0)); - BOOST_CHECK(!direct.isBound(a, &k2, 0)); - BOOST_CHECK(direct.isBound(b, 0, 0)); - BOOST_CHECK(direct.isBound(b, &k2, 0)); - BOOST_CHECK(direct.isBound(c, &k1, 0)); - BOOST_CHECK(!direct.isBound(d, 0, 0)); - BOOST_CHECK(!direct.isBound(d, &k1, 0)); - BOOST_CHECK(!direct.isBound(d, &k2, 0)); - BOOST_CHECK(!direct.isBound(d, &k3, 0)); - - TopicExchange topic("topic"); - BOOST_CHECK(topic.bind(a, k1, 0)); - BOOST_CHECK(topic.bind(a, k3, 0)); - BOOST_CHECK(topic.bind(b, k2, 0)); - BOOST_CHECK(topic.bind(c, k1, 0)); - - BOOST_CHECK(topic.isBound(a, 0, 0)); - BOOST_CHECK(topic.isBound(a, &k1, 0)); - BOOST_CHECK(topic.isBound(a, &k3, 0)); - BOOST_CHECK(!topic.isBound(a, &k2, 0)); - BOOST_CHECK(topic.isBound(b, 0, 0)); - BOOST_CHECK(topic.isBound(b, &k2, 0)); - BOOST_CHECK(topic.isBound(c, &k1, 0)); - BOOST_CHECK(!topic.isBound(d, 0, 0)); - BOOST_CHECK(!topic.isBound(d, &k1, 0)); - BOOST_CHECK(!topic.isBound(d, &k2, 0)); - BOOST_CHECK(!topic.isBound(d, &k3, 0)); - - HeadersExchange headers("headers"); - FieldTable args1; - args1.setString("x-match", "all"); - args1.setString("a", "A"); - args1.setInt("b", 1); - FieldTable args2; - args2.setString("x-match", "any"); - args2.setString("a", "A"); - args2.setInt("b", 1); - FieldTable args3; - args3.setString("x-match", "any"); - args3.setString("c", "C"); - args3.setInt("b", 6); - - headers.bind(a, "", &args1); - headers.bind(a, "other", &args3);//need to use different binding key to correctly identify second binding - headers.bind(b, "", &args2); - headers.bind(c, "", &args1); - - BOOST_CHECK(headers.isBound(a, 0, 0)); - BOOST_CHECK(headers.isBound(a, 0, &args1)); - BOOST_CHECK(headers.isBound(a, 0, &args3)); - BOOST_CHECK(!headers.isBound(a, 0, &args2)); - BOOST_CHECK(headers.isBound(b, 0, 0)); - BOOST_CHECK(headers.isBound(b, 0, &args2)); - BOOST_CHECK(headers.isBound(c, 0, &args1)); - BOOST_CHECK(!headers.isBound(d, 0, 0)); - BOOST_CHECK(!headers.isBound(d, 0, &args1)); - BOOST_CHECK(!headers.isBound(d, 0, &args2)); - BOOST_CHECK(!headers.isBound(d, 0, &args3)); -} - -QPID_AUTO_TEST_CASE(testDeleteGetAndRedeclare) -{ - ExchangeRegistry exchanges; - exchanges.declare("my-exchange", "direct", false, false, FieldTable()); - exchanges.destroy("my-exchange"); - try { - exchanges.get("my-exchange"); - } catch (const NotFoundException&) {} - std::pair response = exchanges.declare("my-exchange", "direct", false, false, FieldTable()); - BOOST_CHECK_EQUAL(string("direct"), response.first->getType()); -} - -QPID_AUTO_TEST_CASE(testSequenceOptions) -{ - FieldTable args; - args.setInt("qpid.msg_sequence",1); - char* buff = new char[10000]; - framing::Buffer buffer(buff,10000); - { - DirectExchange direct("direct1", false, false, args); - - DeliverableMessage msg1(MessageUtils::createMessage("e", "abc"), 0); - DeliverableMessage msg2(MessageUtils::createMessage("e", "abc"), 0); - DeliverableMessage msg3(MessageUtils::createMessage("e", "abc"), 0); - - direct.route(msg1); - direct.route(msg2); - direct.route(msg3); - - BOOST_CHECK_EQUAL(1, msg1.getMessage().getAnnotation("qpid.msg_sequence").asInt64()); - BOOST_CHECK_EQUAL(2, msg2.getMessage().getAnnotation("qpid.msg_sequence").asInt64()); - BOOST_CHECK_EQUAL(3, msg3.getMessage().getAnnotation("qpid.msg_sequence").asInt64()); - - FanOutExchange fanout("fanout1", false, false, args); - HeadersExchange header("headers1", false, false, args); - TopicExchange topic ("topic1", false, false, args); - - // check other exchanges, that they preroute - DeliverableMessage msg4(MessageUtils::createMessage("e", "abc"), 0); - DeliverableMessage msg5(MessageUtils::createMessage("e", "abc"), 0); - DeliverableMessage msg6(MessageUtils::createMessage("e", "abc"), 0); - - fanout.route(msg4); - BOOST_CHECK_EQUAL(1, msg4.getMessage().getAnnotation("qpid.msg_sequence").asInt64()); - - header.route(msg5); - BOOST_CHECK_EQUAL(1, msg5.getMessage().getAnnotation("qpid.msg_sequence").asInt64()); - - topic.route(msg6); - BOOST_CHECK_EQUAL(1, msg6.getMessage().getAnnotation("qpid.msg_sequence").asInt64()); - direct.encode(buffer); - } - { - - ExchangeRegistry exchanges; - buffer.reset(); - DirectExchange::shared_ptr exch_dec = Exchange::decode(exchanges, buffer); - - DeliverableMessage msg1(MessageUtils::createMessage("e", "abc"), 0); - exch_dec->route(msg1); - - BOOST_CHECK_EQUAL(4, msg1.getMessage().getAnnotation("qpid.msg_sequence").asInt64()); - - } - delete [] buff; -} - -QPID_AUTO_TEST_CASE(testIVEOption) -{ - FieldTable args; - args.setInt("qpid.ive",1); - DirectExchange direct("direct1", false, false, args); - FanOutExchange fanout("fanout1", false, false, args); - HeadersExchange header("headers1", false, false, args); - TopicExchange topic ("topic1", false, false, args); - - qpid::types::Variant::Map properties; - properties["routing-key"] = "abc"; - properties["a"] = "abc"; - Message msg1 = MessageUtils::createMessage(properties, "my-message", "direct1"); - DeliverableMessage dmsg1(msg1, 0); - - FieldTable args2; - args2.setString("x-match", "any"); - args2.setString("a", "abc"); - - direct.route(dmsg1); - fanout.route(dmsg1); - header.route(dmsg1); - topic.route(dmsg1); - Queue::shared_ptr queue(new Queue("queue", true)); - Queue::shared_ptr queue1(new Queue("queue1", true)); - Queue::shared_ptr queue2(new Queue("queue2", true)); - Queue::shared_ptr queue3(new Queue("queue3", true)); - - BOOST_CHECK(direct.bind(queue, "abc", 0)); - BOOST_CHECK(fanout.bind(queue1, "abc", 0)); - BOOST_CHECK(header.bind(queue2, "", &args2)); - BOOST_CHECK(topic.bind(queue3, "abc", 0)); - - BOOST_CHECK_EQUAL(1u,queue->getMessageCount()); - BOOST_CHECK_EQUAL(1u,queue1->getMessageCount()); - BOOST_CHECK_EQUAL(1u,queue2->getMessageCount()); - BOOST_CHECK_EQUAL(1u,queue3->getMessageCount()); - -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/FieldTable.cpp b/qpid/cpp/src/tests/FieldTable.cpp deleted file mode 100644 index c040f1d433..0000000000 --- a/qpid/cpp/src/tests/FieldTable.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include -#include -#include "qpid/framing/Array.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/List.h" - -#include "unit_test.h" - -using namespace qpid::framing; - -using std::string; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(FieldTableTestSuite) - -QPID_AUTO_TEST_CASE(testMe) -{ - FieldTable ft; - ft.setString("A", "BCDE"); - BOOST_CHECK(string("BCDE") == ft.getAsString("A")); - - char buff[100]; - Buffer wbuffer(buff, 100); - wbuffer.put(ft); - - Buffer rbuffer(buff, 100); - FieldTable ft2; - rbuffer.get(ft2); - BOOST_CHECK(string("BCDE") == ft2.getAsString("A")); - -} - -QPID_AUTO_TEST_CASE(testAssignment) -{ - FieldTable a; - FieldTable b; - - a.setString("A", "BBBB"); - a.setInt("B", 1234); - b = a; - a.setString("A", "CCCC"); - - BOOST_CHECK(string("CCCC") == a.getAsString("A")); - BOOST_CHECK(string("BBBB") == b.getAsString("A")); - BOOST_CHECK_EQUAL(1234, a.getAsInt("B")); - BOOST_CHECK_EQUAL(1234, b.getAsInt("B")); - BOOST_CHECK(IntegerValue(1234) == *a.get("B")); - BOOST_CHECK(IntegerValue(1234) == *b.get("B")); - - FieldTable d; - { - FieldTable c; - c = a; - - std::vector buff(c.encodedSize()); - Buffer wbuffer(&buff[0], c.encodedSize()); - wbuffer.put(c); - - Buffer rbuffer(&buff[0], c.encodedSize()); - rbuffer.get(d); - BOOST_CHECK_EQUAL(c, d); - BOOST_CHECK(string("CCCC") == c.getAsString("A")); - BOOST_CHECK(IntegerValue(1234) == *c.get("B")); - } - BOOST_CHECK(string("CCCC") == d.getAsString("A")); - BOOST_CHECK(IntegerValue(1234) == *d.get("B")); -} - - -QPID_AUTO_TEST_CASE(testNestedValues) -{ - double d = 1.2345; - uint32_t u = 101; - char buff[1000]; - { - FieldTable a; - FieldTable b; - std::vector items; - items.push_back("one"); - items.push_back("two"); - Array c(items); - List list; - list.push_back(List::ValuePtr(new Str16Value("red"))); - list.push_back(List::ValuePtr(new Unsigned32Value(u))); - list.push_back(List::ValuePtr(new Str8Value("yellow"))); - list.push_back(List::ValuePtr(new DoubleValue(d))); - - a.setString("id", "A"); - b.setString("id", "B"); - a.setTable("B", b); - a.setArray("C", c); - a.set("my-list", FieldTable::ValuePtr(new ListValue(list))); - - - Buffer wbuffer(buff, 100); - wbuffer.put(a); - } - { - Buffer rbuffer(buff, 100); - FieldTable a; - FieldTable b; - Array c; - rbuffer.get(a); - BOOST_CHECK(string("A") == a.getAsString("id")); - a.getTable("B", b); - BOOST_CHECK(string("B") == b.getAsString("id")); - a.getArray("C", c); - std::vector items; - std::transform(c.begin(), c.end(), std::back_inserter(items), Array::get); - BOOST_CHECK((uint) 2 == items.size()); - BOOST_CHECK(string("one") == items[0]); - BOOST_CHECK(string("two") == items[1]); - - List list; - BOOST_CHECK(a.get("my-list")->get(list)); - List::const_iterator i = list.begin(); - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL(std::string("red"), (*i)->get()); - - i++; - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL(u, (uint32_t) (*i)->get()); - - i++; - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL(std::string("yellow"), (*i)->get()); - - i++; - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL(d, (*i)->get()); - - i++; - BOOST_CHECK(i == list.end()); - } -} - -QPID_AUTO_TEST_CASE(testFloatAndDouble) -{ - char buff[100]; - float f = 5.672f; - double d = 56.720001; - { - FieldTable a; - a.setString("string", "abc"); - a.setInt("int", 5672); - a.setFloat("float", f); - a.setDouble("double", d); - - Buffer wbuffer(buff, 100); - wbuffer.put(a); - } - { - Buffer rbuffer(buff, 100); - FieldTable a; - rbuffer.get(a); - BOOST_CHECK_EQUAL(string("abc"), a.getAsString("string")); - BOOST_CHECK_EQUAL(5672, a.getAsInt("int")); - float f2; - BOOST_CHECK(!a.getFloat("string", f2)); - BOOST_CHECK(!a.getFloat("int", f2)); - BOOST_CHECK(a.getFloat("float", f2)); - BOOST_CHECK_EQUAL(f2, f); - - double d2; - BOOST_CHECK(!a.getDouble("string", d2)); - BOOST_CHECK(!a.getDouble("int", d2)); - BOOST_CHECK(a.getDouble("double", d2)); - BOOST_CHECK_EQUAL(d2, d); - } -} - -QPID_AUTO_TEST_CASE(test64GetAndSetConverts) -{ - FieldTable args; - args.setInt64("a",100); - args.setInt64("b",-(int64_t) ((int64_t) 1<<34)); - - args.setUInt64("c",1u); - args.setUInt64("d",(uint64_t) ((uint64_t) 1<<34)); - BOOST_CHECK_EQUAL(1u, args.getAsUInt64("c")); - BOOST_CHECK_EQUAL(100u, args.getAsUInt64("a")); - BOOST_CHECK_EQUAL(1, args.getAsInt64("c")); - BOOST_CHECK_EQUAL(100, args.getAsInt64("a")); - BOOST_CHECK_EQUAL(-(int64_t) ((int64_t) 1<<34), args.getAsInt64("b")); - BOOST_CHECK_EQUAL((uint64_t) ((uint64_t) 1<<34), args.getAsUInt64("d")); - BOOST_CHECK_EQUAL((int64_t) ((int64_t) 1<<34), args.getAsInt64("d")); - -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/FieldValue.cpp b/qpid/cpp/src/tests/FieldValue.cpp deleted file mode 100644 index 9cea48e3cf..0000000000 --- a/qpid/cpp/src/tests/FieldValue.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#include "qpid/framing/FieldValue.h" - -#include "unit_test.h" -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(FieldValueTestSuite) - -using namespace qpid::framing; - -Str16Value s("abc"); -IntegerValue i(42); -FloatValue f((float)42.42); -DoubleValue df(123.123); - -QPID_AUTO_TEST_CASE(testStr16ValueEquals) -{ - - BOOST_CHECK(Str16Value("abc") == s); - BOOST_CHECK(Str16Value("foo") != s); - BOOST_CHECK(s != i); - BOOST_CHECK(s.convertsTo() == true); - BOOST_CHECK(s.convertsTo() == false); - BOOST_CHECK(s.get() == "abc"); - BOOST_CHECK_THROW(s.get(), InvalidConversionException); - -} - -QPID_AUTO_TEST_CASE(testIntegerValueEquals) -{ - BOOST_CHECK(i.get() == 42); - BOOST_CHECK(IntegerValue(42) == i); - BOOST_CHECK(IntegerValue(5) != i); - BOOST_CHECK(i != s); - BOOST_CHECK(i.convertsTo() == false); - BOOST_CHECK(i.convertsTo() == true); - BOOST_CHECK(i.convertsTo() == true); - BOOST_CHECK_THROW(i.get(), InvalidConversionException); - BOOST_CHECK_EQUAL(i.get(), 42.0); -} - -QPID_AUTO_TEST_CASE(testFloatValueEquals) -{ - BOOST_CHECK(f.convertsTo() == true); - BOOST_CHECK(FloatValue((float)42.42) == f); - BOOST_CHECK_CLOSE(double(f.get()), 42.42, 0.001); - // Check twice, regression test for QPID-6470 where the value was corrupted during get. - BOOST_CHECK(FloatValue((float)42.42) == f); - BOOST_CHECK_CLOSE(f.get(), 42.42, 0.001); - - // Float to double conversion - BOOST_CHECK(f.convertsTo() == true); - BOOST_CHECK_CLOSE(f.get(), 42.42, 0.001); - - // Double value - BOOST_CHECK(f.convertsTo() == true); - BOOST_CHECK(f.convertsTo() == true); - BOOST_CHECK_CLOSE(double(df.get()), 123.123, 0.001); - BOOST_CHECK_CLOSE(df.get(), 123.123, 0.001); - - // Invalid conversions should fail. - BOOST_CHECK(!f.convertsTo()); - BOOST_CHECK(!f.convertsTo()); - BOOST_CHECK_THROW(f.get(), InvalidConversionException); - BOOST_CHECK_THROW(f.get(), InvalidConversionException); - - // getFloatingPointValue: check twice, regression test for QPID-6470 - BOOST_CHECK_CLOSE((double(f.getFloatingPointValue())), 42.42, 0.001); - BOOST_CHECK_CLOSE((double(f.getFloatingPointValue())), 42.42, 0.001); - BOOST_CHECK_CLOSE((df.getFloatingPointValue()), 123.123, 0.001); - // getFloatingPointValue should *not* convert float/double, require exact type. - BOOST_CHECK_THROW((f.getFloatingPointValue()), InvalidConversionException); - BOOST_CHECK_THROW((double(df.getFloatingPointValue())), InvalidConversionException); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Frame.cpp b/qpid/cpp/src/tests/Frame.cpp deleted file mode 100644 index cfcfde04a7..0000000000 --- a/qpid/cpp/src/tests/Frame.cpp +++ /dev/null @@ -1,84 +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/framing/Frame.h" - -#include -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(FrameTestSuite) - -using namespace std; -using namespace qpid::framing; - -QPID_AUTO_TEST_CASE(testContentBody) { - Frame f(42, AMQContentBody("foobar")); - AMQBody* body=f.getBody(); - BOOST_CHECK(dynamic_cast(body)); - Buffer b(f.encodedSize(); - f.encode(b); - b.flip(); - Frame g; - g.decode(b); - AMQContentBody* content=dynamic_cast(g.getBody()); - BOOST_REQUIRE(content); - BOOST_CHECK_EQUAL(content->getData(), "foobar"); -} - -QPID_AUTO_TEST_CASE(testMethodBody) { - FieldTable args; - args.setString("foo", "bar"); - Frame f( - 42, QueueDeclareBody(ProtocolVersion(), 1, "q", "altex", - true, false, true, false, true, args)); - BOOST_CHECK_EQUAL(f.getChannel(), 42); - Buffer b(f.encodedSize(); - f.encode(b); - b.flip(); - Frame g; - g.decode(b); - BOOST_CHECK_EQUAL(f.getChannel(), g.getChannel()); - QueueDeclareBody* declare=dynamic_cast(g.getBody()); - BOOST_REQUIRE(declare); - BOOST_CHECK_EQUAL(declare->getAlternateExchange(), "altex"); - BOOST_CHECK_EQUAL(lexical_cast(*f.getBody()), lexical_cast(*g.getBody())); -} - -QPID_AUTO_TEST_CASE(testLoop) { - // Run in a loop so heap profiler can spot any allocations. - Buffer b(1024); - for (int i = 0; i < 100; ++i) { - Frame ctor(2, AccessRequestOkBody(ProtocolVersion(), 42)); - Frame assign(3); - assign.body = AccessRequestOkBody(ProtocolVersion(), 42); - assign.encode(b); - b.flip(); - Frame g; - g.decode(b); - BOOST_REQUIRE(dynamic_cast(g.getBody())->getTicket() == 42); - } -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/FrameDecoder.cpp b/qpid/cpp/src/tests/FrameDecoder.cpp deleted file mode 100644 index 9eeff2a41e..0000000000 --- a/qpid/cpp/src/tests/FrameDecoder.cpp +++ /dev/null @@ -1,78 +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 "unit_test.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FrameDecoder.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/Buffer.h" -#include - - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(FrameDecoderTest) - -using namespace std; -using namespace qpid::framing; - - -string makeData(int size) { - string data; - data.resize(size); - for (int i =0; i < size; ++i) - data[i] = 'a' + (i%26); - return data; -} -string encodeFrame(string data) { - AMQFrame f((AMQContentBody(data))); - string encoded; - encoded.resize(f.encodedSize()); - Buffer b(&encoded[0], encoded.size()); - f.encode(b); - return encoded; -} - -string getData(const AMQFrame& frame) { - const AMQContentBody* content = dynamic_cast(frame.getBody()); - BOOST_CHECK(content); - return content->getData(); -} - -QPID_AUTO_TEST_CASE(testByteFragments) { - string data = makeData(42); - string encoded = encodeFrame(data); - FrameDecoder decoder; - for (size_t i = 0; i < encoded.size()-1; ++i) { - Buffer buf(&encoded[i], 1); - BOOST_CHECK(!decoder.decode(buf)); - } - Buffer buf(&encoded[encoded.size()-1], 1); - BOOST_CHECK(decoder.decode(buf)); - BOOST_CHECK_EQUAL(data, getData(decoder.getFrame())); -} - - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/FramingTest.cpp b/qpid/cpp/src/tests/FramingTest.cpp deleted file mode 100644 index 2392b6fec4..0000000000 --- a/qpid/cpp/src/tests/FramingTest.cpp +++ /dev/null @@ -1,168 +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/client/Connection.h" -#include "qpid/client/Connector.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/FieldValue.h" -#include "unit_test.h" - -#include -#include -#include - -#include -#include -#include - -using namespace qpid; -using namespace qpid::framing; -using namespace std; - -namespace qpid { -namespace tests { - -template -std::string tostring(const T& x) -{ - std::ostringstream out; - out << x; - return out.str(); -} - -QPID_AUTO_TEST_SUITE(FramingTestSuite) - -QPID_AUTO_TEST_CASE(testMessageTransferBody) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - MessageTransferBody in(version, "my-exchange", 1, 1); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - MessageTransferBody out(version); - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testConnectionSecureBody) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - std::string s = "security credential"; - ConnectionSecureBody in(version, s); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - ConnectionSecureBody out(version); - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testConnectionRedirectBody) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - std::string a = "hostA"; - std::string b = "hostB"; - Array hosts(0x95); - hosts.add(boost::shared_ptr(new Str16Value(a))); - hosts.add(boost::shared_ptr(new Str16Value(b))); - - ConnectionRedirectBody in(version, a, hosts); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - ConnectionRedirectBody out(version); - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testQueueDeclareBody) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - QueueDeclareBody in(version, "name", "dlq", true, false, true, false, FieldTable()); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - QueueDeclareBody out(version); - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testConnectionRedirectBodyFrame) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - std::string a = "hostA"; - std::string b = "hostB"; - Array hosts(0x95); - hosts.add(boost::shared_ptr(new Str16Value(a))); - hosts.add(boost::shared_ptr(new Str16Value(b))); - - AMQFrame in((ConnectionRedirectBody(version, a, hosts))); - in.setChannel(999); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - AMQFrame out; - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testMessageCancelBodyFrame) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - AMQFrame in((MessageCancelBody(version, "tag"))); - in.setChannel(999); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - AMQFrame out; - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(badStrings) { - char data[(65535 + 2) + (255 + 1)]; - Buffer b(data, sizeof(data)); - BOOST_CHECK_THROW(b.putShortString(std::string(256, 'X')), - Exception); - BOOST_CHECK_THROW(b.putMediumString(std::string(65536, 'X')), - Exception); - b.putShortString(std::string(255, 'X')); - b.putMediumString(std::string(65535, 'X')); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/HeaderTest.cpp b/qpid/cpp/src/tests/HeaderTest.cpp deleted file mode 100644 index 4b16f3c793..0000000000 --- a/qpid/cpp/src/tests/HeaderTest.cpp +++ /dev/null @@ -1,114 +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 -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/FieldValue.h" -#include "unit_test.h" - -using namespace qpid::framing; -using namespace std; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(HeaderTestSuite) - -QPID_AUTO_TEST_CASE(testGenericProperties) -{ - AMQHeaderBody body; - body.get(true)->getApplicationHeaders().setString( - "A", "BCDE"); - char buff[100]; - Buffer wbuffer(buff, 100); - body.encode(wbuffer); - - Buffer rbuffer(buff, 100); - AMQHeaderBody body2; - body2.decode(rbuffer, body.encodedSize()); - MessageProperties* props = - body2.get(true); - BOOST_CHECK_EQUAL( - string("BCDE"), - props->getApplicationHeaders().get("A")->get()); -} - -QPID_AUTO_TEST_CASE(testMessageProperties) -{ - AMQFrame out((AMQHeaderBody())); - MessageProperties* props1 = - out.castBody()->get(true); - - props1->setContentLength(42); - props1->setMessageId(Uuid(true)); - props1->setCorrelationId("correlationId"); - props1->setReplyTo(ReplyTo("ex","key")); - props1->setContentType("contentType"); - props1->setContentEncoding("contentEncoding"); - props1->setUserId("userId"); - props1->setAppId("appId"); - - char buff[10000]; - Buffer wbuffer(buff, 10000); - out.encode(wbuffer); - - Buffer rbuffer(buff, 10000); - AMQFrame in; - in.decode(rbuffer); - MessageProperties* props2 = - in.castBody()->get(true); - - BOOST_CHECK_EQUAL(props1->getContentLength(), props2->getContentLength()); - BOOST_CHECK_EQUAL(props1->getMessageId(), props2->getMessageId()); - BOOST_CHECK_EQUAL(props1->getCorrelationId(), props2->getCorrelationId()); - BOOST_CHECK_EQUAL(props1->getContentType(), props2->getContentType()); - BOOST_CHECK_EQUAL(props1->getContentEncoding(), props2->getContentEncoding()); - BOOST_CHECK_EQUAL(props1->getUserId(), props2->getUserId()); - BOOST_CHECK_EQUAL(props1->getAppId(), props2->getAppId()); - -} - -QPID_AUTO_TEST_CASE(testDeliveryProperies) -{ - AMQFrame out((AMQHeaderBody())); - DeliveryProperties* props1 = - out.castBody()->get(true); - - props1->setDiscardUnroutable(true); - props1->setExchange("foo"); - - char buff[10000]; - Buffer wbuffer(buff, 10000); - out.encode(wbuffer); - - Buffer rbuffer(buff, 10000); - AMQFrame in; - in.decode(rbuffer); - DeliveryProperties* props2 = - in.castBody()->get(true); - - BOOST_CHECK(props2->getDiscardUnroutable()); - BOOST_CHECK_EQUAL(string("foo"), props2->getExchange()); - BOOST_CHECK(!props2->hasTimestamp()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/HeadersExchangeTest.cpp b/qpid/cpp/src/tests/HeadersExchangeTest.cpp deleted file mode 100644 index 3e68b84bc3..0000000000 --- a/qpid/cpp/src/tests/HeadersExchangeTest.cpp +++ /dev/null @@ -1,194 +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/Exception.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/Message.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "MessageUtils.h" -#include "unit_test.h" - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::types; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(HeadersExchangeTestSuite) - -QPID_AUTO_TEST_CASE(testMatchAll) -{ - FieldTable b; - b.setString("x-match", "all"); - b.setString("foo", "FOO"); - b.setInt("n", 42); - - Variant::Map m; - const int32_t int_n(42); - m["foo"] = "FOO"; - m["n"] = int_n; - BOOST_CHECK(HeadersExchange::match(b, MessageUtils::createMessage(m, "", "", true))); - - // Ignore extras. - m["extra"] = "x"; - BOOST_CHECK(HeadersExchange::match(b, MessageUtils::createMessage(m, "", "", true))); - - // Fail mismatch, wrong value. - m["foo"] = "NotFoo"; - BOOST_CHECK(!HeadersExchange::match(b, MessageUtils::createMessage(m, "", "", true))); - - // Fail mismatch, missing value - Variant::Map n; - n["n"] = int_n; - n["extra"] = "x"; - BOOST_CHECK(!HeadersExchange::match(b, MessageUtils::createMessage(n, "", "", true))); -} - -QPID_AUTO_TEST_CASE(testMatchAny) -{ - FieldTable b; - b.setString("x-match", "any"); - b.setString("foo", "FOO"); - b.setInt("n", 42); - - Variant::Map n; - Variant::Map m; - m["foo"] = "FOO"; - BOOST_CHECK(!HeadersExchange::match(b, MessageUtils::createMessage(n, "", "", true))); - BOOST_CHECK(HeadersExchange::match(b, MessageUtils::createMessage(m, "", "", true))); - const int32_t int_n(42); - m["n"] = int_n; - BOOST_CHECK(HeadersExchange::match(b, MessageUtils::createMessage(m, "", "", true))); -} - -QPID_AUTO_TEST_CASE(testMatchEmptyValue) -{ - FieldTable b; - b.setString("x-match", "all"); - b.set("foo", FieldTable::ValuePtr()); - b.set("n", FieldTable::ValuePtr()); - Variant::Map m; - BOOST_CHECK(!HeadersExchange::match(b, MessageUtils::createMessage(m, "", "", true))); -} - -QPID_AUTO_TEST_CASE(testMatchEmptyArgs) -{ - FieldTable b; - Variant::Map m; - m["foo"] = "FOO"; - Message msg = MessageUtils::createMessage(m, "", "", true); - - b.setString("x-match", "all"); - BOOST_CHECK(HeadersExchange::match(b, msg)); - b.setString("x-match", "any"); - BOOST_CHECK(!HeadersExchange::match(b, msg)); -} - - -QPID_AUTO_TEST_CASE(testMatchNoXMatch) -{ - FieldTable b; - b.setString("foo", "FOO"); - Variant::Map m; - m["foo"] = "FOO"; - BOOST_CHECK(!HeadersExchange::match(b, MessageUtils::createMessage(m, "", "", true))); -} - -QPID_AUTO_TEST_CASE(testBindNoXMatch) -{ - HeadersExchange exchange("test"); - Queue::shared_ptr queue; - std::string key; - FieldTable args; - try { - //just checking this doesn't cause assertion etc - exchange.bind(queue, key, &args); - } catch(qpid::Exception&) { - //expected - } -} - - -QPID_AUTO_TEST_CASE(testMatchSizedIntUint) -{ - typedef std::list vml; - - const int8_t i8(1); - const int16_t i16(1); - const int32_t i32(1); - const int64_t i64(1); - const uint8_t u8(1); - const uint16_t u16(1); - const uint32_t u32(1); - const uint64_t u64(1); - - Variant::Map mi8, mi16, mi32, mi64; - Variant::Map mu8, mu16, mu32, mu64; - - mi8["bk"] = i8; - mi16["bk"] = i16; - mi32["bk"] = i32; - mi64["bk"] = i64; - mu8["bk"] = u8; - mu16["bk"] = u16; - mu32["bk"] = u32; - mu64["bk"] = u64; - - vml mMap; - mMap.push_back(mi8); - mMap.push_back(mi16); - mMap.push_back(mi32); - mMap.push_back(mi64); - mMap.push_back(mu8); - mMap.push_back(mu16); - mMap.push_back(mu32); - mMap.push_back(mu64); - - for (vml::iterator bVal=mMap.begin(); bVal!=mMap.end(); ++bVal) { - FieldTable b; - qpid::amqp_0_10::translate(*bVal, b); - b.setString("x-match", "all"); - for (vml::iterator mVal=mMap.begin(); mVal!=mMap.end(); ++mVal) { - BOOST_CHECK(HeadersExchange::match(b, MessageUtils::createMessage(*mVal, "", "", true))); - } - } -} - -// TODO: Headers exchange match on single - -QPID_AUTO_TEST_CASE(testMatchFloatDouble) -{ - const double iFloat(1.0); - Variant::Map m; - m["bk"] = iFloat; - - FieldTable b; - qpid::amqp_0_10::translate(m, b); - b.setString("x-match", "all"); - BOOST_CHECK(HeadersExchange::match(b, MessageUtils::createMessage(m, "", "", true))); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/InlineAllocator.cpp b/qpid/cpp/src/tests/InlineAllocator.cpp deleted file mode 100644 index a4c4d64cea..0000000000 --- a/qpid/cpp/src/tests/InlineAllocator.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/InlineAllocator.h" -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(InlineAllocatorTestSuite) - -using namespace qpid; -using namespace std; - -QPID_AUTO_TEST_CASE(testAllocate) { - InlineAllocator, 2> alloc; - - char* p = alloc.allocate(1); - BOOST_CHECK(p == (char*)&alloc); - alloc.deallocate(p,1); - - p = alloc.allocate(2); - BOOST_CHECK(p == (char*)&alloc); - alloc.deallocate(p,2); - - p = alloc.allocate(3); - BOOST_CHECK(p != (char*)&alloc); - alloc.deallocate(p,3); -} - -QPID_AUTO_TEST_CASE(testAllocateFull) { - InlineAllocator, 1> alloc; - - char* p = alloc.allocate(1); - BOOST_CHECK(p == (char*)&alloc); - - char* q = alloc.allocate(1); - BOOST_CHECK(q != (char*)&alloc); - - alloc.deallocate(p,1); - p = alloc.allocate(1); - BOOST_CHECK(p == (char*)&alloc); - - alloc.deallocate(p,1); - alloc.deallocate(q,1); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/InlineVector.cpp b/qpid/cpp/src/tests/InlineVector.cpp deleted file mode 100644 index ba5165886d..0000000000 --- a/qpid/cpp/src/tests/InlineVector.cpp +++ /dev/null @@ -1,128 +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/InlineVector.h" -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(InlineVectorTestSuite) - -using namespace qpid; -using namespace std; - -typedef InlineVector Vec; - -bool isInline(const Vec& v) { - // If nothing, give it the benefit of the doubt; - // can't take address of nothing. - if (v.size() <= 0) - return true; - return (const char*)&v <= (const char*)(&v[0]) && - (const char*)(&v[0]) < (const char*)&v+sizeof(v); -} - -QPID_AUTO_TEST_CASE(testCtor) { - { - Vec v; - BOOST_CHECK(isInline(v)); - BOOST_CHECK(v.empty()); - } - { - Vec v(3, 42); - BOOST_CHECK(isInline(v)); - BOOST_CHECK_EQUAL(3u, v.size()); - BOOST_CHECK_EQUAL(v[0], 42); - BOOST_CHECK_EQUAL(v[2], 42); - - Vec u(v); - BOOST_CHECK(isInline(u)); - BOOST_CHECK_EQUAL(3u, u.size()); - BOOST_CHECK_EQUAL(u[0], 42); - BOOST_CHECK_EQUAL(u[2], 42); - } - - { - Vec v(4, 42); - - BOOST_CHECK_EQUAL(v.size(), 4u); - BOOST_CHECK(!isInline(v)); - Vec u(v); - BOOST_CHECK_EQUAL(u.size(), 4u); - BOOST_CHECK(!isInline(u)); - } -} - -QPID_AUTO_TEST_CASE(testInsert) { - { - Vec v; - v.push_back(1); - BOOST_CHECK_EQUAL(v.size(), 1u); - BOOST_CHECK_EQUAL(v.back(), 1); - BOOST_CHECK(isInline(v)); - - v.insert(v.begin(), 2); - BOOST_CHECK_EQUAL(v.size(), 2u); - BOOST_CHECK_EQUAL(v.back(), 1); - BOOST_CHECK(isInline(v)); - - v.push_back(3); - BOOST_CHECK(isInline(v)); - - v.push_back(4); - - BOOST_CHECK(!isInline(v)); - } - { - Vec v(3,42); - v.insert(v.begin(), 9); - BOOST_CHECK_EQUAL(v.size(), 4u); - BOOST_CHECK(!isInline(v)); - } - { - Vec v(3,42); - v.insert(v.begin()+1, 9); - BOOST_CHECK(!isInline(v)); - BOOST_CHECK_EQUAL(v.size(), 4u); - } -} - -QPID_AUTO_TEST_CASE(testAssign) { - Vec v(3,42); - Vec u; - u = v; - BOOST_CHECK(isInline(u)); - u.push_back(4); - BOOST_CHECK(!isInline(u)); - v = u; - BOOST_CHECK(!isInline(v)); -} - -QPID_AUTO_TEST_CASE(testResize) { - Vec v; - v.resize(5); - BOOST_CHECK(!isInline(v)); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/ManagementTest.cpp b/qpid/cpp/src/tests/ManagementTest.cpp deleted file mode 100644 index 98ef591fae..0000000000 --- a/qpid/cpp/src/tests/ManagementTest.cpp +++ /dev/null @@ -1,97 +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/ManagementObject.h" -#include "qpid/framing/Buffer.h" -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ManagementTestSuite) - -using namespace qpid::framing; -using namespace qpid::management; - -QPID_AUTO_TEST_CASE(testObjectIdSerializeStream) { - std::string text("0-10-4-2500-80000000000()"); - std::stringstream input(text); - - ObjectId oid(input); - - std::stringstream output; - output << oid; - - BOOST_CHECK_EQUAL(text, output.str()); -} - -QPID_AUTO_TEST_CASE(testObjectIdSerializeString) { - std::string text("0-10-4-2500-80000000000()"); - - ObjectId oid(text); - - std::stringstream output; - output << oid; - - BOOST_CHECK_EQUAL(text, output.str()); -} - -QPID_AUTO_TEST_CASE(testObjectIdEncode) { - qpid::types::Variant::Map oidMap; - - ObjectId oid(1, 2, 3, 9999); - oid.setV2Key("testkey"); - oid.setAgentName("myAgent"); - - std::stringstream out1; - out1 << oid; - - BOOST_CHECK_EQUAL(out1.str(), "1-2-3-myAgent-9999(testkey)"); -} - -QPID_AUTO_TEST_CASE(testObjectIdAttach) { - AgentAttachment agent; - ObjectId oid(&agent, 10, 20); - oid.setV2Key("GabbaGabbaHey"); - oid.setAgentName("MrSmith"); - - std::stringstream out1; - out1 << oid; - - BOOST_CHECK_EQUAL(out1.str(), "10-20-0-MrSmith-0(GabbaGabbaHey)"); - - agent.setBanks(30, 40); - std::stringstream out2; - out2 << oid; - - BOOST_CHECK_EQUAL(out2.str(), "10-20-30-MrSmith-0(GabbaGabbaHey)"); -} - -QPID_AUTO_TEST_CASE(testObjectIdCreate) { - ObjectId oid("some-agent-name", "an-object-name"); - - BOOST_CHECK_EQUAL(oid.getAgentName(), "some-agent-name"); - BOOST_CHECK_EQUAL(oid.getV2Key(), "an-object-name"); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/MessageReplayTracker.cpp b/qpid/cpp/src/tests/MessageReplayTracker.cpp deleted file mode 100644 index c0778247f0..0000000000 --- a/qpid/cpp/src/tests/MessageReplayTracker.cpp +++ /dev/null @@ -1,104 +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 "unit_test.h" -#include "BrokerFixture.h" -#include "qpid/client/MessageReplayTracker.h" -#include "qpid/sys/Time.h" - -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(MessageReplayTrackerTests) - -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - -class ReplayBufferChecker -{ - public: - - ReplayBufferChecker(uint from, uint to) : end(to), i(from) {} - - void operator()(const Message& m) - { - if (i > end) BOOST_FAIL("Extra message found: " + m.getData()); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i++)).str(), m.getData()); - } - private: - const uint end; - uint i; - -}; - -QPID_AUTO_TEST_CASE(testReplay) -{ - SessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - MessageReplayTracker tracker(10); - tracker.init(fix.session); - for (uint i = 0; i < 5; i++) { - Message message((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - tracker.send(message); - } - ReplayBufferChecker checker(1, 10); - tracker.foreach(checker); - - tracker.replay(fix.session); - for (uint j = 0; j < 2; j++) {//each message should have been sent twice - for (uint i = 0; i < 5; i++) { - Message m; - BOOST_CHECK(fix.subs.get(m, "my-queue", TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData()); - } - } - Message m; - BOOST_CHECK(!fix.subs.get(m, "my-queue")); -} - -QPID_AUTO_TEST_CASE(testCheckCompletion) -{ - SessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - MessageReplayTracker tracker(10); - tracker.init(fix.session); - for (uint i = 0; i < 5; i++) { - Message message((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - tracker.send(message); - } - fix.session.sync();//ensures all messages are complete - tracker.checkCompletion(); - tracker.replay(fix.session); - Message received; - for (uint i = 0; i < 5; i++) { - BOOST_CHECK(fix.subs.get(received, "my-queue")); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), received.getData()); - } - BOOST_CHECK(!fix.subs.get(received, "my-queue")); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/MessageTest.cpp b/qpid/cpp/src/tests/MessageTest.cpp deleted file mode 100644 index a6c5157b47..0000000000 --- a/qpid/cpp/src/tests/MessageTest.cpp +++ /dev/null @@ -1,89 +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/broker/Message.h" -#include "qpid/broker/Protocol.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/Uuid.h" -#include "MessageUtils.h" - -#include "unit_test.h" - -#include - -using namespace qpid::broker; -using namespace qpid::framing; - -using std::string; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(MessageTestSuite) - -QPID_AUTO_TEST_CASE(testEncodeDecode) -{ - string exchange = "MyExchange"; - string routingKey = "MyRoutingKey"; - uint64_t ttl(60); - Uuid messageId(true); - string data("abcdefghijklmn"); - - qpid::types::Variant::Map properties; - properties["routing-key"] = routingKey; - properties["ttl"] = ttl; - properties["durable"] = true; - properties["message-id"] = qpid::types::Uuid(messageId.data()); - properties["abc"] = "xyz"; - Message msg = MessageUtils::createMessage(properties, data); - - std::vector bytes(msg.getPersistentContext()->encodedSize()); - qpid::framing::Buffer buffer(&bytes[0], bytes.size()); - msg.getPersistentContext()->encode(buffer); - buffer.reset(); - ProtocolRegistry registry(std::set(), 0); - msg = registry.decode(buffer); - - BOOST_CHECK_EQUAL(routingKey, msg.getRoutingKey()); - BOOST_CHECK_EQUAL((uint64_t) data.size(), msg.getContent().size()); - BOOST_CHECK_EQUAL(data, msg.getContent()); - //BOOST_CHECK_EQUAL(messageId, msg->getProperties()->getMessageId()); - BOOST_CHECK_EQUAL(string("xyz"), msg.getPropertyAsString("abc")); - BOOST_CHECK(msg.isPersistent()); -} - -QPID_AUTO_TEST_CASE(testMessageProperties) -{ - string data("abcdefghijklmn"); - - qpid::types::Variant::Map properties; - properties["abc"] = "xyz"; - Message msg = MessageUtils::createMessage(properties, data); - - // Regression test that looking up a property doesn't return a prefix - BOOST_CHECK_EQUAL(msg.getProperty("abcdef").getType(), qpid::types::VAR_VOID); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/MessageUtils.h b/qpid/cpp/src/tests/MessageUtils.h deleted file mode 100644 index f05b0d8b20..0000000000 --- a/qpid/cpp/src/tests/MessageUtils.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef TESTS_MESSAGEUTILS_H -#define TESTS_MESSAGEUTILS_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/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/Uuid.h" -#include "qpid/types/Variant.h" -#include "qpid/amqp_0_10/Codecs.h" - -using namespace qpid; -using namespace broker; -using namespace framing; - -namespace qpid { -namespace tests { - -struct MessageUtils -{ - static Message createMessage(const qpid::types::Variant::Map& properties, - const std::string& content="", - const std::string& destination = "", - bool replaceHeaders = false - ) - { - boost::intrusive_ptr msg(new broker::amqp_0_10::MessageTransfer()); - - AMQFrame method(( MessageTransferBody(ProtocolVersion(), destination, 0, 0))); - AMQFrame header((AMQHeaderBody())); - - msg->getFrames().append(method); - msg->getFrames().append(header); - if (content.size()) { - msg->getFrames().getHeaders()->get(true)->setContentLength(content.size()); - AMQFrame data((AMQContentBody(content))); - msg->getFrames().append(data); - } - if (!replaceHeaders) { - for (qpid::types::Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - if (i->first == "routing-key" && !i->second.isVoid()) { - msg->getFrames().getHeaders()->get(true)->setRoutingKey(i->second); - } else if (i->first == "message-id" && !i->second.isVoid()) { - qpid::types::Uuid id = i->second; - qpid::framing::Uuid id2(id.data()); - msg->getFrames().getHeaders()->get(true)->setMessageId(id2); - } else if (i->first == "ttl" && !i->second.isVoid()) { - msg->getFrames().getHeaders()->get(true)->setTtl(i->second); - } else if (i->first == "priority" && !i->second.isVoid()) { - msg->getFrames().getHeaders()->get(true)->setPriority(i->second); - } else if (i->first == "durable" && !i->second.isVoid()) { - msg->getFrames().getHeaders()->get(true)->setDeliveryMode(i->second.asBool() ? 2 : 1); - } else { - msg->getFrames().getHeaders()->get(true)->getApplicationHeaders().setString(i->first, i->second); - } - } - } else { - framing::FieldTable newHeaders; - qpid::amqp_0_10::translate(properties, newHeaders); - msg->getFrames().getHeaders()->get(true)->getApplicationHeaders() = newHeaders; - } - return Message(msg, msg); - } - - - static Message createMessage(const std::string& exchange="", const std::string& routingKey="", - uint64_t ttl = 0, bool durable = false, const Uuid& messageId=Uuid(true), - const std::string& content="") - { - boost::intrusive_ptr msg(new broker::amqp_0_10::MessageTransfer()); - - AMQFrame method(( MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - - msg->getFrames().append(method); - msg->getFrames().append(header); - MessageProperties* props = msg->getFrames().getHeaders()->get(true); - props->setContentLength(content.size()); - props->setMessageId(messageId); - msg->getFrames().getHeaders()->get(true)->setRoutingKey(routingKey); - if (durable) - msg->getFrames().getHeaders()->get(true)->setDeliveryMode(2); - if (ttl) - msg->getFrames().getHeaders()->get(true)->setTtl(ttl); - if (content.size()) { - AMQFrame data((AMQContentBody(content))); - msg->getFrames().append(data); - } - if (ttl) msg->computeExpiration(); - return Message(msg, msg); - } -}; - -}} // namespace qpid::tests - -#endif /*!TESTS_MESSAGEUTILS_H*/ diff --git a/qpid/cpp/src/tests/MessagingFixture.h b/qpid/cpp/src/tests/MessagingFixture.h deleted file mode 100644 index 165aefeeec..0000000000 --- a/qpid/cpp/src/tests/MessagingFixture.h +++ /dev/null @@ -1,352 +0,0 @@ -#ifndef TESTS_MESSAGINGFIXTURE_H -#define TESTS_MESSAGINGFIXTURE_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 "BrokerFixture.h" -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Session.h" -#include "qpid/framing/Uuid.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Message.h" -#include "qpid/types/Variant.h" - -#include - -namespace qpid { -namespace tests { - -using qpid::types::Variant; - -struct BrokerAdmin -{ - qpid::client::Connection connection; - qpid::client::Session session; - - BrokerAdmin(uint16_t port) - { - connection.open("localhost", port); - session = connection.newSession(); - } - - void createQueue(const std::string& name) - { - session.queueDeclare(qpid::client::arg::queue=name); - } - - void deleteQueue(const std::string& name) - { - session.queueDelete(qpid::client::arg::queue=name); - } - - void createExchange(const std::string& name, const std::string& type) - { - session.exchangeDeclare(qpid::client::arg::exchange=name, qpid::client::arg::type=type); - } - - void deleteExchange(const std::string& name) - { - session.exchangeDelete(qpid::client::arg::exchange=name); - } - - bool checkQueueExists(const std::string& name) - { - return session.queueQuery(name).getQueue() == name; - } - - bool checkExchangeExists(const std::string& name, std::string& type) - { - qpid::framing::ExchangeQueryResult result = session.exchangeQuery(name); - type = result.getType(); - return !result.getNotFound(); - } - - void send(qpid::client::Message& message, const std::string& exchange=std::string()) - { - session.messageTransfer(qpid::client::arg::destination=exchange, qpid::client::arg::content=message); - } - - ~BrokerAdmin() - { - session.close(); - connection.close(); - } -}; - -struct MessagingFixture : public BrokerFixture -{ - messaging::Connection connection; - messaging::Session session; - BrokerAdmin admin; - - MessagingFixture(const BrokerOptions& opts = BrokerOptions(), bool mgmtEnabled=false) : - BrokerFixture(opts, mgmtEnabled), - connection(open(broker->getPort(Broker::TCP_TRANSPORT))), - session(connection.createSession()), - admin(broker->getPort(Broker::TCP_TRANSPORT)) - { - } - - static messaging::Connection open(uint16_t port) - { - messaging::Connection connection( - (boost::format("amqp:tcp:localhost:%1%") % (port)).str()); - connection.open(); - return connection; - - } - - /** Open a connection to the broker. */ - qpid::messaging::Connection newConnection() - { - qpid::messaging::Connection connection( - (boost::format("amqp:tcp:localhost:%1%") % (broker->getPort(qpid::broker::Broker::TCP_TRANSPORT))).str()); - return connection; - } - - void ping(const qpid::messaging::Address& address) - { - messaging::Receiver r = session.createReceiver(address); - messaging::Sender s = session.createSender(address); - messaging::Message out(framing::Uuid(true).str()); - s.send(out); - messaging::Message in; - BOOST_CHECK(r.fetch(in, 5*messaging::Duration::SECOND)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - r.close(); - s.close(); - } - - ~MessagingFixture() - { - session.close(); - connection.close(); - } -}; - -struct QueueFixture : MessagingFixture -{ - std::string queue; - - QueueFixture(const std::string& name = "test-queue") : queue(name) - { - admin.createQueue(queue); - } - - ~QueueFixture() - { - admin.deleteQueue(queue); - } - -}; - -struct TopicFixture : MessagingFixture -{ - std::string topic; - - TopicFixture(const std::string& name = "test-topic", const std::string& type="fanout") : topic(name) - { - admin.createExchange(topic, type); - } - - ~TopicFixture() - { - admin.deleteExchange(topic); - } - -}; - -struct MultiQueueFixture : MessagingFixture -{ - typedef std::vector::const_iterator const_iterator; - std::vector queues; - - MultiQueueFixture(const std::vector& names = boost::assign::list_of("q1")("q2")("q3")) : queues(names) - { - for (const_iterator i = queues.begin(); i != queues.end(); ++i) { - admin.createQueue(*i); - } - } - - ~MultiQueueFixture() - { - connection.close(); - for (const_iterator i = queues.begin(); i != queues.end(); ++i) { - admin.deleteQueue(*i); - } - } - -}; - -inline std::vector fetch(messaging::Receiver& receiver, int count, messaging::Duration timeout=messaging::Duration::SECOND*5) -{ - std::vector data; - messaging::Message message; - for (int i = 0; i < count && receiver.fetch(message, timeout); i++) { - data.push_back(message.getContent()); - } - return data; -} - - -inline void send(messaging::Sender& sender, uint count = 1, uint start = 1, - const std::string& base = "Message") -{ - for (uint i = start; i < start + count; ++i) { - sender.send(messaging::Message((boost::format("%1%_%2%") % base % i).str())); - } -} - -inline void receive(messaging::Receiver& receiver, uint count = 1, uint start = 1, - const std::string& base = "Message", - messaging::Duration timeout=messaging::Duration::SECOND*5) -{ - for (uint i = start; i < start + count; ++i) { - BOOST_CHECK_EQUAL(receiver.fetch(timeout).getContent(), (boost::format("%1%_%2%") % base % i).str()); - } -} - - -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)) {} - - void createExchange(const std::string& name, const std::string& type, bool durable=false) - { - Variant::Map params; - params["name"]=name; - params["type"]="exchange"; - params["properties"] = Variant::Map(); - params["properties"].asMap()["exchange-type"] = type; - params["properties"].asMap()["durable"] = durable; - methodRequest("create", params); - } - - void deleteExchange(const std::string& name) - { - Variant::Map params; - params["name"]=name; - params["type"]="exchange"; - methodRequest("delete", params); - } - - void createQueue(const std::string& name, bool durable=false, bool autodelete=false, - const Variant::Map& options=Variant::Map()) - { - Variant::Map params; - params["name"]=name; - params["type"]="queue"; - params["properties"] = options; - params["properties"].asMap()["durable"] = durable; - params["properties"].asMap()["auto-delete"] = autodelete; - methodRequest("create", params); - } - - void deleteQueue(const std::string& name) - { - Variant::Map params; - params["name"]=name; - params["type"]="queue"; - methodRequest("delete", params); - } - - void bind(const std::string& exchange, const std::string& queue, const std::string& key, - const Variant::Map& options=Variant::Map()) - { - Variant::Map params; - params["name"]=(boost::format("%1%/%2%/%3%") % (exchange) % (queue) % (key)).str(); - params["type"]="binding"; - params["properties"] = options; - methodRequest("create", params); - } - - void unbind(const std::string& exchange, const std::string& queue, const std::string& key) - { - Variant::Map params; - params["name"]=(boost::format("%1%/%2%/%3%") % (exchange) % (queue) % (key)).str(); - params["type"]="binding"; - methodRequest("delete", params); - } - - 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"] = objectName;; - content["_object_id"] = objectId; - content["_method_name"] = method; - content["_arguments"] = inParams; - - messaging::Message request; - request.setReplyTo(replyTo); - request.getProperties()["x-amqp-0-10.app-id"] = "qmf2"; - request.getProperties()["qmf.opcode"] = "_method_request"; - encode(content, request); - - sender.send(request); - - messaging::Message response; - if (receiver.fetch(response, messaging::Duration::SECOND*5)) { - if (response.getProperties()["x-amqp-0-10.app-id"] == "qmf2") { - std::string opcode = response.getProperties()["qmf.opcode"]; - if (opcode == "_method_response") { - if (outParams) { - Variant::Map m; - decode(response, m); - *outParams = m["_arguments"].asMap(); - } - } else if (opcode == "_exception") { - Variant::Map m; - decode(response, m); - throw Exception(QPID_MSG("Error: " << m["_values"])); - } else { - throw Exception(QPID_MSG("Invalid response received, unexpected opcode: " << opcode)); - } - } else { - throw Exception(QPID_MSG("Invalid response received, not a qmfv2 message: app-id=" - << response.getProperties()["x-amqp-0-10.app-id"])); - } - } else { - throw Exception(QPID_MSG("No response received")); - } - } - private: - messaging::Address replyTo; - messaging::Sender sender; - messaging::Receiver receiver; -}; - -}} // namespace qpid::tests - -#endif /*!TESTS_MESSAGINGFIXTURE_H*/ diff --git a/qpid/cpp/src/tests/MessagingLogger.cpp b/qpid/cpp/src/tests/MessagingLogger.cpp deleted file mode 100644 index 195a33db12..0000000000 --- a/qpid/cpp/src/tests/MessagingLogger.cpp +++ /dev/null @@ -1,149 +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/log/Statement.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Logger.h" - -#include -#include -#include - -#include - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(MessagingLoggerSuite) - -class StringLogger : public qpid::messaging::LoggerOutput { - std::string& outString; - - void log(qpid::messaging::Level /*level*/, bool user, const char* /*file*/, int /*line*/, const char* /*function*/, const std::string& message){ - if (user) outString += "User "; - outString += message; - } - -public: - StringLogger(std::string& os) : - outString(os) - {} -}; - -#define SETUP_LOGGING(logger, ...) \ -do {\ - const char* args[]={"", __VA_ARGS__, 0};\ - qpid::messaging::Logger::configure((sizeof (args)/sizeof (char*))-1, args);\ - logOutput.clear();\ - qpid::messaging::Logger::setOutput(logger);\ -} while (0) -#define LOG_LEVEL(level)\ - QPID_LOG(level, #level " level output") -#define LOG_ALL_LOGGING_LEVELS \ -do { \ - LOG_LEVEL(trace); \ - LOG_LEVEL(debug); \ - LOG_LEVEL(info); \ - LOG_LEVEL(notice); \ - LOG_LEVEL(warning); \ - LOG_LEVEL(critical); \ -} while (0) -#define LOG_USER_LEVEL(level)\ - qpid::messaging::Logger::log(qpid::messaging::level, __FILE__, __LINE__, __FUNCTION__, #level " message") -#define LOG_ALL_USER_LOGGING_LEVELS \ -do { \ - LOG_USER_LEVEL(trace); \ - LOG_USER_LEVEL(debug); \ - LOG_USER_LEVEL(info); \ - LOG_USER_LEVEL(notice); \ - LOG_USER_LEVEL(warning); \ - LOG_USER_LEVEL(critical); \ -} while (0) - -std::string logOutput; - -QPID_AUTO_TEST_CASE(testLoggerLevels) -{ - StringLogger logger(logOutput); - - SETUP_LOGGING(logger, "--log-enable", "debug"); - LOG_ALL_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "debug level output\ncritical level output\n"); - - SETUP_LOGGING(logger, "--log-enable", "trace+", "--log-disable", "notice"); - LOG_ALL_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "trace level output\ndebug level output\ninfo level output\nwarning level output\ncritical level output\n"); - - SETUP_LOGGING(logger, "--log-enable", "info-"); - LOG_ALL_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "trace level output\ndebug level output\ninfo level output\ncritical level output\n"); - - SETUP_LOGGING(logger, "--log-enable", "trace+", "--log-disable", "notice+"); - LOG_ALL_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "trace level output\ndebug level output\ninfo level output\ncritical level output\n"); -} - -QPID_AUTO_TEST_CASE(testUserLoggerLevels) -{ - StringLogger logger(logOutput); - - SETUP_LOGGING(logger, "--log-enable", "debug"); - LOG_ALL_USER_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "User debug message\nUser critical message\n"); - - SETUP_LOGGING(logger, "--log-enable", "trace+", "--log-disable", "notice"); - LOG_ALL_USER_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "User trace message\nUser debug message\nUser info message\nUser warning message\nUser critical message\n"); - - SETUP_LOGGING(logger, "--log-enable", "info-"); - LOG_ALL_USER_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "User trace message\nUser debug message\nUser info message\nUser critical message\n"); - - SETUP_LOGGING(logger, "--log-enable", "trace+", "--log-disable", "notice+"); - LOG_ALL_USER_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "User trace message\nUser debug message\nUser info message\nUser critical message\n"); - - SETUP_LOGGING(logger, "--log-disable", "trace+"); - LOG_ALL_LOGGING_LEVELS; - LOG_ALL_USER_LOGGING_LEVELS; - BOOST_CHECK_EQUAL(logOutput, "critical level output\nUser critical message\n"); -} - -QPID_AUTO_TEST_CASE(testLoggerUsage) -{ - qpid::messaging::Logger::configure(0, 0, "blah"); - std::string u = qpid::messaging::Logger::usage(); - - BOOST_CHECK(!u.empty()); - BOOST_CHECK( u.find("--blah-log-enable")!=u.npos ); -} - -QPID_AUTO_TEST_CASE(testLoggerException) -{ - const char* args[]={"", "--blah-log-enable", "illegal", 0}; - BOOST_CHECK_THROW(qpid::messaging::Logger::configure(3, args, "blah"), qpid::messaging::MessagingException); -} - -QPID_AUTO_TEST_SUITE_END() -}} diff --git a/qpid/cpp/src/tests/MessagingSessionTests.cpp b/qpid/cpp/src/tests/MessagingSessionTests.cpp deleted file mode 100644 index 3b7ba34fe9..0000000000 --- a/qpid/cpp/src/tests/MessagingSessionTests.cpp +++ /dev/null @@ -1,1628 +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 "MessagingFixture.h" -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Session.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Session.h" -#include "qpid/framing/ExchangeQueryResult.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/Time.h" -#include -#include -#include -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(MessagingSessionTests) - -using namespace qpid::messaging; -using namespace qpid::types; -using namespace qpid; -using qpid::broker::BrokerOptions; -using qpid::framing::Uuid; - - -QPID_AUTO_TEST_CASE(testSimpleSendReceive) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - out.setSubject("test-subject"); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::SECOND * 5); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - BOOST_CHECK_EQUAL(in.getSubject(), out.getSubject()); -} - -QPID_AUTO_TEST_CASE(testSyncSendReceive) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - sender.send(out, true); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::IMMEDIATE); - fix.session.acknowledge(true); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); -} - -QPID_AUTO_TEST_CASE(testSendReceiveHeaders) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - for (uint i = 0; i < 10; ++i) { - out.getProperties()["a"] = i; - out.setProperty("b", i + 100); - sender.send(out); - } - uint8_t v1(255u); - int8_t v2(-120); - out.getProperties()["c"] = v1; - out.getProperties()["d"] = v2; - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in; - for (uint i = 0; i < 10; ++i) { - BOOST_CHECK(receiver.fetch(in, Duration::SECOND * 5)); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - BOOST_CHECK_EQUAL(in.getProperties()["a"].asUint32(), i); - BOOST_CHECK_EQUAL(in.getProperties()["b"].asUint32(), i + 100); - fix.session.acknowledge(); - } - BOOST_CHECK(receiver.fetch(in, Duration::SECOND * 5)); - Variant& c = in.getProperties()["c"]; - BOOST_CHECK_EQUAL(c.getType(), VAR_UINT8); - BOOST_CHECK_EQUAL(c.asUint8(), v1); - Variant& d = in.getProperties()["d"]; - BOOST_CHECK_EQUAL(d.getType(), VAR_INT8); - BOOST_CHECK_EQUAL(d.asInt8(), v2); -} - -QPID_AUTO_TEST_CASE(testSenderError) -{ - MessagingFixture fix; - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(fix.session.createSender("NonExistentAddress"), qpid::messaging::NotFound); - fix.session = fix.connection.createSession(); - BOOST_CHECK_THROW(fix.session.createSender("NonExistentAddress; {create:receiver}"), - qpid::messaging::NotFound); -} - -QPID_AUTO_TEST_CASE(testReceiverError) -{ - MessagingFixture fix; - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(fix.session.createReceiver("NonExistentAddress"), qpid::messaging::NotFound); - fix.session = fix.connection.createSession(); - BOOST_CHECK_THROW(fix.session.createReceiver("NonExistentAddress; {create:sender}"), - qpid::messaging::NotFound); -} - -QPID_AUTO_TEST_CASE(testSimpleTopic) -{ - TopicFixture fix; - - Sender sender = fix.session.createSender(fix.topic); - Message msg("one"); - sender.send(msg); - Receiver sub1 = fix.session.createReceiver(fix.topic); - sub1.setCapacity(10u); - msg.setContent("two"); - sender.send(msg); - Receiver sub2 = fix.session.createReceiver(fix.topic); - sub2.setCapacity(10u); - msg.setContent("three"); - sender.send(msg); - Receiver sub3 = fix.session.createReceiver(fix.topic); - sub3.setCapacity(10u); - msg.setContent("four"); - sender.send(msg); - BOOST_CHECK_EQUAL(fetch(sub2, 2), boost::assign::list_of("three")("four")); - sub2.close(); - - msg.setContent("five"); - sender.send(msg); - BOOST_CHECK_EQUAL(fetch(sub1, 4), boost::assign::list_of("two")("three")("four")("five")); - BOOST_CHECK_EQUAL(fetch(sub3, 2), boost::assign::list_of("four")("five")); - Message in; - BOOST_CHECK(!sub2.fetch(in, Duration::IMMEDIATE));//TODO: or should this raise an error? - - - //TODO: check pending messages... -} - -QPID_AUTO_TEST_CASE(testNextReceiver) -{ - MultiQueueFixture fix; - - for (uint i = 0; i < fix.queues.size(); i++) { - Receiver r = fix.session.createReceiver(fix.queues[i]); - r.setCapacity(10u); - } - - for (uint i = 0; i < fix.queues.size(); i++) { - Sender s = fix.session.createSender(fix.queues[i]); - Message msg((boost::format("Message_%1%") % (i+1)).str()); - s.send(msg); - } - - for (uint i = 0; i < fix.queues.size(); i++) { - Message msg; - BOOST_CHECK(fix.session.nextReceiver().fetch(msg, Duration::SECOND)); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1)).str()); - } -} - -QPID_AUTO_TEST_CASE(testMapMessage) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - Variant::Map content; - content["abc"] = "def"; - content["pi"] = 3.14f; - Variant utf8("A utf 8 string"); - utf8.setEncoding("utf8"); - content["utf8"] = utf8; - Variant utf16("\x00\x61\x00\x62\x00\x63"); - utf16.setEncoding("utf16"); - content["utf16"] = utf16; - encode(content, out); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - Variant::Map view; - decode(in, view); - BOOST_CHECK_EQUAL(view["abc"].asString(), "def"); - BOOST_CHECK_EQUAL(view["pi"].asFloat(), 3.14f); - BOOST_CHECK_EQUAL(view["utf8"].asString(), utf8.asString()); - BOOST_CHECK_EQUAL(view["utf8"].getEncoding(), utf8.getEncoding()); - BOOST_CHECK_EQUAL(view["utf16"].asString(), utf16.asString()); - BOOST_CHECK_EQUAL(view["utf16"].getEncoding(), utf16.getEncoding()); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testMapMessageWithInitial) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - Variant::Map imap; - imap["abc"] = "def"; - imap["pi"] = 3.14f; - encode(imap, out); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - Variant::Map view; - decode(in, view); - BOOST_CHECK_EQUAL(view["abc"].asString(), "def"); - BOOST_CHECK_EQUAL(view["pi"].asFloat(), 3.14f); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testListMessage) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - Variant::List content; - content.push_back(Variant("abc")); - content.push_back(Variant(1234)); - content.push_back(Variant("def")); - content.push_back(Variant(56.789)); - encode(content, out); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - Variant::List view; - decode(in, view); - BOOST_CHECK_EQUAL(view.size(), content.size()); - BOOST_CHECK_EQUAL(view.front().asString(), "abc"); - BOOST_CHECK_EQUAL(view.back().asDouble(), 56.789); - - Variant::List::const_iterator i = view.begin(); - BOOST_CHECK(i != view.end()); - BOOST_CHECK_EQUAL(i->asString(), "abc"); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asInt64(), 1234); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asString(), "def"); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asDouble(), 56.789); - BOOST_CHECK(++i == view.end()); - - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testListMessageWithInitial) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - Variant::List ilist; - ilist.push_back(Variant("abc")); - ilist.push_back(Variant(1234)); - ilist.push_back(Variant("def")); - ilist.push_back(Variant(56.789)); - encode(ilist, out); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - Variant::List view; - decode(in, view); - BOOST_CHECK_EQUAL(view.size(), ilist.size()); - BOOST_CHECK_EQUAL(view.front().asString(), "abc"); - BOOST_CHECK_EQUAL(view.back().asDouble(), 56.789); - - Variant::List::const_iterator i = view.begin(); - BOOST_CHECK(i != view.end()); - BOOST_CHECK_EQUAL(i->asString(), "abc"); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asInt64(), 1234); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asString(), "def"); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asDouble(), 56.789); - BOOST_CHECK(++i == view.end()); - - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testReject) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message m1("reject-me"); - sender.send(m1); - Message m2("accept-me"); - sender.send(m2); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - BOOST_CHECK_EQUAL(in.getContent(), m1.getContent()); - fix.session.reject(in); - in = receiver.fetch(5 * Duration::SECOND); - BOOST_CHECK_EQUAL(in.getContent(), m2.getContent()); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testAvailable) -{ - MultiQueueFixture fix; - - Receiver r1 = fix.session.createReceiver(fix.queues[0]); - r1.setCapacity(100); - - Receiver r2 = fix.session.createReceiver(fix.queues[1]); - r2.setCapacity(100); - - Sender s1 = fix.session.createSender(fix.queues[0]); - Sender s2 = fix.session.createSender(fix.queues[1]); - - for (uint i = 0; i < 10; ++i) { - s1.send(Message((boost::format("A_%1%") % (i+1)).str())); - } - for (uint i = 0; i < 5; ++i) { - s2.send(Message((boost::format("B_%1%") % (i+1)).str())); - } - qpid::sys::sleep(1);//is there any avoid an arbitrary sleep while waiting for messages to be dispatched? - for (uint i = 0; i < 5; ++i) { - BOOST_CHECK_EQUAL(fix.session.getReceivable(), 15u - 2*i); - BOOST_CHECK_EQUAL(r1.getAvailable(), 10u - i); - BOOST_CHECK_EQUAL(r1.fetch().getContent(), (boost::format("A_%1%") % (i+1)).str()); - BOOST_CHECK_EQUAL(r2.getAvailable(), 5u - i); - BOOST_CHECK_EQUAL(r2.fetch().getContent(), (boost::format("B_%1%") % (i+1)).str()); - fix.session.acknowledge(); - } - for (uint i = 5; i < 10; ++i) { - BOOST_CHECK_EQUAL(fix.session.getReceivable(), 10u - i); - BOOST_CHECK_EQUAL(r1.getAvailable(), 10u - i); - BOOST_CHECK_EQUAL(r1.fetch().getContent(), (boost::format("A_%1%") % (i+1)).str()); - } -} - -QPID_AUTO_TEST_CASE(testUnsettledAcks) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - for (uint i = 0; i < 10; ++i) { - sender.send(Message((boost::format("Message_%1%") % (i+1)).str())); - } - Receiver receiver = fix.session.createReceiver(fix.queue); - for (uint i = 0; i < 10; ++i) { - BOOST_CHECK_EQUAL(receiver.fetch().getContent(), (boost::format("Message_%1%") % (i+1)).str()); - } - BOOST_CHECK_EQUAL(fix.session.getUnsettledAcks(), 0u); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(fix.session.getUnsettledAcks(), 10u); - fix.session.sync(); - BOOST_CHECK_EQUAL(fix.session.getUnsettledAcks(), 0u); -} - -QPID_AUTO_TEST_CASE(testUnsettledSend) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - send(sender, 10); - //Note: this test relies on 'inside knowledge' of the sender - //implementation and the fact that the simple test case makes it - //possible to predict when completion information will be sent to - //the client. TODO: is there a better way of testing this? - BOOST_CHECK_EQUAL(sender.getUnsettled(), 10u); - fix.session.sync(); - BOOST_CHECK_EQUAL(sender.getUnsettled(), 0u); - - Receiver receiver = fix.session.createReceiver(fix.queue); - receive(receiver, 10); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testBrowse) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - send(sender, 10); - Receiver browser1 = fix.session.createReceiver(fix.queue + "; {mode:browse}"); - receive(browser1, 10); - Receiver browser2 = fix.session.createReceiver(fix.queue + "; {mode:browse}"); - receive(browser2, 10); - Receiver releaser1 = fix.session.createReceiver(fix.queue); - Message m1 = releaser1.fetch(messaging::Duration::SECOND*5); - BOOST_CHECK(!m1.getRedelivered()); - fix.session.release(m1); - Receiver releaser2 = fix.session.createReceiver(fix.queue); - Message m2 = releaser2.fetch(messaging::Duration::SECOND*5); - BOOST_CHECK(m2.getRedelivered()); - fix.session.release(m2); - Receiver consumer = fix.session.createReceiver(fix.queue); - receive(consumer, 10); - fix.session.acknowledge(); -} - -struct QueueCreatePolicyFixture : public MessagingFixture -{ - qpid::messaging::Address address; - - QueueCreatePolicyFixture(const std::string& a) : address(a) {} - - void test() - { - ping(address); - BOOST_CHECK(admin.checkQueueExists(address.getName())); - } - - ~QueueCreatePolicyFixture() - { - admin.deleteQueue(address.getName()); - } -}; - -QPID_AUTO_TEST_CASE(testCreatePolicyQueueAlways) -{ - QueueCreatePolicyFixture fix("#; {create:always, node:{type:queue}}"); - fix.test(); -} - -QPID_AUTO_TEST_CASE(testCreatePolicyQueueReceiver) -{ - QueueCreatePolicyFixture fix("#; {create:receiver, node:{type:queue}}"); - Receiver r = fix.session.createReceiver(fix.address); - fix.test(); - r.close(); -} - -QPID_AUTO_TEST_CASE(testCreatePolicyQueueSender) -{ - QueueCreatePolicyFixture fix("#; {create:sender, node:{type:queue}}"); - Sender s = fix.session.createSender(fix.address); - fix.test(); - s.close(); -} - -struct ExchangeCreatePolicyFixture : public MessagingFixture -{ - qpid::messaging::Address address; - const std::string exchangeType; - - ExchangeCreatePolicyFixture(const std::string& a, const std::string& t) : - address(a), exchangeType(t) {} - - void test() - { - ping(address); - std::string actualType; - BOOST_CHECK(admin.checkExchangeExists(address.getName(), actualType)); - BOOST_CHECK_EQUAL(exchangeType, actualType); - } - - ~ExchangeCreatePolicyFixture() - { - admin.deleteExchange(address.getName()); - } -}; - -QPID_AUTO_TEST_CASE(testCreatePolicyTopic) -{ - ExchangeCreatePolicyFixture fix("#; {create:always, node:{type:topic}}", - "topic"); - fix.test(); -} - -QPID_AUTO_TEST_CASE(testCreatePolicyTopicReceiverFanout) -{ - ExchangeCreatePolicyFixture fix("#/my-subject; {create:receiver, node:{type:topic, x-declare:{type:fanout}}}", "fanout"); - Receiver r = fix.session.createReceiver(fix.address); - fix.test(); - r.close(); -} - -QPID_AUTO_TEST_CASE(testCreatePolicyTopicSenderDirect) -{ - ExchangeCreatePolicyFixture fix("#/my-subject; {create:sender, node:{type:topic, x-declare:{type:direct}}}", "direct"); - Sender s = fix.session.createSender(fix.address); - fix.test(); - s.close(); -} - -struct DeletePolicyFixture : public MessagingFixture -{ - enum Mode {RECEIVER, SENDER, ALWAYS, NEVER}; - - std::string getPolicy(Mode mode) - { - switch (mode) { - case SENDER: - return "{delete:sender}"; - case RECEIVER: - return "{delete:receiver}"; - case ALWAYS: - return "{delete:always}"; - case NEVER: - return "{delete:never}"; - } - return ""; - } - - void testAll() - { - test(RECEIVER); - test(SENDER); - test(ALWAYS); - test(NEVER); - } - - virtual ~DeletePolicyFixture() {} - virtual void create(const qpid::messaging::Address&) = 0; - virtual void destroy(const qpid::messaging::Address&) = 0; - virtual bool exists(const qpid::messaging::Address&) = 0; - - void test(Mode mode) - { - qpid::messaging::Address address("testqueue#; " + getPolicy(mode)); - create(address); - - Sender s = session.createSender(address); - Receiver r = session.createReceiver(address); - switch (mode) { - case RECEIVER: - s.close(); - BOOST_CHECK(exists(address)); - r.close(); - BOOST_CHECK(!exists(address)); - break; - case SENDER: - r.close(); - BOOST_CHECK(exists(address)); - s.close(); - BOOST_CHECK(!exists(address)); - break; - case ALWAYS: - s.close(); - BOOST_CHECK(!exists(address)); - break; - case NEVER: - r.close(); - BOOST_CHECK(exists(address)); - s.close(); - BOOST_CHECK(exists(address)); - destroy(address); - } - } -}; - -struct QueueDeletePolicyFixture : DeletePolicyFixture -{ - void create(const qpid::messaging::Address& address) - { - admin.createQueue(address.getName()); - } - void destroy(const qpid::messaging::Address& address) - { - admin.deleteQueue(address.getName()); - } - bool exists(const qpid::messaging::Address& address) - { - return admin.checkQueueExists(address.getName()); - } -}; - -struct ExchangeDeletePolicyFixture : DeletePolicyFixture -{ - const std::string exchangeType; - ExchangeDeletePolicyFixture(const std::string type = "topic") : exchangeType(type) {} - - void create(const qpid::messaging::Address& address) - { - admin.createExchange(address.getName(), exchangeType); - } - void destroy(const qpid::messaging::Address& address) - { - admin.deleteExchange(address.getName()); - } - bool exists(const qpid::messaging::Address& address) - { - std::string actualType; - return admin.checkExchangeExists(address.getName(), actualType) && actualType == exchangeType; - } -}; - -QPID_AUTO_TEST_CASE(testDeletePolicyQueue) -{ - QueueDeletePolicyFixture fix; - fix.testAll(); -} - -QPID_AUTO_TEST_CASE(testDeletePolicyExchange) -{ - ExchangeDeletePolicyFixture fix; - fix.testAll(); -} - -QPID_AUTO_TEST_CASE(testAssertPolicyQueue) -{ - MessagingFixture fix; - std::string a1 = "q; {create:always, assert:always, node:{type:queue, durable:false, x-declare:{arguments:{qpid.max-count:100}}}}"; - Sender s1 = fix.session.createSender(a1); - s1.close(); - Receiver r1 = fix.session.createReceiver(a1); - r1.close(); - - std::string a2 = "q; {assert:receiver, node:{durable:true, x-declare:{arguments:{qpid.max-count:100}}}}"; - Sender s2 = fix.session.createSender(a2); - s2.close(); - BOOST_CHECK_THROW(fix.session.createReceiver(a2), qpid::messaging::AssertionFailed); - - std::string a3 = "q; {assert:sender, node:{x-declare:{arguments:{qpid.max-count:99}}}}"; - BOOST_CHECK_THROW(fix.session.createSender(a3), qpid::messaging::AssertionFailed); - Receiver r3 = fix.session.createReceiver(a3); - r3.close(); - - fix.admin.deleteQueue("q"); -} - -QPID_AUTO_TEST_CASE(testAssertExchangeOption) -{ - MessagingFixture fix; - std::string a1 = "e; {create:always, assert:always, node:{type:topic, x-declare:{type:direct, arguments:{qpid.msg_sequence:True}}}}"; - Sender s1 = fix.session.createSender(a1); - s1.close(); - Receiver r1 = fix.session.createReceiver(a1); - r1.close(); - - std::string a2 = "e; {assert:receiver, node:{type:topic, x-declare:{type:fanout, arguments:{qpid.msg_sequence:True}}}}"; - Sender s2 = fix.session.createSender(a2); - s2.close(); - BOOST_CHECK_THROW(fix.session.createReceiver(a2), qpid::messaging::AssertionFailed); - - std::string a3 = "e; {assert:sender, node:{x-declare:{arguments:{qpid.msg_sequence:False}}}}"; - BOOST_CHECK_THROW(fix.session.createSender(a3), qpid::messaging::AssertionFailed); - Receiver r3 = fix.session.createReceiver(a3); - r3.close(); - - fix.admin.deleteExchange("e"); -} - -QPID_AUTO_TEST_CASE(testGetSender) -{ - QueueFixture fix; - std::string name = fix.session.createSender(fix.queue).getName(); - Sender sender = fix.session.getSender(name); - BOOST_CHECK_EQUAL(name, sender.getName()); - Message out(Uuid(true).str()); - sender.send(out); - Message in; - BOOST_CHECK(fix.session.createReceiver(fix.queue).fetch(in)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - BOOST_CHECK_THROW(fix.session.getSender("UnknownSender"), qpid::messaging::KeyError); -} - -QPID_AUTO_TEST_CASE(testGetReceiver) -{ - QueueFixture fix; - std::string name = fix.session.createReceiver(fix.queue).getName(); - Receiver receiver = fix.session.getReceiver(name); - BOOST_CHECK_EQUAL(name, receiver.getName()); - Message out(Uuid(true).str()); - fix.session.createSender(fix.queue).send(out); - Message in; - BOOST_CHECK(receiver.fetch(in)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - BOOST_CHECK_THROW(fix.session.getReceiver("UnknownReceiver"), qpid::messaging::KeyError); -} - -QPID_AUTO_TEST_CASE(testGetSessionFromConnection) -{ - QueueFixture fix; - fix.connection.createSession("my-session"); - Session session = fix.connection.getSession("my-session"); - Message out(Uuid(true).str()); - session.createSender(fix.queue).send(out); - Message in; - BOOST_CHECK(session.createReceiver(fix.queue).fetch(in)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - BOOST_CHECK_THROW(fix.connection.getSession("UnknownSession"), qpid::messaging::KeyError); -} - -QPID_AUTO_TEST_CASE(testGetConnectionFromSession) -{ - QueueFixture fix; - Message out(Uuid(true).str()); - Sender sender = fix.session.createSender(fix.queue); - sender.send(out); - Message in; - sender.getSession().getConnection().createSession("incoming"); - BOOST_CHECK(fix.connection.getSession("incoming").createReceiver(fix.queue).fetch(in)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); -} - -QPID_AUTO_TEST_CASE(testTx) -{ - QueueFixture fix; - Session ssn1 = fix.connection.createTransactionalSession(); - Session ssn2 = fix.connection.createTransactionalSession(); - Sender sender1 = ssn1.createSender(fix.queue); - Sender sender2 = ssn2.createSender(fix.queue); - Receiver receiver1 = ssn1.createReceiver(fix.queue); - Receiver receiver2 = ssn2.createReceiver(fix.queue); - Message in; - - send(sender1, 5, 1, "A"); - send(sender2, 5, 1, "B"); - ssn2.commit(); - receive(receiver1, 5, 1, "B");//(only those from sender2 should be received) - BOOST_CHECK(!receiver1.fetch(in, Duration::IMMEDIATE));//check there are no more messages - ssn1.rollback(); - receive(receiver2, 5, 1, "B"); - BOOST_CHECK(!receiver2.fetch(in, Duration::IMMEDIATE));//check there are no more messages - ssn2.rollback(); - receive(receiver1, 5, 1, "B"); - BOOST_CHECK(!receiver1.fetch(in, Duration::IMMEDIATE));//check there are no more messages - ssn1.commit(); - //check neither receiver gets any more messages: - BOOST_CHECK(!receiver1.fetch(in, Duration::IMMEDIATE)); - BOOST_CHECK(!receiver2.fetch(in, Duration::IMMEDIATE)); -} - -QPID_AUTO_TEST_CASE(testRelease) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - sender.send(out, true); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message m1 = receiver.fetch(Duration::IMMEDIATE); - fix.session.release(m1); - Message m2 = receiver.fetch(Duration::SECOND * 1); - BOOST_CHECK_EQUAL(m1.getContent(), out.getContent()); - BOOST_CHECK_EQUAL(m1.getContent(), m2.getContent()); - BOOST_CHECK(m2.getRedelivered()); - fix.session.acknowledge(true); -} - -QPID_AUTO_TEST_CASE(testOptionVerification) -{ - MessagingFixture fix; - fix.session.createReceiver("my-queue; {create: always, assert: always, delete: always, node: {type: queue, durable: false, x-declare: {arguments: {a: b}}, x-bindings: [{exchange: amq.fanout}]}, link: {name: abc, durable: false, reliability: exactly-once, x-subscribe: {arguments:{a:b}}, x-bindings:[{exchange: amq.fanout}]}, mode: browse}"); - BOOST_CHECK_THROW(fix.session.createReceiver("my-queue; {invalid-option:blah}"), qpid::messaging::AddressError); -} - -QPID_AUTO_TEST_CASE(testReceiveSpecialProperties) -{ - QueueFixture fix; - - qpid::client::Message out; - out.getDeliveryProperties().setRoutingKey(fix.queue); - out.getMessageProperties().setAppId("my-app-id"); - out.getMessageProperties().setMessageId(qpid::framing::Uuid(true)); - out.getMessageProperties().setContentEncoding("my-content-encoding"); - fix.admin.send(out); - - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::SECOND * 5); - BOOST_CHECK_EQUAL(in.getProperties()["x-amqp-0-10.routing-key"].asString(), out.getDeliveryProperties().getRoutingKey()); - BOOST_CHECK_EQUAL(in.getProperties()["x-amqp-0-10.app-id"].asString(), out.getMessageProperties().getAppId()); - BOOST_CHECK_EQUAL(in.getProperties()["x-amqp-0-10.content-encoding"].asString(), out.getMessageProperties().getContentEncoding()); - BOOST_CHECK_EQUAL(in.getMessageId(), out.getMessageProperties().getMessageId().str()); - fix.session.acknowledge(true); -} - -QPID_AUTO_TEST_CASE(testSendSpecialProperties) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - std::string appId = "my-app-id"; - std::string contentEncoding = "my-content-encoding"; - out.getProperties()["x-amqp-0-10.app-id"] = appId; - out.getProperties()["x-amqp-0-10.content-encoding"] = contentEncoding; - out.setMessageId(qpid::framing::Uuid(true).str()); - sender.send(out, true); - - qpid::client::LocalQueue q; - qpid::client::SubscriptionManager subs(fix.admin.session); - qpid::client::Subscription s = subs.subscribe(q, fix.queue); - qpid::client::Message in = q.get(); - s.cancel(); - fix.admin.session.sync(); - - BOOST_CHECK_EQUAL(in.getMessageProperties().getAppId(), appId); - BOOST_CHECK_EQUAL(in.getMessageProperties().getContentEncoding(), contentEncoding); - BOOST_CHECK_EQUAL(in.getMessageProperties().getMessageId().str(), out.getMessageId()); -} - -QPID_AUTO_TEST_CASE(testExclusiveSubscriber) -{ - QueueFixture fix; - std::string address = (boost::format("%1%; { link: { x-subscribe : { exclusive:true } } }") % fix.queue).str(); - Receiver receiver = fix.session.createReceiver(address); - ScopedSuppressLogging sl; - try { - fix.session.createReceiver(address); - fix.session.sync(); - BOOST_FAIL("Expected exception."); - } catch (const MessagingException& /*e*/) {} -} - - -QPID_AUTO_TEST_CASE(testExclusiveQueueSubscriberAndBrowser) -{ - MessagingFixture fix; - - std::string address = "exclusive-queue; { create: receiver, node : { x-declare : { auto-delete: true, exclusive: true } } }"; - std::string browseAddress = "exclusive-queue; { mode: browse }"; - - Receiver receiver = fix.session.createReceiver(address); - fix.session.sync(); - - Connection c2 = fix.newConnection(); - c2.open(); - Session s2 = c2.createSession(); - - BOOST_CHECK_NO_THROW(Receiver browser = s2.createReceiver(browseAddress)); - c2.close(); -} - - -QPID_AUTO_TEST_CASE(testDeleteQueueWithUnackedMessages) -{ - MessagingFixture fix; - const uint capacity = 5; - - Sender sender = fix.session.createSender("test.ex;{create:always,node:{type:topic}}"); - Receiver receiver2 = fix.session.createReceiver("alternate.ex;{create:always,node:{type:topic}}"); - Receiver receiver1 = fix.session.createReceiver("test.q;{create:always, delete:always,node:{type:queue, x-declare:{alternate-exchange:alternate.ex}},link:{x-bindings:[{exchange:test.ex,queue:test.q,key:#}]}}"); - - receiver1.setCapacity(capacity); - receiver2.setCapacity(capacity*2); - - Message out("test-message"); - for (uint i = 0; i < capacity*2; ++i) { - sender.send(out); - } - - receiver1.close(); - - // Make sure all pending messages were sent to the alternate - // exchange when the queue was deleted. - Message in; - for (uint i = 0; i < capacity*2; ++i) { - in = receiver2.fetch(Duration::SECOND * 5); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - } -} - -QPID_AUTO_TEST_CASE(testAuthenticatedUsername) -{ - MessagingFixture fix; - Connection connection = fix.newConnection(); - connection.setOption("sasl-mechanism", "PLAIN"); - connection.setOption("username", "test-user"); - connection.setOption("password", "ignored"); - connection.open(); - BOOST_CHECK_EQUAL(connection.getAuthenticatedUsername(), std::string("test-user")); -} - -QPID_AUTO_TEST_CASE(testExceptionOnClosedConnection) -{ - MessagingFixture fix; - fix.connection.close(); - BOOST_CHECK_THROW(fix.connection.createSession(), MessagingException); - Connection connection("blah"); - BOOST_CHECK_THROW(connection.createSession(), MessagingException); -} - -QPID_AUTO_TEST_CASE(testAcknowledge) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - const uint count(20); - for (uint i = 0; i < count; ++i) { - sender.send(Message((boost::format("Message_%1%") % (i+1)).str())); - } - - Session other = fix.connection.createSession(); - Receiver receiver = other.createReceiver(fix.queue); - std::vector messages; - for (uint i = 0; i < count; ++i) { - Message msg = receiver.fetch(); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1)).str()); - messages.push_back(msg); - } - const uint batch(10); //acknowledge first 10 messages only - for (uint i = 0; i < batch; ++i) { - other.acknowledge(messages[i]); - } - messages.clear(); - other.sync(); - other.close(); - - other = fix.connection.createSession(); - receiver = other.createReceiver(fix.queue); - for (uint i = 0; i < (count-batch); ++i) { - Message msg = receiver.fetch(); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1+batch)).str()); - if (i % 2) other.acknowledge(msg); //acknowledge every other message - } - other.sync(); - other.close(); - - //check unacknowledged messages are still enqueued - other = fix.connection.createSession(); - receiver = other.createReceiver(fix.queue); - for (uint i = 0; i < ((count-batch)/2); ++i) { - Message msg = receiver.fetch(); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % ((i*2)+1+batch)).str()); - } - other.acknowledge();//acknowledge all messages - other.sync(); - other.close(); - - Message m; - //check queue is empty - BOOST_CHECK(!fix.session.createReceiver(fix.queue).fetch(m, Duration::IMMEDIATE)); -} - -QPID_AUTO_TEST_CASE(testQmfCreateAndDelete) -{ - MessagingFixture fix(BrokerOptions(), true/*enable management*/); - MethodInvoker control(fix.session); - control.createQueue("my-queue"); - control.createExchange("my-exchange", "topic"); - control.bind("my-exchange", "my-queue", "subject1"); - - Sender sender = fix.session.createSender("my-exchange"); - Receiver receiver = fix.session.createReceiver("my-queue"); - Message out; - out.setSubject("subject1"); - out.setContent("one"); - sender.send(out); - Message in; - BOOST_CHECK(receiver.fetch(in, Duration::SECOND*5)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - control.unbind("my-exchange", "my-queue", "subject1"); - control.bind("my-exchange", "my-queue", "subject2"); - - out.setContent("two"); - sender.send(out);//should be dropped - - out.setSubject("subject2"); - out.setContent("three"); - sender.send(out);//should not be dropped - - BOOST_CHECK(receiver.fetch(in, Duration::SECOND*5)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - BOOST_CHECK(!receiver.fetch(in, Duration::IMMEDIATE)); - sender.close(); - receiver.close(); - - control.deleteExchange("my-exchange"); - messaging::Session other = fix.connection.createSession(); - { - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(other.createSender("my-exchange"), qpid::messaging::NotFound); - } - control.deleteQueue("my-queue"); - other = fix.connection.createSession(); - { - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(other.createReceiver("my-queue"), qpid::messaging::NotFound); - } -} - -QPID_AUTO_TEST_CASE(testRejectAndCredit) -{ - //Ensure credit is restored on completing rejected messages - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Receiver receiver = fix.session.createReceiver(fix.queue); - - const uint count(10); - receiver.setCapacity(count); - for (uint i = 0; i < count; i++) { - sender.send(Message((boost::format("Message_%1%") % (i+1)).str())); - } - - Message in; - for (uint i = 0; i < count; ++i) { - if (receiver.fetch(in, Duration::SECOND)) { - BOOST_CHECK_EQUAL(in.getContent(), (boost::format("Message_%1%") % (i+1)).str()); - fix.session.reject(in); - } else { - BOOST_FAIL((boost::format("Message_%1% not received as expected") % (i+1)).str()); - break; - } - } - //send another batch of messages - for (uint i = 0; i < count; i++) { - sender.send(Message((boost::format("Message_%1%") % (i+count)).str())); - } - - for (uint i = 0; i < count; ++i) { - if (receiver.fetch(in, Duration::SECOND)) { - BOOST_CHECK_EQUAL(in.getContent(), (boost::format("Message_%1%") % (i+count)).str()); - } else { - BOOST_FAIL((boost::format("Message_%1% not received as expected") % (i+count)).str()); - break; - } - } - fix.session.acknowledge(); - receiver.close(); - sender.close(); -} - -QPID_AUTO_TEST_CASE(testTtlForever) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("I want to live forever!"); - out.setTtl(Duration::FOREVER); - sender.send(out, true); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::IMMEDIATE); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - BOOST_CHECK(in.getTtl() == Duration::FOREVER); -} - -QPID_AUTO_TEST_CASE(testExclusiveTopicSubscriber) -{ - TopicFixture fix; - std::string address = (boost::format("%1%; { link: { name: 'my-subscription', x-declare: { auto-delete: true, exclusive: true }}}") % fix.topic).str(); - Sender sender = fix.session.createSender(fix.topic); - Receiver receiver1 = fix.session.createReceiver(address); - { - ScopedSuppressLogging sl; - try { - fix.session.createReceiver(address); - fix.session.sync(); - BOOST_FAIL("Expected exception."); - } catch (const MessagingException& /*e*/) {} - } -} - -QPID_AUTO_TEST_CASE(testNonExclusiveSubscriber) -{ - TopicFixture fix; - std::string address = (boost::format("%1%; {node:{type:topic}, link:{name:'my-subscription', x-declare:{auto-delete:true, exclusive:false}}}") % fix.topic).str(); - Receiver receiver1 = fix.session.createReceiver(address); - Receiver receiver2 = fix.session.createReceiver(address); - Sender sender = fix.session.createSender(fix.topic); - sender.send(Message("one"), true); - Message in = receiver1.fetch(Duration::IMMEDIATE); - BOOST_CHECK_EQUAL(in.getContent(), std::string("one")); - sender.send(Message("two"), true); - in = receiver2.fetch(Duration::IMMEDIATE); - BOOST_CHECK_EQUAL(in.getContent(), std::string("two")); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testAcknowledgeUpTo) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - const uint count(20); - for (uint i = 0; i < count; ++i) { - sender.send(Message((boost::format("Message_%1%") % (i+1)).str())); - } - - Session other = fix.connection.createSession(); - Receiver receiver = other.createReceiver(fix.queue); - std::vector messages; - for (uint i = 0; i < count; ++i) { - Message msg = receiver.fetch(); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1)).str()); - messages.push_back(msg); - } - const uint batch = 10; - other.acknowledgeUpTo(messages[batch-1]);//acknowledge first 10 messages only - - messages.clear(); - other.sync(); - other.close(); - - other = fix.connection.createSession(); - receiver = other.createReceiver(fix.queue); - Message msg; - for (uint i = 0; i < (count-batch); ++i) { - msg = receiver.fetch(); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1+batch)).str()); - } - other.acknowledgeUpTo(msg); - other.sync(); - other.close(); - - Message m; - //check queue is empty - BOOST_CHECK(!fix.session.createReceiver(fix.queue).fetch(m, Duration::IMMEDIATE)); -} - -QPID_AUTO_TEST_CASE(testCreateBindingsOnStandardExchange) -{ - QueueFixture fix; - Sender sender = fix.session.createSender((boost::format("amq.direct; {create:always, node:{type:topic, x-bindings:[{queue:%1%, key:my-subject}]}}") % fix.queue).str()); - Message out("test-message"); - out.setSubject("my-subject"); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::SECOND * 5); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - BOOST_CHECK_EQUAL(in.getSubject(), out.getSubject()); -} - -QPID_AUTO_TEST_CASE(testUnsubscribeOnClose) -{ - MessagingFixture fix; - Sender sender = fix.session.createSender("my-exchange/my-subject; {create: always, delete:sender, node:{type:topic, x-declare:{alternate-exchange:amq.fanout}}}"); - Receiver receiver = fix.session.createReceiver("my-exchange/my-subject"); - Receiver deadletters = fix.session.createReceiver("amq.fanout"); - - sender.send(Message("first")); - Message in = receiver.fetch(Duration::SECOND); - BOOST_CHECK_EQUAL(in.getContent(), std::string("first")); - fix.session.acknowledge(); - receiver.close(); - sender.send(Message("second")); - in = deadletters.fetch(Duration::SECOND); - BOOST_CHECK_EQUAL(in.getContent(), std::string("second")); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testHeadersExchange) -{ - MessagingFixture fix; - //use both quoted and unquoted values - Receiver receiver = fix.session.createReceiver("amq.match; {link:{x-bindings:[{arguments:{x-match:all,qpid.subject:'abc',my-property:abc}}]}}"); - Sender sender = fix.session.createSender("amq.match"); - Message out("test-message"); - out.setSubject("abc"); - Variant& property = out.getProperties()["my-property"]; - property = "abc"; - property.setEncoding("utf8"); - sender.send(out, true); - Message in; - if (receiver.fetch(in, Duration::SECOND)) { - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - } else { - BOOST_FAIL("Message did not match as expected!"); - } -} - -QPID_AUTO_TEST_CASE(testLargeRoutingKey) -{ - MessagingFixture fix; - std::string address = "amq.direct/" + std::string(300, 'x');//routing/binding key can be at most 225 chars in 0-10 - BOOST_CHECK_THROW(fix.session.createReceiver(address), qpid::messaging::MessagingException); -} - -QPID_AUTO_TEST_CASE(testAlternateExchangeInLinkDeclare) -{ - MessagingFixture fix; - Sender s = fix.session.createSender("amq.direct/key"); - Receiver r1 = fix.session.createReceiver("amq.direct/key;{link:{x-declare:{alternate-exchange:'amq.fanout'}}}"); - Receiver r2 = fix.session.createReceiver("amq.fanout"); - - for (uint i = 0; i < 10; ++i) { - s.send(Message((boost::format("Message_%1%") % (i+1)).str()), true); - } - r1.close();//orphans all messages in subscription queue, which should then be routed through alternate exchange - for (uint i = 0; i < 10; ++i) { - Message received; - BOOST_CHECK(r2.fetch(received, Duration::SECOND)); - BOOST_CHECK_EQUAL(received.getContent(), (boost::format("Message_%1%") % (i+1)).str()); - } -} - -QPID_AUTO_TEST_CASE(testBrowseOnly) -{ - /* Set up a queue browse-only, and try to receive - the same messages twice with two different receivers. - This works because the browse-only queue does not - allow message acquisition. */ - - QueueFixture fix; - std::string addr = "q; {create:always, node:{type:queue, durable:false, x-declare:{arguments:{qpid.browse-only:1}}}}"; - Sender sender = fix.session.createSender(addr); - Message out("test-message"); - - int count = 10; - for ( int i = 0; i < count; ++ i ) { - sender.send(out); - } - - Message m; - - Receiver receiver_1 = fix.session.createReceiver(addr); - for ( int i = 0; i < count; ++ i ) { - BOOST_CHECK(receiver_1.fetch(m, Duration::SECOND)); - } - - Receiver receiver_2 = fix.session.createReceiver(addr); - for ( int i = 0; i < count; ++ i ) { - BOOST_CHECK(receiver_2.fetch(m, Duration::SECOND)); - } - - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testLinkBindingCleanup) -{ - MessagingFixture fix; - - Sender sender = fix.session.createSender("test.ex;{create:always,node:{type:topic}}"); - - Connection connection = fix.newConnection(); - connection.open(); - - Session session(connection.createSession()); - Receiver receiver1 = session.createReceiver("test.q;{create:always, node:{type:queue, x-bindings:[{exchange:test.ex,queue:test.q,key:#,arguments:{x-scope:session}}]}}"); - Receiver receiver2 = fix.session.createReceiver("test.q;{create:never, delete:always}"); - connection.close(); - - sender.send(Message("test-message"), true); - - // The session-scoped binding should be removed when receiver1's network connection is lost - Message in; - BOOST_CHECK(!receiver2.fetch(in, Duration::IMMEDIATE)); -} - -namespace { -struct Fetcher : public qpid::sys::Runnable { - Receiver receiver; - Message message; - bool result; - qpid::messaging::Duration timeout; - bool timedOut; - - Fetcher(Receiver r) : receiver(r), result(false), timeout(Duration::SECOND*10), timedOut(false) {} - void run() - { - qpid::sys::AbsTime start(qpid::sys::now()); - try { - result = receiver.fetch(message, timeout); - } catch (const MessagingException&) {} - qpid::sys::Duration timeTaken(start, qpid::sys::now()); - timedOut = (uint64_t) timeTaken >= timeout.getMilliseconds() * qpid::sys::TIME_MSEC; - } -}; -} - -QPID_AUTO_TEST_CASE(testConcurrentFetch) -{ - MessagingFixture fix; - Sender sender = fix.session.createSender("my-test-queue;{create:always, node : { x-declare : { auto-delete: true}}}"); - Receiver receiver = fix.session.createReceiver("my-test-queue"); - Fetcher fetcher(fix.session.createReceiver("amq.fanout")); - qpid::sys::Thread runner(fetcher); - Message out("test-message"); - for (int i = 0; i < 10; i++) {//try several times to make sure - sender.send(out, true); - //since the message is now on the queue, it should take less than the timeout to actually fetch it - qpid::sys::AbsTime start = qpid::sys::AbsTime::now(); - Message in; - BOOST_CHECK(receiver.fetch(in, qpid::messaging::Duration::SECOND*2)); - qpid::sys::Duration time(start, qpid::sys::AbsTime::now()); - BOOST_CHECK(time < qpid::sys::TIME_SEC*2); - if (time >= qpid::sys::TIME_SEC*2) break;//if we failed, no need to keep testing - } - fix.session.createSender("amq.fanout").send(out); - runner.join(); - BOOST_CHECK(fetcher.result); -} - -QPID_AUTO_TEST_CASE(testSimpleRequestResponse) -{ - QueueFixture fix; - //create receiver on temp queue for responses (using shorthand for temp queue) - Receiver r1 = fix.session.createReceiver("#"); - //send request - Sender s1 = fix.session.createSender(fix.queue); - Message original("test-message"); - original.setSubject("test-subject"); - original.setReplyTo(r1.getAddress()); - s1.send(original); - - //receive request and send response - Receiver r2 = fix.session.createReceiver(fix.queue); - Message m = r2.fetch(Duration::SECOND * 5); - Sender s2 = fix.session.createSender(m.getReplyTo()); - s2.send(m); - m = r1.fetch(Duration::SECOND * 5); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(m.getContent(), original.getContent()); - 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_CASE(testCloseAndConcurrentFetch) -{ - QueueFixture fix; - Receiver receiver = fix.session.createReceiver(fix.queue); - Fetcher fetcher(receiver); - qpid::sys::Thread runner(fetcher); - qpid::sys::usleep(500); - receiver.close(); - runner.join(); - BOOST_CHECK(!fetcher.timedOut); -} - -QPID_AUTO_TEST_CASE(testCloseAndMultipleConcurrentFetches) -{ - QueueFixture fix; - Receiver receiver = fix.session.createReceiver(fix.queue); - Receiver receiver2 = fix.session.createReceiver("amq.fanout"); - Receiver receiver3 = fix.session.createReceiver("amq.fanout"); - Fetcher fetcher(receiver); - Fetcher fetcher2(receiver2); - Fetcher fetcher3(receiver3); - qpid::sys::Thread runner(fetcher); - qpid::sys::Thread runner2(fetcher2); - qpid::sys::Thread runner3(fetcher3); - qpid::sys::usleep(500); - receiver.close(); - Message message("Test"); - fix.session.createSender("amq.fanout").send(message); - runner2.join(); - BOOST_CHECK(fetcher2.result); - BOOST_CHECK_EQUAL(fetcher2.message.getContent(), message.getContent()); - runner3.join(); - BOOST_CHECK(fetcher3.result); - BOOST_CHECK_EQUAL(fetcher3.message.getContent(), message.getContent()); - runner.join(); - BOOST_CHECK(!fetcher.timedOut); -} - -QPID_AUTO_TEST_CASE(testSessionCheckError) -{ - MessagingFixture fix; - Session session = fix.connection.createSession(); - Sender sender = session.createSender("q; {create:always, node:{x-declare:{auto-delete:True, arguments:{qpid.max_count:1}}}}"); - ScopedSuppressLogging sl; - for (uint i = 0; i < 2; ++i) { - sender.send(Message((boost::format("A_%1%") % (i+1)).str())); - } - try { - while (true) session.checkError(); - } catch (const qpid::types::Exception&) { - //this is ok - } catch (const qpid::Exception&) { - BOOST_FAIL("Wrong exception type thrown"); - } -} - -QPID_AUTO_TEST_CASE(testImmediateNextReceiver) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test message"); - sender.send(out); - fix.session.createReceiver(fix.queue).setCapacity(1); - Receiver next; - qpid::sys::AbsTime start = qpid::sys::now(); - try { - while (!fix.session.nextReceiver(next, qpid::messaging::Duration::IMMEDIATE)) { - qpid::sys::Duration running(start, qpid::sys::now()); - if (running > 5*qpid::sys::TIME_SEC) { - throw qpid::types::Exception("Timed out spinning on nextReceiver(IMMEDIATE)"); - } - qpid::sys::usleep(1); // for valgrind - } - Message in; - BOOST_CHECK(next.fetch(in, qpid::messaging::Duration::IMMEDIATE)); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - next.close(); - } catch (const std::exception& e) { - BOOST_FAIL(e.what()); - } -} - -QPID_AUTO_TEST_CASE(testImmediateNextReceiverNoMessage) -{ - QueueFixture fix; - Receiver r = fix.session.createReceiver(fix.queue); - r.setCapacity(1); - Receiver next; - try { - BOOST_CHECK(!fix.session.nextReceiver(next, qpid::messaging::Duration::IMMEDIATE)); - r.close(); - } catch (const std::exception& e) { - BOOST_FAIL(e.what()); - } -} - -QPID_AUTO_TEST_CASE(testResendEmpty) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::SECOND * 5); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - //set content on received message to empty string and resend - in.setContent(""); - sender.send(in); - in = receiver.fetch(Duration::SECOND * 5); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), std::string()); -} - -QPID_AUTO_TEST_CASE(testResendMapAsString) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - qpid::types::Variant::Map content; - content["foo"] = "bar"; - encode(content, out); - sender.send(out); - - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::SECOND * 5); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - //change content and resend - std::string newContent("something random"); - in.setContent(newContent); - in.setContentType(std::string());//it is no longer a map - sender.send(in); - in = receiver.fetch(Duration::SECOND * 5); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), newContent); -} - -QPID_AUTO_TEST_CASE(testClientExpiration) -{ - QueueFixture fix; - Receiver receiver = fix.session.createReceiver(fix.queue); - receiver.setCapacity(5); - Sender sender = fix.session.createSender(fix.queue); - for (uint i = 0; i < 5000; ++i) { - Message msg((boost::format("a_%1%") % (i+1)).str()); - msg.setSubject("a"); - msg.setTtl(Duration(10)); - sender.send(msg); - } - for (uint i = 0; i < 50; ++i) { - Message msg((boost::format("b_%1%") % (i+1)).str()); - msg.setSubject("b"); - sender.send(msg); - } - Message received; - bool done = false; - uint b_count = 0; - while (!done && receiver.fetch(received, Duration::IMMEDIATE)) { - if (received.getSubject() == "b") { - b_count++; - } - done = received.getContent() == "b_50"; - fix.session.acknowledge(); - } - BOOST_CHECK_EQUAL(b_count, 50); -} - -QPID_AUTO_TEST_CASE(testExpiredPrefetchOnClose) -{ - QueueFixture fix; - Receiver receiver = fix.session.createReceiver(fix.queue); - Session other = fix.connection.createSession(); - Receiver receiver2 = other.createReceiver("amq.fanout"); - receiver.setCapacity(500); - Sender sender = fix.session.createSender(fix.queue); - for (uint i = 0; i < 500; ++i) { - Message msg((boost::format("a_%1%") % (i+1)).str()); - msg.setSubject("a"); - msg.setTtl(Duration(5)); - sender.send(msg); - } - Sender sender2 = other.createSender("amq.fanout"); - sender2.send(Message("done")); - BOOST_CHECK_EQUAL(receiver2.fetch().getContent(), "done"); - qpid::sys::usleep(qpid::sys::TIME_MSEC*5);//sorry Alan, I can't see any way to avoid a sleep; need to ensure messages in prefetch have expired - receiver.close(); -} - -QPID_AUTO_TEST_CASE(testPriorityRingEviction) -{ - MessagingFixture fix; - std::string queue("queue; {create:always, node:{x-declare:{auto-delete:True, arguments:{qpid.priorities:10, qpid.max_count:5, qpid.policy_type:ring}}}}"); - Sender sender = fix.session.createSender(queue); - Receiver receiver = fix.session.createReceiver(queue); - std::vector acquired; - for (uint i = 0; i < 5; ++i) { - Message msg((boost::format("msg_%1%") % (i+1)).str()); - sender.send(msg); - } - //fetch but don't acknowledge messages, leaving them in acquired state - for (uint i = 0; i < 5; ++i) { - Message msg; - BOOST_CHECK(receiver.fetch(msg, Duration::IMMEDIATE)); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("msg_%1%") % (i+1)).str()); - acquired.push_back(msg); - } - //send 5 more messages to the queue, which should cause all the - //acquired messages to be dropped - for (uint i = 5; i < 10; ++i) { - Message msg((boost::format("msg_%1%") % (i+1)).str()); - sender.send(msg); - } - //now release the acquired messages, which should have been evicted... - for (std::vector::iterator i = acquired.begin(); i != acquired.end(); ++i) { - fix.session.release(*i); - } - acquired.clear(); - //and check that the newest five are received - for (uint i = 5; i < 10; ++i) { - Message msg; - BOOST_CHECK(receiver.fetch(msg, Duration::IMMEDIATE)); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("msg_%1%") % (i+1)).str()); - acquired.push_back(msg); - } - Message msg; - BOOST_CHECK(!receiver.fetch(msg, Duration::IMMEDIATE)); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/MessagingThreadTests.cpp b/qpid/cpp/src/tests/MessagingThreadTests.cpp deleted file mode 100644 index 48264735b1..0000000000 --- a/qpid/cpp/src/tests/MessagingThreadTests.cpp +++ /dev/null @@ -1,144 +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 "MessagingFixture.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include - -namespace qpid { -namespace tests { -QPID_AUTO_TEST_SUITE(MessagingThreadTests) - -using namespace messaging; -using namespace boost::assign; -using namespace std; - -struct ReceiveThread : public sys::Runnable { - Receiver receiver; - vector received; - string error; - - ReceiveThread(Receiver s) : receiver(s) {} - void run() { - try { - while(true) { - Message m = receiver.fetch(Duration::SECOND*5); - if (m.getContent() == "END") break; - received.push_back(m.getContent()); - } - } catch (const NoMessageAvailable& e) { - // Indicates that fetch timed out OR receiver was closed by other thread. - if (!receiver.isClosed()) // timeout - error = e.what(); - } catch (const std::exception& e) { - error = e.what(); - } - } -}; - -struct NextReceiverThread : public sys::Runnable { - Session session; - vector received; - string error; - - NextReceiverThread(Session s) : session(s) {} - void run() { - try { - while(true) { - Message m = session.nextReceiver(Duration::SECOND*5).fetch(); - if (m.getContent() == "END") break; - received.push_back(m.getContent()); - } - } catch (const std::exception& e) { - error = e.what(); - } - } -}; - - -QPID_AUTO_TEST_CASE(testConcurrentSendReceive) { - MessagingFixture fix; - Sender s = fix.session.createSender("concurrent;{create:always}"); - Receiver r = fix.session.createReceiver("concurrent;{create:always,link:{reliability:unreliable}}"); - ReceiveThread rt(r); - sys::Thread thread(rt); - const size_t COUNT=100; - for (size_t i = 0; i < COUNT; ++i) { - s.send(Message()); - } - s.send(Message("END")); - thread.join(); - BOOST_CHECK_EQUAL(rt.error, string()); - BOOST_CHECK_EQUAL(COUNT, rt.received.size()); -} - -QPID_AUTO_TEST_CASE(testCloseBusyReceiver) { - MessagingFixture fix; - Receiver r = fix.session.createReceiver("closeReceiver;{create:always}"); - ReceiveThread rt(r); - sys::Thread thread(rt); - sys::usleep(1000); // Give the receive thread time to block. - r.close(); - thread.join(); - BOOST_CHECK_EQUAL(rt.error, string()); - - // Fetching on closed receiver should fail. - Message m; - BOOST_CHECK(!r.fetch(m, Duration(0))); - BOOST_CHECK_THROW(r.fetch(Duration(0)), NoMessageAvailable); -} - -QPID_AUTO_TEST_CASE(testCloseSessionBusyReceiver) { - MessagingFixture fix; - Receiver r = fix.session.createReceiver("closeSession;{create:always}"); - ReceiveThread rt(r); - sys::Thread thread(rt); - sys::usleep(1000); // Give the receive thread time to block. - fix.session.close(); - thread.join(); - BOOST_CHECK_EQUAL(rt.error, string()); - - // Fetching on closed receiver should fail. - Message m; - BOOST_CHECK(!r.fetch(m, Duration(0))); - BOOST_CHECK_THROW(r.fetch(Duration(0)), NoMessageAvailable); -} - -QPID_AUTO_TEST_CASE(testConcurrentSendNextReceiver) { - MessagingFixture fix; - Receiver r = fix.session.createReceiver("concurrent;{create:always,link:{reliability:unreliable}}"); - const size_t COUNT=100; - r.setCapacity(COUNT); - NextReceiverThread rt(fix.session); - sys::Thread thread(rt); - sys::usleep(1000); // Give the receive thread time to block. - Sender s = fix.session.createSender("concurrent;{create:always}"); - for (size_t i = 0; i < COUNT; ++i) { - s.send(Message()); - } - s.send(Message("END")); - thread.join(); - BOOST_CHECK_EQUAL(rt.error, string()); - BOOST_CHECK_EQUAL(COUNT, rt.received.size()); -} - -QPID_AUTO_TEST_SUITE_END() -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/PollableCondition.cpp b/qpid/cpp/src/tests/PollableCondition.cpp deleted file mode 100644 index f9b3c25c93..0000000000 --- a/qpid/cpp/src/tests/PollableCondition.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "test_tools.h" -#include "unit_test.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/PollableCondition.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(PollableConditionTest) - -using namespace qpid::sys; - -const Duration SHORT = TIME_SEC/100; -const Duration LONG = TIME_SEC/10; - -class Callback { - public: - enum Action { NONE, CLEAR }; - - Callback() : count(), action(NONE) {} - - void call(PollableCondition& pc) { - Mutex::ScopedLock l(lock); - ++count; - switch(action) { - case NONE: break; - case CLEAR: pc.clear(); break; - } - action = NONE; - lock.notify(); - } - - bool isCalling() { Mutex::ScopedLock l(lock); return wait(LONG); } - - bool isNotCalling() { Mutex::ScopedLock l(lock); return !wait(SHORT); } - - bool nextCall(Action a=NONE) { - Mutex::ScopedLock l(lock); - action = a; - return wait(LONG); - } - - private: - bool wait(Duration timeout) { - int n = count; - AbsTime deadline(now(), timeout); - while (n == count && lock.wait(deadline)) - ; - return n != count; - } - - Monitor lock; - int count; - Action action; -}; - -QPID_AUTO_TEST_CASE(testPollableCondition) { - boost::shared_ptr poller(new Poller()); - Callback callback; - PollableCondition pc(boost::bind(&Callback::call, &callback, _1), poller); - - Thread runner = Thread(*poller); - - BOOST_CHECK(callback.isNotCalling()); // condition is not set. - - pc.set(); - BOOST_CHECK(callback.isCalling()); // Set. - BOOST_CHECK(callback.isCalling()); // Still set. - - callback.nextCall(Callback::CLEAR); - BOOST_CHECK(callback.isNotCalling()); // Cleared - - pc.set(); - BOOST_CHECK(callback.isCalling()); // Set. - callback.nextCall(Callback::CLEAR); - BOOST_CHECK(callback.isNotCalling()); // Cleared. - - poller->shutdown(); - runner.join(); -} - -QPID_AUTO_TEST_SUITE_END() - -}} //namespace qpid::tests diff --git a/qpid/cpp/src/tests/PollerTest.cpp b/qpid/cpp/src/tests/PollerTest.cpp deleted file mode 100644 index 5a1d02964c..0000000000 --- a/qpid/cpp/src/tests/PollerTest.cpp +++ /dev/null @@ -1,262 +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. - * - */ - -/** - * Use socketpair to test the poller - */ - -#include "qpid/sys/Poller.h" -#include "qpid/sys/posix/PrivatePosix.h" - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -using namespace std; -using namespace qpid::sys; - -int writeALot(int fd, const string& s) { - int bytesWritten = 0; - do { - errno = 0; - int lastWrite = ::write(fd, s.c_str(), s.size()); - if ( lastWrite >= 0) { - bytesWritten += lastWrite; - } - } while (errno != EAGAIN); - return bytesWritten; -} - -int readALot(int fd) { - int bytesRead = 0; - char buf[1024]; - - do { - errno = 0; - int lastRead = ::read(fd, buf, sizeof(buf)); - if ( lastRead >= 0) { - bytesRead += lastRead; - } - } while (errno != EAGAIN); - return bytesRead; -} - -void makesocketpair(int (&sv)[2]) { - int rc = ::socketpair(AF_UNIX, SOCK_STREAM, 0, sv); - assert(rc >= 0); - - // Set non-blocking - rc = ::fcntl(sv[0], F_SETFL, O_NONBLOCK); - assert(rc >= 0); - - rc = ::fcntl(sv[1], F_SETFL, O_NONBLOCK); - assert(rc >= 0); -} - -int main(int /*argc*/, char** /*argv*/) -{ - try - { - int sv[2]; - makesocketpair(sv); - - // Make up a large string - string testString = "This is only a test ... 1,2,3,4,5,6,7,8,9,10;"; - for (int i = 0; i < 6; i++) - testString += testString; - - // Read as much as we can from socket 0 - int bytesRead = readALot(sv[0]); - assert(bytesRead == 0); - - // Write as much as we can to socket 0 - int bytesWritten = writeALot(sv[0], testString); - - // Read as much as we can from socket 1 - bytesRead = readALot(sv[1]); - assert(bytesRead == bytesWritten); - - auto_ptr poller(new Poller); - - IOHandle f0(sv[0]); - IOHandle f1(sv[1]); - - PollerHandle h0(f0); - PollerHandle h1(f1); - - poller->registerHandle(h0); - poller->monitorHandle(h0, Poller::INOUT); - - // h0 should be writable - Poller::Event event = poller->wait(); - assert(event.handle == &h0); - assert(event.type == Poller::WRITABLE); - - // Write as much as we can to socket 0 - bytesWritten = writeALot(sv[0], testString); - - // Wait for 500ms - h0 no longer writable - event = poller->wait(500000000); - assert(event.handle == 0); - - // Test we can read it all now - poller->registerHandle(h1); - poller->monitorHandle(h1, Poller::INOUT); - event = poller->wait(); - assert(event.handle == &h1); - assert(event.type == Poller::READ_WRITABLE); - - bytesRead = readALot(sv[1]); - assert(bytesRead == bytesWritten); - - // Test poller interrupt - assert(poller->interrupt(h0) == true); - event = poller->wait(); - assert(event.handle == &h0); - assert(event.type == Poller::INTERRUPTED); - - // Test multiple interrupts - assert(poller->interrupt(h0) == true); - assert(poller->interrupt(h1) == true); - - // Make sure we can interrupt them again - assert(poller->interrupt(h0) == true); - assert(poller->interrupt(h1) == true); - - // Make sure that they both come out - event = poller->wait(); - assert(event.type == Poller::INTERRUPTED); - assert(event.handle == &h0 || event.handle == &h1); - if (event.handle == &h0) { - event = poller->wait(); - assert(event.type == Poller::INTERRUPTED); - assert(event.handle == &h1); - } else { - event = poller->wait(); - assert(event.type == Poller::INTERRUPTED); - assert(event.handle == &h0); - } - - poller->unmonitorHandle(h1, Poller::INOUT); - - event = poller->wait(); - assert(event.handle == &h0); - assert(event.type == Poller::WRITABLE); - - // We didn't write anything so it should still be writable - event = poller->wait(); - assert(event.handle == &h0); - assert(event.type == Poller::WRITABLE); - - poller->unmonitorHandle(h0, Poller::INOUT); - - event = poller->wait(500000000); - assert(event.handle == 0); - - poller->unregisterHandle(h1); - assert(poller->interrupt(h1) == false); - - // close the other end to force a disconnect - ::close(sv[1]); - - // Now make sure that we are readable followed by disconnected - // and after that we never return again - poller->monitorHandle(h0, Poller::INOUT); - event = poller->wait(500000000); - assert(event.handle == &h0); - assert(event.type == Poller::READABLE); - event = poller->wait(500000000); - assert(event.handle == &h0); - assert(event.type == Poller::DISCONNECTED); - event = poller->wait(1500000000); - assert(event.handle == 0); - - // Now we're disconnected monitoring should have no effect at all - poller->unmonitorHandle(h0, Poller::INOUT); - event = poller->wait(1500000000); - assert(event.handle == 0); - - poller->unregisterHandle(h0); - assert(poller->interrupt(h0) == false); - - // Test shutdown - poller->shutdown(); - event = poller->wait(); - assert(event.handle == 0); - assert(event.type == Poller::SHUTDOWN); - - event = poller->wait(); - assert(event.handle == 0); - assert(event.type == Poller::SHUTDOWN); - - ::close(sv[0]); - - // Test for correct interaction of shutdown and interrupts - need to have new poller - // etc. for this - makesocketpair(sv); - - auto_ptr poller1(new Poller); - - IOHandle f2(sv[0]); - IOHandle f3(sv[1]); - - PollerHandle h2(f2); - PollerHandle h3(f3); - - poller1->registerHandle(h2); - poller1->monitorHandle(h2, Poller::INOUT); - event = poller1->wait(); - assert(event.handle == &h2); - assert(event.type == Poller::WRITABLE); - - // Shutdown - poller1->shutdown(); - event = poller1->wait(); - assert(event.handle == 0); - assert(event.type == Poller::SHUTDOWN); - - assert(poller1->interrupt(h2) == true); - event = poller1->wait(); - assert(event.handle == &h2); - assert(event.type == Poller::INTERRUPTED); - poller1->unmonitorHandle(h2, Poller::INOUT); - - event = poller1->wait(); - assert(event.handle == 0); - assert(event.type == Poller::SHUTDOWN); - - poller1->unregisterHandle(h2); - return 0; - } catch (exception& e) { - cout << "Caught exception " << e.what() << "\n"; - } -} - - diff --git a/qpid/cpp/src/tests/ProxyTest.cpp b/qpid/cpp/src/tests/ProxyTest.cpp deleted file mode 100644 index a926b28395..0000000000 --- a/qpid/cpp/src/tests/ProxyTest.cpp +++ /dev/null @@ -1,56 +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 -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/ExecutionSyncBody.h" -#include "qpid/framing/Proxy.h" - -#include "unit_test.h" - -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ProxyTestSuite) - - -QPID_AUTO_TEST_CASE(testScopedSync) -{ - struct DummyHandler : FrameHandler - { - void handle(AMQFrame& f) { - AMQMethodBody* m = f.getMethod(); - BOOST_CHECK(m); - BOOST_CHECK(m->isA()); - BOOST_CHECK(m->isSync()); - } - }; - DummyHandler f; - Proxy p(f); - Proxy::ScopedSync s(p); - p.send(ExecutionSyncBody(p.getVersion())); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Qmf2.cpp b/qpid/cpp/src/tests/Qmf2.cpp deleted file mode 100644 index bc263d5c6d..0000000000 --- a/qpid/cpp/src/tests/Qmf2.cpp +++ /dev/null @@ -1,422 +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 -#include "qpid/types/Variant.h" -#include "qmf/QueryImpl.h" -#include "qmf/SchemaImpl.h" -#include "qmf/exceptions.h" -#include "qpid/messaging/Connection.h" -#include "qmf/PosixEventNotifierImpl.h" -#include "qmf/AgentSession.h" -#include "qmf/AgentSessionImpl.h" -#include "qmf/ConsoleSession.h" -#include "qmf/ConsoleSessionImpl.h" -#include "unit_test.h" - -using namespace std; -using namespace qpid::types; -using namespace qpid::messaging; -using namespace qmf; - -bool isReadable(int fd) -{ - fd_set rfds; - struct timeval tv; - int nfds, result; - - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - nfds = fd + 1; - tv.tv_sec = 0; - tv.tv_usec = 0; - - result = select(nfds, &rfds, NULL, NULL, &tv); - - return result > 0; -} - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(Qmf2Suite) - -QPID_AUTO_TEST_CASE(testQuery) -{ - Query query(QUERY_OBJECT, "class_name", "package_name", "[and, [eq, name, [quote, smith]], [lt, age, [quote, 27]]]"); - Query newQuery(new QueryImpl(QueryImplAccess::get(query).asMap())); - - BOOST_CHECK_EQUAL(newQuery.getTarget(), QUERY_OBJECT); - BOOST_CHECK_EQUAL(newQuery.getSchemaId().getName(), "class_name"); - BOOST_CHECK_EQUAL(newQuery.getSchemaId().getPackageName(), "package_name"); - - Variant::List pred(newQuery.getPredicate()); - BOOST_CHECK_EQUAL(pred.size(), size_t(3)); - - Variant::List::iterator iter(pred.begin()); - BOOST_CHECK_EQUAL(iter->asString(), "and"); - iter++; - BOOST_CHECK_EQUAL(iter->getType(), VAR_LIST); - iter++; - BOOST_CHECK_EQUAL(iter->getType(), VAR_LIST); - iter = iter->asList().begin(); - BOOST_CHECK_EQUAL(iter->asString(), "lt"); - iter++; - BOOST_CHECK_EQUAL(iter->asString(), "age"); - iter++; - BOOST_CHECK_EQUAL(iter->getType(), VAR_LIST); - iter = iter->asList().begin(); - BOOST_CHECK_EQUAL(iter->asString(), "quote"); - iter++; - BOOST_CHECK_EQUAL(iter->asUint32(), uint32_t(27)); - - Query query2(QUERY_OBJECT_ID); - Query newQuery2(new QueryImpl(QueryImplAccess::get(query2).asMap())); - BOOST_CHECK_EQUAL(newQuery2.getTarget(), QUERY_OBJECT_ID); - - Query query3(QUERY_SCHEMA); - Query newQuery3(new QueryImpl(QueryImplAccess::get(query3).asMap())); - BOOST_CHECK_EQUAL(newQuery3.getTarget(), QUERY_SCHEMA); - - Query query4(QUERY_SCHEMA_ID); - Query newQuery4(new QueryImpl(QueryImplAccess::get(query4).asMap())); - BOOST_CHECK_EQUAL(newQuery4.getTarget(), QUERY_SCHEMA_ID); - - DataAddr addr("name", "agent_name", 34); - Query query5(addr); - Query newQuery5(new QueryImpl(QueryImplAccess::get(query5).asMap())); - BOOST_CHECK_EQUAL(newQuery5.getTarget(), QUERY_OBJECT); - BOOST_CHECK_EQUAL(newQuery5.getDataAddr().getName(), "name"); - BOOST_CHECK_EQUAL(newQuery5.getDataAddr().getAgentName(), "agent_name"); - BOOST_CHECK_EQUAL(newQuery5.getDataAddr().getAgentEpoch(), uint32_t(34)); -} - -QPID_AUTO_TEST_CASE(testQueryPredicateErrors) -{ - Query query; - Variant::Map map; - - BOOST_CHECK_THROW(Query(QUERY_OBJECT, "INVALID"), QmfException); - query = Query(QUERY_OBJECT, "[unknown, one, two]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[exists]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first, [quote, 1, 2, 3]]]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first, [unexpected, 3]]]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first, {}]]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first, second, third]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[and, first, second, third]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); -} - -QPID_AUTO_TEST_CASE(testQueryPredicate) -{ - Query query; - Variant::Map map; - - map["forty"] = 40; - map["fifty"] = 50; - map["minus_ten"] = -10; - map["pos_float"] = 100.05; - map["neg_float"] = -1000.33; - map["name"] = "jones"; - map["bool_t"] = true; - map["bool_f"] = false; - - BOOST_CHECK_THROW(Query(QUERY_OBJECT, "INVALID"), QmfException); - - query = Query(QUERY_OBJECT); - BOOST_CHECK_EQUAL(query.matchesPredicate(Variant::Map()), true); - - query = Query(QUERY_OBJECT, "[eq, forty, [quote, 40]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[eq, forty, [quote, 41]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[le, forty, fifty]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[and, [eq, forty, [quote, 40]], [eq, name, [quote, jones]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[and, [eq, forty, [quote, 40]], [eq, name, [quote, smith]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[or, [eq, forty, [quote, 40]], [eq, name, [quote, smith]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[or, [eq, forty, [quote, 41]], [eq, name, [quote, smith]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[not, [le, forty, [quote, 40]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[le, forty, [quote, 40]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[ge, forty, [quote, 40]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[lt, forty, [quote, 45]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[lt, [quote, 45], forty]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[gt, forty, [quote, 45]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[gt, [quote, 45], forty]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[eq, bool_t, [quote, True]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[eq, bool_t, [quote, False]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[eq, bool_f, [quote, True]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[eq, bool_f, [quote, False]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[eq, minus_ten, [quote, -10]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[lt, minus_ten, [quote, -20]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[lt, [quote, -20], minus_ten]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[exists, name]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[exists, nonexfield]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[eq, pos_float, [quote, 100.05]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); -} - -QPID_AUTO_TEST_CASE(testSchema) -{ - Schema in(SCHEMA_TYPE_DATA, "package", "class"); - in.addProperty(SchemaProperty("prop1", SCHEMA_DATA_BOOL, "{desc:'Property One'}")); - in.addProperty(SchemaProperty("prop2", SCHEMA_DATA_INT, "{desc:'Property Two',unit:'Furlong'}")); - in.addProperty(SchemaProperty("prop3", SCHEMA_DATA_STRING, "{desc:'Property Three'}")); - - SchemaMethod method1("method1", "{desc:'Method One'}"); - method1.addArgument(SchemaProperty("arg1", SCHEMA_DATA_BOOL, "{desc:'Argument One',dir:IN}")); - method1.addArgument(SchemaProperty("arg2", SCHEMA_DATA_INT, "{desc:'Argument Two',dir:OUT}")); - method1.addArgument(SchemaProperty("arg3", SCHEMA_DATA_FLOAT, "{desc:'Argument Three',dir:INOUT}")); - in.addMethod(method1); - - SchemaMethod method2("method2", "{desc:'Method Two'}"); - method2.addArgument(SchemaProperty("arg21", SCHEMA_DATA_BOOL, "{desc:'Argument One',dir:IN}")); - method2.addArgument(SchemaProperty("arg22", SCHEMA_DATA_INT, "{desc:'Argument Two',dir:OUT}")); - method2.addArgument(SchemaProperty("arg23", SCHEMA_DATA_FLOAT, "{desc:'Argument Three',dir:INOUT}")); - in.addMethod(method2); - - BOOST_CHECK(!in.isFinalized()); - in.finalize(); - BOOST_CHECK(in.isFinalized()); - - Variant::Map map(SchemaImplAccess::get(in).asMap()); - Schema out(new SchemaImpl(map)); - - BOOST_CHECK(out.isFinalized()); - BOOST_CHECK_EQUAL(out.getSchemaId().getType(), SCHEMA_TYPE_DATA); - BOOST_CHECK_EQUAL(out.getSchemaId().getPackageName(), "package"); - BOOST_CHECK_EQUAL(out.getSchemaId().getName(), "class"); - BOOST_CHECK_EQUAL(out.getSchemaId().getHash(), in.getSchemaId().getHash()); - - BOOST_CHECK_EQUAL(out.getPropertyCount(), uint32_t(3)); - SchemaProperty prop; - - prop = out.getProperty(0); - BOOST_CHECK_EQUAL(prop.getName(), "prop1"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_BOOL); - BOOST_CHECK_EQUAL(prop.getDesc(), "Property One"); - - prop = out.getProperty(1); - BOOST_CHECK_EQUAL(prop.getName(), "prop2"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_INT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Property Two"); - BOOST_CHECK_EQUAL(prop.getUnit(), "Furlong"); - BOOST_CHECK(!prop.isIndex()); - - prop = out.getProperty(2); - BOOST_CHECK_EQUAL(prop.getName(), "prop3"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_STRING); - BOOST_CHECK_EQUAL(prop.getDesc(), "Property Three"); - - BOOST_CHECK_THROW(out.getProperty(3), QmfException); - - BOOST_CHECK_EQUAL(out.getMethodCount(), uint32_t(2)); - SchemaMethod method; - - method = out.getMethod(0); - BOOST_CHECK_EQUAL(method.getName(), "method1"); - BOOST_CHECK_EQUAL(method.getDesc(), "Method One"); - BOOST_CHECK_EQUAL(method.getArgumentCount(), uint32_t(3)); - - prop = method.getArgument(0); - BOOST_CHECK_EQUAL(prop.getName(), "arg1"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_BOOL); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument One"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_IN); - - prop = method.getArgument(1); - BOOST_CHECK_EQUAL(prop.getName(), "arg2"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_INT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument Two"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_OUT); - - prop = method.getArgument(2); - BOOST_CHECK_EQUAL(prop.getName(), "arg3"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_FLOAT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument Three"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_IN_OUT); - - BOOST_CHECK_THROW(method.getArgument(3), QmfException); - - method = out.getMethod(1); - BOOST_CHECK_EQUAL(method.getName(), "method2"); - BOOST_CHECK_EQUAL(method.getDesc(), "Method Two"); - BOOST_CHECK_EQUAL(method.getArgumentCount(), uint32_t(3)); - - prop = method.getArgument(0); - BOOST_CHECK_EQUAL(prop.getName(), "arg21"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_BOOL); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument One"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_IN); - - prop = method.getArgument(1); - BOOST_CHECK_EQUAL(prop.getName(), "arg22"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_INT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument Two"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_OUT); - - prop = method.getArgument(2); - BOOST_CHECK_EQUAL(prop.getName(), "arg23"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_FLOAT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument Three"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_IN_OUT); - - BOOST_CHECK_THROW(method.getArgument(3), QmfException); -} - -QPID_AUTO_TEST_CASE(testAgentSessionEventListener) -{ - Connection connection("localhost"); - AgentSession session(connection, ""); - posix::EventNotifier notifier(session); - - AgentSessionImpl& sessionImpl = AgentSessionImplAccess::get(session); - - BOOST_CHECK(sessionImpl.getEventNotifier() != 0); -} - -QPID_AUTO_TEST_CASE(testConsoleSessionEventListener) -{ - Connection connection("localhost"); - ConsoleSession session(connection, ""); - posix::EventNotifier notifier(session); - - ConsoleSessionImpl& sessionImpl = ConsoleSessionImplAccess::get(session); - - BOOST_CHECK(sessionImpl.getEventNotifier() != 0); -} - -QPID_AUTO_TEST_CASE(testGetHandle) -{ - Connection connection("localhost"); - ConsoleSession session(connection, ""); - posix::EventNotifier notifier(session); - - BOOST_CHECK(notifier.getHandle() > 0); -} - -QPID_AUTO_TEST_CASE(testSetReadableToFalse) -{ - Connection connection("localhost"); - ConsoleSession session(connection, ""); - posix::EventNotifier notifier(session); - PosixEventNotifierImplAccess::get(notifier).setReadable(false); - - bool readable(isReadable(notifier.getHandle())); - BOOST_CHECK(!readable); -} - -QPID_AUTO_TEST_CASE(testSetReadable) -{ - Connection connection("localhost"); - ConsoleSession session(connection, ""); - posix::EventNotifier notifier(session); - PosixEventNotifierImplAccess::get(notifier).setReadable(true); - - bool readable(isReadable(notifier.getHandle())); - BOOST_CHECK(readable); -} - -QPID_AUTO_TEST_CASE(testSetReadableMultiple) -{ - Connection connection("localhost"); - ConsoleSession session(connection, ""); - posix::EventNotifier notifier(session); - for (int i = 0; i < 15; i++) - PosixEventNotifierImplAccess::get(notifier).setReadable(true); - PosixEventNotifierImplAccess::get(notifier).setReadable(false); - - bool readable(isReadable(notifier.getHandle())); - BOOST_CHECK(!readable); -} - -QPID_AUTO_TEST_CASE(testDeleteNotifier) -{ - Connection connection("localhost"); - ConsoleSession session(connection, ""); - ConsoleSessionImpl& sessionImpl = ConsoleSessionImplAccess::get(session); - { - posix::EventNotifier notifier(session); - BOOST_CHECK(sessionImpl.getEventNotifier() != 0); - } - BOOST_CHECK(sessionImpl.getEventNotifier() == 0); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/QueueDepth.cpp b/qpid/cpp/src/tests/QueueDepth.cpp deleted file mode 100644 index 09b221b3a8..0000000000 --- a/qpid/cpp/src/tests/QueueDepth.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * 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/broker/QueueDepth.h" - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueueDepthTestSuite) - -using namespace qpid::broker; - -QPID_AUTO_TEST_CASE(testCompare) -{ - QueueDepth a(0, 0); - QueueDepth b(1, 1); - QueueDepth c(2, 2); - QueueDepth d(1, 1); - - BOOST_CHECK(a < b); - BOOST_CHECK(b < c); - BOOST_CHECK(a < c); - - BOOST_CHECK(b > a); - BOOST_CHECK(c > b); - BOOST_CHECK(c > a); - - BOOST_CHECK(b == d); - BOOST_CHECK(d == b); - BOOST_CHECK(a != b); - BOOST_CHECK(b != a); - - QueueDepth e; e.setCount(1); - QueueDepth f; f.setCount(2); - BOOST_CHECK(e < f); - BOOST_CHECK(f > e); - - QueueDepth g; g.setSize(1); - QueueDepth h; h.setSize(2); - BOOST_CHECK(g < h); - BOOST_CHECK(h > g); -} - -QPID_AUTO_TEST_CASE(testIncrement) -{ - QueueDepth a(5, 10); - QueueDepth b(3, 6); - QueueDepth c(8, 16); - a += b; - BOOST_CHECK(a == c); - BOOST_CHECK_EQUAL(8u, a.getCount()); - BOOST_CHECK_EQUAL(16u, a.getSize()); -} - -QPID_AUTO_TEST_CASE(testDecrement) -{ - QueueDepth a(5, 10); - QueueDepth b(3, 6); - QueueDepth c(2, 4); - a -= b; - BOOST_CHECK(a == c); - BOOST_CHECK_EQUAL(2u, a.getCount()); - BOOST_CHECK_EQUAL(4u, a.getSize()); -} - -QPID_AUTO_TEST_CASE(testAddition) -{ - QueueDepth a(5, 10); - QueueDepth b(3, 6); - - QueueDepth c = a + b; - BOOST_CHECK_EQUAL(8u, c.getCount()); - BOOST_CHECK_EQUAL(16u, c.getSize()); -} - -QPID_AUTO_TEST_CASE(testSubtraction) -{ - QueueDepth a(5, 10); - QueueDepth b(3, 6); - - QueueDepth c = a - b; - BOOST_CHECK_EQUAL(2u, c.getCount()); - BOOST_CHECK_EQUAL(4u, c.getSize()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/QueueFlowLimitTest.cpp b/qpid/cpp/src/tests/QueueFlowLimitTest.cpp deleted file mode 100644 index b35294922d..0000000000 --- a/qpid/cpp/src/tests/QueueFlowLimitTest.cpp +++ /dev/null @@ -1,457 +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 -#include -#include "unit_test.h" -#include "test_tools.h" - -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/FieldValue.h" -#include "MessageUtils.h" -#include "BrokerFixture.h" - -using namespace qpid::broker; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueueFlowLimitTestSuite) - -namespace { - -class TestFlow : public QueueFlowLimit -{ -public: - TestFlow(uint32_t flowStopCount, uint32_t flowResumeCount, - uint64_t flowStopSize, uint64_t flowResumeSize) : - QueueFlowLimit("", flowStopCount, flowResumeCount, flowStopSize, flowResumeSize) - {} - virtual ~TestFlow() {} - - static TestFlow *createTestFlow(const qpid::framing::FieldTable& settings) - { - FieldTable::ValuePtr v; - - v = settings.get(flowStopCountKey); - uint32_t flowStopCount = (v) ? (uint32_t)v->get() : 0; - v = settings.get(flowResumeCountKey); - uint32_t flowResumeCount = (v) ? (uint32_t)v->get() : 0; - v = settings.get(flowStopSizeKey); - uint64_t flowStopSize = (v) ? (uint64_t)v->get() : 0; - v = settings.get(flowResumeSizeKey); - uint64_t flowResumeSize = (v) ? (uint64_t)v->get() : 0; - - return new TestFlow(flowStopCount, flowResumeCount, flowStopSize, flowResumeSize); - } - - static boost::shared_ptr getQueueFlowLimit(const qpid::framing::FieldTable& arguments) - { - QueueSettings settings; - settings.populate(arguments, settings.storeSettings); - return QueueFlowLimit::createLimit("", settings); - } -}; - -Message createMessage(uint32_t size) -{ - static uint32_t seqNum; - //Need to compute what data size is required to make a given - //overall size (use one byte of content in test message to ensure - //content frame is added) - Message test = MessageUtils::createMessage(qpid::types::Variant::Map(), std::string("x")); - size_t min = test.getMessageSize() - 1; - if (min > size) throw qpid::Exception("Can't create message that small!"); - Message msg = MessageUtils::createMessage(qpid::types::Variant::Map(), std::string (size - min, 'x')); - msg.setSequence(++seqNum);//this doesn't affect message size - return msg; -} -} - -QPID_AUTO_TEST_CASE(testFlowCount) -{ - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 7); - args.setInt(QueueFlowLimit::flowResumeCountKey, 5); - - std::auto_ptr flow(TestFlow::createTestFlow(args)); - - BOOST_CHECK_EQUAL((uint32_t) 7, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 5, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - - std::deque msgs; - for (size_t i = 0; i < 6; i++) { - msgs.push_back(createMessage(100)); - flow->enqueued(msgs.back()); - BOOST_CHECK(!flow->isFlowControlActive()); - } - BOOST_CHECK(!flow->isFlowControlActive()); // 6 on queue - msgs.push_back(createMessage(100)); - flow->enqueued(msgs.back()); - BOOST_CHECK(!flow->isFlowControlActive()); // 7 on queue - msgs.push_back(createMessage(100)); - flow->enqueued(msgs.back()); - BOOST_CHECK(flow->isFlowControlActive()); // 8 on queue, ON - msgs.push_back(createMessage(100)); - flow->enqueued(msgs.back()); - BOOST_CHECK(flow->isFlowControlActive()); // 9 on queue, no change to flow control - - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 8 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 7 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 6 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 5 on queue, no change - - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); // 4 on queue, OFF -} - -QPID_AUTO_TEST_CASE(testFlowSize) -{ - FieldTable args; - args.setUInt64(QueueFlowLimit::flowStopSizeKey, 700); - args.setUInt64(QueueFlowLimit::flowResumeSizeKey, 460); - - std::auto_ptr flow(TestFlow::createTestFlow(args)); - - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint32_t) 700, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint32_t) 460, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - - std::deque msgs; - for (size_t i = 0; i < 6; i++) { - msgs.push_back(createMessage(100)); - flow->enqueued(msgs.back()); - BOOST_CHECK(!flow->isFlowControlActive()); - } - BOOST_CHECK(!flow->isFlowControlActive()); // 600 on queue - BOOST_CHECK_EQUAL(6u, flow->getFlowCount()); - BOOST_CHECK_EQUAL(600u, flow->getFlowSize()); - - Message msg_50 = createMessage(50); - flow->enqueued(msg_50); - BOOST_CHECK(!flow->isFlowControlActive()); // 650 on queue - Message tinyMsg_1 = createMessage(40); - flow->enqueued(tinyMsg_1); - BOOST_CHECK(!flow->isFlowControlActive()); // 690 on queue - - Message tinyMsg_2 = createMessage(40); - flow->enqueued(tinyMsg_2); - BOOST_CHECK(flow->isFlowControlActive()); // 730 on queue, ON - msgs.push_back(createMessage(100)); - flow->enqueued(msgs.back()); - BOOST_CHECK(flow->isFlowControlActive()); // 830 on queue - BOOST_CHECK_EQUAL(10u, flow->getFlowCount()); - BOOST_CHECK_EQUAL(830u, flow->getFlowSize()); - - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 730 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 630 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 530 on queue - - flow->dequeued(tinyMsg_1); - BOOST_CHECK(flow->isFlowControlActive()); // 490 on queue - flow->dequeued(tinyMsg_2); - BOOST_CHECK(!flow->isFlowControlActive()); // 450 on queue, OFF - - flow->dequeued(msg_50); - BOOST_CHECK(!flow->isFlowControlActive()); // 400 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); // 300 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); // 200 on queue - BOOST_CHECK_EQUAL(2u, flow->getFlowCount()); - BOOST_CHECK_EQUAL(200u, flow->getFlowSize()); -} - -QPID_AUTO_TEST_CASE(testFlowArgs) -{ - FieldTable args; - const uint64_t stop(0x2FFFFFFFFull); - const uint64_t resume(0x1FFFFFFFFull); - args.setInt(QueueFlowLimit::flowStopCountKey, 30); - args.setInt(QueueFlowLimit::flowResumeCountKey, 21); - args.setUInt64(QueueFlowLimit::flowStopSizeKey, stop); - args.setUInt64(QueueFlowLimit::flowResumeSizeKey, resume); - - std::auto_ptr flow(TestFlow::createTestFlow(args)); - - BOOST_CHECK_EQUAL((uint32_t) 30, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 21, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL(stop, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL(resume, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); -} - - -QPID_AUTO_TEST_CASE(testFlowCombo) -{ - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 10); - args.setInt(QueueFlowLimit::flowResumeCountKey, 5); - args.setUInt64(QueueFlowLimit::flowStopSizeKey, 2000); - args.setUInt64(QueueFlowLimit::flowResumeSizeKey, 1000); - - std::deque msgs_50; - std::deque msgs_100; - std::deque msgs_500; - std::deque msgs_1000; - - Message msg; - - std::auto_ptr flow(TestFlow::createTestFlow(args)); - BOOST_CHECK(!flow->isFlowControlActive()); // count:0 size:0 - - // verify flow control comes ON when only count passes its stop point. - - for (size_t i = 0; i < 10; i++) { - msgs_100.push_back(createMessage(100)); - flow->enqueued(msgs_100.back()); - BOOST_CHECK(!flow->isFlowControlActive()); - } - // count:10 size:1000 - - msgs_50.push_back(createMessage(50)); - flow->enqueued(msgs_50.back()); // count:11 size: 1050 ->ON - BOOST_CHECK(flow->isFlowControlActive()); - - for (size_t i = 0; i < 6; i++) { - flow->dequeued(msgs_100.front()); - msgs_100.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - } - // count:5 size: 450 - - flow->dequeued(msgs_50.front()); // count: 4 size: 400 ->OFF - msgs_50.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); - - for (size_t i = 0; i < 4; i++) { - flow->dequeued(msgs_100.front()); - msgs_100.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); - } - // count:0 size:0 - - // verify flow control comes ON when only size passes its stop point. - - msgs_1000.push_back(createMessage(1000)); - flow->enqueued(msgs_1000.back()); // count:1 size: 1000 - BOOST_CHECK(!flow->isFlowControlActive()); - - msgs_500.push_back(createMessage(500)); - flow->enqueued(msgs_500.back()); // count:2 size: 1500 - BOOST_CHECK(!flow->isFlowControlActive()); - - msgs_500.push_back(createMessage(500)); - flow->enqueued(msgs_500.back()); // count:3 size: 2000 - BOOST_CHECK(!flow->isFlowControlActive()); - - msgs_50.push_back(createMessage(50)); - flow->enqueued(msgs_50.back()); // count:4 size: 2050 ->ON - BOOST_CHECK(flow->isFlowControlActive()); - - flow->dequeued(msgs_1000.front()); // count:3 size:1050 - msgs_1000.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - - flow->dequeued(msgs_50.front()); // count:2 size:1000 - msgs_50.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - - flow->dequeued(msgs_500.front()); // count:1 size:500 ->OFF - msgs_500.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); - - // verify flow control remains ON until both thresholds drop below their - // resume point. - - for (size_t i = 0; i < 8; i++) { - msgs_100.push_back(createMessage(100)); - flow->enqueued(msgs_100.back()); - BOOST_CHECK(!flow->isFlowControlActive()); - } - // count:9 size:1300 - - msgs_100.push_back(createMessage(100)); - flow->enqueued(msgs_100.back()); // count:10 size: 1400 - BOOST_CHECK(!flow->isFlowControlActive()); - - msgs_50.push_back(createMessage(50)); - flow->enqueued(msgs_50.back()); // count:11 size: 1450 ->ON - BOOST_CHECK(flow->isFlowControlActive()); - - msgs_1000.push_back(createMessage(1000)); - flow->enqueued(msgs_1000.back()); // count:12 size: 2450 (both thresholds crossed) - BOOST_CHECK(flow->isFlowControlActive()); - - // at this point: 9@100 + 1@500 + 1@1000 + 1@50 == 12@2450 - - flow->dequeued(msgs_500.front()); // count:11 size:1950 - msgs_500.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - - for (size_t i = 0; i < 9; i++) { - flow->dequeued(msgs_100.front()); - msgs_100.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - } - // count:2 size:1050 - flow->dequeued(msgs_50.front()); // count:1 size:1000 - msgs_50.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // still active due to size - - flow->dequeued(msgs_1000.front()); // count:0 size:0 ->OFF - msgs_1000.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); -} - - -QPID_AUTO_TEST_CASE(testFlowDefaultArgs) -{ - QueueFlowLimit::setDefaults(2950001, // max queue byte count - 80, // 80% stop threshold - 70); // 70% resume threshold - FieldTable args; - boost::shared_ptr flow = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(flow); - - BOOST_CHECK_EQUAL((uint64_t) 2360001, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint64_t) 2065000, flow->getFlowResumeSize()); - BOOST_CHECK_EQUAL( 0u, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL( 0u, flow->getFlowResumeCount()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); -} - - -QPID_AUTO_TEST_CASE(testFlowOverrideArgs) -{ - QueueFlowLimit::setDefaults(0, // max queue byte count - 80, // 80% stop threshold - 70); // 70% resume threshold - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 35000); - args.setInt(QueueFlowLimit::flowResumeCountKey, 30000); -// args.setInt(QueueFlowLimit::flowStopSizeKey, 0); - - boost::shared_ptr flow = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(flow); - - BOOST_CHECK_EQUAL((uint32_t) 35000, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 30000, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint64_t) 0, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint64_t) 0, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - } - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopSizeKey, 350000); - args.setInt(QueueFlowLimit::flowResumeSizeKey, 300000); - - boost::shared_ptr flow = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(flow); - - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint64_t) 350000, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint64_t) 300000, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - } - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 35000); - args.setInt(QueueFlowLimit::flowResumeCountKey, 30000); - args.setInt(QueueFlowLimit::flowStopSizeKey, 350000); - args.setInt(QueueFlowLimit::flowResumeSizeKey, 300000); - - boost::shared_ptr flow = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(flow); - - BOOST_CHECK_EQUAL((uint32_t) 35000, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 30000, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint64_t) 350000, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint64_t) 300000, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - } -} - - -QPID_AUTO_TEST_CASE(testFlowOverrideDefaults) -{ - QueueFlowLimit::setDefaults(2950001, // max queue byte count - 97, // stop threshold - 73); // resume threshold - FieldTable args; - boost::shared_ptr flow = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(flow); - - BOOST_CHECK_EQUAL((uint32_t) 2861501, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint32_t) 2153500, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); -} - - -QPID_AUTO_TEST_CASE(testFlowDisable) -{ - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 0); - args.setInt(QueueFlowLimit::flowStopSizeKey, 0); - boost::shared_ptr flow = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(!flow); - } -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/QueueOptionsTest.cpp b/qpid/cpp/src/tests/QueueOptionsTest.cpp deleted file mode 100644 index bdb83d7d22..0000000000 --- a/qpid/cpp/src/tests/QueueOptionsTest.cpp +++ /dev/null @@ -1,85 +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 -#include "qpid/framing/Array.h" -#include "qpid/client/QueueOptions.h" - -#include "unit_test.h" - -using namespace qpid::client; - - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueueOptionsTestSuite) - -QPID_AUTO_TEST_CASE(testSizePolicy) -{ - QueueOptions ft; - - ft.setSizePolicy(REJECT,1,2); - - BOOST_CHECK(QueueOptions::strREJECT == ft.getAsString(QueueOptions::strTypeKey)); - BOOST_CHECK(1 == ft.getAsInt(QueueOptions::strMaxSizeKey)); - BOOST_CHECK(2 == ft.getAsInt(QueueOptions::strMaxCountKey)); - - ft.setSizePolicy(FLOW_TO_DISK,0,2); - BOOST_CHECK(QueueOptions::strFLOW_TO_DISK == ft.getAsString(QueueOptions::strTypeKey)); - BOOST_CHECK(1 == ft.getAsInt(QueueOptions::strMaxSizeKey)); - BOOST_CHECK(2 == ft.getAsInt(QueueOptions::strMaxCountKey)); - - ft.setSizePolicy(RING,1,0); - BOOST_CHECK(QueueOptions::strRING == ft.getAsString(QueueOptions::strTypeKey)); - - ft.setSizePolicy(RING_STRICT,1,0); - BOOST_CHECK(QueueOptions::strRING_STRICT == ft.getAsString(QueueOptions::strTypeKey)); - - ft.clearSizePolicy(); - BOOST_CHECK(!ft.isSet(QueueOptions::strTypeKey)); - BOOST_CHECK(!ft.isSet(QueueOptions::strMaxSizeKey)); - BOOST_CHECK(!ft.isSet(QueueOptions::strMaxCountKey)); -} - -QPID_AUTO_TEST_CASE(testFlags) -{ - QueueOptions ft; - - ft.setOrdering(LVQ); - BOOST_CHECK(1 == ft.getAsInt(QueueOptions::strLastValueQueue)); - ft.setOrdering(FIFO); - BOOST_CHECK(!ft.isSet(QueueOptions::strLastValueQueue)); - -} - -QPID_AUTO_TEST_CASE(testSetOrdering) -{ - //ensure setOrdering(FIFO) works even if not preceded by a call to - //setOrdering(LVQ) - QueueOptions ft; - ft.setOrdering(FIFO); - BOOST_CHECK(!ft.isSet(QueueOptions::strLastValueQueue)); - -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/QueuePolicyTest.cpp b/qpid/cpp/src/tests/QueuePolicyTest.cpp deleted file mode 100644 index f61c283fd4..0000000000 --- a/qpid/cpp/src/tests/QueuePolicyTest.cpp +++ /dev/null @@ -1,300 +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 -#include "unit_test.h" -#include "test_tools.h" - -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/reply_exceptions.h" -#include "BrokerFixture.h" - -#include - -using namespace qpid::broker; -using namespace qpid::client; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueuePolicyTestSuite) - -QPID_AUTO_TEST_CASE(testRingPolicyCount) -{ - QueueOptions args; - args.setSizePolicy(RING, 0, 5); - - SessionFixture f; - std::string q("my-ring-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - for (int i = 0; i < 10; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - client::Message msg; - for (int i = 5; i < 10; i++) { - BOOST_CHECK(f.subs.get(msg, q, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("%1%_%2%") % "Message" % (i+1)).str(), msg.getData()); - } - BOOST_CHECK(!f.subs.get(msg, q)); - - for (int i = 10; i < 20; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 15; i < 20; i++) { - BOOST_CHECK(f.subs.get(msg, q, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("%1%_%2%") % "Message" % (i+1)).str(), msg.getData()); - } - BOOST_CHECK(!f.subs.get(msg, q)); -} - -QPID_AUTO_TEST_CASE(testRingPolicySize) -{ - //The message size now includes all headers as well as the content - //aka body, so compute the amount of data needed to hit a given - //overall size - std::string q("my-ring-queue"); - size_t minMessageSize = 25/*minimum size of headers*/ + q.size()/*routing key length*/ + 4/*default exchange, added by broker*/; - - std::string hundredBytes = std::string(100 - minMessageSize, 'h'); - std::string fourHundredBytes = std::string (400 - minMessageSize, 'f'); - std::string thousandBytes = std::string(1000 - minMessageSize, 't'); - - // Ring queue, 500 bytes maxSize - - QueueOptions args; - args.setSizePolicy(RING, 500, 0); - - SessionFixture f; - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - - // A. Send messages 0 .. 5, each 100 bytes - - client::Message m(hundredBytes, q); - - for (int i = 0; i < 6; i++) { - std::stringstream id; - id << i; - m.getMessageProperties().setCorrelationId(id.str()); - f.session.messageTransfer(arg::content=m); - } - - // should find 1 .. 5 on the queue, 0 is displaced by 5 - client::Message msg; - for (int i = 1; i < 6; i++) { - std::stringstream id; - id << i; - BOOST_CHECK(f.subs.get(msg, q, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL(msg.getMessageProperties().getCorrelationId(), id.str()); - } - BOOST_CHECK(!f.subs.get(msg, q)); - - // B. Now make sure that one 400 byte message displaces four 100 byte messages - - // Send messages 0 .. 5, each 100 bytes - for (int i = 0; i < 6; i++) { - client::Message m(hundredBytes, q); - std::stringstream id; - id << i; - m.getMessageProperties().setCorrelationId(id.str()); - f.session.messageTransfer(arg::content=m); - } - - // Now send one 400 byte message - client::Message m2(fourHundredBytes, q); - m2.getMessageProperties().setCorrelationId("6"); - f.session.messageTransfer(arg::content=m2); - - // expect to see 5, 6 on the queue - for (int i = 5; i < 7; i++) { - std::stringstream id; - id << i; - BOOST_CHECK(f.subs.get(msg, q, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL(msg.getMessageProperties().getCorrelationId(), id.str()); - } - BOOST_CHECK(!f.subs.get(msg, q)); - - - // C. Try sending a 1000-byte message, should fail - exceeds maxSize of queue - - client::Message m3(thousandBytes, q); - m3.getMessageProperties().setCorrelationId("6"); - try { - ScopedSuppressLogging sl; - f.session.messageTransfer(arg::content=m3); - BOOST_FAIL("Ooops - successfully added a 1000 byte message to a 512 byte ring queue ..."); - } - catch (...) { - } - -} - - -QPID_AUTO_TEST_CASE(testStrictRingPolicy) -{ - QueueOptions args; - args.setSizePolicy(RING_STRICT, 0, 5); - args.setString("qpid.flow_stop_count", "0"); - - SessionFixture f; - std::string q("my-ring-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - LocalQueue incoming; - SubscriptionSettings settings(FlowControl::unlimited()); - settings.autoAck = 0; // no auto ack. - Subscription sub = f.subs.subscribe(incoming, q, settings); - for (int i = 0; i < 5; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 0; i < 5; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f.session.messageTransfer(arg::content=client::Message("Message_6", q)); - BOOST_FAIL("expecting ResourceLimitExceededException."); - } catch (const ResourceLimitExceededException&) {} -} - -QPID_AUTO_TEST_CASE(testPolicyWithDtx) -{ - QueueOptions args; - args.setSizePolicy(REJECT, 0, 5); - - SessionFixture f; - std::string q("my-policy-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - LocalQueue incoming; - SubscriptionSettings settings(FlowControl::unlimited()); - settings.autoAck = 0; // no auto ack. - Subscription sub = f.subs.subscribe(incoming, q, settings); - f.session.dtxSelect(); - Xid tx1(1, "test-dtx-mgr", "tx1"); - f.session.dtxStart(arg::xid=tx1); - for (int i = 0; i < 5; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - f.session.dtxEnd(arg::xid=tx1); - f.session.dtxCommit(arg::xid=tx1, arg::onePhase=true); - - Xid tx2(1, "test-dtx-mgr", "tx2"); - f.session.dtxStart(arg::xid=tx2); - for (int i = 0; i < 5; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - SequenceSet accepting=sub.getUnaccepted(); - f.session.messageAccept(accepting); - f.session.dtxEnd(arg::xid=tx2); - f.session.dtxPrepare(arg::xid=tx2); - f.session.dtxRollback(arg::xid=tx2); - f.session.messageRelease(accepting); - - Xid tx3(1, "test-dtx-mgr", "tx3"); - f.session.dtxStart(arg::xid=tx3); - for (int i = 0; i < 5; i++) { - incoming.pop(); - } - accepting=sub.getUnaccepted(); - f.session.messageAccept(accepting); - f.session.dtxEnd(arg::xid=tx3); - f.session.dtxPrepare(arg::xid=tx3); - - Session other = f.connection.newSession(); - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - other.messageTransfer(arg::content=client::Message("Message_6", q)); - BOOST_FAIL("expecting ResourceLimitExceededException."); - } catch (const ResourceLimitExceededException&) {} - - f.session.dtxCommit(arg::xid=tx3); - //now retry and this time should succeed - other = f.connection.newSession(); - other.messageTransfer(arg::content=client::Message("Message_6", q)); -} - -QPID_AUTO_TEST_CASE(testFlowToDiskWithNoStore) -{ - //Ensure that with no store loaded, we don't flow to disk but - //fallback to rejecting messages - QueueOptions args; - args.setSizePolicy(FLOW_TO_DISK, 0, 5); - // Disable flow control, or else we'll never hit the max limit - args.setInt(QueueFlowLimit::flowStopCountKey, 0); - - SessionFixture f; - std::string q("my-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - LocalQueue incoming; - SubscriptionSettings settings(FlowControl::unlimited()); - settings.autoAck = 0; // no auto ack. - Subscription sub = f.subs.subscribe(incoming, q, settings); - for (int i = 0; i < 5; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 0; i < 5; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f.session.messageTransfer(arg::content=client::Message("Message_6", q)); - BOOST_FAIL("expecting ResourceLimitExceededException."); - } catch (const ResourceLimitExceededException&) {} -} - -QPID_AUTO_TEST_CASE(testPolicyFailureOnCommit) -{ - QueueOptions args; - args.setSizePolicy(REJECT, 0, 5); - - SessionFixture f; - std::string q("q"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - f.session.txSelect(); - for (int i = 0; i < 10; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - ScopedSuppressLogging sl; // Suppress messages for expected errors. - BOOST_CHECK_THROW(f.session.txCommit(), InternalErrorException); -} - -QPID_AUTO_TEST_CASE(testCapacityConversion) -{ - FieldTable args; - args.setString("qpid.max_count", "5"); - args.setString("qpid.flow_stop_count", "0"); - - SessionFixture f; - std::string q("q"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - for (int i = 0; i < 5; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f.session.messageTransfer(arg::content=client::Message("Message_6", q)); - BOOST_FAIL("expecting ResourceLimitExceededException."); - } catch (const ResourceLimitExceededException&) {} -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/QueueRegistryTest.cpp b/qpid/cpp/src/tests/QueueRegistryTest.cpp deleted file mode 100644 index 364d66c525..0000000000 --- a/qpid/cpp/src/tests/QueueRegistryTest.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/broker/QueueRegistry.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueSettings.h" -#include "unit_test.h" -#include - -using namespace qpid::broker; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueueRegistryTest) - -QPID_AUTO_TEST_CASE(testDeclare) -{ - std::string foo("foo"); - std::string bar("bar"); - QueueRegistry reg; - std::pair qc; - - qc = reg.declare(foo, QueueSettings()); - Queue::shared_ptr q = qc.first; - BOOST_CHECK(q); - BOOST_CHECK(qc.second); // New queue - BOOST_CHECK_EQUAL(foo, q->getName()); - - qc = reg.declare(foo, QueueSettings()); - BOOST_CHECK_EQUAL(q, qc.first); - BOOST_CHECK(!qc.second); - - qc = reg.declare(bar, QueueSettings()); - q = qc.first; - BOOST_CHECK(q); - BOOST_CHECK_EQUAL(true, qc.second); - BOOST_CHECK_EQUAL(bar, q->getName()); -} - -QPID_AUTO_TEST_CASE(testFind) -{ - std::string foo("foo"); - std::string bar("bar"); - QueueRegistry reg; - std::pair qc; - - BOOST_CHECK(reg.find(foo) == 0); - - reg.declare(foo, QueueSettings()); - reg.declare(bar, QueueSettings()); - Queue::shared_ptr q = reg.find(bar); - BOOST_CHECK(q); - BOOST_CHECK_EQUAL(bar, q->getName()); -} - -QPID_AUTO_TEST_CASE(testDestroy) -{ - std::string foo("foo"); - QueueRegistry reg; - std::pair qc; - - qc = reg.declare(foo, QueueSettings()); - reg.destroy(foo); - // Queue is gone from the registry. - BOOST_CHECK(reg.find(foo) == 0); - // Queue is not actually destroyed till we drop our reference. - BOOST_CHECK_EQUAL(foo, qc.first->getName()); - // We shoud be the only reference. - BOOST_CHECK_EQUAL(1L, qc.first.use_count()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/QueueTest.cpp b/qpid/cpp/src/tests/QueueTest.cpp deleted file mode 100644 index ee9d37e76d..0000000000 --- a/qpid/cpp/src/tests/QueueTest.cpp +++ /dev/null @@ -1,629 +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 "MessageUtils.h" -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/Exception.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/broker/QueueSettings.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Timer.h" - -#include -#include -#include -#include - -using namespace std; -using boost::intrusive_ptr; -using namespace qpid; -using namespace qpid::broker; -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -namespace qpid { -namespace tests { -class TestConsumer : public virtual Consumer{ -public: - typedef boost::shared_ptr shared_ptr; - - QueueCursor lastCursor; - Message lastMessage; - bool received; - TestConsumer(std::string name="test", bool acquire = true) : Consumer(name, acquire ? CONSUMER : BROWSER, ""), received(false) {}; - - virtual bool deliver(const QueueCursor& cursor, const Message& message){ - lastCursor = cursor; - lastMessage = message; - received = true; - return true; - }; - void notify() {} - void cancel() {} - void acknowledged(const DeliveryRecord&) {} - OwnershipToken* getSession() { return 0; } -}; - -class FailOnDeliver : public Deliverable -{ - Message msg; -public: - FailOnDeliver() : msg(MessageUtils::createMessage()) {} - void deliverTo(const boost::shared_ptr& queue) - { - throw Exception(QPID_MSG("Invalid delivery to " << queue->getName())); - } - Message& getMessage() { return msg; } -}; - -QPID_AUTO_TEST_SUITE(QueueTestSuite) - -QPID_AUTO_TEST_CASE(testBound){ - //test the recording of bindings, and use of those to allow a queue to be unbound - string key("my-key"); - FieldTable args; - - Queue::shared_ptr queue(new Queue("my-queue")); - ExchangeRegistry exchanges; - //establish bindings from exchange->queue and notify the queue as it is bound: - Exchange::shared_ptr exchange1 = exchanges.declare("my-exchange-1", "direct").first; - exchange1->bind(queue, key, &args); - queue->bound(exchange1->getName(), key, args); - - Exchange::shared_ptr exchange2 = exchanges.declare("my-exchange-2", "fanout").first; - exchange2->bind(queue, key, &args); - queue->bound(exchange2->getName(), key, args); - - Exchange::shared_ptr exchange3 = exchanges.declare("my-exchange-3", "topic").first; - exchange3->bind(queue, key, &args); - queue->bound(exchange3->getName(), key, args); - - //delete one of the exchanges: - exchanges.destroy(exchange2->getName()); - exchange2.reset(); - - //unbind the queue from all exchanges it knows it has been bound to: - queue->unbind(exchanges); - - //ensure the remaining exchanges don't still have the queue bound to them: - FailOnDeliver deliverable; - exchange1->route(deliverable); - exchange3->route(deliverable); -} - -QPID_AUTO_TEST_CASE(testLVQ){ - - QueueSettings settings; - string key="key"; - settings.lvqKey = key; - QueueFactory factory; - Queue::shared_ptr q(factory.create("my-queue", settings)); - - const char* values[] = { "a", "b", "c", "a"}; - for (size_t i = 0; i < sizeof(values)/sizeof(values[0]); ++i) { - qpid::types::Variant::Map properties; - properties[key] = values[i]; - q->deliver(MessageUtils::createMessage(properties, boost::lexical_cast(i+1))); - } - BOOST_CHECK_EQUAL(q->getMessageCount(), 3u); - - TestConsumer::shared_ptr c(new TestConsumer("test", true)); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(std::string("2"), c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(std::string("3"), c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(std::string("4"), c->lastMessage.getContent()); - - - const char* values2[] = { "a", "b", "c"}; - for (size_t i = 0; i < sizeof(values2)/sizeof(values2[0]); ++i) { - qpid::types::Variant::Map properties; - properties[key] = values[i]; - q->deliver(MessageUtils::createMessage(properties, boost::lexical_cast(i+5))); - } - BOOST_CHECK_EQUAL(q->getMessageCount(), 3u); - - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(std::string("5"), c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(std::string("6"), c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(std::string("7"), c->lastMessage.getContent()); -} - -QPID_AUTO_TEST_CASE(testLVQEmptyKey){ - - QueueSettings settings; - string key="key"; - settings.lvqKey = key; - QueueFactory factory; - Queue::shared_ptr q(factory.create("my-queue", settings)); - - - qpid::types::Variant::Map properties; - properties["key"] = "a"; - q->deliver(MessageUtils::createMessage(properties, "one")); - properties.clear(); - q->deliver(MessageUtils::createMessage(properties, "two")); - BOOST_CHECK_EQUAL(q->getMessageCount(), 2u); -} - -void addMessagesToQueue(uint count, Queue& queue, uint oddTtl = 200, uint evenTtl = 0) -{ - for (uint i = 0; i < count; i++) { - Message m = MessageUtils::createMessage("exchange", "key", i % 2 ? oddTtl : evenTtl); - queue.deliver(m); - } -} - -QPID_AUTO_TEST_CASE(testPurgeExpired) { - Queue queue("my-queue"); - addMessagesToQueue(10, queue); - BOOST_CHECK_EQUAL(queue.getMessageCount(), 10u); - ::usleep(300*1000); - queue.purgeExpired(0); - BOOST_CHECK_EQUAL(queue.getMessageCount(), 5u); -} - -QPID_AUTO_TEST_CASE(testQueueCleaner) { - boost::shared_ptr poller(new Poller); - Thread runner(poller.get()); - Timer timer; - QueueRegistry queues; - Queue::shared_ptr queue = queues.declare("my-queue", QueueSettings()).first; - addMessagesToQueue(10, *queue, 200, 400); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 10u); - - QueueCleaner cleaner(queues, poller, &timer); - cleaner.start(100 * qpid::sys::TIME_MSEC); - ::usleep(300*1000); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 5u); - ::usleep(300*1000); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 0u); - poller->shutdown(); - runner.join(); -} -namespace { -int getIntProperty(const Message& message, const std::string& key) -{ - qpid::types::Variant v = message.getProperty(key); - int i(0); - if (!v.isVoid()) i = v; - return i; -} -// helper for group tests -void verifyAcquire( Queue::shared_ptr queue, - TestConsumer::shared_ptr c, - std::deque& results, - const std::string& expectedGroup, - const int expectedId ) -{ - bool success = queue->dispatch(c); - BOOST_CHECK(success); - if (success) { - results.push_back(c->lastCursor); - std::string group = c->lastMessage.getPropertyAsString("GROUP-ID"); - int id = getIntProperty(c->lastMessage, "MY-ID"); - BOOST_CHECK_EQUAL( group, expectedGroup ); - BOOST_CHECK_EQUAL( id, expectedId ); - } -} - -Message createGroupMessage(int id, const std::string& group) -{ - qpid::types::Variant::Map properties; - properties["GROUP-ID"] = group; - properties["MY-ID"] = id; - return MessageUtils::createMessage(properties); -} -} - -QPID_AUTO_TEST_CASE(testGroupsMultiConsumer) { - // - // Verify that consumers of grouped messages own the groups once a message is acquired, - // and release the groups once all acquired messages have been dequeued or requeued - // - QueueSettings settings; - settings.shareGroups = 1; - settings.groupKey = "GROUP-ID"; - QueueFactory factory; - Queue::shared_ptr queue(factory.create("my_queue", settings)); - - std::string groups[] = { std::string("a"), std::string("a"), std::string("a"), - std::string("b"), std::string("b"), std::string("b"), - std::string("c"), std::string("c"), std::string("c") }; - for (int i = 0; i < 9; ++i) { - queue->deliver(createGroupMessage(i, groups[i])); - } - - // Queue = a-0, a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8... - // Owners= ---, ---, ---, ---, ---, ---, ---, ---, ---, - - BOOST_CHECK_EQUAL(uint32_t(9), queue->getMessageCount()); - - TestConsumer::shared_ptr c1(new TestConsumer("C1")); - TestConsumer::shared_ptr c2(new TestConsumer("C2")); - - queue->consume(c1); - queue->consume(c2); - - std::deque dequeMeC1; - std::deque dequeMeC2; - - - verifyAcquire(queue, c1, dequeMeC1, "a", 0 ); // c1 now owns group "a" (acquire a-0) - verifyAcquire(queue, c2, dequeMeC2, "b", 3 ); // c2 should now own group "b" (acquire b-3) - - // now let c1 complete the 'a-0' message - this should free the 'a' group - queue->dequeue( 0, dequeMeC1.front() ); - dequeMeC1.pop_front(); - - // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8... - // Owners= ---, ---, ^C2, ^C2, ^C2, ---, ---, --- - - // now c2 should pick up the next 'a-1', since it is oldest free - verifyAcquire(queue, c2, dequeMeC2, "a", 1 ); // c2 should now own groups "a" and "b" - - // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8... - // Owners= ^C2, ^C2, ^C2, ^C2, ^C2, ---, ---, --- - - // c1 should only be able to snarf up the first "c" message now... - verifyAcquire(queue, c1, dequeMeC1, "c", 6 ); // should skip to the first "c" - - // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8... - // Owners= ^C2, ^C2, ^C2, ^C2, ^C2, ^C1, ^C1, ^C1 - - // hmmm... what if c2 now dequeues "b-3"? (now only has a-1 acquired) - queue->dequeue( 0, dequeMeC2.front() ); - dequeMeC2.pop_front(); - - // Queue = a-1, a-2, b-4, b-5, c-6, c-7, c-8... - // Owners= ^C2, ^C2, ---, ---, ^C1, ^C1, ^C1 - - // b group is free, c is owned by c1 - c1's next get should grab 'b-4' - verifyAcquire(queue, c1, dequeMeC1, "b", 4 ); - - // Queue = a-1, a-2, b-4, b-5, c-6, c-7, c-8... - // Owners= ^C2, ^C2, ^C1, ^C1, ^C1, ^C1, ^C1 - - // c2 can now only grab a-2, and that's all - verifyAcquire(queue, c2, dequeMeC2, "a", 2 ); - - // now C2 can't get any more, since C1 owns "b" and "c" group... - bool gotOne = queue->dispatch(c2); - BOOST_CHECK( !gotOne ); - - // hmmm... what if c1 now dequeues "c-6"? (now only own's b-4) - queue->dequeue( 0, dequeMeC1.front() ); - dequeMeC1.pop_front(); - - // Queue = a-1, a-2, b-4, b-5, c-7, c-8... - // Owners= ^C2, ^C2, ^C1, ^C1, ---, --- - - // c2 can now grab c-7 - verifyAcquire(queue, c2, dequeMeC2, "c", 7 ); - - // Queue = a-1, a-2, b-4, b-5, c-7, c-8... - // Owners= ^C2, ^C2, ^C1, ^C1, ^C2, ^C2 - - // what happens if C-2 "requeues" a-1 and a-2? - queue->release( dequeMeC2.front() ); - dequeMeC2.pop_front(); - queue->release( dequeMeC2.front() ); - dequeMeC2.pop_front(); // now just has c-7 acquired - - // Queue = a-1, a-2, b-4, b-5, c-7, c-8... - // Owners= ---, ---, ^C1, ^C1, ^C2, ^C2 - - // now c1 will grab a-1 and a-2... - verifyAcquire(queue, c1, dequeMeC1, "a", 1 ); - verifyAcquire(queue, c1, dequeMeC1, "a", 2 ); - - // Queue = a-1, a-2, b-4, b-5, c-7, c-8... - // Owners= ^C1, ^C1, ^C1, ^C1, ^C2, ^C2 - - // c2 can now acquire c-8 only - verifyAcquire(queue, c2, dequeMeC2, "c", 8 ); - - // and c1 can get b-5 - verifyAcquire(queue, c1, dequeMeC1, "b", 5 ); - - // should be no more acquire-able for anyone now: - gotOne = queue->dispatch(c1); - BOOST_CHECK( !gotOne ); - gotOne = queue->dispatch(c2); - BOOST_CHECK( !gotOne ); - - // release all of C1's acquired messages, then cancel C1 - while (!dequeMeC1.empty()) { - queue->release(dequeMeC1.front()); - dequeMeC1.pop_front(); - } - queue->cancel(c1); - - // Queue = a-1, a-2, b-4, b-5, c-7, c-8... - // Owners= ---, ---, ---, ---, ^C2, ^C2 - - // b-4, a-1, a-2, b-5 all should be available, right? - verifyAcquire(queue, c2, dequeMeC2, "a", 1 ); - - while (!dequeMeC2.empty()) { - queue->dequeue(0, dequeMeC2.front()); - dequeMeC2.pop_front(); - } - - // Queue = a-2, b-4, b-5 - // Owners= ---, ---, --- - - TestConsumer::shared_ptr c3(new TestConsumer("C3")); - queue->consume(c3); - std::deque dequeMeC3; - - verifyAcquire(queue, c3, dequeMeC3, "a", 2 ); - verifyAcquire(queue, c2, dequeMeC2, "b", 4 ); - - // Queue = a-2, b-4, b-5 - // Owners= ^C3, ^C2, ^C2 - - gotOne = queue->dispatch(c3); - BOOST_CHECK( !gotOne ); - - verifyAcquire(queue, c2, dequeMeC2, "b", 5 ); - - while (!dequeMeC2.empty()) { - queue->dequeue(0, dequeMeC2.front()); - dequeMeC2.pop_front(); - } - - // Queue = a-2, - // Owners= ^C3, - queue->deliver(createGroupMessage(9, "a")); - - // Queue = a-2, a-9 - // Owners= ^C3, ^C3 - - gotOne = queue->dispatch(c2); - BOOST_CHECK( !gotOne ); - - queue->deliver(createGroupMessage(10, "b")); - - // Queue = a-2, a-9, b-10 - // Owners= ^C3, ^C3, ---- - - verifyAcquire(queue, c2, dequeMeC2, "b", 10 ); - verifyAcquire(queue, c3, dequeMeC3, "a", 9 ); - - gotOne = queue->dispatch(c3); - BOOST_CHECK( !gotOne ); - - queue->cancel(c2); - queue->cancel(c3); -} - - -QPID_AUTO_TEST_CASE(testGroupsMultiConsumerDefaults) { - // - // Verify that the same default group name is automatically applied to messages that - // do not specify a group name. - // - QueueSettings settings; - settings.shareGroups = 1; - settings.groupKey = "GROUP-ID"; - QueueFactory factory; - Queue::shared_ptr queue(factory.create("my_queue", settings)); - - for (int i = 0; i < 3; ++i) { - qpid::types::Variant::Map properties; - // no "GROUP-ID" header - properties["MY-ID"] = i; - queue->deliver(MessageUtils::createMessage(properties)); - } - - // Queue = 0, 1, 2 - - BOOST_CHECK_EQUAL(uint32_t(3), queue->getMessageCount()); - - TestConsumer::shared_ptr c1(new TestConsumer("C1")); - TestConsumer::shared_ptr c2(new TestConsumer("C2")); - - queue->consume(c1); - queue->consume(c2); - - std::deque dequeMeC1; - std::deque dequeMeC2; - - queue->dispatch(c1); // c1 now owns default group (acquired 0) - dequeMeC1.push_back(c1->lastCursor); - int id = getIntProperty(c1->lastMessage, "MY-ID"); - BOOST_CHECK_EQUAL( id, 0 ); - - bool gotOne = queue->dispatch(c2); // c2 should get nothing - BOOST_CHECK( !gotOne ); - - queue->dispatch(c1); // c1 now acquires 1 - dequeMeC1.push_back(c1->lastCursor); - id = getIntProperty(c1->lastMessage, "MY-ID"); - BOOST_CHECK_EQUAL( id, 1 ); - - gotOne = queue->dispatch(c2); // c2 should still get nothing - BOOST_CHECK( !gotOne ); - - while (!dequeMeC1.empty()) { - queue->dequeue(0, dequeMeC1.front()); - dequeMeC1.pop_front(); - } - - // now default group should be available... - queue->dispatch(c2); // c2 now owns default group (acquired 2) - id = c2->lastMessage.getProperty("MY-ID"); - BOOST_CHECK_EQUAL( id, 2 ); - - gotOne = queue->dispatch(c1); // c1 should get nothing - BOOST_CHECK( !gotOne ); - - queue->cancel(c1); - queue->cancel(c2); -} - -QPID_AUTO_TEST_CASE(testSetPositionFifo) { - Queue::shared_ptr q(new Queue("my-queue", true)); - BOOST_CHECK_EQUAL(q->getPosition(), SequenceNumber(0)); - for (int i = 0; i < 10; ++i) - q->deliver(MessageUtils::createMessage(qpid::types::Variant::Map(), boost::lexical_cast(i+1))); - - // Verify the front of the queue - TestConsumer::shared_ptr c(new TestConsumer("test", false)); // Don't acquire - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(1u, c->lastMessage.getSequence()); // Numbered from 1 - BOOST_CHECK_EQUAL("1", c->lastMessage.getContent()); - - // Verify the back of the queue - BOOST_CHECK_EQUAL(10u, q->getPosition()); - BOOST_CHECK_EQUAL(10u, q->getMessageCount()); - - // Using setPosition to introduce a gap in sequence numbers. - q->setPosition(15); - BOOST_CHECK_EQUAL(10u, q->getMessageCount()); - BOOST_CHECK_EQUAL(15u, q->getPosition()); - q->deliver(MessageUtils::createMessage(qpid::types::Variant::Map(), "16")); - - q->seek(*c, Queue::MessagePredicate(), 9); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(10u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("10", c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(16u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("16", c->lastMessage.getContent()); - - // Using setPosition to trunkcate the queue - q->setPosition(5); - BOOST_CHECK_EQUAL(5u, q->getMessageCount()); - q->deliver(MessageUtils::createMessage(qpid::types::Variant::Map(), "6a")); - c = boost::shared_ptr(new TestConsumer("test", false)); // Don't acquire - q->seek(*c, Queue::MessagePredicate(), 4); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(5u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("5", c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(6u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("6a", c->lastMessage.getContent()); - BOOST_CHECK(!q->dispatch(c)); // No more messages. -} - -QPID_AUTO_TEST_CASE(testSetPositionLvq) { - QueueSettings settings; - string key="key"; - settings.lvqKey = key; - QueueFactory factory; - Queue::shared_ptr q(factory.create("my-queue", settings)); - - const char* values[] = { "a", "b", "c", "a", "b", "c" }; - for (size_t i = 0; i < sizeof(values)/sizeof(values[0]); ++i) { - qpid::types::Variant::Map properties; - properties[key] = values[i]; - q->deliver(MessageUtils::createMessage(properties, boost::lexical_cast(i+1))); - } - BOOST_CHECK_EQUAL(3u, q->getMessageCount()); - // Verify the front of the queue - TestConsumer::shared_ptr c(new TestConsumer("test", false)); // Don't acquire - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(4u, c->lastMessage.getSequence()); // Numbered from 1 - BOOST_CHECK_EQUAL("4", c->lastMessage.getContent()); - // Verify the back of the queue - BOOST_CHECK_EQUAL(6u, q->getPosition()); - - q->setPosition(5); - - c = boost::shared_ptr(new TestConsumer("test", false)); // Don't acquire - q->seek(*c, Queue::MessagePredicate(), 4); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(5u, c->lastMessage.getSequence()); // Numbered from 1 - BOOST_CHECK(!q->dispatch(c)); -} - -QPID_AUTO_TEST_CASE(testSetPositionPriority) { - QueueSettings settings; - settings.priorities = 10; - QueueFactory factory; - Queue::shared_ptr q(factory.create("my-queue", settings)); - - const int priorities[] = { 1, 2, 3, 2, 1, 3 }; - for (size_t i = 0; i < sizeof(priorities)/sizeof(priorities[0]); ++i) { - qpid::types::Variant::Map properties; - properties["priority"] = priorities[i]; - q->deliver(MessageUtils::createMessage(properties, boost::lexical_cast(i+1))); - } - - // Truncation removes messages in fifo order, not priority order. - q->setPosition(3); - TestConsumer::shared_ptr c(new TestConsumer("test", false)); // Browse in priority order - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(3u, c->lastMessage.getSequence()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(2u, c->lastMessage.getSequence()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(1u, c->lastMessage.getSequence()); - BOOST_CHECK(!q->dispatch(c)); - - qpid::types::Variant::Map properties; - properties["priority"] = 4; - q->deliver(MessageUtils::createMessage(properties, "4a")); - - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(4u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("4a", c->lastMessage.getContent()); - - // But consumers see priority order - c.reset(new TestConsumer("test", true)); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(4u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("4a", c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(3u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("3", c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(2u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("2", c->lastMessage.getContent()); - BOOST_CHECK(q->dispatch(c)); - BOOST_CHECK_EQUAL(1u, c->lastMessage.getSequence()); - BOOST_CHECK_EQUAL("1", c->lastMessage.getContent()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/README.txt b/qpid/cpp/src/tests/README.txt deleted file mode 100644 index 50bd181ab0..0000000000 --- a/qpid/cpp/src/tests/README.txt +++ /dev/null @@ -1,30 +0,0 @@ -= Running Qpid C++ tests = - -General philosophy is that "make test" run all tests by default, but -developers can run tests selectively as explained below. - -== Unit Tests == - -Unit tests use the boost test framework, and are compiled to the programd -unit_test - -There are several options to control how test results are displayed. See -http://www.boost.org/doc/libs/1_35_0/libs/test/doc/components/utf/parameters/index.html. - -== System Tests == - -System tests are executables or scripts. You can run executable tests -directly as well as via "make test" or "ctest". Some tests require -environment settings which are set by src/tests/env.sh on Unix or by -src/tests/env.ps1 on Windows. - -== Running selected tests == - -The make target "make test" simply runs the command "ctest". Running ctest -directly gives you additional options, e.g. - - ctest -R -VV - -This runs tests with names matching the regular expression and will -print the full output of the tests rather than just listing which tests pass or -fail. diff --git a/qpid/cpp/src/tests/RangeSet.cpp b/qpid/cpp/src/tests/RangeSet.cpp deleted file mode 100644 index 285f432bf7..0000000000 --- a/qpid/cpp/src/tests/RangeSet.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * 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 "unit_test.h" -#include "test_tools.h" -#include "qpid/RangeSet.h" - -using namespace std; -using namespace qpid; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(RangeSetTestSuite) - -typedef qpid::Range TR; // Test Range -typedef RangeSet TRSet; - -QPID_AUTO_TEST_CASE(testEmptyRange) { - TR r; - BOOST_CHECK_EQUAL(r, TR(0,0)); - BOOST_CHECK(r.empty()); - BOOST_CHECK(!r.contains(0)); -} - -QPID_AUTO_TEST_CASE(testRangeSetAddPoint) { - TRSet r; - BOOST_CHECK(r.empty()); - r += 3; - BOOST_CHECK_MESSAGE(r.contains(3), r); - BOOST_CHECK_MESSAGE(r.contains(TR(3,4)), r); - BOOST_CHECK(!r.empty()); - r += 5; - BOOST_CHECK_MESSAGE(r.contains(5), r); - BOOST_CHECK_MESSAGE(r.contains(TR(5,6)), r); - BOOST_CHECK_MESSAGE(!r.contains(TR(3,6)), r); - r += 4; - BOOST_CHECK_MESSAGE(r.contains(TR(3,6)), r); -} - -QPID_AUTO_TEST_CASE(testRangeSetAddRange) { - TRSet r; - r += TR(0,3); - BOOST_CHECK(r.contains(TR(0,3))); - BOOST_CHECK(r.contiguous()); - r += TR(4,6); - BOOST_CHECK(!r.contiguous()); - BOOST_CHECK_MESSAGE(r.contains(TR(4,6)), r); - r += 3; - BOOST_CHECK_MESSAGE(r.contains(TR(0,6)), r); - BOOST_CHECK(r.front() == 0); - BOOST_CHECK(r.back() == 6); - - // Merging additions - r = TRSet(0,3)+TR(5,6); - TRSet e(0,6); - BOOST_CHECK_EQUAL(r + TR(3,5), e); - BOOST_CHECK(e.contiguous()); - r = TRSet(0,5)+TR(10,15)+TR(20,25)+TR(30,35)+TR(40,45); - BOOST_CHECK_EQUAL(r + TR(11,37), TRSet(0,5)+TR(11,37)+TR(40,45)); -} - -QPID_AUTO_TEST_CASE(testRangeSetAddSet) { - TRSet r; - TRSet s = TRSet(0,3)+TR(5,10); - r += s; - BOOST_CHECK_EQUAL(r,s); - r += TRSet(3,5) + TR(7,12) + 15; - BOOST_CHECK_EQUAL(r, TRSet(0,12) + 15); - - r.clear(); - BOOST_CHECK(r.empty()); - r += TR::makeClosed(6,10); - BOOST_CHECK_EQUAL(r, TRSet(6,11)); - r += TRSet(2,6)+8; - BOOST_CHECK_EQUAL(r, TRSet(2,11)); -} - -QPID_AUTO_TEST_CASE(testRangeSetIterate) { - TRSet r = TRSet(1,3)+TR(4,7)+TR(10,11); - std::vector actual; - std::copy(r.begin(), r.end(), std::back_inserter(actual)); - std::vector expect = boost::assign::list_of(1)(2)(4)(5)(6)(10); - BOOST_CHECK_EQUAL(expect, actual); -} - -QPID_AUTO_TEST_CASE(testRangeSetRemove) { - // points - BOOST_CHECK_EQUAL(TRSet(0,5)-3, TRSet(0,3)+TR(4,5)); - BOOST_CHECK_EQUAL(TRSet(1,5)-5, TRSet(1,5)); - BOOST_CHECK_EQUAL(TRSet(1,5)-0, TRSet(1,5)); - - TRSet r(TRSet(0,5)+TR(10,15)+TR(20,25)); - - // TRs - BOOST_CHECK_EQUAL(r-TR(0,5), TRSet(10,15)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(10,15), TRSet(0,5)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(20,25), TRSet(0,5)+TR(10,15)); - - BOOST_CHECK_EQUAL(r-TR(-5, 30), TRSet()); - - BOOST_CHECK_EQUAL(r-TR(-5, 7), TRSet(10,15)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(8,19), TRSet(0,5)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(17,30), TRSet(0,5)+TR(10,15)); - - BOOST_CHECK_EQUAL(r-TR(-5, 5), TRSet(10,15)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(10,19), TRSet(0,5)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(18,25), TRSet(0,5)+TR(10,15)); - BOOST_CHECK_EQUAL(r-TR(23,25), TRSet(0,5)+TR(10,15)+TR(20,23)); - - BOOST_CHECK_EQUAL(r-TR(-3, 3), TRSet(3,5)+TR(10,15)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(3, 7), TRSet(0,2)+TR(10,15)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(3, 12), TRSet(0,3)+TR(12,15)+TR(20,25)); - BOOST_CHECK_EQUAL(r-TR(3, 22), TRSet(12,15)+TR(22,25)); - BOOST_CHECK_EQUAL(r-TR(12, 22), TRSet(0,5)+TR(10,11)+TR(22,25)); - - // Sets - BOOST_CHECK_EQUAL(r-(TRSet(-1,6)+TR(11,14)+TR(23,25)), - TRSet(10,11)+TR(14,15)+TR(20,23)); - // Split the ranges - BOOST_CHECK_EQUAL(r-(TRSet(2,3)+TR(11,13)+TR(21,23)), - TRSet(0,2)+TR(4,5)+ - TR(10,11)+TR(14,15)+ - TR(20,21)+TR(23,25)); - // Truncate the ranges - BOOST_CHECK_EQUAL(r-(TRSet(0,3)+TR(13,15)+TR(19,23)), - TRSet(3,5)+TR(10,13)+TR(20,23)); - // Remove multiple ranges with truncation - BOOST_CHECK_EQUAL(r-(TRSet(3,23)), TRSet(0,3)+TR(23,25)); - // Remove multiple ranges in middle - TRSet r2 = TRSet(0,5)+TR(10,15)+TR(20,25)+TR(30,35); - BOOST_CHECK_EQUAL(r2-TRSet(11,24), - TRSet(0,5)+TR(10,11)+TR(24,25)+TR(30,35)); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/RefCounted.cpp b/qpid/cpp/src/tests/RefCounted.cpp deleted file mode 100644 index 3ac3895322..0000000000 --- a/qpid/cpp/src/tests/RefCounted.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * 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/RefCounted.h" -#include - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(RefCountedTestSuiteTestSuite) - -using boost::intrusive_ptr; -using namespace std; -using namespace qpid; - -struct CountMe : public RefCounted { - static int instances; - CountMe() { ++instances; } - ~CountMe() { --instances; } -}; - -int CountMe::instances=0; - -QPID_AUTO_TEST_CASE(testRefCounted) { - BOOST_CHECK_EQUAL(0, CountMe::instances); - intrusive_ptr p(new CountMe()); - BOOST_CHECK_EQUAL(1, CountMe::instances); - intrusive_ptr q(p); - BOOST_CHECK_EQUAL(1, CountMe::instances); - q=0; - BOOST_CHECK_EQUAL(1, CountMe::instances); - p=0; - BOOST_CHECK_EQUAL(0, CountMe::instances); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/RetryList.cpp b/qpid/cpp/src/tests/RetryList.cpp deleted file mode 100644 index 50cd5edfe8..0000000000 --- a/qpid/cpp/src/tests/RetryList.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * 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 "unit_test.h" -#include "test_tools.h" -#include "qpid/broker/RetryList.h" - -using namespace qpid; -using namespace qpid::broker; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(RetryListTestSuite) - -struct RetryListFixture -{ - RetryList list; - std::vector urls; - std::vector
expected; - - void addUrl(const std::string& s) - { - urls.push_back(Url(s)); - } - - void addExpectation(const std::string& host, uint16_t port) - { - expected.push_back(Address("tcp", host, port)); - } - - void check() - { - list.reset(urls); - for (int t = 0; t < 2; t++) { - Address next; - for (std::vector
::const_iterator i = expected.begin(); i != expected.end(); ++i) { - BOOST_CHECK(list.next(next)); - BOOST_CHECK_EQUAL(i->host, next.host); - BOOST_CHECK_EQUAL(i->port, next.port); - } - BOOST_CHECK(!list.next(next)); - } - } -}; - -QPID_AUTO_TEST_CASE(testWithSingleAddress) -{ - RetryListFixture test; - test.addUrl("amqp:host:5673"); - test.addExpectation("host", 5673); - test.check(); -} - -QPID_AUTO_TEST_CASE(testWithSingleUrlOfMultipleAddresses) -{ - RetryListFixture test; - test.addUrl("amqp:host1,host2:2222,tcp:host3:5673,host4:1"); - - test.addExpectation("host1", 5672); - test.addExpectation("host2", 2222); - test.addExpectation("host3", 5673); - test.addExpectation("host4", 1); - - test.check(); -} - -QPID_AUTO_TEST_CASE(testWithMultipleUrlsOfMultipleAddresses) -{ - RetryListFixture test; - test.addUrl("amqp:my-host"); - test.addUrl("amqp:host1:6666,host2:2222,tcp:host3:5673,host4:1"); - test.addUrl("amqp:host5,host6:2222,tcp:host7:5673"); - - test.addExpectation("my-host", 5672); - test.addExpectation("host1", 6666); - test.addExpectation("host2", 2222); - test.addExpectation("host3", 5673); - test.addExpectation("host4", 1); - test.addExpectation("host5", 5672); - test.addExpectation("host6", 2222); - test.addExpectation("host7", 5673); - - test.check(); -} - -QPID_AUTO_TEST_CASE(testEmptyList) -{ - RetryListFixture test; - test.check(); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Selector.cpp b/qpid/cpp/src/tests/Selector.cpp deleted file mode 100644 index 6995420f17..0000000000 --- a/qpid/cpp/src/tests/Selector.cpp +++ /dev/null @@ -1,501 +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/broker/SelectorToken.h" -#include "qpid/broker/Selector.h" -#include "qpid/broker/SelectorValue.h" - -#include "unit_test.h" - -#include -#include -#include - -using std::string; -using std::map; -using std::vector; - -namespace qb = qpid::broker; - -using qpid::broker::Token; -using qpid::broker::TokenType; -using qpid::broker::Tokeniser; -using qpid::broker::tokenise; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(SelectorSuite) - -typedef bool (*TokeniseF)(string::const_iterator&,string::const_iterator&,Token&); - -bool tokeniseEos(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok) -{ - Token t1; - std::string::const_iterator t = s; - bool r = tokenise(t, e, t1); - if (r && (t1.type==qb::T_EOS)) {tok = t1; s = t; return true;} - return false; -} - -bool tokeniseParens(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok) -{ - Token t1; - std::string::const_iterator t = s; - bool r = tokenise(t, e, t1); - if (r && (t1.type==qb::T_LPAREN || t1.type==qb::T_RPAREN)) {tok = t1; s = t; return true;} - return false; -} - -bool tokeniseOperator(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok) -{ - Token t1; - std::string::const_iterator t = s; - bool r = tokenise(t, e, t1); - if (r && (t1.type>=qb::T_PLUS && t1.type<=qb::T_GREQ)) {tok = t1; s = t; return true;} - return false; -} - -bool tokeniseString(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok) -{ - Token t1; - std::string::const_iterator t = s; - bool r = tokenise(t, e, t1); - if (r && (t1.type==qb::T_STRING)) {tok = t1; s = t; return true;} - return false; -} - -bool tokeniseIdentifier(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok) -{ - Token t1; - std::string::const_iterator t = s; - bool r = tokenise(t, e, t1); - if (r && (t1.type==qb::T_IDENTIFIER)) {tok = t1; s = t; return true;} - return false; -} - -bool tokeniseReservedWord(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok) -{ - std::string::const_iterator t = s; - Token t1; - if (tokenise(t, e, t1)) { - switch (t1.type) { - case qb::T_AND: - case qb::T_BETWEEN: - case qb::T_ESCAPE: - case qb::T_FALSE: - case qb::T_IN: - case qb::T_IS: - case qb::T_LIKE: - case qb::T_NOT: - case qb::T_NULL: - case qb::T_OR: - case qb::T_TRUE: - tok = t1; - s = t; - return true; - default: - break; - } - } - return false; -} - -bool tokeniseNumeric(std::string::const_iterator& s, std::string::const_iterator& e, Token& tok) -{ - Token t1; - std::string::const_iterator t = s; - bool r = tokenise(t, e, t1); - if (r && (t1.type==qb::T_NUMERIC_EXACT || t1.type==qb::T_NUMERIC_APPROX)) {tok = t1; s = t; return true;} - return false; -} - - -void verifyTokeniserSuccess(TokeniseF t, const char* ss, TokenType tt, const char* tv, const char* fs) { - Token tok; - string s(ss); - string::const_iterator sb = s.begin(); - string::const_iterator se = s.end(); - BOOST_CHECK(t(sb, se, tok)); - BOOST_CHECK_EQUAL(tok, Token(tt, tv)); - BOOST_CHECK_EQUAL(string(sb, se), fs); -} - -void verifyTokeniserFail(TokeniseF t, const char* c) { - Token tok; - string s(c); - string::const_iterator sb = s.begin(); - string::const_iterator se = s.end(); - BOOST_CHECK(!t(sb, se, tok)); - BOOST_CHECK_EQUAL(string(sb, se), c); -} - -QPID_AUTO_TEST_CASE(tokeniseSuccess) -{ - verifyTokeniserSuccess(&tokenise, "", qb::T_EOS, "", ""); - verifyTokeniserSuccess(&tokenise, " ", qb::T_EOS, "", ""); - verifyTokeniserSuccess(&tokenise, "null_123+blah", qb::T_IDENTIFIER, "null_123", "+blah"); - verifyTokeniserSuccess(&tokenise, "\"null-123\"+blah", qb::T_IDENTIFIER, "null-123", "+blah"); - verifyTokeniserSuccess(&tokenise, "\"This is an \"\"odd!\"\" identifier\"+blah", qb::T_IDENTIFIER, "This is an \"odd!\" identifier", "+blah"); - verifyTokeniserSuccess(&tokenise, "null+blah", qb::T_NULL, "null", "+blah"); - verifyTokeniserSuccess(&tokenise, "null+blah", qb::T_NULL, "null", "+blah"); - verifyTokeniserSuccess(&tokenise, "Is nOt null", qb::T_IS, "Is", " nOt null"); - verifyTokeniserSuccess(&tokenise, "nOt null", qb::T_NOT, "nOt", " null"); - verifyTokeniserSuccess(&tokenise, "Is nOt null", qb::T_IS, "Is", " nOt null"); - verifyTokeniserSuccess(&tokenise, "'Hello World'", qb::T_STRING, "Hello World", ""); - verifyTokeniserSuccess(&tokenise, "'Hello World''s end'a bit more", qb::T_STRING, "Hello World's end", "a bit more"); - verifyTokeniserSuccess(&tokenise, "=blah", qb::T_EQUAL, "=", "blah"); - verifyTokeniserSuccess(&tokenise, "<> Identifier", qb::T_NEQ, "<>", " Identifier"); - verifyTokeniserSuccess(&tokenise, "(a and b) not c", qb::T_LPAREN, "(", "a and b) not c"); - verifyTokeniserSuccess(&tokenise, ") not c", qb::T_RPAREN, ")", " not c"); - verifyTokeniserSuccess(&tokenise, "017kill", qb::T_NUMERIC_EXACT, "017", "kill"); - verifyTokeniserSuccess(&tokenise, "019kill", qb::T_NUMERIC_EXACT, "01", "9kill"); - verifyTokeniserSuccess(&tokenise, "0kill", qb::T_NUMERIC_EXACT, "0", "kill"); - verifyTokeniserSuccess(&tokenise, "0.kill", qb::T_NUMERIC_APPROX, "0.", "kill"); - verifyTokeniserSuccess(&tokenise, "3.1415=pi", qb::T_NUMERIC_APPROX, "3.1415", "=pi"); - verifyTokeniserSuccess(&tokenise, ".25.kill", qb::T_NUMERIC_APPROX, ".25", ".kill"); - verifyTokeniserSuccess(&tokenise, "2e5.kill", qb::T_NUMERIC_APPROX, "2e5", ".kill"); - verifyTokeniserSuccess(&tokenise, "3.e50easy to kill", qb::T_NUMERIC_APPROX, "3.e50", "easy to kill"); - verifyTokeniserSuccess(&tokenise, "34.25e+50easy to kill", qb::T_NUMERIC_APPROX, "34.25e+50", "easy to kill"); - verifyTokeniserSuccess(&tokenise, "34de", qb::T_NUMERIC_APPROX, "34d", "e"); - verifyTokeniserSuccess(&tokenise, "34fuller", qb::T_NUMERIC_APPROX, "34f", "uller"); - verifyTokeniserSuccess(&tokenise, "34Longer", qb::T_NUMERIC_EXACT, "34L", "onger"); - verifyTokeniserSuccess(&tokenise, "34littler", qb::T_NUMERIC_EXACT, "34l", "ittler"); - verifyTokeniserSuccess(&tokenise, "034Longer", qb::T_NUMERIC_EXACT, "034L", "onger"); - verifyTokeniserSuccess(&tokenise, "034littler", qb::T_NUMERIC_EXACT, "034l", "ittler"); - verifyTokeniserSuccess(&tokenise, "0X34littler", qb::T_NUMERIC_EXACT, "0X34l", "ittler"); - verifyTokeniserSuccess(&tokenise, "0X3456_fffflittler", qb::T_NUMERIC_EXACT, "0X3456_ffffl", "ittler"); - verifyTokeniserSuccess(&tokenise, "0xdead_beafittler", qb::T_NUMERIC_EXACT, "0xdead_beaf", "ittler"); -} - -QPID_AUTO_TEST_CASE(tokeniseFailure) -{ - verifyTokeniserFail(&tokeniseEos, "hb23"); - verifyTokeniserFail(&tokeniseIdentifier, "123"); - verifyTokeniserFail(&tokeniseIdentifier, "'Embedded 123'"); - verifyTokeniserFail(&tokeniseReservedWord, "1.2e5"); - verifyTokeniserFail(&tokeniseReservedWord, "'Stringy thing'"); - verifyTokeniserFail(&tokeniseReservedWord, "oR_andsomething"); - verifyTokeniserFail(&tokeniseString, "'Embedded 123"); - verifyTokeniserFail(&tokeniseString, "'This isn''t fair"); - verifyTokeniserFail(&tokeniseOperator, "123"); - verifyTokeniserFail(&tokeniseOperator, "'Stringy thing'"); - verifyTokeniserFail(&tokeniseOperator, "NoT"); - verifyTokeniserFail(&tokeniseOperator, "(a and b)"); - verifyTokeniserFail(&tokeniseOperator, ")"); - verifyTokeniserFail(&tokeniseParens, "="); - verifyTokeniserFail(&tokeniseParens, "what ho!"); - verifyTokeniserFail(&tokeniseNumeric, "kill"); - verifyTokeniserFail(&tokeniseNumeric, "e3"); - verifyTokeniserFail(&tokeniseNumeric, "1.e.5"); - verifyTokeniserFail(&tokeniseNumeric, ".e5"); - verifyTokeniserFail(&tokeniseNumeric, "34e"); - verifyTokeniserFail(&tokeniseNumeric, ".3e+"); - verifyTokeniserFail(&tokeniseNumeric, ".3e-."); - verifyTokeniserFail(&tokenise, "0b34Longer"); - verifyTokeniserFail(&tokenise, "0X_34Longer"); -} - -QPID_AUTO_TEST_CASE(tokenString) -{ - - string exp(" a =b"); - string::const_iterator s = exp.begin(); - string::const_iterator e = exp.end(); - Tokeniser t(s, e); - - BOOST_CHECK_EQUAL(t.nextToken(), Token(qb::T_IDENTIFIER, "a")); - BOOST_CHECK_EQUAL(t.nextToken(), Token(qb::T_EQUAL, "=")); - BOOST_CHECK_EQUAL(t.nextToken(), Token(qb::T_IDENTIFIER, "b")); - BOOST_CHECK_EQUAL(t.nextToken(), Token(qb::T_EOS, "")); - - exp = " not 'hello kitty''s friend' = Is null "; - s = exp.begin(); - e = exp.end(); - Tokeniser u(s, e); - - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_NOT, "not")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_STRING, "hello kitty's friend")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_EQUAL, "=")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_IS, "Is")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_NULL, "null")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_EOS, "")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_EOS, "")); - - u.returnTokens(3); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_IS, "Is")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_NULL, "null")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_EOS, "")); - BOOST_CHECK_EQUAL(u.nextToken(), Token(qb::T_EOS, "")); - - exp = "(a+6)*7.5/1e6"; - s = exp.begin(); - e = exp.end(); - Tokeniser v(s, e); - - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_LPAREN, "(")); - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_IDENTIFIER, "a")); - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_PLUS, "+")); - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_NUMERIC_EXACT, "6")); - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_RPAREN, ")")); - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_MULT, "*")); - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_NUMERIC_APPROX, "7.5")); - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_DIV, "/")); - BOOST_CHECK_EQUAL(v.nextToken(), Token(qb::T_NUMERIC_APPROX, "1e6")); -} - -QPID_AUTO_TEST_CASE(parseStringFail) -{ - BOOST_CHECK_THROW(qb::Selector e("hello world"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("hello ^ world"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A is null not"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A is null or not"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A is null or and"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A is null and (B='hello out there'"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("in='hello kitty'"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A like 234"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A not 234 escape"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A not like 'eclecti_' escape 'happy'"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A not like 'eclecti_' escape happy"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A not like 'eclecti_' escape '%'"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A BETWEEN AND 'true'"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A NOT BETWEEN 34 OR 3.9"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A IN ()"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A NOT IN ()"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A IN 'hello', 'there', 1, true, (1-17))"), std::range_error); - BOOST_CHECK_THROW(qb::Selector e("A IN ('hello', 'there' 1, true, (1-17))"), std::range_error); -} - -QPID_AUTO_TEST_CASE(parseString) -{ - BOOST_CHECK_NO_THROW(qb::Selector e("'Daft' is not null")); - BOOST_CHECK_NO_THROW(qb::Selector e("42 is null")); - BOOST_CHECK_NO_THROW(qb::Selector e("A is not null")); - BOOST_CHECK_NO_THROW(qb::Selector e("A is null")); - BOOST_CHECK_NO_THROW(qb::Selector e("A = C")); - BOOST_CHECK_NO_THROW(qb::Selector e("A <> C")); - BOOST_CHECK_NO_THROW(qb::Selector e("A='hello kitty'")); - BOOST_CHECK_NO_THROW(qb::Selector e("A<>'hello kitty'")); - BOOST_CHECK_NO_THROW(qb::Selector e("A=B")); - BOOST_CHECK_NO_THROW(qb::Selector e("A<>B")); - BOOST_CHECK_NO_THROW(qb::Selector e("A='hello kitty' OR B='Bye, bye cruel world'")); - BOOST_CHECK_NO_THROW(qb::Selector e("B='hello kitty' AnD A='Bye, bye cruel world'")); - BOOST_CHECK_NO_THROW(qb::Selector e("A is null or A='Bye, bye cruel world'")); - BOOST_CHECK_NO_THROW(qb::Selector e("Z is null OR A is not null and A<>'Bye, bye cruel world'")); - BOOST_CHECK_NO_THROW(qb::Selector e("(Z is null OR A is not null) and A<>'Bye, bye cruel world'")); - BOOST_CHECK_NO_THROW(qb::Selector e("NOT C is not null OR C is null")); - BOOST_CHECK_NO_THROW(qb::Selector e("Not A='' or B=z")); - BOOST_CHECK_NO_THROW(qb::Selector e("Not A=17 or B=5.6")); - BOOST_CHECK_NO_THROW(qb::Selector e("A<>17 and B=5.6e17")); - BOOST_CHECK_NO_THROW(qb::Selector e("A LIKE 'excep%ional'")); - BOOST_CHECK_NO_THROW(qb::Selector e("B NOT LIKE 'excep%ional'")); - BOOST_CHECK_NO_THROW(qb::Selector e("A LIKE 'excep%ional' EScape '\'")); - BOOST_CHECK_NO_THROW(qb::Selector e("A BETWEEN 13 AND 'true'")); - BOOST_CHECK_NO_THROW(qb::Selector e("A NOT BETWEEN 100 AND 3.9")); - BOOST_CHECK_NO_THROW(qb::Selector e("true")); - BOOST_CHECK_NO_THROW(qb::Selector e("-354")); - BOOST_CHECK_NO_THROW(qb::Selector e("-(X or Y)")); - BOOST_CHECK_NO_THROW(qb::Selector e("-687 or 567")); - BOOST_CHECK_NO_THROW(qb::Selector e("(354.6)")); - BOOST_CHECK_NO_THROW(qb::Selector e("A is null and 'hello out there'")); - BOOST_CHECK_NO_THROW(qb::Selector e("17/4>4")); - BOOST_CHECK_NO_THROW(qb::Selector e("17/4>+4")); - BOOST_CHECK_NO_THROW(qb::Selector e("17/4>-4")); - BOOST_CHECK_NO_THROW(qb::Selector e("A IN ('hello', 'there', 1 , true, (1-17))")); -} - -class TestSelectorEnv : public qpid::broker::SelectorEnv { - mutable map values; - boost::ptr_vector strings; - static const qb::Value EMPTY; - - const qb::Value& value(const string& v) const { - const qb::Value& r = values.find(v)!=values.end() ? values[v] : EMPTY; - return r; - } - -public: - void set(const string& id, const char* value) { - strings.push_back(new string(value)); - values[id] = strings[strings.size()-1]; - } - - void set(const string& id, const qb::Value& value) { - if (value.type==qb::Value::T_STRING) { - strings.push_back(new string(*value.s)); - values[id] = strings[strings.size()-1]; - } else { - values[id] = value; - } - } -}; - -const qb::Value TestSelectorEnv::EMPTY; - -QPID_AUTO_TEST_CASE(simpleEval) -{ - TestSelectorEnv env; - env.set("A", "Bye, bye cruel world"); - env.set("B", "hello kitty"); - - BOOST_CHECK(qb::Selector("").eval(env)); - BOOST_CHECK(qb::Selector(" ").eval(env)); - BOOST_CHECK(qb::Selector("A is not null").eval(env)); - BOOST_CHECK(!qb::Selector("A is null").eval(env)); - BOOST_CHECK(!qb::Selector("A = C").eval(env)); - BOOST_CHECK(!qb::Selector("A <> C").eval(env)); - BOOST_CHECK(!qb::Selector("C is not null").eval(env)); - BOOST_CHECK(qb::Selector("C is null").eval(env)); - BOOST_CHECK(qb::Selector("A='Bye, bye cruel world'").eval(env)); - BOOST_CHECK(!qb::Selector("A<>'Bye, bye cruel world'").eval(env)); - BOOST_CHECK(!qb::Selector("A='hello kitty'").eval(env)); - BOOST_CHECK(qb::Selector("A<>'hello kitty'").eval(env)); - BOOST_CHECK(!qb::Selector("A=B").eval(env)); - BOOST_CHECK(qb::Selector("A<>B").eval(env)); - BOOST_CHECK(!qb::Selector("A='hello kitty' OR B='Bye, bye cruel world'").eval(env)); - BOOST_CHECK(qb::Selector("B='hello kitty' OR A='Bye, bye cruel world'").eval(env)); - BOOST_CHECK(qb::Selector("B='hello kitty' AnD A='Bye, bye cruel world'").eval(env)); - BOOST_CHECK(!qb::Selector("B='hello kitty' AnD B='Bye, bye cruel world'").eval(env)); - BOOST_CHECK(qb::Selector("A is null or A='Bye, bye cruel world'").eval(env)); - BOOST_CHECK(qb::Selector("Z is null OR A is not null and A<>'Bye, bye cruel world'").eval(env)); - BOOST_CHECK(!qb::Selector("(Z is null OR A is not null) and A<>'Bye, bye cruel world'").eval(env)); - BOOST_CHECK(qb::Selector("NOT C is not null OR C is null").eval(env)); - BOOST_CHECK(qb::Selector("Not A='' or B=z").eval(env)); - BOOST_CHECK(qb::Selector("Not A=17 or B=5.6").eval(env)); - BOOST_CHECK(!qb::Selector("A<>17 and B=5.6e17").eval(env)); - BOOST_CHECK(!qb::Selector("C=D").eval(env)); - BOOST_CHECK(qb::Selector("13 is not null").eval(env)); - BOOST_CHECK(!qb::Selector("'boo!' is null").eval(env)); - BOOST_CHECK(qb::Selector("A LIKE '%cru_l%'").eval(env)); - BOOST_CHECK(qb::Selector("'_%%_hello.th_re%' LIKE 'z_%.%z_%z%' escape 'z'").eval(env)); - BOOST_CHECK(qb::Selector("A NOT LIKE 'z_%.%z_%z%' escape 'z'").eval(env)); - BOOST_CHECK(qb::Selector("'{}[]<>,.!\"$%^&*()_-+=?/|\\' LIKE '{}[]<>,.!\"$z%^&*()z_-+=?/|\\' escape 'z'").eval(env)); -} - -QPID_AUTO_TEST_CASE(numericEval) -{ - TestSelectorEnv env; - env.set("A", 42.0); - env.set("B", 39); - - BOOST_CHECK(qb::Selector("A>B").eval(env)); - BOOST_CHECK(qb::Selector("A=42").eval(env)); - BOOST_CHECK(qb::Selector("B=39.0").eval(env)); - BOOST_CHECK(qb::Selector("Not A=17 or B=5.6").eval(env)); - BOOST_CHECK(!qb::Selector("A<>17 and B=5.6e17").eval(env)); - BOOST_CHECK(qb::Selector("3 BETWEEN -17 and 98.5").eval(env)); - BOOST_CHECK(qb::Selector("A BETWEEN B and 98.5").eval(env)); - BOOST_CHECK(!qb::Selector("B NOT BETWEEN 35 AND 100").eval(env)); - BOOST_CHECK(!qb::Selector("A BETWEEN B and 40").eval(env)); - BOOST_CHECK(!qb::Selector("A BETWEEN C and 40").eval(env)); - BOOST_CHECK(!qb::Selector("A BETWEEN 45 and C").eval(env)); - BOOST_CHECK(qb::Selector("(A BETWEEN 40 and C) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(A BETWEEN C and 45) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("17/4=4").eval(env)); - BOOST_CHECK(!qb::Selector("A/0=0").eval(env)); - BOOST_CHECK(qb::Selector("A*B+190").eval(env)); - BOOST_CHECK(qb::Selector("-9223372036854775807<0").eval(env)); - BOOST_CHECK_THROW(qb::Selector(" 9223372036854775808>0").eval(env), std::range_error); - BOOST_CHECK(qb::Selector("0x8000_0000_0000_0001=-9223372036854775807").eval(env)); - BOOST_CHECK_THROW(qb::Selector("-9223372036854775809<0").eval(env), std::range_error); - BOOST_CHECK(qb::Selector(" 9223372036854775807L<>0").eval(env)); - BOOST_CHECK(qb::Selector("-9223372036854775807L<>0").eval(env)); - BOOST_CHECK(qb::Selector("-9223372036854775808<>0").eval(env)); - BOOST_CHECK(qb::Selector("-9223372036854775808=0x8000_0000_0000_0000").eval(env)); - BOOST_CHECK(qb::Selector("0x8000_0000_0000_0000<9223372036854775807").eval(env)); - BOOST_CHECK(qb::Selector(" 0.4f>0.3d").eval(env)); - BOOST_CHECK(qb::Selector(" 1000_020.4f>0.3d").eval(env)); - BOOST_CHECK(qb::Selector(" 1000_020.4f>0x800p-3").eval(env)); - BOOST_CHECK(qb::Selector(" 0x1000_0000=0x1000_0000p0").eval(env)); - BOOST_CHECK(qb::Selector(" 0xFF=255L").eval(env)); - BOOST_CHECK(qb::Selector(" 077L=0b111_111").eval(env)); - BOOST_CHECK(qb::Selector(" 077L=63").eval(env)); -} - -QPID_AUTO_TEST_CASE(comparisonEval) -{ - TestSelectorEnv env; - - BOOST_CHECK(!qb::Selector("17 > 19.0").eval(env)); - BOOST_CHECK(!qb::Selector("'hello' > 19.0").eval(env)); - BOOST_CHECK(!qb::Selector("'hello' < 19.0").eval(env)); - BOOST_CHECK(!qb::Selector("'hello' = 19.0").eval(env)); - BOOST_CHECK(!qb::Selector("'hello'>42 and 'hello'<42 and 'hello'=42 and 'hello'<>42").eval(env)); - BOOST_CHECK(qb::Selector("20 >= 19.0 and 20 > 19").eval(env)); - BOOST_CHECK(qb::Selector("42 <= 42.0 and 37.0 >= 37").eval(env)); - BOOST_CHECK(qb::Selector("(A IN ('hello', 'there', 1 , true, (1-17))) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(-16 IN ('hello', A, 'there', true)) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(-16 NOT IN ('hello', 'there', A, true)) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(-16 IN ('hello', 'there', true)) IS NOT NULL").eval(env)); - BOOST_CHECK(!qb::Selector("-16 IN ('hello', 'there', true)").eval(env)); - BOOST_CHECK(qb::Selector("(-16 NOT IN ('hello', 'there', true)) IS NOT NULL").eval(env)); - BOOST_CHECK(!qb::Selector("-16 NOT IN ('hello', 'there', true)").eval(env)); - BOOST_CHECK(qb::Selector("(-16 NOT IN ('hello', 'there', A, 1 , true)) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("'hello' IN ('hello', 'there', 1 , true, (1-17))").eval(env)); - BOOST_CHECK(qb::Selector("TRUE IN ('hello', 'there', 1 , true, (1-17))").eval(env)); - BOOST_CHECK(qb::Selector("-16 IN ('hello', 'there', 1 , true, (1-17))").eval(env)); - BOOST_CHECK(!qb::Selector("-16 NOT IN ('hello', 'there', 1 , true, (1-17))").eval(env)); - BOOST_CHECK(!qb::Selector("1 IN ('hello', 'there', 'polly')").eval(env)); - BOOST_CHECK(!qb::Selector("1 NOT IN ('hello', 'there', 'polly')").eval(env)); - BOOST_CHECK(!qb::Selector("'hell' IN ('hello', 'there', 1 , true, (1-17))").eval(env)); - BOOST_CHECK(qb::Selector("('hell' IN ('hello', 'there', 1 , true, (1-17), A)) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("('hell' NOT IN ('hello', 'there', 1 , true, (1-17), A)) IS NULL").eval(env)); - BOOST_CHECK(!qb::Selector("'hello kitty' BETWEEN 30 and 40").eval(env)); - BOOST_CHECK(qb::Selector("'hello kitty' NOT BETWEEN 30 and 40").eval(env)); - BOOST_CHECK(!qb::Selector("14 BETWEEN 'aardvark' and 'zebra'").eval(env)); - BOOST_CHECK(qb::Selector("14 NOT BETWEEN 'aardvark' and 'zebra'").eval(env)); - BOOST_CHECK(!qb::Selector("TRUE BETWEEN 'aardvark' and 'zebra'").eval(env)); - BOOST_CHECK(qb::Selector("TRUE NOT BETWEEN 'aardvark' and 'zebra'").eval(env)); - BOOST_CHECK(qb::Selector("(A BETWEEN 'aardvark' and 14) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(A NOT BETWEEN 'aardvark' and 14) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(14 BETWEEN A and 17) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(14 NOT BETWEEN A and 17) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(14 BETWEEN 11 and A) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("(14 NOT BETWEEN 11 and A) IS NULL").eval(env)); - BOOST_CHECK(qb::Selector("14 NOT BETWEEN 11 and 9").eval(env)); - BOOST_CHECK(qb::Selector("14 BETWEEN -11 and 54367").eval(env)); -} - -QPID_AUTO_TEST_CASE(NullEval) -{ - TestSelectorEnv env; - - BOOST_CHECK(qb::Selector("P > 19.0 or (P is null)").eval(env)); - BOOST_CHECK(qb::Selector("P is null or P=''").eval(env)); - BOOST_CHECK(!qb::Selector("P=Q").eval(env)); - BOOST_CHECK(!qb::Selector("not P=Q").eval(env)); - BOOST_CHECK(!qb::Selector("not P=Q and not P=Q").eval(env)); - BOOST_CHECK(!qb::Selector("P=Q or not P=Q").eval(env)); - BOOST_CHECK(!qb::Selector("P > 19.0 or P <= 19.0").eval(env)); - BOOST_CHECK(qb::Selector("P > 19.0 or 17 <= 19.0").eval(env)); -} - -QPID_AUTO_TEST_SUITE_END() - -}} diff --git a/qpid/cpp/src/tests/SequenceNumberTest.cpp b/qpid/cpp/src/tests/SequenceNumberTest.cpp deleted file mode 100644 index f3c934e3ca..0000000000 --- a/qpid/cpp/src/tests/SequenceNumberTest.cpp +++ /dev/null @@ -1,209 +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 "unit_test.h" -#include -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceNumberSet.h" - -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -void checkDifference(SequenceNumber& a, SequenceNumber& b, int gap) -{ - BOOST_CHECK_EQUAL(gap, a - b); - BOOST_CHECK_EQUAL(-gap, b - a); - - //increment until b wraps around - for (int i = 0; i < (gap + 2); i++, ++a, ++b) { - BOOST_CHECK_EQUAL(gap, a - b); - } - //keep incrementing until a also wraps around - for (int i = 0; i < (gap + 2); i++, ++a, ++b) { - BOOST_CHECK_EQUAL(gap, a - b); - } - //let b catch up and overtake - for (int i = 0; i < (gap*2); i++, ++b) { - BOOST_CHECK_EQUAL(gap - i, a - b); - BOOST_CHECK_EQUAL(i - gap, b - a); - } -} - -void checkComparison(SequenceNumber& a, SequenceNumber& b, int gap) -{ - //increment until b wraps around - for (int i = 0; i < (gap + 2); i++) { - BOOST_CHECK(++a < ++b);//test prefix - } - //keep incrementing until a also wraps around - for (int i = 0; i < (gap + 2); i++) { - BOOST_CHECK(a++ < b++);//test postfix - } - //let a 'catch up' - for (int i = 0; i < gap; i++) { - a++; - } - BOOST_CHECK(a == b); - BOOST_CHECK(++a > b); -} - - -QPID_AUTO_TEST_SUITE(SequenceNumberTestSuite) - -QPID_AUTO_TEST_CASE(testIncrementPostfix) -{ - SequenceNumber a; - SequenceNumber b; - BOOST_CHECK(!(a > b)); - BOOST_CHECK(!(b < a)); - BOOST_CHECK(a == b); - - SequenceNumber c = a++; - BOOST_CHECK(a > b); - BOOST_CHECK(b < a); - BOOST_CHECK(a != b); - BOOST_CHECK(c < a); - BOOST_CHECK(a != c); - - b++; - BOOST_CHECK(!(a > b)); - BOOST_CHECK(!(b < a)); - BOOST_CHECK(a == b); - BOOST_CHECK(c < b); - BOOST_CHECK(b != c); -} - -QPID_AUTO_TEST_CASE(testIncrementPrefix) -{ - SequenceNumber a; - SequenceNumber b; - BOOST_CHECK(!(a > b)); - BOOST_CHECK(!(b < a)); - BOOST_CHECK(a == b); - - SequenceNumber c = ++a; - BOOST_CHECK(a > b); - BOOST_CHECK(b < a); - BOOST_CHECK(a != b); - BOOST_CHECK(a == c); - - ++b; - BOOST_CHECK(!(a > b)); - BOOST_CHECK(!(b < a)); - BOOST_CHECK(a == b); -} - -QPID_AUTO_TEST_CASE(testWrapAround) -{ - const uint32_t max = 0xFFFFFFFF; - SequenceNumber a(max - 10); - SequenceNumber b(max - 5); - checkComparison(a, b, 5); - - const uint32_t max_signed = 0x7FFFFFFF; - SequenceNumber c(max_signed - 10); - SequenceNumber d(max_signed - 5); - checkComparison(c, d, 5); -} - -QPID_AUTO_TEST_CASE(testCondense) -{ - SequenceNumberSet set; - for (uint i = 0; i < 6; i++) { - set.push_back(SequenceNumber(i)); - } - set.push_back(SequenceNumber(7)); - for (uint i = 9; i < 13; i++) { - set.push_back(SequenceNumber(i)); - } - set.push_back(SequenceNumber(13)); - SequenceNumberSet actual = set.condense(); - - SequenceNumberSet expected; - expected.addRange(SequenceNumber(0), SequenceNumber(5)); - expected.addRange(SequenceNumber(7), SequenceNumber(7)); - expected.addRange(SequenceNumber(9), SequenceNumber(13)); - BOOST_CHECK_EQUAL(expected, actual); -} - -QPID_AUTO_TEST_CASE(testCondenseSingleRange) -{ - SequenceNumberSet set; - for (uint i = 0; i < 6; i++) { - set.push_back(SequenceNumber(i)); - } - SequenceNumberSet actual = set.condense(); - - SequenceNumberSet expected; - expected.addRange(SequenceNumber(0), SequenceNumber(5)); - BOOST_CHECK_EQUAL(expected, actual); -} - -QPID_AUTO_TEST_CASE(testCondenseSingleItem) -{ - SequenceNumberSet set; - set.push_back(SequenceNumber(1)); - SequenceNumberSet actual = set.condense(); - - SequenceNumberSet expected; - expected.addRange(SequenceNumber(1), SequenceNumber(1)); - BOOST_CHECK_EQUAL(expected, actual); -} - -QPID_AUTO_TEST_CASE(testDifference) -{ - SequenceNumber a; - SequenceNumber b; - - for (int i = 0; i < 10; i++, ++a) { - BOOST_CHECK_EQUAL(i, a - b); - BOOST_CHECK_EQUAL(-i, b - a); - } - - b = a; - - for (int i = 0; i < 10; i++, ++b) { - BOOST_CHECK_EQUAL(-i, a - b); - BOOST_CHECK_EQUAL(i, b - a); - } -} - -QPID_AUTO_TEST_CASE(testDifferenceWithWrapAround1) -{ - const uint32_t max = 0xFFFFFFFF; - SequenceNumber a(max - 5); - SequenceNumber b(max - 10); - checkDifference(a, b, 5); -} - -QPID_AUTO_TEST_CASE(testDifferenceWithWrapAround2) -{ - const uint32_t max_signed = 0x7FFFFFFF; - SequenceNumber c(max_signed - 5); - SequenceNumber d(max_signed - 10); - checkDifference(c, d, 5); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/SequenceSet.cpp b/qpid/cpp/src/tests/SequenceSet.cpp deleted file mode 100644 index bc0a8ea509..0000000000 --- a/qpid/cpp/src/tests/SequenceSet.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * - * 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/framing/SequenceSet.h" -#include "unit_test.h" -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(SequenceSetTestSuite) - -using namespace qpid::framing; - -struct RangeExpectations -{ - typedef std::pair Range; - typedef std::list Ranges; - - Ranges ranges; - - RangeExpectations& expect(const SequenceNumber& start, const SequenceNumber& end) { - ranges.push_back(Range(start, end)); - return *this; - } - - void operator()(const SequenceNumber& start, const SequenceNumber& end) { - BOOST_CHECK(!ranges.empty()); - if (!ranges.empty()) { - BOOST_CHECK_EQUAL(start, ranges.front().first); - BOOST_CHECK_EQUAL(end, ranges.front().second); - ranges.pop_front(); - } - } - - void check(SequenceSet& set) { - set.for_each(*this); - BOOST_CHECK(ranges.empty()); - } -}; - -QPID_AUTO_TEST_CASE(testAdd) { - SequenceSet s; - s.add(2); - s.add(8,8); - s.add(3,5); - - for (uint32_t i = 0; i <= 1; i++) - BOOST_CHECK(!s.contains(i)); - - for (uint32_t i = 2; i <= 5; i++) - BOOST_CHECK(s.contains(i)); - - for (uint32_t i = 6; i <= 7; i++) - BOOST_CHECK(!s.contains(i)); - - BOOST_CHECK(s.contains(8)); - - for (uint32_t i = 9; i <= 10; i++) - BOOST_CHECK(!s.contains(i)); - - RangeExpectations().expect(2, 5).expect(8, 8).check(s); - - SequenceSet t; - t.add(6, 10); - t.add(s); - - for (uint32_t i = 0; i <= 1; i++) - BOOST_CHECK(!t.contains(i)); - - for (uint32_t i = 2; i <= 10; i++) - BOOST_CHECK_MESSAGE(t.contains(i), t << " contains " << i); - - RangeExpectations().expect(2, 10).check(t); -} - -QPID_AUTO_TEST_CASE(testAdd2) { - SequenceSet s; - s.add(7,6); - s.add(4,4); - s.add(3,10); - s.add(2); - RangeExpectations().expect(2, 10).check(s); -} - -QPID_AUTO_TEST_CASE(testRemove) { - SequenceSet s; - SequenceSet t; - s.add(0, 10); - t.add(0, 10); - - s.remove(7); - s.remove(3, 5); - s.remove(9, 10); - - t.remove(s); - - for (uint32_t i = 0; i <= 2; i++) { - BOOST_CHECK(s.contains(i)); - BOOST_CHECK(!t.contains(i)); - } - - for (uint32_t i = 3; i <= 5; i++) { - BOOST_CHECK(!s.contains(i)); - BOOST_CHECK(t.contains(i)); - } - - BOOST_CHECK(s.contains(6)); - BOOST_CHECK(!t.contains(6)); - - BOOST_CHECK(!s.contains(7)); - BOOST_CHECK(t.contains(7)); - - BOOST_CHECK(s.contains(8)); - BOOST_CHECK(!t.contains(8)); - - for (uint32_t i = 9; i <= 10; i++) { - BOOST_CHECK(!s.contains(i)); - BOOST_CHECK(t.contains(i)); - } - - RangeExpectations().expect(0, 2).expect(6, 6).expect(8, 8).check(s); - RangeExpectations().expect(3, 5).expect(7, 7).expect(9, 10).check(t); -} - - -QPID_AUTO_TEST_CASE(testOutOfOrderRemove) { - - SequenceSet s(2, 20); - - // test remove from middle: - s.remove(7); - RangeExpectations().expect(2, 6).expect(8, 20).check(s); - s.remove(14); - RangeExpectations().expect(2, 6).expect(8, 13).expect(15, 20).check(s); - - // remove from front of subrange: - s.remove(8, 8); - RangeExpectations().expect(2, 6).expect(9, 13).expect(15, 20).check(s); - - // remove from tail of subrange: - s.remove(6); - RangeExpectations().expect(2, 5).expect(9, 13).expect(15, 20).check(s); - - // remove across subrange: - s.remove(13, 15); - RangeExpectations().expect(2, 5).expect(9, 12).expect(16, 20).check(s); - - // remove within subrange: - s.remove(6, 8); - RangeExpectations().expect(2, 5).expect(9, 12).expect(16, 20).check(s); - - // remove overlap subrange tail: - s.remove(11, 15); - RangeExpectations().expect(2, 5).expect(9, 10).expect(16, 20).check(s); - - // remove overlap subrange head: - s.remove(14, 17); - RangeExpectations().expect(2, 5).expect(9, 10).expect(18, 20).check(s); - - // remove overlap sequence tail: - s.remove(20, 22); - RangeExpectations().expect(2, 5).expect(9, 10).expect(18, 19).check(s); - - // remove overlap sequence head: - s.remove(1, 3); - RangeExpectations().expect(4, 5).expect(9, 10).expect(18, 19).check(s); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/SessionState.cpp b/qpid/cpp/src/tests/SessionState.cpp deleted file mode 100644 index 1cf3415484..0000000000 --- a/qpid/cpp/src/tests/SessionState.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * - * 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 "unit_test.h" - -#include "qpid/SessionState.h" -#include "qpid/Exception.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/SessionFlushBody.h" - -#include -#include -#include -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(SessionStateTestSuite) - -using namespace std; -using namespace qpid::framing; - -// ================================================================ -// Utility functions. - -// Apply f to [begin, end) and accumulate the result -template -T applyAccumulate(Iter begin, Iter end, T seed, const F& f) { - return std::accumulate(begin, end, seed, boost::bind(std::plus(), _1, boost::bind(f, _2))); -} - -// Create a frame with a one-char string. -AMQFrame& frame(char s) { - static AMQFrame frame((AMQContentBody(string(&s, 1)))); - return frame; -} - -// Simple string representation of a frame. -string str(const AMQFrame& f) { - if (f.getMethod()) return "C"; // Command or Control - const AMQContentBody* c = dynamic_cast(f.getBody()); - if (c) return c->getData(); // Return data for content frames. - return "H"; // Must be a header. -} -// Make a string from a range of frames. -string str(const boost::iterator_range::const_iterator>& frames) { - string (*strFrame)(const AMQFrame&) = str; - return applyAccumulate(frames.begin(), frames.end(), string(), ptr_fun(strFrame)); -} -// Make a transfer command frame. -AMQFrame transferFrame(bool hasContent) { - AMQFrame t((MessageTransferBody())); - t.setFirstFrame(true); - t.setLastFrame(true); - t.setFirstSegment(true); - t.setLastSegment(!hasContent); - return t; -} -// Make a content frame -AMQFrame contentFrame(string content, bool isLast=true) { - AMQFrame f((AMQContentBody(content))); - f.setFirstFrame(true); - f.setLastFrame(true); - f.setFirstSegment(false); - f.setLastSegment(isLast); - return f; -} -AMQFrame contentFrameChar(char content, bool isLast=true) { - return contentFrame(string(1, content), isLast); -} - -// Send frame & return size of frame. -size_t send(qpid::SessionState& s, const AMQFrame& f) { s.senderRecord(f); return f.encodedSize(); } -// Send transfer command with no content. -size_t transfer0(qpid::SessionState& s) { return send(s, transferFrame(false)); } -// Send transfer frame with single content frame. -size_t transfer1(qpid::SessionState& s, string content) { - return send(s,transferFrame(true)) + send(s,contentFrame(content)); -} -size_t transfer1Char(qpid::SessionState& s, char content) { - return transfer1(s, string(1,content)); -} - -// Send transfer frame with multiple single-byte content frames. -size_t transferN(qpid::SessionState& s, string content) { - size_t size=send(s, transferFrame(!content.empty())); - if (!content.empty()) { - char last = content[content.size()-1]; - content.resize(content.size()-1); - size += applyAccumulate(content.begin(), content.end(), 0, - boost::bind(&send, boost::ref(s), - boost::bind(contentFrameChar, _1, false))); - size += send(s, contentFrameChar(last, true)); - } - return size; -} - -// Send multiple transfers with single-byte content. -size_t transfers(qpid::SessionState& s, string content) { - return applyAccumulate(content.begin(), content.end(), 0, - boost::bind(transfer1Char, boost::ref(s), _1)); -} - -size_t contentFrameSize(size_t n=1) { return AMQFrame(( AMQContentBody())).encodedSize() + n; } -size_t transferFrameSize() { return AMQFrame((MessageTransferBody())).encodedSize(); } - -// ==== qpid::SessionState test classes - -using qpid::SessionId; -using qpid::SessionPoint; - - -QPID_AUTO_TEST_CASE(testSendGetReplyList) { - qpid::SessionState s; - s.setTimeout(1); - s.senderGetCommandPoint(); - transfer1(s, "abc"); - transfers(s, "def"); - transferN(s, "xyz"); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(0,0))),"CabcCdCeCfCxyz"); - // Ignore controls. - s.senderRecord(AMQFrame(new SessionFlushBody())); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(2,0))),"CeCfCxyz"); -} - -QPID_AUTO_TEST_CASE(testNeedFlush) { - qpid::SessionState::Configuration c; - // sync after 2 1-byte transfers or equivalent bytes. - c.replayFlushLimit = 2*(transferFrameSize()+contentFrameSize()); - qpid::SessionState s(SessionId(), c); - s.setTimeout(1); - s.senderGetCommandPoint(); - transfers(s, "a"); - BOOST_CHECK(!s.senderNeedFlush()); - transfers(s, "b"); - BOOST_CHECK(s.senderNeedFlush()); - s.senderRecordFlush(); - BOOST_CHECK(!s.senderNeedFlush()); - transfers(s, "c"); - BOOST_CHECK(!s.senderNeedFlush()); - transfers(s, "d"); - BOOST_CHECK(s.senderNeedFlush()); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint())), "CaCbCcCd"); -} - -QPID_AUTO_TEST_CASE(testPeerConfirmed) { - qpid::SessionState::Configuration c; - // sync after 2 1-byte transfers or equivalent bytes. - c.replayFlushLimit = 2*(transferFrameSize()+contentFrameSize()); - qpid::SessionState s(SessionId(), c); - s.setTimeout(1); - s.senderGetCommandPoint(); - transfers(s, "ab"); - BOOST_CHECK(s.senderNeedFlush()); - transfers(s, "cd"); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(0,0))), "CaCbCcCd"); - s.senderConfirmed(SessionPoint(3)); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(3,0))), "Cd"); - BOOST_CHECK(!s.senderNeedFlush()); - - // Multi-frame transfer. - transfer1(s, "efg"); - transfers(s, "xy"); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(3,0))), "CdCefgCxCy"); - BOOST_CHECK(s.senderNeedFlush()); - - s.senderConfirmed(SessionPoint(4)); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(4,0))), "CefgCxCy"); - BOOST_CHECK(s.senderNeedFlush()); - - s.senderConfirmed(SessionPoint(5)); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(5,0))), "CxCy"); - BOOST_CHECK(s.senderNeedFlush()); - - s.senderConfirmed(SessionPoint(6)); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(6,0))), "Cy"); - BOOST_CHECK(!s.senderNeedFlush()); -} - -QPID_AUTO_TEST_CASE(testPeerCompleted) { - qpid::SessionState s; - s.setTimeout(1); - s.senderGetCommandPoint(); - // Completion implies confirmation - transfers(s, "abc"); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(0,0))), "CaCbCc"); - SequenceSet set(SequenceSet() + 0 + 1); - s.senderCompleted(set); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(2,0))), "Cc"); - - transfers(s, "def"); - // We dont do out-of-order confirmation, so this will only confirm up to 3: - set = SequenceSet(SequenceSet() + 2 + 3 + 5); - s.senderCompleted(set); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(4,0))), "CeCf"); -} - -QPID_AUTO_TEST_CASE(testReceive) { - // Advance expected/received correctly - qpid::SessionState s; - s.receiverSetCommandPoint(SessionPoint()); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(0)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(0)); - - BOOST_CHECK(s.receiverRecord(transferFrame(false))); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(1)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(1)); - - BOOST_CHECK(s.receiverRecord(transferFrame(true))); - SessionPoint point = SessionPoint(1, transferFrameSize()); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), point); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), point); - BOOST_CHECK(s.receiverRecord(contentFrame("", false))); - point.offset += contentFrameSize(0); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), point); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), point); - BOOST_CHECK(s.receiverRecord(contentFrame("", true))); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(2)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(2)); - - // Idempotence barrier, rewind expected & receive some duplicates. - s.receiverSetCommandPoint(SessionPoint(1)); - BOOST_CHECK(!s.receiverRecord(transferFrame(false))); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(2)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(2)); - BOOST_CHECK(s.receiverRecord(transferFrame(false))); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(3)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(3)); -} - -QPID_AUTO_TEST_CASE(testCompleted) { - // completed & unknownCompleted - qpid::SessionState s; - s.receiverSetCommandPoint(SessionPoint()); - s.receiverRecord(transferFrame(false)); - s.receiverRecord(transferFrame(false)); - s.receiverRecord(transferFrame(false)); - s.receiverCompleted(1); - BOOST_CHECK_EQUAL(s.receiverGetUnknownComplete(), SequenceSet(SequenceSet()+1)); - s.receiverCompleted(0); - BOOST_CHECK_EQUAL(s.receiverGetUnknownComplete(), - SequenceSet(SequenceSet() + qpid::Range(0,2))); - s.receiverKnownCompleted(SequenceSet(SequenceSet()+1)); - BOOST_CHECK_EQUAL(s.receiverGetUnknownComplete(), SequenceSet(SequenceSet()+2)); - // TODO aconway 2008-04-30: missing tests for known-completed. -} - -QPID_AUTO_TEST_CASE(testNeedKnownCompleted) { - size_t flushInterval= 2*(transferFrameSize()+contentFrameSize())+1; - qpid::SessionState::Configuration c(flushInterval); - qpid::SessionState s(qpid::SessionId(), c); - s.senderGetCommandPoint(); - transfers(s, "a"); - SequenceSet set(SequenceSet() + 0); - s.senderCompleted(set); - BOOST_CHECK(!s.senderNeedKnownCompleted()); - - transfers(s, "b"); - set += 1; - s.senderCompleted(set); - BOOST_CHECK(!s.senderNeedKnownCompleted()); - - transfers(s, "c"); - set += 2; - s.senderCompleted(set); - BOOST_CHECK(s.senderNeedKnownCompleted()); - s.senderRecordKnownCompleted(); - BOOST_CHECK(!s.senderNeedKnownCompleted()); - - transfers(s, "de"); - set += 3; - set += 4; - s.senderCompleted(set); - BOOST_CHECK(!s.senderNeedKnownCompleted()); - - transfers(s, "f"); - set += 2; - s.senderCompleted(set); - BOOST_CHECK(s.senderNeedKnownCompleted()); - s.senderRecordKnownCompleted(); - BOOST_CHECK(!s.senderNeedKnownCompleted()); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Shlib.cpp b/qpid/cpp/src/tests/Shlib.cpp deleted file mode 100644 index 7f01323e3c..0000000000 --- a/qpid/cpp/src/tests/Shlib.cpp +++ /dev/null @@ -1,67 +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 "test_tools.h" -#include "config.h" -#include "qpid/sys/Shlib.h" -#include "qpid/Exception.h" - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ShlibTestSuite) - -using namespace qpid::sys; -typedef void (*CallMe)(int*); - - -QPID_AUTO_TEST_CASE(testShlib) { - Shlib sh("./" QPID_SHLIB_PREFIX "shlibtest" QPID_SHLIB_POSTFIX QPID_SHLIB_SUFFIX); - // Double cast to avoid ISO warning. - CallMe callMe=sh.getSymbol("callMe"); - BOOST_REQUIRE(callMe != 0); - int unloaded=0; - callMe(&unloaded); - sh.unload(); - BOOST_CHECK_EQUAL(42, unloaded); - try { - sh.getSymbol("callMe"); - BOOST_FAIL("Expected exception"); - } - catch (const qpid::Exception&) {} -} - -QPID_AUTO_TEST_CASE(testAutoShlib) { - int unloaded = 0; - { - AutoShlib sh("./" QPID_SHLIB_PREFIX "shlibtest" QPID_SHLIB_POSTFIX QPID_SHLIB_SUFFIX); - CallMe callMe=sh.getSymbol("callMe"); - BOOST_REQUIRE(callMe != 0); - callMe(&unloaded); - } - BOOST_CHECK_EQUAL(42, unloaded); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Statistics.cpp b/qpid/cpp/src/tests/Statistics.cpp deleted file mode 100644 index 7cacde8b74..0000000000 --- a/qpid/cpp/src/tests/Statistics.cpp +++ /dev/null @@ -1,131 +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 "Statistics.h" -#include -#include -#include - -namespace qpid { -namespace tests { - -using namespace std; - -Statistic::~Statistic() {} - -Throughput::Throughput() : messages(0), started(false) {} - -void Throughput::message(const messaging::Message&) { - ++messages; - if (!started) { - start = sys::now(); - started = true; - } -} - -void Throughput::header(ostream& o) const { - o << "tp(m/s)"; -} - -void Throughput::report(ostream& o) const { - double elapsed(int64_t(sys::Duration(start, sys::now()))/double(sys::TIME_SEC)); - o << fixed << setprecision(0) << messages/elapsed; -} - -ThroughputAndLatency::ThroughputAndLatency() : - total(0), - min(numeric_limits::max()), - max(numeric_limits::min()), - samples(0) -{} - -const std::string TS = "ts"; - -void ThroughputAndLatency::message(const messaging::Message& m) { - Throughput::message(m); - types::Variant::Map::const_iterator i = m.getProperties().find(TS); - if (i != m.getProperties().end()) { - ++samples; - int64_t start(i->second.asInt64()); - int64_t end(sys::Duration::FromEpoch()); - double latency = double(end - start)/sys::TIME_MSEC; - if (latency > 0) { - total += latency; - if (latency < min) min = latency; - if (latency > max) max = latency; - } - } -} - -void ThroughputAndLatency::header(ostream& o) const { - Throughput::header(o); - o << '\t' << "l-min" << '\t' << "l-max" << '\t' << "l-avg"; -} - -void ThroughputAndLatency::report(ostream& o) const { - Throughput::report(o); - if (samples) { - o << fixed << setprecision(2) - << '\t' << min << '\t' << max << '\t' << total/samples; - } -} - -ReporterBase::ReporterBase(ostream& o, int batch, bool wantHeader) - : batchSize(batch), batchCount(0), headerPrinted(!wantHeader), out(o) -{} - -ReporterBase::~ReporterBase() {} - -/** Count message in the statistics */ -void ReporterBase::message(const messaging::Message& m) { - if (!overall.get()) overall = create(); - overall->message(m); - if (batchSize) { - if (!batch.get()) batch = create(); - batch->message(m); - if (++batchCount == batchSize) { - header(); - batch->report(out); - out << endl; - batch = create(); - batchCount = 0; - } - } -} - -/** Print overall report. */ -void ReporterBase::report() { - if (!overall.get()) overall = create(); - header(); - overall->report(out); - out << endl; -} - -void ReporterBase::header() { - if (!headerPrinted) { - if (!overall.get()) overall = create(); - overall->header(out); - out << endl; - headerPrinted = true; - } -} - - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Statistics.h b/qpid/cpp/src/tests/Statistics.h deleted file mode 100644 index 091046a17f..0000000000 --- a/qpid/cpp/src/tests/Statistics.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef TESTS_STATISTICS_H -#define TESTS_STATISTICS_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 -#include -#include -#include - -namespace qpid { - -namespace messaging { -class Message; -} - -namespace tests { - -class Statistic { - public: - virtual ~Statistic(); - virtual void message(const messaging::Message&) = 0; - virtual void report(std::ostream&) const = 0; - virtual void header(std::ostream&) const = 0; -}; - -class Throughput : public Statistic { - public: - Throughput(); - virtual void message(const messaging::Message&); - virtual void report(std::ostream&) const; - virtual void header(std::ostream&) const; - - protected: - int messages; - - private: - bool started; - sys::AbsTime start; -}; - -class ThroughputAndLatency : public Throughput { - public: - ThroughputAndLatency(); - virtual void message(const messaging::Message&); - virtual void report(std::ostream&) const; - virtual void header(std::ostream&) const; - - private: - double total, min, max; // Milliseconds - int samples; -}; - -/** Report batch and overall statistics */ -class ReporterBase { - public: - virtual ~ReporterBase(); - - /** Count message in the statistics */ - void message(const messaging::Message& m); - - /** Print overall report. */ - void report(); - - protected: - ReporterBase(std::ostream& o, int batchSize, bool wantHeader); - virtual std::auto_ptr create() = 0; - - private: - void header(); - void report(const Statistic& s); - std::auto_ptr overall; - std::auto_ptr batch; - int batchSize, batchCount; - bool stopped, headerPrinted; - std::ostream& out; -}; - -template class Reporter : public ReporterBase { - public: - Reporter(std::ostream& o, int batchSize, bool wantHeader) - : ReporterBase(o, batchSize, wantHeader) {} - - virtual std::auto_ptr create() { - return std::auto_ptr(new Stats); - } -}; - -}} // namespace qpid::tests - -#endif /*!TESTS_STATISTICS_H*/ diff --git a/qpid/cpp/src/tests/StringUtils.cpp b/qpid/cpp/src/tests/StringUtils.cpp deleted file mode 100644 index c50287a4f4..0000000000 --- a/qpid/cpp/src/tests/StringUtils.cpp +++ /dev/null @@ -1,81 +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 -#include "qpid/StringUtils.h" - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(StringUtilsTestSuite) - -using std::string; - -QPID_AUTO_TEST_CASE(testSplit_general) -{ - std::vector results = split("a bbbb, car,d123,,,e", ", "); - BOOST_CHECK_EQUAL(5u, results.size()); - BOOST_CHECK_EQUAL(string("a"), results[0]); - BOOST_CHECK_EQUAL(string("bbbb"), results[1]); - BOOST_CHECK_EQUAL(string("car"), results[2]); - BOOST_CHECK_EQUAL(string("d123"), results[3]); - BOOST_CHECK_EQUAL(string("e"), results[4]); -} - -QPID_AUTO_TEST_CASE(testSplit_noDelims) -{ - std::vector results = split("abc", ", "); - BOOST_CHECK_EQUAL(1u, results.size()); - BOOST_CHECK_EQUAL(string("abc"), results[0]); -} - -QPID_AUTO_TEST_CASE(testSplit_delimAtEnd) -{ - std::vector results = split("abc def,,", ", "); - BOOST_CHECK_EQUAL(2u, results.size()); - BOOST_CHECK_EQUAL(string("abc"), results[0]); - BOOST_CHECK_EQUAL(string("def"), results[1]); -} - -QPID_AUTO_TEST_CASE(testSplit_delimAtStart) -{ - std::vector results = split(",,abc def", ", "); - BOOST_CHECK_EQUAL(2u, results.size()); - BOOST_CHECK_EQUAL(string("abc"), results[0]); - BOOST_CHECK_EQUAL(string("def"), results[1]); -} - -QPID_AUTO_TEST_CASE(testSplit_onlyDelims) -{ - std::vector results = split(",, , ", ", "); - BOOST_CHECK_EQUAL(0u, results.size()); -} - -QPID_AUTO_TEST_CASE(testSplit_empty) -{ - std::vector results = split("", ", "); - BOOST_CHECK_EQUAL(0u, results.size()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} diff --git a/qpid/cpp/src/tests/SystemInfo.cpp b/qpid/cpp/src/tests/SystemInfo.cpp deleted file mode 100644 index 34f1ac408e..0000000000 --- a/qpid/cpp/src/tests/SystemInfo.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * - * 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 "unit_test.h" -#include "test_tools.h" -#include "qpid/sys/SystemInfo.h" -#include - -using namespace std; -using namespace qpid::sys; -using namespace boost::assign; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(SystemInfoTestSuite) - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/TestMessageStore.h b/qpid/cpp/src/tests/TestMessageStore.h deleted file mode 100644 index 0b63bc9c15..0000000000 --- a/qpid/cpp/src/tests/TestMessageStore.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _tests_TestMessageStore_h -#define _tests_TestMessageStore_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/NullMessageStore.h" -#include - -using namespace qpid; -using namespace qpid::broker; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -typedef std::pair > msg_queue_pair; - -class TestMessageStore : public NullMessageStore -{ - public: - std::vector > dequeued; - std::vector enqueued; - - void dequeue(TransactionContext*, - const boost::intrusive_ptr& msg, - const PersistableQueue& /*queue*/) - { - dequeued.push_back(msg); - } - - void enqueue(TransactionContext*, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) - { - msg->enqueueComplete(); - enqueued.push_back(msg_queue_pair(queue.getName(), msg)); - } - - TestMessageStore() : NullMessageStore() {} - ~TestMessageStore(){} -}; - -}} // namespace qpid::tests - -#endif diff --git a/qpid/cpp/src/tests/TestOptions.h b/qpid/cpp/src/tests/TestOptions.h deleted file mode 100644 index f8da0f59cf..0000000000 --- a/qpid/cpp/src/tests/TestOptions.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef _TestOptions_ -#define _TestOptions_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/log/Options.h" -#include "qpid/Url.h" -#include "qpid/log/Logger.h" -#include "qpid/client/Connection.h" -#include "ConnectionOptions.h" - -#include -#include - -namespace qpid { - -struct TestOptions : public qpid::Options -{ - TestOptions(const std::string& helpText_=std::string(), - const std::string& argv0=std::string()) - : Options("Test Options"), help(false), log(argv0), helpText(helpText_) - { - addOptions() - ("help", optValue(help), "print this usage statement"); - add(con); - add(log); - } - - /** As well as parsing, throw help message if requested. */ - void parse(int argc, char** argv) { - try { - qpid::Options::parse(argc, argv); - } catch (const std::exception& e) { - std::ostringstream msg; - msg << *this << std::endl << std::endl << e.what() << std::endl; - throw qpid::Options::Exception(msg.str()); - } - qpid::log::Logger::instance().configure(log); - if (help) { - std::ostringstream msg; - msg << *this << std::endl << std::endl << helpText << std::endl; - throw qpid::Options::Exception(msg.str()); - } - } - - /** Open a connection using option values */ - void open(qpid::client::Connection& connection) { - connection.open(con); - } - - - bool help; - ConnectionOptions con; - qpid::log::Options log; - std::string helpText; -}; - -} - -#endif diff --git a/qpid/cpp/src/tests/TimerTest.cpp b/qpid/cpp/src/tests/TimerTest.cpp deleted file mode 100644 index d28eeeffc1..0000000000 --- a/qpid/cpp/src/tests/TimerTest.cpp +++ /dev/null @@ -1,176 +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/sys/Timer.h" -#include "qpid/sys/Monitor.h" -#include "qpid/Options.h" -#include "unit_test.h" -#include -#include -#include -#include -#include - -using namespace qpid::sys; -using boost::intrusive_ptr; -using boost::dynamic_pointer_cast; - -namespace qpid { -namespace tests { - -class Counter -{ - Mutex lock; - uint counter; - public: - Counter() : counter(0) {} - uint next() - { - Mutex::ScopedLock l(lock); - return ++counter; - } -}; - -class TestTask : public TimerTask -{ - const AbsTime start; - const Duration expected; - AbsTime end; - bool fired; - uint position; - Monitor monitor; - Counter& counter; - - public: - TestTask(Duration timeout, Counter& _counter) - : TimerTask(timeout, "Test"), start(now()), expected(timeout), end(start), fired(false), counter(_counter) {} - - void fire() - { - Monitor::ScopedLock l(monitor); - fired = true; - position = counter.next(); - end = now(); - monitor.notify(); - } - - void check(uint expected_position, uint64_t tolerance = 500 * TIME_MSEC) - { - Monitor::ScopedLock l(monitor); - BOOST_CHECK(fired); - BOOST_CHECK_EQUAL(expected_position, position); - Duration actual(start, end); -#ifdef _MSC_VER - uint64_t difference = _abs64(expected - actual); -#elif defined(_WIN32) - uint64_t difference = labs(expected - actual); -#elif defined(__SUNPRO_CC) || defined (__IBMCPP__) - uint64_t difference = llabs(expected - actual); -#else - uint64_t difference = abs(expected - actual); -#endif - std::string msg(boost::lexical_cast(boost::format("tolerance = %1%, difference = %2%") % tolerance % difference)); - BOOST_CHECK_MESSAGE(difference < tolerance, msg); - } - - void wait(Duration d) - { - Monitor::ScopedLock l(monitor); - monitor.wait(AbsTime(now(), d)); - } -}; - -class DummyRunner : public Runnable -{ - public: - void run() {} -}; - -QPID_AUTO_TEST_SUITE(TimerTestSuite) - -QPID_AUTO_TEST_CASE(testGeneral) -{ - Counter counter; - Timer timer; - intrusive_ptr task1(new TestTask(Duration(3 * TIME_SEC), counter)); - intrusive_ptr task2(new TestTask(Duration(1 * TIME_SEC), counter)); - intrusive_ptr task3(new TestTask(Duration(4 * TIME_SEC), counter)); - intrusive_ptr task4(new TestTask(Duration(2 * TIME_SEC), counter)); - - timer.add(task1); - timer.add(task2); - timer.add(task3); - timer.add(task4); - - dynamic_pointer_cast(task3)->wait(Duration(6 * TIME_SEC)); - - dynamic_pointer_cast(task1)->check(3); - dynamic_pointer_cast(task2)->check(1); - dynamic_pointer_cast(task3)->check(4); - dynamic_pointer_cast(task4)->check(2); -} - -std::string toString(Duration d) { return boost::lexical_cast(d); } -Duration fromString(const std::string& str) { return boost::lexical_cast(str); } - -QPID_AUTO_TEST_CASE(testOstreamInOut) { - std::string empty; - BOOST_CHECK_EQUAL(toString(Duration(int64_t(TIME_SEC))), "1s"); - BOOST_CHECK_EQUAL(toString(Duration(int64_t(TIME_SEC*123.4))), "123.4s"); - BOOST_CHECK_EQUAL(toString(Duration(int64_t(TIME_MSEC*123.4))), "123.4ms"); - BOOST_CHECK_EQUAL(toString(Duration(int64_t(TIME_USEC*123.4))), "123.4us"); - BOOST_CHECK_EQUAL(toString(Duration(int64_t(TIME_NSEC*123))), "123ns"); - - BOOST_CHECK_EQUAL(fromString("123.4"), Duration(int64_t(TIME_SEC*123.4))); - BOOST_CHECK_EQUAL(fromString("123.4s"), Duration(int64_t(TIME_SEC*123.4))); - BOOST_CHECK_EQUAL(fromString("123ms"), Duration(int64_t(TIME_MSEC*123))); - BOOST_CHECK_EQUAL(fromString("123us"), Duration(int64_t(TIME_USEC*123))); - BOOST_CHECK_EQUAL(fromString("123ns"), Duration(int64_t(TIME_NSEC*123))); - - Duration d = 0; - std::istringstream i; - std::string s; - - i.str("123x"); - i >> d; - BOOST_CHECK(i.fail()); - BOOST_CHECK_EQUAL(d, 0); - BOOST_CHECK_EQUAL(i.str(), "123x"); - - i.str("xxx"); - i >> d; - BOOST_CHECK(i.fail()); - BOOST_CHECK_EQUAL(d, 0); - BOOST_CHECK_EQUAL(i.str(), "xxx"); -} - -QPID_AUTO_TEST_CASE(testOptionParse) { - Options opts; - Duration interval; - opts.addOptions()("interval", optValue(interval, "I"), "blah"); - const char *args[] = { "fakeexe", "--interval", "123.4" }; - opts.parse(sizeof(args)/sizeof(args[0]), args); - BOOST_CHECK_EQUAL(interval, Duration(int64_t(TIME_SEC*123.4))); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/TopicExchangeTest.cpp b/qpid/cpp/src/tests/TopicExchangeTest.cpp deleted file mode 100644 index d57951ea3f..0000000000 --- a/qpid/cpp/src/tests/TopicExchangeTest.cpp +++ /dev/null @@ -1,408 +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/broker/TopicKeyNode.h" -#include "qpid/broker/TopicExchange.h" -#include "unit_test.h" -#include "test_tools.h" - -using namespace qpid::broker; -using namespace std; - - -namespace qpid { -namespace broker { - -// Class for exercising the pattern match code in the TopicExchange -class TopicExchange::TopicExchangeTester { - -public: - typedef std::vector BindingVec; - typedef TopicKeyNode TestBindingNode; - -private: - // binding node iterator that collects all routes that are bound - class TestFinder : public TestBindingNode::TreeIterator { - public: - TestFinder(BindingVec& m) : bv(m) {}; - ~TestFinder() {}; - bool visit(TestBindingNode& node) { - if (!node.bindings.bindingVector.empty()) - bv.push_back(node.routePattern); - return true; - } - - BindingVec& bv; - }; - -public: - TopicExchangeTester() {}; - ~TopicExchangeTester() {}; - bool addBindingKey(const std::string& bKey) { - string routingPattern = normalize(bKey); - BindingKey *bk = bindingTree.add(routingPattern); - if (bk) { - // push a dummy binding to mark this node as "non-leaf" - bk->bindingVector.push_back(Binding::shared_ptr()); - return true; - } - return false; - } - - bool removeBindingKey(const std::string& bKey){ - string routingPattern = normalize(bKey); - BindingKey *bk = bindingTree.get(routingPattern); - if (bk) { - bk->bindingVector.pop_back(); - if (bk->bindingVector.empty()) { - // no more bindings - remove this node - bindingTree.remove(routingPattern); - } - return true; - } - return false; - } - - void findMatches(const std::string& rKey, BindingVec& matches) { - TestFinder testFinder(matches); - bindingTree.iterateMatch( rKey, testFinder ); - } - - void getAll(BindingVec& bindings) { - TestFinder testFinder(bindings); - bindingTree.iterateAll( testFinder ); - } - -private: - TestBindingNode bindingTree; -}; -} // namespace broker - - -namespace tests { - -QPID_AUTO_TEST_SUITE(TopicExchangeTestSuite) - -#define CHECK_NORMALIZED(expect, pattern) BOOST_CHECK_EQUAL(expect, TopicExchange::normalize(pattern)); - -namespace { - // return the count of bindings that match 'pattern' - int match(TopicExchange::TopicExchangeTester &tt, - const std::string& pattern) - { - TopicExchange::TopicExchangeTester::BindingVec bv; - tt.findMatches(pattern, bv); - return int(bv.size()); - } - - // return true if expected contains exactly all bindings that match - // against pattern. - bool compare(TopicExchange::TopicExchangeTester& tt, - const std::string& pattern, - const TopicExchange::TopicExchangeTester::BindingVec& expected) - { - TopicExchange::TopicExchangeTester::BindingVec bv; - tt.findMatches(pattern, bv); - if (expected.size() != bv.size()) { - // std::cout << "match failed 1 f=[" << bv << "]" << std::endl; - // std::cout << "match failed 1 e=[" << expected << "]" << std::endl; - return false; - } - TopicExchange::TopicExchangeTester::BindingVec::const_iterator i; - for (i = expected.begin(); i != expected.end(); i++) { - TopicExchange::TopicExchangeTester::BindingVec::iterator j; - for (j = bv.begin(); j != bv.end(); j++) { - // std::cout << "matched [" << *j << "]" << std::endl; - if (*i == *j) break; - } - if (j == bv.end()) { - // std::cout << "match failed 2 [" << bv << "]" << std::endl; - return false; - } - } - return true; - } -} - - -QPID_AUTO_TEST_CASE(testNormalize) -{ - CHECK_NORMALIZED("", ""); - CHECK_NORMALIZED("a.b.c", "a.b.c"); - CHECK_NORMALIZED("a.*.c", "a.*.c"); - CHECK_NORMALIZED("#", "#"); - CHECK_NORMALIZED("#", "#.#.#.#"); - CHECK_NORMALIZED("*.*.*.#", "#.*.#.*.#.#.*"); - CHECK_NORMALIZED("a.*.*.*.#", "a.*.#.*.#.*.#"); - CHECK_NORMALIZED("a.*.*.*.#", "a.*.#.*.#.*"); - CHECK_NORMALIZED("*.*.*.#", "*.#.#.*.*.#"); -} - -QPID_AUTO_TEST_CASE(testPlain) -{ - TopicExchange::TopicExchangeTester tt; - string pattern("ab.cd.e"); - - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "ab.cd.e")); - BOOST_CHECK_EQUAL(0, match(tt, "abx.cd.e")); - BOOST_CHECK_EQUAL(0, match(tt, "ab.cd")); - BOOST_CHECK_EQUAL(0, match(tt, "ab.cd..e.")); - BOOST_CHECK_EQUAL(0, match(tt, "ab.cd.e.")); - BOOST_CHECK_EQUAL(0, match(tt, ".ab.cd.e")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = ""; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "."; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, ".")); - BOOST_CHECK(tt.removeBindingKey(pattern)); -} - - -QPID_AUTO_TEST_CASE(testStar) -{ - TopicExchange::TopicExchangeTester tt; - string pattern("a.*.b"); - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.xx.b")); - BOOST_CHECK_EQUAL(0, match(tt, "a.b")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "*.x"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "y.x")); - BOOST_CHECK_EQUAL(1, match(tt, ".x")); - BOOST_CHECK_EQUAL(0, match(tt, "x")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "x.x.*"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "x.x.y")); - BOOST_CHECK_EQUAL(1, match(tt, "x.x.")); - BOOST_CHECK_EQUAL(0, match(tt, "x.x")); - BOOST_CHECK_EQUAL(0, match(tt, "q.x.y")); - BOOST_CHECK(tt.removeBindingKey(pattern)); -} - -QPID_AUTO_TEST_CASE(testHash) -{ - TopicExchange::TopicExchangeTester tt; - string pattern("a.#.b"); - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.b")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.b")); - BOOST_CHECK_EQUAL(1, match(tt, "a..x.y.zz.b")); - BOOST_CHECK_EQUAL(0, match(tt, "a.b.")); - BOOST_CHECK_EQUAL(0, match(tt, "q.x.b")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "a.#"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a")); - BOOST_CHECK_EQUAL(1, match(tt, "a.b")); - BOOST_CHECK_EQUAL(1, match(tt, "a.b.c")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "#.a"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a")); - BOOST_CHECK_EQUAL(1, match(tt, "x.y.a")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "a.#.b.#.c"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.b.c")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.b.y.c")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.x.b.y.y.c")); - BOOST_CHECK(tt.removeBindingKey(pattern)); -} - -QPID_AUTO_TEST_CASE(testMixed) -{ - TopicExchange::TopicExchangeTester tt; - string pattern("*.x.#.y"); - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.y")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.p.qq.y")); - BOOST_CHECK_EQUAL(0, match(tt, "a.a.x.y")); - BOOST_CHECK_EQUAL(0, match(tt, "aa.x.b.c")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "a.#.b.*"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.b.x")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.x.x.b.x")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "*.*.*.#"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "x.y.z")); - BOOST_CHECK_EQUAL(1, match(tt, "x.y.z.a.b.c")); - BOOST_CHECK_EQUAL(0, match(tt, "x.y")); - BOOST_CHECK_EQUAL(0, match(tt, "x")); - BOOST_CHECK(tt.removeBindingKey(pattern)); -} - - -QPID_AUTO_TEST_CASE(testMultiple) -{ - TopicExchange::TopicExchangeTester tt; - const std::string bindings[] = - { "a", "b", - "a.b", "b.c", - "a.b.c.d", "b.c.d.e", - "a.*", "a.#", "a.*.#", - "#.b", "*.b", "*.#.b", - "a.*.b", "a.#.b", "a.*.#.b", - "*.b.*", "#.b.#", - }; - const size_t nBindings = sizeof(bindings)/sizeof(bindings[0]); - - // setup bindings - for (size_t idx = 0; idx < nBindings; idx++) { - BOOST_CHECK(tt.addBindingKey(bindings[idx])); - } - - { - // read all bindings, and verify all are present - TopicExchange::TopicExchangeTester::BindingVec b; - tt.getAll(b); - BOOST_CHECK_EQUAL(b.size(), nBindings); - for (size_t idx = 0; idx < nBindings; idx++) { - bool found = false; - for (TopicExchange::TopicExchangeTester::BindingVec::iterator i = b.begin(); - i != b.end(); i++) { - if (*i == bindings[idx]) { - found = true; - break; - } - } - BOOST_CHECK(found); - } - } - - { // test match on pattern "a" - const std::string matches[] = { "a", "a.#" }; - const size_t nMatches = 2; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a", expected)); - } - - { // test match on pattern "a.z" - const std::string matches[] = { "a.*", "a.#", "a.*.#" }; - const size_t nMatches = 3; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.z", expected)); - } - - { // test match on pattern "a.b" - const std::string matches[] = { - "a.b", "a.*", "a.#", "a.*.#", - "#.b", "#.b.#", "*.#.b", "*.b", - "a.#.b" - }; - const size_t nMatches = 9; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.b", expected)); - } - - { // test match on pattern "a.c.c.b" - - const std::string matches[] = { - "#.b", "#.b.#", "*.#.b", "a.#.b", - "a.#", "a.*.#.b", "a.*.#" - }; - const size_t nMatches = 7; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.c.c.b", expected)); - } - - { // test match on pattern "a.b.c" - - const std::string matches[] = { - "#.b.#", "*.b.*", "a.#", "a.*.#" - }; - const size_t nMatches = 4; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.b.c", expected)); - } - - { // test match on pattern "b" - - const std::string matches[] = { - "#.b", "#.b.#", "b" - }; - const size_t nMatches = 3; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "b", expected)); - } - - { // test match on pattern "x.b" - - const std::string matches[] = { - "#.b", "#.b.#", "*.#.b", "*.b" - }; - const size_t nMatches = 4; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "x.b", expected)); - } - - { // test match on pattern "x.y.z.b" - - const std::string matches[] = { - "#.b", "#.b.#", "*.#.b" - }; - const size_t nMatches = 3; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "x.y.z.b", expected)); - } - - { // test match on pattern "x.y.z.b.a.b.c" - - const std::string matches[] = { - "#.b.#", "#.b.#" - }; - const size_t nMatches = 2; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "x.y.z.b.a.b.c", expected)); - } - - { // test match on pattern "a.b.c.d" - - const std::string matches[] = { - "#.b.#", "a.#", "a.*.#", "a.b.c.d", - }; - const size_t nMatches = 4; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.b.c.d", expected)); - } - - // cleanup bindings - for (size_t idx = 0; idx < nBindings; idx++) { - BOOST_CHECK(tt.removeBindingKey(bindings[idx])); - } -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/TransactionObserverTest.cpp b/qpid/cpp/src/tests/TransactionObserverTest.cpp deleted file mode 100644 index 80ef494c21..0000000000 --- a/qpid/cpp/src/tests/TransactionObserverTest.cpp +++ /dev/null @@ -1,147 +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 "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 -#include -#include -#include -#include - -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 events; - - MockTransactionObserver(bool prep_=true) : prep(prep_) {} - - void record(const string& e) { events.push_back(e); } - - void enqueue(const shared_ptr& 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(p)+" "+lexical_cast(r)); - } - bool prepare() { record("prepare"); return prep; } - void commit() { record("commit"); } - void rollback() {record("rollback"); } -}; - -struct MockBrokerObserver : public BrokerObserver { - bool prep; - shared_ptr tx; - - MockBrokerObserver(bool prep_=true) : prep(prep_) {} - - void startTx(const intrusive_ptr& buffer) { - if (!tx) { // Don't overwrite first tx with automatically started second tx. - 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(testTxCommit) { - MessagingFixture fix; - shared_ptr 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("enqueue q2 bar")("dequeue q1 1 0")("prepare")("commit"), - brokerObserver->tx->events - ); -} - -QPID_AUTO_TEST_CASE(testTxFail) { - MessagingFixture fix; - shared_ptr brokerObserver(new MockBrokerObserver(false)); - fix.broker->getBrokerObservers().add(brokerObserver); - Session txSession = simpleTxTransaction(fix); - try { - ScopedSuppressLogging sl; // Suppress messages for expected error. - txSession.commit(); - BOOST_FAIL("Expected exception"); - } catch(...) {} - - BOOST_CHECK_EQUAL( - list_of("enqueue q2 bar")("dequeue q1 1 0")("prepare")("rollback"), - brokerObserver->tx->events - ); -} - -QPID_AUTO_TEST_CASE(testTxRollback) { - MessagingFixture fix; - shared_ptr 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("enqueue q2 bar")("rollback"), - brokerObserver->tx->events - ); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/TxBufferTest.cpp b/qpid/cpp/src/tests/TxBufferTest.cpp deleted file mode 100644 index 3f052d213e..0000000000 --- a/qpid/cpp/src/tests/TxBufferTest.cpp +++ /dev/null @@ -1,188 +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/broker/TxBuffer.h" -#include "unit_test.h" -#include "test_tools.h" -#include -#include -#include "TxMocks.h" - -using namespace qpid::broker; -using boost::static_pointer_cast; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(TxBufferTestSuite) - -QPID_AUTO_TEST_CASE(testCommitLocal) -{ - MockTransactionalStore store; - store.expectBegin().expectCommit(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectCommit(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare().expectPrepare().expectCommit().expectCommit();//opB enlisted twice to test relative order - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectPrepare().expectCommit(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast(opA)); - buffer.enlist(static_pointer_cast(opB)); - buffer.enlist(static_pointer_cast(opB));//opB enlisted twice - buffer.enlist(static_pointer_cast(opC)); - - buffer.startCommit(&store); - buffer.endCommit(&store); - store.check(); - BOOST_CHECK(store.isCommitted()); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testFailOnCommitLocal) -{ - MockTransactionalStore store; - store.expectBegin().expectAbort(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opC(new MockTxOp());//will never get prepare as b will fail - opC->expectRollback(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast(opA)); - buffer.enlist(static_pointer_cast(opB)); - buffer.enlist(static_pointer_cast(opC)); - - try { - ScopedSuppressLogging sl; // Suppress messages for expected error. - buffer.startCommit(&store); - buffer.endCommit(&store); - BOOST_FAIL("Expected exception"); - } catch (...) {} - BOOST_CHECK(store.isAborted()); - store.check(); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testPrepare) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare(); - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectPrepare(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast(opA)); - buffer.enlist(static_pointer_cast(opB)); - buffer.enlist(static_pointer_cast(opC)); - - BOOST_CHECK(buffer.prepare(0)); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testFailOnPrepare) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectPrepare(); - MockTxOp::shared_ptr opC(new MockTxOp());//will never get prepare as b will fail - - TxBuffer buffer; - buffer.enlist(static_pointer_cast(opA)); - buffer.enlist(static_pointer_cast(opB)); - buffer.enlist(static_pointer_cast(opC)); - - BOOST_CHECK(!buffer.prepare(0)); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testRollback) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectRollback(); - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectRollback(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast(opA)); - buffer.enlist(static_pointer_cast(opB)); - buffer.enlist(static_pointer_cast(opC)); - - buffer.rollback(); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testBufferIsClearedAfterRollback) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectRollback(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast(opA)); - buffer.enlist(static_pointer_cast(opB)); - - buffer.rollback(); - buffer.commit();//second call should not reach ops - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_CASE(testBufferIsClearedAfterCommit) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectCommit(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectCommit(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast(opA)); - buffer.enlist(static_pointer_cast(opB)); - - buffer.commit(); - buffer.rollback();//second call should not reach ops - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/TxMocks.h b/qpid/cpp/src/tests/TxMocks.h deleted file mode 100644 index 8b54e7484b..0000000000 --- a/qpid/cpp/src/tests/TxMocks.h +++ /dev/null @@ -1,236 +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. - * - */ -#ifndef _tests_TxMocks_h -#define _tests_TxMocks_h - - -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/broker/TxOp.h" -#include -#include - -using namespace qpid::broker; -using boost::static_pointer_cast; -using std::string; - -namespace qpid { -namespace tests { - -template void assertEqualVector(std::vector& expected, std::vector& actual){ - unsigned int i = 0; - while(i < expected.size() && i < actual.size()){ - BOOST_CHECK_EQUAL(expected[i], actual[i]); - i++; - } - if (i < expected.size()) { - throw qpid::Exception(QPID_MSG("Missing " << expected[i])); - } else if (i < actual.size()) { - throw qpid::Exception(QPID_MSG("Extra " << actual[i])); - } - BOOST_CHECK_EQUAL(expected.size(), actual.size()); -} - -class TxOpConstants{ -protected: - const string PREPARE; - const string COMMIT; - const string ROLLBACK; - - TxOpConstants() : PREPARE("PREPARE"), COMMIT("COMMIT"), ROLLBACK("ROLLBACK") {} -}; - -class MockTxOp : public TxOp, public TxOpConstants{ - std::vector expected; - std::vector actual; - bool failOnPrepare; - string debugName; -public: - typedef boost::shared_ptr shared_ptr; - - MockTxOp() : failOnPrepare(false) {} - MockTxOp(bool _failOnPrepare) : failOnPrepare(_failOnPrepare) {} - - void setDebugName(string name){ - debugName = name; - } - - void printExpected(){ - std::cout << std::endl << "MockTxOp[" << debugName << "] expects: "; - for (std::vector::iterator i = expected.begin(); i < expected.end(); i++) { - if(i != expected.begin()) std::cout << ", "; - std::cout << *i; - } - std::cout << std::endl; - } - - void printActual(){ - std::cout << std::endl << "MockTxOp[" << debugName << "] actual: "; - for (std::vector::iterator i = actual.begin(); i < actual.end(); i++) { - if(i != actual.begin()) std::cout << ", "; - std::cout << *i; - } - std::cout << std::endl; - } - - bool prepare(TransactionContext*) throw(){ - actual.push_back(PREPARE); - return !failOnPrepare; - } - void commit() throw(){ - actual.push_back(COMMIT); - } - void rollback() throw(){ - if(!debugName.empty()) std::cout << std::endl << "MockTxOp[" << debugName << "]::rollback()" << std::endl; - actual.push_back(ROLLBACK); - } - - void callObserver(const boost::shared_ptr&) {} - - MockTxOp& expectPrepare(){ - expected.push_back(PREPARE); - return *this; - } - MockTxOp& expectCommit(){ - expected.push_back(COMMIT); - return *this; - } - MockTxOp& expectRollback(){ - expected.push_back(ROLLBACK); - return *this; - } - void check(){ - assertEqualVector(expected, actual); - } - - ~MockTxOp(){} -}; - -class MockTransactionalStore : public TransactionalStore{ - const string BEGIN; - const string BEGIN2PC; - const string PREPARE; - const string COMMIT; - const string ABORT; - std::vector expected; - std::vector actual; - - enum states {OPEN = 1, PREPARED = 2, COMMITTED = 3, ABORTED = 4}; - int state; - - class TestTransactionContext : public TPCTransactionContext{ - MockTransactionalStore* store; - public: - TestTransactionContext(MockTransactionalStore* _store) : store(_store) {} - void prepare(){ - if(!store->isOpen()) throw "txn already completed"; - store->state = PREPARED; - } - - void commit(){ - if(!store->isOpen() && !store->isPrepared()) throw "txn already completed"; - store->state = COMMITTED; - } - - void abort(){ - if(!store->isOpen() && !store->isPrepared()) throw "txn already completed"; - store->state = ABORTED; - } - ~TestTransactionContext(){} - }; - -public: - MockTransactionalStore() : - BEGIN("BEGIN"), BEGIN2PC("BEGIN2PC"), PREPARE("PREPARE"), COMMIT("COMMIT"), ABORT("ABORT"), state(OPEN){} - - void collectPreparedXids(std::set&) - { - throw "Operation not supported"; - } - - std::auto_ptr begin(const std::string&){ - actual.push_back(BEGIN2PC); - std::auto_ptr txn(new TestTransactionContext(this)); - return txn; - } - std::auto_ptr begin(){ - actual.push_back(BEGIN); - std::auto_ptr txn(new TestTransactionContext(this)); - return txn; - } - void prepare(TPCTransactionContext& ctxt){ - actual.push_back(PREPARE); - dynamic_cast(ctxt).prepare(); - } - void commit(TransactionContext& ctxt){ - actual.push_back(COMMIT); - dynamic_cast(ctxt).commit(); - } - void abort(TransactionContext& ctxt){ - actual.push_back(ABORT); - dynamic_cast(ctxt).abort(); - } - MockTransactionalStore& expectBegin(){ - expected.push_back(BEGIN); - return *this; - } - MockTransactionalStore& expectBegin2PC(){ - expected.push_back(BEGIN2PC); - return *this; - } - MockTransactionalStore& expectPrepare(){ - expected.push_back(PREPARE); - return *this; - } - MockTransactionalStore& expectCommit(){ - expected.push_back(COMMIT); - return *this; - } - MockTransactionalStore& expectAbort(){ - expected.push_back(ABORT); - return *this; - } - void check(){ - assertEqualVector(expected, actual); - } - - bool isPrepared(){ - return state == PREPARED; - } - - bool isCommitted(){ - return state == COMMITTED; - } - - bool isAborted(){ - return state == ABORTED; - } - - bool isOpen() const{ - return state == OPEN; - } - ~MockTransactionalStore(){} -}; - -}} // namespace qpid::tests - -#endif diff --git a/qpid/cpp/src/tests/Url.cpp b/qpid/cpp/src/tests/Url.cpp deleted file mode 100644 index b30de682bc..0000000000 --- a/qpid/cpp/src/tests/Url.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * 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 "unit_test.h" -#include "test_tools.h" -#include "qpid/Url.h" -#include - -using namespace std; -using namespace qpid; -using namespace boost::assign; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(UrlTestSuite) - -#define URL_CHECK_STR(STR) BOOST_CHECK_EQUAL(Url(STR).str(), STR) -#define URL_CHECK_INVALID(STR) BOOST_CHECK_THROW(Url(STR), Url::Invalid) - -QPID_AUTO_TEST_CASE(TestParseTcp) { - URL_CHECK_STR("amqp:tcp:host:42"); - URL_CHECK_STR("amqp:tcp:host-._~%ff%23:42"); // unreserved chars and pct encoded hex. - // Check defaults - BOOST_CHECK_EQUAL(Url("amqp:host:42").str(), "amqp:tcp:host:42"); - BOOST_CHECK_EQUAL(Url("amqp:tcp:host").str(), "amqp:tcp:host:5672"); - BOOST_CHECK_EQUAL(Url("host").str(), "amqp:tcp:host:5672"); -} - -QPID_AUTO_TEST_CASE(TestParseInvalid) { - //host is required: - URL_CHECK_INVALID("amqp:tcp:"); - URL_CHECK_INVALID("amqp:"); - URL_CHECK_INVALID("amqp::42"); - URL_CHECK_INVALID(""); - - // Port must be numeric - URL_CHECK_INVALID("host:badPort"); -} - -QPID_AUTO_TEST_CASE(TestParseXyz) { - Url::addProtocol("xyz"); - URL_CHECK_STR("amqp:xyz:host:123"); - BOOST_CHECK_EQUAL(Url("xyz:host").str(), "amqp:xyz:host:5672"); -} - -QPID_AUTO_TEST_CASE(TestParseTricky) { - BOOST_CHECK_EQUAL(Url("amqp").str(), "amqp:tcp:amqp:5672"); - BOOST_CHECK_EQUAL(Url("amqp:tcp").str(), "amqp:tcp:tcp:5672"); - // These are ambiguous parses and arguably not the best result - BOOST_CHECK_EQUAL(Url("amqp:876").str(), "amqp:tcp:876:5672"); - BOOST_CHECK_EQUAL(Url("tcp:567").str(), "amqp:tcp:567:5672"); -} - -QPID_AUTO_TEST_CASE(TestParseIPv6) { - Url u1("[::]"); - BOOST_CHECK_EQUAL(u1[0].host, "::"); - BOOST_CHECK_EQUAL(u1[0].port, 5672); - Url u2("[::1]"); - BOOST_CHECK_EQUAL(u2[0].host, "::1"); - BOOST_CHECK_EQUAL(u2[0].port, 5672); - Url u3("[::127.0.0.1]"); - BOOST_CHECK_EQUAL(u3[0].host, "::127.0.0.1"); - BOOST_CHECK_EQUAL(u3[0].port, 5672); - Url u4("[2002::222:68ff:fe0b:e61a]"); - BOOST_CHECK_EQUAL(u4[0].host, "2002::222:68ff:fe0b:e61a"); - BOOST_CHECK_EQUAL(u4[0].port, 5672); - Url u5("[2002::222:68ff:fe0b:e61a]:123"); - BOOST_CHECK_EQUAL(u5[0].host, "2002::222:68ff:fe0b:e61a"); - BOOST_CHECK_EQUAL(u5[0].port, 123); -} - -QPID_AUTO_TEST_CASE(TestParseMultiAddress) { - Url::addProtocol("xyz"); - URL_CHECK_STR("amqp:tcp:host:0,xyz:foo:123,tcp:foo:0,xyz:bar:1"); - URL_CHECK_STR("amqp:xyz:foo:222,tcp:foo:0"); - URL_CHECK_INVALID("amqp:tcp:h:0,"); - URL_CHECK_INVALID(",amqp:tcp:h"); -} - -QPID_AUTO_TEST_CASE(TestParseUserPass) { - URL_CHECK_STR("amqp:user/pass@tcp:host:123"); - URL_CHECK_STR("amqp:user@tcp:host:123"); - BOOST_CHECK_EQUAL(Url("user/pass@host").str(), "amqp:user/pass@tcp:host:5672"); - BOOST_CHECK_EQUAL(Url("user@host").str(), "amqp:user@tcp:host:5672"); - - Url u("user/pass@host"); - BOOST_CHECK_EQUAL(u.getUser(), "user"); - BOOST_CHECK_EQUAL(u.getPass(), "pass"); - Url v("foo@host"); - BOOST_CHECK_EQUAL(v.getUser(), "foo"); - BOOST_CHECK_EQUAL(v.getPass(), ""); - u = v; - BOOST_CHECK_EQUAL(u.getUser(), "foo"); - BOOST_CHECK_EQUAL(u.getPass(), ""); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Uuid.cpp b/qpid/cpp/src/tests/Uuid.cpp deleted file mode 100644 index f9a67d9db0..0000000000 --- a/qpid/cpp/src/tests/Uuid.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * - * 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/framing/Uuid.h" -#include "qpid/framing/Buffer.h" -#include "qpid/types/Uuid.h" - -#include "unit_test.h" - -#include - -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(UuidTestSuite) - -using namespace std; -using namespace qpid::framing; - -struct UniqueSet : public std::set { - void operator()(const Uuid& uuid) { - BOOST_REQUIRE(find(uuid) == end()); - insert(uuid); - } -}; - -QPID_AUTO_TEST_CASE(testUuidCtor) { - // Uniqueness - boost::array uuids; - for_each(uuids.begin(), uuids.end(), mem_fun_ref(&Uuid::generate)); - UniqueSet unique; - for_each(uuids.begin(), uuids.end(), unique); -} - -boost::array sample = {{0x1b, 0x4e, 0x28, 0xba, 0x2f, 0xa1, 0x11, 0x02, 0x88, 0x3f, 0xb9, 0xa7, 0x61, 0xbd, 0xe3, 0xfb}}; -const string sampleStr("1b4e28ba-2fa1-1102-883f-b9a761bde3fb"); -const string zeroStr("00000000-0000-0000-0000-000000000000"); -const string badUuid1("1b4e28ba-2fa1-11d2-883f-b9761bde3fb"); -const string badUuid2("1b4e28ba-2fa1-11d23883f-b9761dbde3fb"); - -QPID_AUTO_TEST_CASE(testUuidIstream) { - Uuid uuid; - istringstream in(sampleStr); - in >> uuid; - BOOST_CHECK(!in.fail()); - BOOST_CHECK(::memcmp(uuid.data(), sample.data(), uuid.size())==0); - - istringstream is(zeroStr); - Uuid zero; - is >> zero; - BOOST_CHECK(!is.fail()); - BOOST_CHECK_EQUAL(zero, Uuid()); -} - -QPID_AUTO_TEST_CASE(testUuidOstream) { - Uuid uuid(sample.c_array()); - ostringstream out; - out << uuid; - BOOST_CHECK(out.good()); - BOOST_CHECK_EQUAL(out.str(), sampleStr); - - ostringstream os; - os << Uuid(); - BOOST_CHECK(out.good()); - BOOST_CHECK_EQUAL(os.str(), zeroStr); -} - -QPID_AUTO_TEST_CASE(testBadUuidIstream) { - Uuid a; - istringstream is(badUuid1); - is >> a; - BOOST_CHECK(!is.good()); - istringstream is2(badUuid2); - is2 >> a; - BOOST_CHECK(!is2.good()); -} - -QPID_AUTO_TEST_CASE(testUuidIOstream) { - Uuid a(true), b(true); - ostringstream os; - os << a << endl << b; - Uuid aa, bb; - istringstream is(os.str()); - is >> aa >> ws >> bb; - BOOST_CHECK(os.good()); - BOOST_CHECK_EQUAL(a, aa); - BOOST_CHECK_EQUAL(b, bb); -} - -QPID_AUTO_TEST_CASE(testUuidEncodeDecode) { - std::vector buff(Uuid::size()); - Buffer wbuf(&buff[0], Uuid::size()); - Uuid uuid(sample.c_array()); - uuid.encode(wbuf); - - Buffer rbuf(&buff[0], Uuid::size()); - Uuid decoded; - decoded.decode(rbuf); - BOOST_CHECK_EQUAL(string(sample.begin(), sample.end()), - string(decoded.data(), decoded.data()+decoded.size())); -} - -QPID_AUTO_TEST_CASE(testTypesUuid) -{ - //tests for the Uuid class in the types namespace (introduced - //to avoid pulling in dependencies from framing) - types::Uuid a; - types::Uuid b(true); - types::Uuid c(true); - types::Uuid d(b); - types::Uuid e; - e = c; - - BOOST_CHECK(!a); - BOOST_CHECK(b); - - BOOST_CHECK(a != b); - BOOST_CHECK(b != c); - - BOOST_CHECK_EQUAL(b, d); - BOOST_CHECK_EQUAL(c, e); - - ostringstream out; - out << b; - istringstream in(out.str()); - in >> a; - BOOST_CHECK(!in.fail()); - BOOST_CHECK_EQUAL(a, b); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/Variant.cpp b/qpid/cpp/src/tests/Variant.cpp deleted file mode 100644 index 5ae7fc89eb..0000000000 --- a/qpid/cpp/src/tests/Variant.cpp +++ /dev/null @@ -1,834 +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 "unit_test.h" -#include "qpid/types/Variant.h" -#include "qpid/amqp_0_10/Codecs.h" -#include -#include - -using namespace qpid::types; -using namespace qpid::amqp_0_10; -using boost::assign::list_of; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(VariantSuite) - -QPID_AUTO_TEST_CASE(testConversions) -{ - Variant value; - - //string to float/double - value = "1.5"; - BOOST_CHECK_EQUAL((float) 1.5, value.asFloat()); - BOOST_CHECK_EQUAL((double) 1.5, value.asDouble()); - - //float to string or double - value = 1.5f; - BOOST_CHECK_EQUAL((float) 1.5, value.asFloat()); - BOOST_CHECK_EQUAL((double) 1.5, value.asDouble()); - BOOST_CHECK_EQUAL(std::string("1.5"), value.asString()); - - //double to string (conversion to float not valid) - value = 1.5; - BOOST_CHECK_THROW(value.asFloat(), InvalidConversion); - BOOST_CHECK_EQUAL((double) 1.5, value.asDouble()); - BOOST_CHECK_EQUAL(std::string("1.5"), value.asString()); - - //uint8 to larger unsigned ints and string - value = (uint8_t) 7; - BOOST_CHECK_EQUAL((uint8_t) 7, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 7, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 7, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 7, value.asUint64()); - BOOST_CHECK_EQUAL(std::string("7"), value.asString()); - - value = (uint16_t) 8; - BOOST_CHECK_EQUAL(std::string("8"), value.asString()); - value = (uint32_t) 9; - BOOST_CHECK_EQUAL(std::string("9"), value.asString()); - - //uint32 to larger unsigned ints and string - value = (uint32_t) 9999999; - BOOST_CHECK_EQUAL((uint32_t) 9999999, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 9999999, value.asUint64()); - BOOST_CHECK_EQUAL(std::string("9999999"), value.asString()); - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - - value = "true"; - BOOST_CHECK(value.asBool()); - value = "false"; - BOOST_CHECK(!value.asBool()); - value = "1"; - BOOST_CHECK(value.asBool()); - value = "0"; - BOOST_CHECK(!value.asBool()); - value = "other"; - BOOST_CHECK_THROW(value.asBool(), InvalidConversion); -} - -QPID_AUTO_TEST_CASE(testConversionsFromString) -{ - Variant value; - value = "5"; - BOOST_CHECK_EQUAL(5, value.asInt16()); - BOOST_CHECK_EQUAL(5u, value.asUint16()); - - value = "-5"; - BOOST_CHECK_EQUAL(-5, value.asInt16()); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - - value = "18446744073709551615"; - BOOST_CHECK_EQUAL(18446744073709551615ull, value.asUint64()); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); - - value = "9223372036854775808"; - BOOST_CHECK_EQUAL(9223372036854775808ull, value.asUint64()); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); - - value = "-9223372036854775809"; - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); - - value = "2147483648"; - BOOST_CHECK_EQUAL(2147483648ul, value.asUint32()); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - - value = "-2147483649"; - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - - value = "32768"; - BOOST_CHECK_EQUAL(32768u, value.asUint16()); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - - value = "-32769"; - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - - value = "-2.5"; - BOOST_CHECK_EQUAL(-2.5, value.asFloat()); - - value = "-0.875432e10"; - BOOST_CHECK_EQUAL(-0.875432e10, value.asDouble()); - - value = "-0"; - BOOST_CHECK_EQUAL(0, value.asInt16()); - BOOST_CHECK_EQUAL(0u, value.asUint16()); - - value = "-Blah"; - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); - BOOST_CHECK_THROW(value.asFloat(), InvalidConversion); - BOOST_CHECK_THROW(value.asDouble(), InvalidConversion); - - value = "-000"; - BOOST_CHECK_EQUAL(0, value.asInt16()); - BOOST_CHECK_EQUAL(0u, value.asUint16()); - - value = "-0010"; - BOOST_CHECK_EQUAL(-10, value.asInt16()); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); -} - -QPID_AUTO_TEST_CASE(testSizeConversionsUint) -{ - Variant value; - - //uint8 (in 7 bits) to other uints, ints - value = (uint8_t) 7; - BOOST_CHECK_EQUAL((uint8_t) 7, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 7, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 7, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 7, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 7, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 7, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 7, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 7, value.asInt64()); - - //uint8 (in 8 bits) to other uints, ints - value = (uint8_t) 200; - BOOST_CHECK_EQUAL((uint8_t) 200, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 200, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 200, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 200, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 200, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 200, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 200, value.asInt64()); - - - - //uint16 (in 7 bits) to other uints, ints - value = (uint16_t) 120; - BOOST_CHECK_EQUAL((uint8_t) 120, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 120, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 120, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 120, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 120, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 120, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 120, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 120, value.asInt64()); - - //uint16 (more than 7 bits) to other uints, ints - value = (uint16_t) 240; - BOOST_CHECK_EQUAL((uint8_t) 240, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 240, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 240, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 240, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 240, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 240, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 240, value.asInt64()); - - //uint16 (more than 8 bits) to other uints, ints - value = (uint16_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //uint16 (more than 15 bits) to other uints, ints - value = (uint16_t) 32770; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 32770, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 32770, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 32770, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 32770, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 32770, value.asInt64()); - - - - //uint32 (in 7 bits) to other uints, ints - value = (uint32_t) 120; - BOOST_CHECK_EQUAL((uint8_t) 120, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 120, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 120, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 120, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 120, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 120, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 120, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 120, value.asInt64()); - - //uint32 (more than 7 bits) to other uints, ints - value = (uint32_t) 240; - BOOST_CHECK_EQUAL((uint8_t) 240, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 240, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 240, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 240, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 240, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 240, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 240, value.asInt64()); - - //uint32 (more than 8 bits) to other uints, ints - value = (uint32_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //uint32 (more than 15 bits) to other uints, ints - value = (uint32_t) 32770; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 32770, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 32770, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 32770, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 32770, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 32770, value.asInt64()); - - //uint32 (more than 16 bits) to other uints, ints - value = (uint32_t) 66000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_EQUAL((uint32_t) 66000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 66000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 66000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 66000, value.asInt64()); - - - - //uint64 (in 7 bits) to other uints, ints - value = (uint64_t) 120; - BOOST_CHECK_EQUAL((uint8_t) 120, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 120, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 120, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 120, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 120, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 120, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 120, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 120, value.asInt64()); - - //uint64 (more than 7 bits) to other uints, ints - value = (uint64_t) 240; - BOOST_CHECK_EQUAL((uint8_t) 240, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 240, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 240, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 240, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 240, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 240, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 240, value.asInt64()); - - //uint64 (more than 8 bits) to other uints, ints - value = (uint64_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //uint64 (more than 15 bits) to other uints, ints - value = (uint64_t) 32770; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 32770, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 32770, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 32770, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 32770, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 32770, value.asInt64()); - - //uint64 (more than 16 bits) to other uints, ints - value = (uint64_t) 66000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_EQUAL((uint32_t) 66000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 66000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 66000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 66000, value.asInt64()); - - //uint64 (more than 31 bits) to other uints, ints - value = (uint64_t) 3000000000ul; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_EQUAL((uint32_t) 3000000000ul, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 3000000000ul, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) 3000000000ul, value.asInt64()); - - //uint64 (more than 32 bits) to other uints, ints - value = (uint64_t) 7000000000ull; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_EQUAL((uint64_t) 7000000000ull, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) 7000000000ull, value.asInt64()); - - //uint64 (more than 63 bits) to other uints, ints - value = (uint64_t) 0x8000000000000000ull; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_EQUAL((uint64_t) 0x8000000000000000ull, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); -} - -QPID_AUTO_TEST_CASE(testSizeConversionsInt) -{ - Variant value; - - //int8 (positive in 7 bits) - value = (int8_t) 100; - BOOST_CHECK_EQUAL((uint8_t) 100, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 100, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 100, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 100, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 100, value.asInt64()); - - //int8 (negative) - value = (int8_t) -100; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_EQUAL((int8_t) -100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) -100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -100, value.asInt64()); - - - - //int16 (positive in 7 bits) - value = (int16_t) 100; - BOOST_CHECK_EQUAL((uint8_t) 100, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 100, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 100, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 100, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 100, value.asInt64()); - - //int16 (positive in 8 bits) - value = (int16_t) 200; - BOOST_CHECK_EQUAL((uint8_t) 200, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 200, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 200, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 200, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 200, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 200, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 200, value.asInt64()); - - //int16 (positive in more than 8 bits) - value = (int16_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //int16 (negative in 7 bits) - value = (int16_t) -100; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_EQUAL((int8_t) -100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) -100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -100, value.asInt64()); - - //int16 (negative in more than 7 bits) - value = (int16_t) -1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) -1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -1000, value.asInt64()); - - - - //int32 (positive in 7 bits) - value = (int32_t) 100; - BOOST_CHECK_EQUAL((uint8_t) 100, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 100, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 100, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 100, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 100, value.asInt64()); - - //int32 (positive in 8 bits) - value = (int32_t) 200; - BOOST_CHECK_EQUAL((uint8_t) 200, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 200, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 200, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 200, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 200, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 200, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 200, value.asInt64()); - - //int32 (positive in more than 8 bits) - value = (int32_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //int32 (positive in more than 15 bits) - value = (int32_t) 40000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 40000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 40000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 40000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 40000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 40000, value.asInt64()); - - //int32 (negative in 7 bits) - value = (int32_t) -100; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_EQUAL((int8_t) -100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) -100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -100, value.asInt64()); - - //int32 (negative in more than 7 bits) - value = (int32_t) -1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) -1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -1000, value.asInt64()); - - //int32 (negative in more than 15 bits) - value = (int32_t) -40000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) -40000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -40000, value.asInt64()); - - - - //int64 (positive in 7 bits) - value = (int64_t) 100; - BOOST_CHECK_EQUAL((uint8_t) 100, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 100, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 100, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 100, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 100, value.asInt64()); - - //int64 (positive in 8 bits) - value = (int64_t) 200; - BOOST_CHECK_EQUAL((uint8_t) 200, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 200, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 200, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 200, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 200, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 200, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 200, value.asInt64()); - - //int64 (positive in more than 8 bits) - value = (int64_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //int64 (positive in more than 15 bits) - value = (int64_t) 40000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 40000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 40000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 40000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 40000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 40000, value.asInt64()); - - //int64 (positive in more than 31 bits) - value = (int64_t) 3000000000ll; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_EQUAL((uint32_t) 3000000000ll, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 3000000000ll, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) 3000000000ll, value.asInt64()); - - //int64 (positive in more than 32 bits) - value = (int64_t) 5000000000ll; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_EQUAL((uint64_t) 5000000000ll, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) 5000000000ll, value.asInt64()); - - //int64 (negative in 7 bits) - value = (int64_t) -100; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_EQUAL((int8_t) -100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) -100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -100, value.asInt64()); - - //int64 (negative in more than 7 bits) - value = (int64_t) -1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) -1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -1000, value.asInt64()); - - //int64 (negative in more than 15 bits) - value = (int64_t) -40000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) -40000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -40000, value.asInt64()); - - //int64 (negative in more than 31 bits) - value = (int64_t) -3000000000ll; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) -3000000000ll, value.asInt64()); -} - -QPID_AUTO_TEST_CASE(testAssignment) -{ - Variant value("abc"); - Variant other = value; - BOOST_CHECK_EQUAL(VAR_STRING, value.getType()); - BOOST_CHECK_EQUAL(other.getType(), value.getType()); - BOOST_CHECK_EQUAL(other.asString(), value.asString()); - - const uint32_t i(1000); - value = i; - BOOST_CHECK_EQUAL(VAR_UINT32, value.getType()); - BOOST_CHECK_EQUAL(VAR_STRING, other.getType()); -} - -QPID_AUTO_TEST_CASE(testList) -{ - const std::string s("abc"); - const float f(9.876f); - const int16_t x(1000); - - Variant value = Variant::List(); - value.asList().push_back(Variant(s)); - value.asList().push_back(Variant(f)); - value.asList().push_back(Variant(x)); - BOOST_CHECK_EQUAL(3u, value.asList().size()); - Variant::List::const_iterator i = value.asList().begin(); - - BOOST_CHECK(i != value.asList().end()); - BOOST_CHECK_EQUAL(VAR_STRING, i->getType()); - BOOST_CHECK_EQUAL(s, i->asString()); - i++; - - BOOST_CHECK(i != value.asList().end()); - BOOST_CHECK_EQUAL(VAR_FLOAT, i->getType()); - BOOST_CHECK_EQUAL(f, i->asFloat()); - i++; - - BOOST_CHECK(i != value.asList().end()); - BOOST_CHECK_EQUAL(VAR_INT16, i->getType()); - BOOST_CHECK_EQUAL(x, i->asInt16()); - i++; - - BOOST_CHECK(i == value.asList().end()); -} - -QPID_AUTO_TEST_CASE(testMap) -{ - const std::string red("red"); - const float pi(3.14f); - const int16_t x(1000); - const Uuid u(true); - - Variant value = Variant::Map(); - value.asMap()["colour"] = red; - value.asMap()["pi"] = pi; - value.asMap()["my-key"] = x; - value.asMap()["id"] = u; - BOOST_CHECK_EQUAL(4u, value.asMap().size()); - - BOOST_CHECK_EQUAL(VAR_STRING, value.asMap()["colour"].getType()); - BOOST_CHECK_EQUAL(red, value.asMap()["colour"].asString()); - - BOOST_CHECK_EQUAL(VAR_FLOAT, value.asMap()["pi"].getType()); - BOOST_CHECK_EQUAL(pi, value.asMap()["pi"].asFloat()); - - BOOST_CHECK_EQUAL(VAR_INT16, value.asMap()["my-key"].getType()); - BOOST_CHECK_EQUAL(x, value.asMap()["my-key"].asInt16()); - - BOOST_CHECK_EQUAL(VAR_UUID, value.asMap()["id"].getType()); - BOOST_CHECK_EQUAL(u, value.asMap()["id"].asUuid()); - - value.asMap()["my-key"] = "now it's a string"; - BOOST_CHECK_EQUAL(VAR_STRING, value.asMap()["my-key"].getType()); - BOOST_CHECK_EQUAL(std::string("now it's a string"), value.asMap()["my-key"].asString()); -} - -QPID_AUTO_TEST_CASE(testIsEqualTo) -{ - BOOST_CHECK_EQUAL(Variant("abc"), Variant("abc")); - BOOST_CHECK_EQUAL(Variant(1234), Variant(1234)); - - Variant a = Variant::Map(); - a.asMap()["colour"] = "red"; - a.asMap()["pi"] = 3.14f; - a.asMap()["my-key"] = 1234; - Variant b = Variant::Map(); - b.asMap()["colour"] = "red"; - b.asMap()["pi"] = 3.14f; - b.asMap()["my-key"] = 1234; - BOOST_CHECK_EQUAL(a, b); -} - -QPID_AUTO_TEST_CASE(testEncoding) -{ - Variant a("abc"); - a.setEncoding("utf8"); - Variant b = a; - Variant map = Variant::Map(); - map.asMap()["a"] = a; - map.asMap()["b"] = b; - BOOST_CHECK_EQUAL(a.getEncoding(), std::string("utf8")); - BOOST_CHECK_EQUAL(a.getEncoding(), b.getEncoding()); - BOOST_CHECK_EQUAL(a.getEncoding(), map.asMap()["a"].getEncoding()); - BOOST_CHECK_EQUAL(b.getEncoding(), map.asMap()["b"].getEncoding()); - BOOST_CHECK_EQUAL(map.asMap()["a"].getEncoding(), map.asMap()["b"].getEncoding()); -} - -QPID_AUTO_TEST_CASE(testBufferEncoding) -{ - Variant a("abc"); - a.setEncoding("utf8"); - std::string buffer; - - Variant::Map inMap, outMap; - inMap["a"] = a; - - MapCodec::encode(inMap, buffer); - MapCodec::decode(buffer, outMap); - BOOST_CHECK_EQUAL(inMap, outMap); - - inMap["b"] = Variant(std::string(65535, 'X')); - inMap["b"].setEncoding("utf16"); - MapCodec::encode(inMap, buffer); - MapCodec::decode(buffer, outMap); - BOOST_CHECK_EQUAL(inMap, outMap); - - inMap["fail"] = Variant(std::string(65536, 'X')); - inMap["fail"].setEncoding("utf16"); - BOOST_CHECK_THROW(MapCodec::encode(inMap, buffer), std::exception); -} - -QPID_AUTO_TEST_CASE(parse) -{ - Variant a; - a.parse("What a fine mess"); - BOOST_CHECK(a.getType()==types::VAR_STRING); - a.parse("true"); - BOOST_CHECK(a.getType()==types::VAR_BOOL); - a.parse("FalsE"); - BOOST_CHECK(a.getType()==types::VAR_BOOL); - a.parse("3.1415926"); - BOOST_CHECK(a.getType()==types::VAR_DOUBLE); - a.parse("-7.2e-15"); - BOOST_CHECK(a.getType()==types::VAR_DOUBLE); - a.parse("9223372036854775807"); - BOOST_CHECK(a.getType()==types::VAR_INT64); - a.parse("9223372036854775808"); - BOOST_CHECK(a.getType()==types::VAR_UINT64); - a.parse("-9223372036854775807"); - BOOST_CHECK(a.getType()==types::VAR_INT64); - a.parse("-9223372036854775808"); - BOOST_CHECK(a.getType()==types::VAR_DOUBLE); - a.parse("18446744073709551615"); - BOOST_CHECK(a.getType()==types::VAR_UINT64); - a.parse("18446744073709551616"); - BOOST_CHECK(a.getType()==types::VAR_DOUBLE); -} - -QPID_AUTO_TEST_CASE(described) -{ - Variant a; - BOOST_CHECK(!a.isDescribed()); - a.getDescriptors().push_back("foo"); - BOOST_CHECK(a.isDescribed()); - BOOST_CHECK_EQUAL(a.getDescriptors().size(), 1U); - BOOST_CHECK_EQUAL(a.getDescriptors().front(), Variant("foo")); - a = 42; - BOOST_CHECK(a.isDescribed()); - BOOST_CHECK_EQUAL(a.getDescriptors().size(), 1U); - BOOST_CHECK_EQUAL(a.getDescriptors().front(), Variant("foo")); - a.getDescriptors().push_back(33); - BOOST_CHECK_EQUAL(a.getDescriptors().size(), 2U); - BOOST_CHECK_EQUAL(a.getDescriptors().front(), Variant("foo")); - BOOST_CHECK_EQUAL(*(++a.getDescriptors().begin()), Variant(33)); - a.getDescriptors().clear(); - BOOST_CHECK(!a.isDescribed()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/XmlClientSessionTest.cpp b/qpid/cpp/src/tests/XmlClientSessionTest.cpp deleted file mode 100644 index bfa6ed096b..0000000000 --- a/qpid/cpp/src/tests/XmlClientSessionTest.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - * - * Licensed to the Apachef Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 "BrokerFixture.h" -#include "qpid/sys/Shlib.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/client/Message.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/LocalQueue.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" - -#include -#include - -#include - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(XmlClientSessionTest) - -struct XmlFixture { - XmlFixture() { - qpid::sys::Shlib shlib(getLibPath("XML_LIB")); - } - ~XmlFixture() {} -}; - -using namespace qpid::client; -using namespace qpid::client::arg; -using namespace qpid::framing; -using namespace qpid; - -using qpid::sys::Monitor; -using std::string; -using std::cout; -using std::endl; - - -class SubscribedLocalQueue : public LocalQueue { - private: - SubscriptionManager& subscriptions; - public: - SubscribedLocalQueue(SubscriptionManager& subs) : subscriptions(subs) {} - Message get () { return pop(); } - Message get (sys::Duration timeout) { return pop(timeout); } - virtual ~SubscribedLocalQueue() {} -}; - - -struct SimpleListener : public MessageListener -{ - Monitor lock; - std::vector messages; - - void received(Message& msg) - { - Monitor::ScopedLock l(lock); - messages.push_back(msg); - lock.notifyAll(); - } - - void waitFor(const uint n) - { - Monitor::ScopedLock l(lock); - while (messages.size() < n) { - lock.wait(); - } - } -}; - -struct ClientSessionFixture : public SessionFixture -{ - void declareSubscribe(const string& q="odd_blue", - const string& dest="xml") - { - session.queueDeclare(queue=q); - session.messageSubscribe(queue=q, destination=dest, acquireMode=1); - session.messageFlow(destination=dest, unit=0, value=0xFFFFFFFF);//messages - session.messageFlow(destination=dest, unit=1, value=0xFFFFFFFF);//bytes - } -}; - -// ########### START HERE #################################### - -QPID_FIXTURE_TEST_CASE(testXmlBinding, XmlFixture) { - ClientSessionFixture f; - - SubscriptionManager subscriptions(f.session); - SubscribedLocalQueue localQueue(subscriptions); - - f.session.exchangeDeclare(qpid::client::arg::exchange="xml", qpid::client::arg::type="xml"); - f.session.queueDeclare(qpid::client::arg::queue="odd_blue"); - subscriptions.subscribe(localQueue, "odd_blue"); - - FieldTable binding; - binding.setString("xquery", "declare variable $color external;" - "(./message/id mod 2 = 1) and ($color = 'blue')"); - f.session.exchangeBind(qpid::client::arg::exchange="xml", qpid::client::arg::queue="odd_blue", qpid::client::arg::bindingKey="query_name", qpid::client::arg::arguments=binding); - - Message message; - message.getDeliveryProperties().setRoutingKey("query_name"); - - message.getHeaders().setString("color", "blue"); - string m = "1"; - message.setData(m); - - f.session.messageTransfer(qpid::client::arg::content=message, qpid::client::arg::destination="xml"); - - Message m2 = localQueue.get(1*qpid::sys::TIME_SEC); - BOOST_CHECK_EQUAL(m, m2.getData()); -} - -/** - * Ensure that multiple queues can be bound using the same routing key - */ -QPID_FIXTURE_TEST_CASE(testXMLBindMultipleQueues, XmlFixture) { - ClientSessionFixture f; - - - f.session.exchangeDeclare(arg::exchange="xml", arg::type="xml"); - f.session.queueDeclare(arg::queue="blue", arg::exclusive=true, arg::autoDelete=true); - f.session.queueDeclare(arg::queue="red", arg::exclusive=true, arg::autoDelete=true); - - FieldTable blue; - blue.setString("xquery", "./colour = 'blue'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="blue", arg::bindingKey="by-colour", arg::arguments=blue); - FieldTable red; - red.setString("xquery", "./colour = 'red'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="red", arg::bindingKey="by-colour", arg::arguments=red); - - Message sent1("blue", "by-colour"); - f.session.messageTransfer(arg::content=sent1, arg::destination="xml"); - - Message sent2("red", "by-colour"); - f.session.messageTransfer(arg::content=sent2, arg::destination="xml"); - - Message received; - BOOST_CHECK(f.subs.get(received, "blue")); - BOOST_CHECK_EQUAL(sent1.getData(), received.getData()); - BOOST_CHECK(f.subs.get(received, "red")); - BOOST_CHECK_EQUAL(sent2.getData(), received.getData()); -} - -//### Test: Bad XML does not kill the server - and does not even -// raise an exception, the content is not required to be XML. - -QPID_FIXTURE_TEST_CASE(testXMLSendBadXML, XmlFixture) { - ClientSessionFixture f; - - f.session.exchangeDeclare(arg::exchange="xml", arg::type="xml"); - f.session.queueDeclare(arg::queue="blue", arg::exclusive=true, arg::autoDelete=true)\ - ; - f.session.queueDeclare(arg::queue="red", arg::exclusive=true, arg::autoDelete=true); - - FieldTable blue; - blue.setString("xquery", "./colour = 'blue'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="blue", arg::bindingKey="by-c\ -olour", arg::arguments=blue); - FieldTable red; - red.setString("xquery", "./colour = 'red'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="red", arg::bindingKey="by-co\ -lour", arg::arguments=red); - - Message sent1("<>colour>blue", "by-colour"); - f.session.messageTransfer(arg::content=sent1, arg::destination="xml"); - - BOOST_CHECK_EQUAL(1, 1); -} - - -//### Test: Bad XQuery does not kill the server, but does raise an exception - -QPID_FIXTURE_TEST_CASE(testXMLBadXQuery, XmlFixture) { - ClientSessionFixture f; - - f.session.exchangeDeclare(arg::exchange="xml", arg::type="xml"); - f.session.queueDeclare(arg::queue="blue", arg::exclusive=true, arg::autoDelete=true)\ - ; - - try { - ScopedSuppressLogging sl; // Supress logging of error messages for expected error. - FieldTable blue; - blue.setString("xquery", "./colour $=! 'blue'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="blue", arg::bindingKey="by-c\ -olour", arg::arguments=blue); - } - catch (const InternalErrorException& e) { - return; - } - BOOST_ERROR("A bad XQuery must raise an exception when used in an XML Binding."); - -} - - -//### Test: double, string, and integer field values can all be bound to queries - -QPID_FIXTURE_TEST_CASE(testXmlBindingUntyped, XmlFixture) { - ClientSessionFixture f; - - SubscriptionManager subscriptions(f.session); - SubscribedLocalQueue localQueue(subscriptions); - - f.session.exchangeDeclare(qpid::client::arg::exchange="xml", qpid::client::arg::type="xml"); - f.session.queueDeclare(qpid::client::arg::queue="odd_blue"); - subscriptions.subscribe(localQueue, "odd_blue"); - - FieldTable binding; - binding.setString("xquery", - "declare variable $s external;" - "declare variable $i external;" - "declare variable $d external;" - "$s = 'string' and $i = 1 and $d < 1"); - f.session.exchangeBind(qpid::client::arg::exchange="xml", qpid::client::arg::queue="odd_blue", qpid::client::arg::bindingKey="query_name", qpid::client::arg::arguments=binding); - - Message message; - message.getDeliveryProperties().setRoutingKey("query_name"); - - message.getHeaders().setString("s", "string"); - message.getHeaders().setInt("i", 1); - message.getHeaders().setDouble("d", 0.5); - string m = "Hi, Mom!"; - message.setData(m); - - f.session.messageTransfer(qpid::client::arg::content=message, qpid::client::arg::destination="xml"); - - Message m2 = localQueue.get(1*qpid::sys::TIME_SEC); - BOOST_CHECK_EQUAL(m, m2.getData()); -} - - -//### Test: double, string, and integer field values can all be bound to queries - -QPID_FIXTURE_TEST_CASE(testXmlBindingTyped, XmlFixture) { - ClientSessionFixture f; - - SubscriptionManager subscriptions(f.session); - SubscribedLocalQueue localQueue(subscriptions); - - f.session.exchangeDeclare(qpid::client::arg::exchange="xml", qpid::client::arg::type="xml"); - f.session.queueDeclare(qpid::client::arg::queue="odd_blue"); - subscriptions.subscribe(localQueue, "odd_blue"); - - FieldTable binding; - binding.setString("xquery", - "declare variable $s as xs:string external;" - "declare variable $i as xs:integer external;" - "declare variable $d external;" // XQilla bug when declaring xs:float, xs:double types? Fine if untyped, acts as float. - "$s = 'string' and $i = 1 and $d < 1"); - f.session.exchangeBind(qpid::client::arg::exchange="xml", qpid::client::arg::queue="odd_blue", qpid::client::arg::bindingKey="query_name", qpid::client::arg::arguments=binding); - - Message message; - message.getDeliveryProperties().setRoutingKey("query_name"); - - message.getHeaders().setString("s", "string"); - message.getHeaders().setInt("i", 1); - message.getHeaders().setDouble("d", 0.5); - string m = "Hi, Mom!"; - message.setData(m); - - f.session.messageTransfer(qpid::client::arg::content=message, qpid::client::arg::destination="xml"); - - Message m2 = localQueue.get(1*qpid::sys::TIME_SEC); - BOOST_CHECK_EQUAL(m, m2.getData()); -} - - -//### Test: Each session can provide its own definition for a query name - - - -//### Test: Bindings persist, surviving broker restart - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/acl.py b/qpid/cpp/src/tests/acl.py deleted file mode 100755 index 2838bd3f83..0000000000 --- a/qpid/cpp/src/tests/acl.py +++ /dev/null @@ -1,3959 +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. -# - -import sys -import qpid -from qpid.util import connect -from qpid.connection import Connection -from qpid.datatypes import uuid4 -from qpid.testlib import TestBase010 -from qmf.console import Session -from qpid.datatypes import Message -import qpid.messaging -from qpidtoollibs import BrokerAgent - -class ACLFile: - def __init__(self, policy='data_dir/policy.acl'): - self.f = open(policy,'w') - - def write(self,line): - self.f.write(line) - - def close(self): - self.f.close() - -class ACLTests(TestBase010): - - # required for testing QMF methods - def get_messaging_connection(self, user, passwd): - parms = {'username':user, 'password':passwd, 'sasl_mechanisms':'PLAIN'} - brokerurl="%s:%s" %(self.broker.host, self.broker.port) - connection = qpid.messaging.Connection(brokerurl, **parms) - connection.open() - return connection - - # For connection limit tests this function - # throws if the connection won't start - # returns a connection that the caller can close if he likes. - def get_connection(self, user, passwd): - socket = connect(self.broker.host, self.broker.port) - connection = Connection (sock=socket, username=user, password=passwd, - mechanism="PLAIN") - connection.start() - return connection - - def get_session(self, user, passwd): - socket = connect(self.broker.host, self.broker.port) - connection = Connection (sock=socket, username=user, password=passwd, - mechanism="PLAIN") - connection.start() - return connection.session(str(uuid4())) - - def port_i(self): - return int(self.defines["port-i"]) - - def port_u(self): - return int(self.defines["port-u"]) - - def port_q(self): - return int(self.defines["port-q"]) - - def get_session_by_port(self, user, passwd, byPort): - socket = connect(self.broker.host, byPort) - connection = Connection (sock=socket, username=user, password=passwd, - mechanism="PLAIN") - connection.start() - return connection.session(str(uuid4())) - - def reload_acl(self): - result = None - try: - self.broker_access.reloadAclFile() - except Exception, e: - result = str(e) - return result - - def acl_lookup(self, userName, action, aclObj, aclObjName, propMap): - result = {} - try: - result = self.broker_access.acl_lookup(userName, action, aclObj, aclObjName, propMap) - except Exception, e: - result['text'] = str(e) - result['result'] = str(e) - return result - - def acl_lookupPublish(self, userName, exchange, key): - result = {} - try: - result = self.broker_access.acl_lookupPublish(userName, exchange, key) - except Exception, e: - result['text'] = str(e) - result['result'] = str(e) - return result - - def get_acl_file(self): - return ACLFile(self.config.defines.get("policy-file", "data_dir/policy.acl")) - - def setUp(self): - aclf = self.get_acl_file() - aclf.write('acl allow all all\n') - aclf.close() - TestBase010.setUp(self) - self.startBrokerAccess() - self.reload_acl() - - def tearDown(self): - aclf = self.get_acl_file() - aclf.write('acl allow all all\n') - aclf.close() - self.reload_acl() - TestBase010.tearDown(self) - - - def Lookup(self, userName, action, aclObj, aclObjName, propMap, expectedResult): - result = self.acl_lookup(userName, action, aclObj, aclObjName, propMap) - if (result['result'] != expectedResult): - suffix = ', [ERROR: Expected= ' + expectedResult - if (result['result'] is None): - suffix = suffix + ', Exception= ' + result['text'] + ']' - else: - suffix = suffix + ', Actual= ' + result['result'] + ']' - self.fail('Lookup: name=' + userName + ', action=' + action + ', aclObj=' + aclObj + ', aclObjName=' + aclObjName + ', propertyMap=' + str(propMap) + suffix) - - - def LookupPublish(self, userName, exchName, keyName, expectedResult): - result = self.acl_lookupPublish(userName, exchName, keyName) - if (result['result'] != expectedResult): - suffix = ', [ERROR: Expected= ' + expectedResult - if (result['result'] is None): - suffix = suffix + ', Exception= ' + result['text'] + ']' - else: - suffix = suffix + ', Actual= ' + result['result'] + ']' - self.fail('LookupPublish: name=' + userName + ', exchange=' + exchName + ', key=' + keyName + suffix) - - def AllBut(self, allList, removeList): - tmpList = allList[:] - for item in removeList: - try: - tmpList.remove(item) - except Exception, e: - self.fail("ERROR in AllBut() \nallList = %s \nremoveList = %s \nerror = %s " \ - % (allList, removeList, e)) - return tmpList - - #===================================== - # ACL general tests - #===================================== - - def test_deny_mode(self): - """ - Test the deny all mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow anonymous all all\n') - aclf.write('acl allow bob@QPID create queue\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - try: - session.queue_declare(queue="deny_queue") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request"); - self.fail("Error during queue create request"); - - try: - session.exchange_bind(exchange="amq.direct", queue="deny_queue", binding_key="routing_key") - self.fail("ACL should deny queue bind request"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - - def test_allow_mode(self): - """ - Test the allow all mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID bind exchange\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - try: - session.queue_declare(queue="allow_queue") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request"); - self.fail("Error during queue create request"); - - try: - session.exchange_bind(exchange="amq.direct", queue="allow_queue", binding_key="routing_key") - self.fail("ACL should deny queue bind request"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - - - def test_allow_mode_with_specfic_allow_override(self): - """ - Specific allow overrides a general deny - """ - aclf = self.get_acl_file() - aclf.write('group admins bob@QPID joe@QPID \n') - aclf.write('acl allow bob@QPID create queue \n') - aclf.write('acl deny admins create queue \n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue='zed') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow create queue request"); - - - #===================================== - # ACL file format tests - #===================================== - - def test_empty_groups(self): - """ - Test empty groups - """ - aclf = self.get_acl_file() - aclf.write('acl group\n') - aclf.write('acl group admins bob@QPID joe@QPID\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.find("Insufficient tokens for acl definition",0,len(result)) == -1): - self.fail("ACL Reader should reject the acl file due to empty group name") - - def test_illegal_acl_formats(self): - """ - Test illegal acl formats - """ - aclf = self.get_acl_file() - aclf.write('acl group admins bob@QPID joe@QPID\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.find("Unknown ACL permission",0,len(result)) == -1): - self.fail(result) - - def test_illegal_extension_lines(self): - """ - Test illegal extension lines - """ - - aclf = self.get_acl_file() - aclf.write('group admins bob@QPID \n') - aclf.write(' \ \n') - aclf.write('joe@QPID \n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.find("contains an illegal extension",0,len(result)) == -1): - self.fail(result) - - if (result.find("Non-continuation line must start with \"group\" or \"acl\"",0,len(result)) == -1): - self.fail(result) - - def test_illegal_extension_lines(self): - """ - Test proper extention lines - """ - aclf = self.get_acl_file() - aclf.write('group test1 joe@EXAMPLE.com \\ \n') # should be allowed - aclf.write(' jack@EXAMPLE.com \\ \n') # should be allowed - aclf.write('jill@TEST.COM \\ \n') # should be allowed - aclf.write('host/123.example.com@TEST.COM\n') # should be allowed - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - def test_nested_groups(self): - """ - Test nested groups - """ - - aclf = self.get_acl_file() - aclf.write('group user-consume martin@QPID ted@QPID\n') - aclf.write('group group2 kim@QPID user-consume rob@QPID \n') - aclf.write('acl allow anonymous all all \n') - aclf.write('acl allow group2 create queue \n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('rob','rob') - try: - session.queue_declare(queue="rob_queue") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request"); - self.fail("Error during queue create request"); - - - - def test_user_realm(self): - """ - Test a user defined without a realm - Ex. group admin rajith - Note: a user name without a realm is interpreted as a group name - """ - aclf = self.get_acl_file() - aclf.write('group admin bob\n') # shouldn't be allowed - aclf.write('acl deny admin bind exchange\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.find("not defined yet.",0,len(result)) == -1): - self.fail(result) - - def test_allowed_chars_for_username(self): - """ - Test a user defined without a realm - Ex. group admin rajith - """ - aclf = self.get_acl_file() - aclf.write('group test1 joe@EXAMPLE.com\n') # should be allowed - aclf.write('group test2 jack_123-jill@EXAMPLE.com\n') # should be allowed - aclf.write('group test4 host/somemachine.example.com@EXAMPLE.COM\n') # should be allowed - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('group test1 joe$H@EXAMPLE.com\n') # shouldn't be allowed - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.find("Username \"joe$H@EXAMPLE.com\" contains illegal characters",0,len(result)) == -1): - self.fail(result) - - #===================================== - # ACL validation tests - #===================================== - - def test_illegal_queue_policy(self): - """ - Test illegal queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ding\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "ding is not a valid value for 'policytype', possible values are one of" - if (result.find(expected) == -1): - self.fail(result) - - def test_illegal_queuemaxsize_upper_limit_spec(self): - """ - Test illegal queue policy - """ - # - # Use maxqueuesize - # - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'queuemaxsizeupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'queuemaxsizeupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - # - # Use queuemaxsizeupperlimit - # - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 queuemaxsizeupperlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'queuemaxsizeupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 queuemaxsizeupperlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'queuemaxsizeupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - - def test_illegal_queuemaxcount_upper_limit_spec(self): - """ - Test illegal queue policy - """ - # - # Use maxqueuecount - # - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'queuemaxcountupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'queuemaxcountupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - # - # use maxqueuecountupperlimit - # - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 queuemaxcountupperlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'queuemaxcountupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 queuemaxcountupperlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'queuemaxcountupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - def test_illegal_queuemaxsize_lower_limit_spec(self): - """ - Test illegal queue policy - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 queuemaxsizelowerlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'queuemaxsizelowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 queuemaxsizelowerlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'queuemaxsizelowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - - def test_illegal_queuemaxcount_lower_limit_spec(self): - """ - Test illegal queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 queuemaxcountlowerlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'queuemaxcountlowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 queuemaxcountlowerlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'queuemaxcountlowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - def test_illegal_filemaxsize_upper_limit_spec(self): - """ - Test illegal file policy - """ - # - # Use filemaxsizeupperlimit - # - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 filemaxsizeupperlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'filemaxsizeupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 filemaxsizeupperlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'filemaxsizeupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - - def test_illegal_filemaxcount_upper_limit_spec(self): - """ - Test illegal file policy - """ - # - # use maxfilecountupperlimit - # - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 filemaxcountupperlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'filemaxcountupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 filemaxcountupperlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'filemaxcountupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - def test_illegal_filemaxsize_lower_limit_spec(self): - """ - Test illegal file policy - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 filemaxsizelowerlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'filemaxsizelowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 filemaxsizelowerlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'filemaxsizelowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - - def test_illegal_filemaxcount_lower_limit_spec(self): - """ - Test illegal file policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 filemaxcountlowerlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'filemaxcountlowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 filemaxcountlowerlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'filemaxcountlowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - def test_illegal_pages_lower_limit_spec(self): - """ - Test illegal paged queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 pageslowerlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'pageslowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 pageslowerlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'pageslowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - def test_illegal_pages_upper_limit_spec(self): - """ - Test illegal paged queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 pagesupperlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'pagesupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 pagesupperlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'pagesupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - def test_illegal_pagefactor_lower_limit_spec(self): - """ - Test illegal paged queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 pagefactorlowerlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'pagefactorlowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 pagefactorlowerlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'pagefactorlowerlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - def test_illegal_pagefactor_upper_limit_spec(self): - """ - Test illegal paged queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 pagefactorupperlimit=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'pagefactorupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 pagefactorupperlimit=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'pagefactorupperlimit', " \ - "values should be between 0 and 9223372036854775807"; - if (result.find(expected) == -1): - self.fail(result) - - - #===================================== - # ACL queue tests - #===================================== - - def test_queue_allow_mode(self): - """ - Test cases for queue acl in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID access queue name=q1\n') - aclf.write('acl deny bob@QPID create queue name=q1 durable=true\n') - aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ring\n') - aclf.write('acl deny bob@QPID access queue name=q3\n') - aclf.write('acl deny bob@QPID delete queue name=q4\n') - aclf.write('acl deny bob@QPID create queue name=q5 maxqueuesize=1000 maxqueuecount=100\n') - aclf.write('acl deny bob@QPID create queue name=q6 paging=true\n') - aclf.write('acl deny bob@QPID purge queue name=q7\n') - aclf.write('acl deny bob@QPID move queue name=q7\n') - aclf.write('acl deny bob@QPID move queue name=q8 queuename=q7\n') - aclf.write('acl deny bob@QPID redirect queue name=q7\n') - aclf.write('acl deny bob@QPID redirect queue name=q8 queuename=q7\n') - aclf.write('acl deny bob@QPID reroute queue name=q7\n') - aclf.write('acl deny bob@QPID reroute queue name=q8 exchangename=amq.fanout\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="q1", durable=True) - self.fail("ACL should deny queue create request with name=q1 durable=true"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="q1", durable=True, passive=True) - self.fail("ACL should deny queue passive declare request with name=q1 durable=true"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.policy_type"] = "ring" - session.queue_declare(queue="q2", exclusive=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=q2 exclusive=true qpid.policy_type=ring"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.policy_type"] = "ring_strict" - session.queue_declare(queue="q2", exclusive=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q2 exclusive=true qpid.policy_type=ring_strict"); - - try: - queue_options = {} - queue_options["qpid.max_count"] = 200 - queue_options["qpid.max_size"] = 500 - session.queue_declare(queue="q5", exclusive=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=q2, qpid.max_size=500 and qpid.max_count=200"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.paging"] = True - session.queue_declare(queue="q6", arguments=queue_options) - self.fail("ACL should deny queue create request with name=q6, qpid.paging=True"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 200 - queue_options["qpid.max_size"] = 100 - session.queue_declare(queue="q2", exclusive=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q2, qpid.max_size=100 and qpid.max_count=200 "); - try: - session.queue_declare(queue="q3", exclusive=True) - session.queue_declare(queue="q4", durable=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request for q3 and q4 with any parameter"); - - try: - session.queue_query(queue="q3") - self.fail("ACL should deny queue query request for q3"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - # some queues needs to be created for testing purge / move / reroute / redirect - session.queue_declare(queue="q7") - session.queue_declare(queue="q8") - session.queue_declare(queue="q9") - try: - session.queue_purge(queue="q7") - self.fail("ACL should deny queue purge request for q7"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_purge(queue="q8") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue purge request for q8"); - - # as we use QMF methods, it is easier to use BrokerAgent from messaging.connection and not use session object as above - broker_agent = BrokerAgent(self.get_messaging_connection('bob','bob')) - - try: - broker_agent.queueMoveMessages("q7", "q8", 0) - self.fail("ACL should deny queue move request from q7 to q8"); - except Exception, e: - self.assertTrue("'error_code': 7" in e.args[0]) - broker_agent = BrokerAgent(self.get_messaging_connection('bob','bob')) - - try: - broker_agent.queueMoveMessages("q8", "q9", 0) - except Exception, e: - if ("'error_code': 7" in e.args[0]): - self.fail("ACL should allow queue move request from q8 to q9"); - - try: - broker_agent.queueMoveMessages("q9", "q8", 0) - except Exception, e: - if ("'error_code': 7" in e.args[0]): - self.fail("ACL should allow queue move request from q9 to q8"); - - try: - broker_agent.Redirect("q7", "q8") - self.fail("ACL should deny queue redirect request from q7 to q8"); - except Exception, e: - self.assertTrue("'error_code': 7" in e.args[0]) - broker_agent = BrokerAgent(self.get_messaging_connection('bob','bob')) - - try: - broker_agent.Redirect("q8", "q9") - except Exception, e: - if ("'error_code': 7" in e.args[0]): - self.fail("ACL should allow queue redirect request from q8 to q9"); - - try: - broker_agent.Redirect("q9", "q8") - except Exception, e: - if ("'error_code': 7" in e.args[0]): - self.fail("ACL should allow queue redirect request from q9 to q8"); - - try: - broker_agent.getQueue('q7').reroute(0, False, "amq.fanout") - self.fail("ACL should deny queue reroute request from q7 to amq.fanout"); - except Exception, e: - self.assertTrue("'error_code': 7" in e.args[0]) - broker_agent = BrokerAgent(self.get_messaging_connection('bob','bob')) - - try: - broker_agent.getQueue('q8').reroute(0, False, "amq.fanout") - self.fail("ACL should deny queue reroute request from q8 to amq.fanout"); - except Exception, e: - self.assertTrue("'error_code': 7" in e.args[0]) - broker_agent = BrokerAgent(self.get_messaging_connection('bob','bob')) - - try: - broker_agent.getQueue('q8').reroute(0, False, "amq.direct") - except Exception, e: - if ("'error_code': 7" in e.args[0]): - self.fail("ACL should allow queue reroute request from q8 to amq.direct"); - - try: - broker_agent.getQueue('q9').reroute(0, False, "amq.fanout") - except Exception, e: - if ("'error_code': 7" in e.args[0]): - self.fail("ACL should allow queue reroute request from q9 to amq.fanout"); - - try: - session.queue_delete(queue="q4") - self.fail("ACL should deny queue delete request for q4"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_delete(queue="q3") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue delete request for q3"); - - - def test_queue_deny_mode(self): - """ - Test cases for queue acl in deny mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID access queue name=q1\n') - aclf.write('acl allow bob@QPID create queue name=q1 durable=true\n') - aclf.write('acl allow bob@QPID create queue name=q2 exclusive=true policytype=ring\n') - aclf.write('acl allow bob@QPID access queue name=q3\n') - aclf.write('acl allow bob@QPID purge queue name=q3\n') - aclf.write('acl allow bob@QPID create queue name=q3\n') - aclf.write('acl allow bob@QPID create queue name=q4\n') - aclf.write('acl allow bob@QPID delete queue name=q4\n') - aclf.write('acl allow bob@QPID create queue name=q5 maxqueuesize=1000 maxqueuecount=100\n') - aclf.write('acl allow bob@QPID create queue name=q6 queuemaxsizelowerlimit=50 queuemaxsizeupperlimit=100 queuemaxcountlowerlimit=50 queuemaxcountupperlimit=100\n') - aclf.write('acl allow bob@QPID create queue name=q7 policytype=self-destruct\n') - aclf.write('acl allow anonymous all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="q1", durable=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q1 durable=true"); - - try: - session.queue_declare(queue="q1", durable=True, passive=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue passive declare request with name=q1 durable=true passive=true"); - - try: - session.queue_declare(queue="q1", durable=False, passive=False) - self.fail("ACL should deny queue create request with name=q1 durable=true passive=false"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="q2", exclusive=False) - self.fail("ACL should deny queue create request with name=q2 exclusive=false"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 200 - queue_options["qpid.max_size"] = 500 - session.queue_declare(queue="q5", arguments=queue_options) - self.fail("ACL should deny queue create request with name=q5 maxqueuesize=500 maxqueuecount=200"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 100 - queue_options["qpid.max_size"] = 500 - session.queue_declare(queue="q5", arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q5 maxqueuesize=500 maxqueuecount=200"); - - try: - queue_options = {} - queue_options["qpid.max_count"] = 49 - queue_options["qpid.max_size"] = 100 - session.queue_declare(queue="q6", arguments=queue_options) - self.fail("ACL should deny queue create request with name=q6 maxqueuesize=100 maxqueuecount=49"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 101 - queue_options["qpid.max_size"] = 100 - session.queue_declare(queue="q6", arguments=queue_options) - self.fail("ACL should allow queue create request with name=q6 maxqueuesize=100 maxqueuecount=101"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 100 - queue_options["qpid.max_size"] = 49 - session.queue_declare(queue="q6", arguments=queue_options) - self.fail("ACL should deny queue create request with name=q6 maxqueuesize=49 maxqueuecount=100"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 100 - queue_options["qpid.max_size"] =101 - session.queue_declare(queue="q6", arguments=queue_options) - self.fail("ACL should deny queue create request with name=q6 maxqueuesize=101 maxqueuecount=100"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 50 - queue_options["qpid.max_size"] = 50 - session.queue_declare(queue="q6", arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q6 maxqueuesize=50 maxqueuecount=50"); - - try: - queue_options = {} - queue_options["qpid.policy_type"] = "ring" - session.queue_declare(queue="q2", exclusive=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request for q2 with exclusive=true policytype=ring"); - - try: - session.queue_declare(queue="q7", arguments={"qpid.policy_type": "ring"}) - self.fail("ACL should not allow queue create request for q7 with policytype=ring"); - except qpid.session.SessionException, e: - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="q7", arguments={"qpid.policy_type": "self-destruct"}) - except qpid.session.SessionException, e: - self.fail("ACL should allow queue create request for q7 with policytype=self-destruct"); - - try: - session.queue_declare(queue="q3") - session.queue_declare(queue="q4") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request for q3 and q4"); - - try: - session.queue_query(queue="q4") - self.fail("ACL should deny queue query request for q4"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_purge(queue="q4") - self.fail("ACL should deny queue purge request for q4"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_purge(queue="q3") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue purge request for q3"); - - try: - session.queue_query(queue="q3") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue query request for q3"); - - try: - session.queue_delete(queue="q3") - self.fail("ACL should deny queue delete request for q3"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_delete(queue="q4") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue delete request for q4"); - - #===================================== - # ACL paged tests - #===================================== - - def test_paged_allow_mode(self): - """ - Test cases for paged acl in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=qf1 pageslowerlimit=1000\n') - aclf.write('acl deny bob@QPID create queue name=qf2 pagesupperlimit=100\n') - aclf.write('acl deny bob@QPID create queue name=qf3 pagefactorlowerlimit=10\n') - aclf.write('acl deny bob@QPID create queue name=qf4 pagefactorupperlimit=1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.paging"] = True - queue_options["qpid.max_pages_loaded"] = 500 - session.queue_declare(queue="qf1", arguments=queue_options) - self.fail("ACL should deny queue create request with name=qf1, qpid.paging=True, qpid.max_pages_loaded=500"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.paging"] = True - queue_options["qpid.max_pages_loaded"] = 500 - session.queue_declare(queue="qf2", arguments=queue_options) - self.fail("ACL should deny queue create request with name=qf2, qpid.paging=True, qpid.max_pages_loaded=500"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.paging"] = True - queue_options["qpid.page_factor"] = 5 - session.queue_declare(queue="qf3", arguments=queue_options) - self.fail("ACL should deny queue create request with name=qf3, qpid.paging=True, qpid.page_factor=5"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.paging"] = True - queue_options["qpid.page_factor"] = 5 - session.queue_declare(queue="qf4", arguments=queue_options) - self.fail("ACL should deny queue create request with name=qf4, qpid.paging=True, qpid.page_factor=5"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - - def test_paged_deny_mode(self): - """ - Test cases for paged acl in deny mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID create queue name=qf1 pageslowerlimit=100 pagesupperlimit=1000\n') - aclf.write('acl allow bob@QPID create queue name=qf2 pagefactorlowerlimit=1 pagefactorupperlimit=10\n') - aclf.write('acl allow anonymous all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.paging"] = True - queue_options["qpid.max_pages_loaded"] = 500 - session.queue_declare(queue="qf1", arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qf1, qpid.paging=True, qpid.max_pages_loaded=500"); - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.paging"] = True - queue_options["qpid.page_factor"] = 5 - session.queue_declare(queue="qf2", arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qf2, qpid.paging=True, qpid.page_factor=5"); - session = self.get_session('bob','bob') - - - #===================================== - # ACL file tests - #===================================== - - def test_file_allow_mode(self): - """ - Test cases for file acl in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID access queue name=qf1\n') - aclf.write('acl deny bob@QPID create queue name=qf1 durable=true\n') - aclf.write('acl deny bob@QPID create queue name=qf2 exclusive=true policytype=ring\n') - aclf.write('acl deny bob@QPID access queue name=qf3\n') - aclf.write('acl deny bob@QPID purge queue name=qf3\n') - aclf.write('acl deny bob@QPID delete queue name=qf4\n') - aclf.write('acl deny bob@QPID create queue name=qf5 filemaxsizeupperlimit=1000 filemaxcountupperlimit=100\n') - aclf.write('acl deny bob@QPID create queue name=ABCDE queuemaxsizelowerlimit=900000 queuemaxsizeupperlimit=1024000 queuemaxcountlowerlimit=900 queuemaxcountupperlimit=2000 filemaxsizelowerlimit=0 filemaxsizeupperlimit=32 filemaxcountlowerlimit=0 filemaxcountupperlimit=4 policytype=ring durable=false autodelete=true\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - self.Lookup("bob@QPID", "create", "queue", "ABCDE", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"0", - "maxfilecount":"0" }, "deny") - - try: - queue_options = {} - queue_options["qpid.file_count"] = 200 - queue_options["qpid.file_size"] = 500 - session.queue_declare(queue="qf5", exclusive=True, durable=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=qf5, qpid.file_size=500 and qpid.file_count=200"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.file_count"] = 200 - queue_options["qpid.file_size"] = 100 - session.queue_declare(queue="qf2", exclusive=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qf2, qpid.file_size=100 and qpid.file_count=200 "); - - - def test_file_deny_mode(self): - """ - Test cases for queue acl in deny mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID access queue name=qfd1\n') - aclf.write('acl allow bob@QPID create queue name=qfd1 durable=true\n') - aclf.write('acl allow bob@QPID create queue name=qfd2 exclusive=true policytype=ring\n') - aclf.write('acl allow bob@QPID access queue name=qfd3\n') - aclf.write('acl allow bob@QPID purge queue name=qfd3\n') - aclf.write('acl allow bob@QPID create queue name=qfd3\n') - aclf.write('acl allow bob@QPID create queue name=qfd4\n') - aclf.write('acl allow bob@QPID delete queue name=qfd4\n') - aclf.write('acl allow bob@QPID create queue name=qfd5 filemaxsizeupperlimit=1000 filemaxcountupperlimit=100\n') - aclf.write('acl allow bob@QPID create queue name=qfd6 filemaxsizelowerlimit=50 filemaxsizeupperlimit=100 filemaxcountlowerlimit=50 filemaxcountupperlimit=100\n') - aclf.write('acl allow bob@QPID create queue name=ABCDE queuemaxsizelowerlimit=900000 queuemaxsizeupperlimit=1024000 queuemaxcountlowerlimit=900 queuemaxcountupperlimit=2000 filemaxsizelowerlimit=0 filemaxsizeupperlimit=32 filemaxcountlowerlimit=0 filemaxcountupperlimit=4 policytype=ring durable=false autodelete=true\n') - aclf.write('acl allow bob@QPID create queue name=FGHIJ queuemaxsizelowerlimit=900000 queuemaxsizeupperlimit=1024000 queuemaxcountlowerlimit=900 queuemaxcountupperlimit=2000 filemaxsizelowerlimit=2 filemaxsizeupperlimit=32 filemaxcountlowerlimit=0 filemaxcountupperlimit=4 policytype=ring durable=false autodelete=true\n') - aclf.write('acl allow bob@QPID create queue name=KLMNO queuemaxsizelowerlimit=900000 queuemaxsizeupperlimit=1024000 queuemaxcountlowerlimit=900 queuemaxcountupperlimit=2000 filemaxsizelowerlimit=0 filemaxsizeupperlimit=0 filemaxcountlowerlimit=0 filemaxcountupperlimit=4 policytype=ring durable=false autodelete=true\n') - aclf.write('acl allow anonymous all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - self.Lookup("bob@QPID", "create", "queue", "ABCDE", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"0", - "maxfilecount":"0" }, "allow") - - self.Lookup("bob@QPID", "create", "queue", "FGHIJ", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"1", - "maxfilecount":"0" }, "deny") - - self.Lookup("bob@QPID", "create", "queue", "FGHIJ", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"2", - "maxfilecount":"0" }, "allow") - - self.Lookup("bob@QPID", "create", "queue", "FGHIJ", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"32", - "maxfilecount":"0" }, "allow") - - self.Lookup("bob@QPID", "create", "queue", "FGHIJ", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"33", - "maxfilecount":"0" }, "deny") - - self.Lookup("bob@QPID", "create", "queue", "KLMNO", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"0", - "maxfilecount":"0" }, "allow") - - self.Lookup("bob@QPID", "create", "queue", "KLMNO", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"17", - "maxfilecount":"0" }, "allow") - - self.Lookup("bob@QPID", "create", "queue", "KLMNO", {"durable":"false", - "autodelete":"true", - "exclusive":"false", - "alternate":"", - "policytype":"ring", - "maxqueuesize":"1024000", - "maxqueuecount":"1000", - "maxfilesize":"33", - "maxfilecount":"0" }, "allow") - - try: - session.queue_declare(queue="qfd1", durable=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qfd1 durable=true"); - - try: - session.queue_declare(queue="qfd1", durable=True, passive=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue passive declare request with name=qfd1 durable=true passive=true"); - - try: - session.queue_declare(queue="qfd1", durable=False, passive=False) - self.fail("ACL should deny queue create request with name=qfd1 durable=true passive=false"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="qfd2", exclusive=False) - self.fail("ACL should deny queue create request with name=qfd2 exclusive=false"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.file_count"] = 200 - queue_options["qpid.file_size"] = 500 - session.queue_declare(queue="qfd5", durable=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=qfd5 filemaxsizeupperlimit=500 filemaxcountupperlimit=200"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.file_count"] = 100 - queue_options["qpid.file_size"] = 500 - session.queue_declare(queue="qfd5", durable=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qfd5 filemaxsizeupperlimit=500 filemaxcountupperlimit=200"); - - try: - queue_options = {} - queue_options["qpid.file_count"] = 49 - queue_options["qpid.file_size"] = 100 - session.queue_declare(queue="qfd6", durable=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=qfd6 filemaxsizeupperlimit=100 filemaxcountupperlimit=49"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.file_count"] = 101 - queue_options["qpid.file_size"] = 100 - session.queue_declare(queue="qfd6", durable=True, arguments=queue_options) - self.fail("ACL should allow queue create request with name=qfd6 filemaxsizeupperlimit=100 filemaxcountupperlimit=101"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.file_count"] = 100 - queue_options["qpid.file_size"] = 49 - session.queue_declare(queue="qfd6", durable=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=qfd6 filemaxsizeupperlimit=49 filemaxcountupperlimit=100"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.file_count"] = 100 - queue_options["qpid.file_size"] =101 - session.queue_declare(queue="qfd6", durable=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=qfd6 filemaxsizeupperlimit=101 filemaxcountupperlimit=100"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.file_count"] = 50 - queue_options["qpid.file_size"] = 50 - session.queue_declare(queue="qfd6", durable=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qfd6 filemaxsizeupperlimit=50 filemaxcountupperlimit=50"); - - - #===================================== - # ACL exchange tests - #===================================== - - def test_exchange_acl_allow_mode(self): - session = self.get_session('bob','bob') - session.queue_declare(queue="baz") - - """ - Test cases for exchange acl in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID access exchange name=testEx\n') - aclf.write('acl deny bob@QPID create exchange name=testEx durable=true\n') - aclf.write('acl deny bob@QPID create exchange name=ex1 type=direct\n') - aclf.write('acl deny bob@QPID access exchange name=myEx queuename=q1 routingkey=rk1.*\n') - aclf.write('acl deny bob@QPID bind exchange name=myEx queuename=q1 routingkey=rk1\n') - aclf.write('acl deny bob@QPID unbind exchange name=myEx queuename=q1 routingkey=rk1\n') - aclf.write('acl deny bob@QPID delete exchange name=myEx\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - session.queue_declare(queue='q1') - session.queue_declare(queue='q2') - session.exchange_declare(exchange='myEx', type='direct') - - try: - session.exchange_declare(exchange='testEx', durable=True) - self.fail("ACL should deny exchange create request with name=testEx durable=true"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='testEx', durable=True, passive=True) - self.fail("ACL should deny passive exchange declare request with name=testEx durable=true passive=true"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='testEx', type='direct', durable=False) - except qpid.session.SessionException, e: - print e - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange create request for testEx with any parameter other than durable=true"); - - try: - session.exchange_declare(exchange='ex1', type='direct') - self.fail("ACL should deny exchange create request with name=ex1 type=direct"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='myXml', type='direct') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange create request for myXml with any parameter"); - - try: - session.exchange_query(name='myEx') - self.fail("ACL should deny exchange query request for myEx"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bound(exchange='myEx', queue='q1', binding_key='rk1.*') - self.fail("ACL should deny exchange bound request for myEx with queuename=q1 and routing_key='rk1.*' "); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_query(name='amq.topic') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange query request for exchange='amq.topic'"); - - try: - session.exchange_bound(exchange='myEx', queue='q1', binding_key='rk2.*') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bound request for myEx with queuename=q1 and binding_key='rk2.*'"); - - try: - session.exchange_bind(exchange='myEx', queue='q1', binding_key='rk1') - self.fail("ACL should deny exchange bind request with exchange='myEx' queuename='q1' bindingkey='rk1'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bind(exchange='myEx', queue='q1', binding_key='x') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bind request for exchange='myEx', queue='q1', binding_key='x'"); - - try: - session.exchange_bind(exchange='myEx', queue='q2', binding_key='rk1') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bind request for exchange='myEx', queue='q2', binding_key='rk1'"); - - try: - session.exchange_unbind(exchange='myEx', queue='q1', binding_key='rk1') - self.fail("ACL should deny exchange unbind request with exchange='myEx' queuename='q1' bindingkey='rk1'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_unbind(exchange='myEx', queue='q1', binding_key='x') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange unbind request for exchange='myEx', queue='q1', binding_key='x'"); - - try: - session.exchange_unbind(exchange='myEx', queue='q2', binding_key='rk1') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange unbind request for exchange='myEx', queue='q2', binding_key='rk1'"); - - try: - session.exchange_delete(exchange='myEx') - self.fail("ACL should deny exchange delete request for myEx"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_delete(exchange='myXml') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange delete request for myXml"); - - - def test_exchange_acl_deny_mode(self): - session = self.get_session('bob','bob') - session.queue_declare(queue='bar') - - """ - Test cases for exchange acl in deny mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID create exchange name=myEx durable=true\n') - aclf.write('acl allow bob@QPID bind exchange name=amq.topic queuename=bar routingkey=foo.*\n') - aclf.write('acl allow bob@QPID unbind exchange name=amq.topic queuename=bar routingkey=foo.*\n') - aclf.write('acl allow bob@QPID access exchange name=myEx queuename=q1 routingkey=rk1.*\n') - aclf.write('acl allow bob@QPID delete exchange name=myEx\n') - aclf.write('acl allow anonymous all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='myEx', type='direct', durable=True, passive=False) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange create request for myEx with durable=true and passive=false"); - - try: - session.exchange_declare(exchange='myEx', type='direct', durable=False) - self.fail("ACL should deny exchange create request with name=myEx durable=false"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bind(exchange='amq.topic', queue='bar', binding_key='foo.bar') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bind request for exchange='amq.topic', queue='bar', binding_key='foor.bar'"); - - try: - session.exchange_bind(exchange='amq.topic', queue='baz', binding_key='foo.bar') - self.fail("ACL should deny exchange bind request for exchange='amq.topic', queue='baz', binding_key='foo.bar'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bind(exchange='amq.topic', queue='bar', binding_key='fooz.bar') - self.fail("ACL should deny exchange bind request for exchange='amq.topic', queue='bar', binding_key='fooz.bar'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_unbind(exchange='amq.topic', queue='bar', binding_key='foo.bar') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange unbind request for exchange='amq.topic', queue='bar', binding_key='foor.bar'"); - try: - session.exchange_unbind(exchange='amq.topic', queue='baz', binding_key='foo.bar') - self.fail("ACL should deny exchange unbind request for exchange='amq.topic', queue='baz', binding_key='foo.bar'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_unbind(exchange='amq.topic', queue='bar', binding_key='fooz.bar') - self.fail("ACL should deny exchange unbind request for exchange='amq.topic', queue='bar', binding_key='fooz.bar'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_query(name='amq.topic') - self.fail("ACL should deny exchange query request for amq.topic"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bound(exchange='myEx', queue='q1', binding_key='rk2.*') - self.fail("ACL should deny exchange bound request for amq.topic with queuename=q1 and routing_key='rk2.*' "); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_query(name='myEx') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange query request for exchange='myEx'"); - - try: - session.exchange_bound(exchange='myEx', queue='q1', binding_key='rk1.*') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bound request for myEx with queuename=q1 and binding_key='rk1.*'"); - - try: - session.exchange_delete(exchange='myEx') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange delete request for myEx"); - - def test_create_and_delete_exchange_via_qmf(self): - """ - Test acl is enforced when creating/deleting via QMF - methods. Note that in order to be able to send the QMF methods - and receive the responses a significant amount of permissions - need to be enabled (TODO: can the set below be narrowed down - at all?) - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID create exchange\n') - aclf.write('acl allow admin@QPID delete exchange\n') - aclf.write('acl allow all access exchange\n') - aclf.write('acl allow all bind exchange\n') - aclf.write('acl allow all create queue\n') - aclf.write('acl allow all access queue\n') - aclf.write('acl allow all delete queue\n') - aclf.write('acl allow all consume queue\n') - aclf.write('acl allow all access method\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - bob = BrokerAdmin(self.config.broker, "bob", "bob") - bob.create_exchange("my-exchange") #should pass - #cleanup by deleting exchange - try: - bob.delete_exchange("my-exchange") #should fail - self.fail("ACL should deny exchange delete request for my-exchange"); - except Exception, e: - self.assertEqual(7,e.args[0]["error_code"]) - assert e.args[0]["error_text"].find("unauthorized-access") == 0 - admin = BrokerAdmin(self.config.broker, "admin", "admin") - admin.delete_exchange("my-exchange") #should pass - - anonymous = BrokerAdmin(self.config.broker) - try: - anonymous.create_exchange("another-exchange") #should fail - self.fail("ACL should deny exchange create request for another-exchange"); - except Exception, e: - self.assertEqual(7,e.args[0]["error_code"]) - assert e.args[0]["error_text"].find("unauthorized-access") == 0 - - def test_qmf_query(self): - aclf = self.get_acl_file() - aclf.write('acl allow all access exchange\n') - aclf.write('acl allow all bind exchange\n') - aclf.write('acl allow all create queue\n') - aclf.write('acl allow all access queue\n') - aclf.write('acl allow all delete queue\n') - aclf.write('acl allow all consume queue\n') - aclf.write('acl allow all access method\n') - aclf.write('acl allow bob@QPID access query name=org.apache.qpid.broker:queue:q1\n') - aclf.write('acl allow bob@QPID access query schemaclass=exchange\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - bob = BrokerAdmin(self.config.broker, "bob", "bob") - - try: - bob.query(object_name="org.apache.qpid.broker:queue:q1") - except Exception, e: - if ("unauthorized-access:" in e.args[0]): - self.fail("ACL should allow queue QMF query for q1"); - - try: - bob.query(object_name="org.apache.qpid.broker:queue:q2") - self.fail("ACL should deny queue QMF query for q2"); - except Exception, e: - self.assertTrue("unauthorized-access:" in e.args[0]) - bob = BrokerAdmin(self.config.broker, "bob", "bob") - - try: - bob.query(class_name="binding") - self.fail("ACL should deny class binding QMF query"); - except Exception, e: - self.assertTrue("unauthorized-access:" in e.args[0]) - bob = BrokerAdmin(self.config.broker, "bob", "bob") - - try: - bob.query(class_name="exchange") - except Exception, e: - if ("unauthorized-access:" in e.args[0]): - self.fail("ACL should allow class exchange QMF query"); - - - #===================================== - # ACL consume tests - #===================================== - - def test_consume_allow_mode(self): - """ - Test cases for consume in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID consume queue name=q1\n') - aclf.write('acl deny bob@QPID consume queue name=q2\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - - try: - session.queue_declare(queue='q1') - session.queue_declare(queue='q2') - session.queue_declare(queue='q3') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow create queue request"); - - try: - session.message_subscribe(queue='q1', destination='myq1') - self.fail("ACL should deny subscription for queue='q1'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_subscribe(queue='q2', destination='myq1') - self.fail("ACL should deny subscription for queue='q2'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_subscribe(queue='q3', destination='myq3') - session.message_cancel(destination='myq3') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow subscription for q3"); - - - def test_consume_deny_mode(self): - """ - Test cases for consume in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID consume queue name=q1\n') - aclf.write('acl allow bob@QPID consume queue name=q2\n') - aclf.write('acl allow bob@QPID create queue\n') - aclf.write('acl allow anonymous all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - - try: - session.queue_declare(queue='q1') - session.queue_declare(queue='q2') - session.queue_declare(queue='q3') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow create queue request"); - - try: - session.message_subscribe(queue='q1', destination='myq1') - session.message_subscribe(queue='q2', destination='myq2') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow subscription for q1 and q2"); - - try: - session.message_subscribe(queue='q3', destination='myq3') - self.fail("ACL should deny subscription for queue='q3'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - - #===================================== - # ACL publish tests - #===================================== - - def test_publish_acl_allow_mode(self): - """ - Test various publish acl - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID publish exchange name=amq.direct routingkey=rk1\n') - aclf.write('acl deny bob@QPID publish exchange name=amq.topic\n') - aclf.write('acl deny bob@QPID publish exchange name=myEx routingkey=rk2\n') - aclf.write("acl deny bob@QPID publish exchange name=amq.default routingkey=restricted\n") - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - props = session.delivery_properties(routing_key="rk1") - - try: - session.message_transfer(destination="amq.direct", message=Message(props,"Test")) - self.fail("ACL should deny message transfer to name=amq.direct routingkey=rk1"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_transfer(destination="amq.topic", message=Message(props,"Test")) - self.fail("ACL should deny message transfer to name=amq.topic"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='myEx', type='direct', durable=False) - session.message_transfer(destination="myEx", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange myEx with routing key rk1"); - - - props = session.delivery_properties(routing_key="rk2") - try: - session.message_transfer(destination="amq.direct", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk2"); - - self.LookupPublish("bob@QPID", "", "restricted", "deny") - self.LookupPublish("bob@QPID", "", "another", "allow") - self.LookupPublish("joe@QPID", "", "restricted", "allow") - - - def test_publish_acl_deny_mode(self): - """ - Test various publish acl - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID publish exchange name=amq.direct routingkey=rk1\n') - aclf.write('acl allow bob@QPID publish exchange name=amq.topic\n') - aclf.write('acl allow bob@QPID publish exchange name=myEx routingkey=rk2\n') - aclf.write('acl allow bob@QPID create exchange\n') - aclf.write("acl allow bob@QPID publish exchange name=amq.default routingkey=unrestricted\n") - aclf.write('acl allow anonymous all all \n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - props = session.delivery_properties(routing_key="rk2") - - try: - session.message_transfer(destination="amq.direct", message=Message(props,"Test")) - self.fail("ACL should deny message transfer to name=amq.direct routingkey=rk2"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_transfer(destination="amq.topic", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange amq.topic with any routing key"); - - try: - session.exchange_declare(exchange='myEx', type='direct', durable=False) - session.message_transfer(destination="myEx", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange myEx with routing key=rk2"); - - props = session.delivery_properties(routing_key="rk1") - - try: - session.message_transfer(destination="myEx", message=Message(props,"Test")) - self.fail("ACL should deny message transfer to name=myEx routingkey=rk1"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_transfer(destination="amq.direct", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk1"); - - self.LookupPublish("bob@QPID", "", "unrestricted", "allow") - self.LookupPublish("bob@QPID", "", "another", "deny") - self.LookupPublish("joe@QPID", "", "unrestricted", "deny") - - - #===================================== - # ACL broker configuration tests - #===================================== - - def test_broker_timestamp_config(self): - """ - Test ACL control of the broker timestamp configuration - """ - aclf = self.get_acl_file() - # enable lots of stuff to allow QMF to work - aclf.write('acl allow all create exchange\n') - aclf.write('acl allow all access exchange\n') - aclf.write('acl allow all bind exchange\n') - aclf.write('acl allow all publish exchange\n') - aclf.write('acl allow all create queue\n') - aclf.write('acl allow all access queue\n') - aclf.write('acl allow all delete queue\n') - aclf.write('acl allow all consume queue\n') - aclf.write('acl allow all access method\n') - # this should let bob access the timestamp configuration - aclf.write('acl allow bob@QPID access broker\n') - aclf.write('acl allow bob@QPID update broker\n') - aclf.write('acl allow admin@QPID all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - ts = None - bob = BrokerAdmin(self.config.broker, "bob", "bob") - ts = bob.get_timestamp_cfg() #should work - bob.set_timestamp_cfg(ts); #should work - - obo = BrokerAdmin(self.config.broker, "obo", "obo") - try: - ts = obo.get_timestamp_cfg() #should fail - failed = False - except Exception, e: - failed = True - self.assertEqual(7,e.args[0]["error_code"]) - assert e.args[0]["error_text"].find("unauthorized-access") == 0 - assert(failed) - - try: - obo.set_timestamp_cfg(ts) #should fail - failed = False - except Exception, e: - failed = True - self.assertEqual(7,e.args[0]["error_code"]) - assert e.args[0]["error_text"].find("unauthorized-access") == 0 - assert(failed) - - admin = BrokerAdmin(self.config.broker, "admin", "admin") - ts = admin.get_timestamp_cfg() #should pass - admin.set_timestamp_cfg(ts) #should pass - - - - #===================================== - # QMF Functional tests - #===================================== - - def test_qmf_functional_tests(self): - """ - Test using QMF method hooks into ACL logic - """ - aclf = self.get_acl_file() - aclf.write('group admins moe@COMPANY.COM \\\n') - aclf.write(' larry@COMPANY.COM \\\n') - aclf.write(' curly@COMPANY.COM \\\n') - aclf.write(' shemp@COMPANY.COM\n') - aclf.write('group auditors aaudit@COMPANY.COM baudit@COMPANY.COM caudit@COMPANY.COM \\\n') - aclf.write(' daudit@COMPANY.COM eaduit@COMPANY.COM eaudit@COMPANY.COM\n') - aclf.write('group tatunghosts tatung01@COMPANY.COM \\\n') - aclf.write(' tatung02/x86.build.company.com@COMPANY.COM \\\n') - aclf.write(' tatung03/x86.build.company.com@COMPANY.COM \\\n') - aclf.write(' tatung04/x86.build.company.com@COMPANY.COM \n') - aclf.write('group publishusers publish@COMPANY.COM x-pubs@COMPANY.COM\n') - aclf.write('acl allow-log admins all all\n') - aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n') - aclf.write('acl allow-log anonymous create queue\n') - aclf.write('acl allow-log anonymous all exchange name=qmf.*\n') - aclf.write('acl allow-log anonymous all exchange name=amq.direct\n') - aclf.write('acl allow-log anonymous all exchange name=qpid.management\n') - aclf.write('acl allow-log anonymous access method name=*\n') - aclf.write('# end hack alert\n') - aclf.write('acl allow-log auditors all exchange name=company.topic routingkey=private.audit.*\n') - aclf.write('acl allow-log tatunghosts publish exchange name=company.topic routingkey=tatung.*\n') - aclf.write('acl allow-log tatunghosts publish exchange name=company.direct routingkey=tatung-service-queue\n') - aclf.write('acl allow-log publishusers create queue\n') - aclf.write('acl allow-log publishusers publish exchange name=qpid.management routingkey=broker\n') - aclf.write('acl allow-log publishusers publish exchange name=qmf.default.topic routingkey=*\n') - aclf.write('acl allow-log publishusers publish exchange name=qmf.default.direct routingkey=*\n') - aclf.write('acl allow-log all bind exchange name=company.topic routingkey=tatung.*\n') - aclf.write('acl allow-log all bind exchange name=company.direct routingkey=tatung-service-queue\n') - aclf.write('acl allow-log all consume queue\n') - aclf.write('acl allow-log all access exchange\n') - aclf.write('acl allow-log all access queue\n') - aclf.write('acl allow-log all create queue name=tmp.* durable=false autodelete=true exclusive=true policytype=ring\n') - aclf.write('acl allow mrQ create queue queuemaxsizelowerlimit=100 queuemaxsizeupperlimit=200 queuemaxcountlowerlimit=300 queuemaxcountupperlimit=400\n') - aclf.write('acl deny-log all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # - # define some group lists - # - g_admins = ['moe@COMPANY.COM', \ - 'larry@COMPANY.COM', \ - 'curly@COMPANY.COM', \ - 'shemp@COMPANY.COM'] - - g_auditors = [ 'aaudit@COMPANY.COM','baudit@COMPANY.COM','caudit@COMPANY.COM', \ - 'daudit@COMPANY.COM','eaduit@COMPANY.COM','eaudit@COMPANY.COM'] - - g_tatunghosts = ['tatung01@COMPANY.COM', \ - 'tatung02/x86.build.company.com@COMPANY.COM', \ - 'tatung03/x86.build.company.com@COMPANY.COM', \ - 'tatung04/x86.build.company.com@COMPANY.COM'] - - g_publishusers = ['publish@COMPANY.COM', 'x-pubs@COMPANY.COM'] - - g_public = ['jpublic@COMPANY.COM', 'me@yahoo.com'] - - g_all = g_admins + g_auditors + g_tatunghosts + g_publishusers + g_public - - action_all = ['consume','publish','create','access','bind','unbind','delete','purge','update'] - - # - # Run some tests verifying against users who are in and who are out of given groups. - # - - for u in g_admins: - self.Lookup(u, "create", "queue", "anything", {"durable":"true"}, "allow-log") - uInTest = g_auditors + g_admins - uOutTest = self.AllBut(g_all, uInTest) - - for u in uInTest: - self.LookupPublish(u, "company.topic", "private.audit.This", "allow-log") - - for u in uInTest: - for a in ['bind', 'unbind', 'access', 'publish']: - self.Lookup(u, a, "exchange", "company.topic", {"routingkey":"private.audit.This"}, "allow-log") - - for u in uOutTest: - self.LookupPublish(u, "company.topic", "private.audit.This", "deny-log") - self.Lookup(u, "bind", "exchange", "company.topic", {"routingkey":"private.audit.This"}, "deny-log") - - uInTest = g_admins + g_tatunghosts - uOutTest = self.AllBut(g_all, uInTest) - - for u in uInTest: - self.LookupPublish(u, "company.topic", "tatung.this2", "allow-log") - self.LookupPublish(u, "company.direct", "tatung-service-queue", "allow-log") - - for u in uOutTest: - self.LookupPublish(u, "company.topic", "tatung.this2", "deny-log") - self.LookupPublish(u, "company.direct", "tatung-service-queue", "deny-log") - - for u in uOutTest: - for a in ["bind", "access"]: - self.Lookup(u, a, "exchange", "company.topic", {"routingkey":"tatung.this2"}, "allow-log") - self.Lookup(u, a, "exchange", "company.direct", {"routingkey":"tatung-service-queue"}, "allow-log") - - uInTest = g_admins + g_publishusers - uOutTest = self.AllBut(g_all, uInTest) - - for u in uInTest: - self.LookupPublish(u, "qpid.management", "broker", "allow-log") - self.LookupPublish(u, "qmf.default.topic", "this3", "allow-log") - self.LookupPublish(u, "qmf.default.direct", "this4", "allow-log") - - for u in uOutTest: - self.LookupPublish(u, "qpid.management", "broker", "deny-log") - self.LookupPublish(u, "qmf.default.topic", "this3", "deny-log") - self.LookupPublish(u, "qmf.default.direct", "this4", "deny-log") - - for u in uOutTest: - for a in ["bind"]: - self.Lookup(u, a, "exchange", "qpid.management", {"routingkey":"broker"}, "deny-log") - self.Lookup(u, a, "exchange", "qmf.default.topic", {"routingkey":"this3"}, "deny-log") - self.Lookup(u, a, "exchange", "qmf.default.direct", {"routingkey":"this4"}, "deny-log") - for a in ["access"]: - self.Lookup(u, a, "exchange", "qpid.management", {"routingkey":"broker"}, "allow-log") - self.Lookup(u, a, "exchange", "qmf.default.topic", {"routingkey":"this3"}, "allow-log") - self.Lookup(u, a, "exchange", "qmf.default.direct", {"routingkey":"this4"}, "allow-log") - - # Test against queue size limits - - self.Lookup('mrQ', 'create', 'queue', 'abc', {"maxqueuesize":"150", "maxqueuecount":"350"}, "allow") - self.Lookup('mrQ', 'create', 'queue', 'def', {"maxqueuesize":"99", "maxqueuecount":"350"}, "deny") - self.Lookup('mrQ', 'create', 'queue', 'uvw', {"maxqueuesize":"201", "maxqueuecount":"350"}, "deny") - self.Lookup('mrQ', 'create', 'queue', 'xyz', {"maxqueuesize":"150", "maxqueuecount":"299"}, "deny") - self.Lookup('mrQ', 'create', 'queue', '', {"maxqueuesize":"150", "maxqueuecount":"401"}, "deny") - self.Lookup('mrQ', 'create', 'queue', '', {"maxqueuesize":"0", "maxqueuecount":"401"}, "deny") - self.Lookup('mrQ', 'create', 'queue', '', {"maxqueuesize":"150", "maxqueuecount":"0" }, "deny") - - - #===================================== - # Routingkey lookup using Topic Exchange tests - #===================================== - - def test_topic_exchange_publish_tests(self): - """ - Test using QMF method hooks into ACL logic - """ - aclf = self.get_acl_file() - aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n') - aclf.write('acl allow-log anonymous create queue\n') - aclf.write('acl allow-log anonymous all exchange name=qmf.*\n') - aclf.write('acl allow-log anonymous all exchange name=amq.direct\n') - aclf.write('acl allow-log anonymous all exchange name=qpid.management\n') - aclf.write('acl allow-log anonymous access method name=*\n') - aclf.write('# end hack alert\n') - aclf.write('acl allow-log uPlain1@COMPANY publish exchange name=X routingkey=ab.cd.e\n') - aclf.write('acl allow-log uPlain2@COMPANY publish exchange name=X routingkey=.\n') - aclf.write('acl allow-log uStar1@COMPANY publish exchange name=X routingkey=a.*.b\n') - aclf.write('acl allow-log uStar2@COMPANY publish exchange name=X routingkey=*.x\n') - aclf.write('acl allow-log uStar3@COMPANY publish exchange name=X routingkey=x.x.*\n') - aclf.write('acl allow-log uHash1@COMPANY publish exchange name=X routingkey=a.#.b\n') - aclf.write('acl allow-log uHash2@COMPANY publish exchange name=X routingkey=a.#\n') - aclf.write('acl allow-log uHash3@COMPANY publish exchange name=X routingkey=#.a\n') - aclf.write('acl allow-log uHash4@COMPANY publish exchange name=X routingkey=a.#.b.#.c\n') - aclf.write('acl allow-log uMixed1@COMPANY publish exchange name=X routingkey=*.x.#.y\n') - aclf.write('acl allow-log uMixed2@COMPANY publish exchange name=X routingkey=a.#.b.*\n') - aclf.write('acl allow-log uMixed3@COMPANY publish exchange name=X routingkey=*.*.*.#\n') - - aclf.write('acl allow-log all publish exchange name=X routingkey=MN.OP.Q\n') - aclf.write('acl allow-log all publish exchange name=X routingkey=M.*.N\n') - aclf.write('acl allow-log all publish exchange name=X routingkey=M.#.N\n') - aclf.write('acl allow-log all publish exchange name=X routingkey=*.M.#.N\n') - - aclf.write('acl deny-log all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # aclKey: "ab.cd.e" - self.LookupPublish("uPlain1@COMPANY", "X", "ab.cd.e", "allow-log") - self.LookupPublish("uPlain1@COMPANY", "X", "abx.cd.e", "deny-log") - self.LookupPublish("uPlain1@COMPANY", "X", "ab.cd", "deny-log") - self.LookupPublish("uPlain1@COMPANY", "X", "ab.cd..e.", "deny-log") - self.LookupPublish("uPlain1@COMPANY", "X", "ab.cd.e.", "deny-log") - self.LookupPublish("uPlain1@COMPANY", "X", ".ab.cd.e", "deny-log") - # aclKey: "." - self.LookupPublish("uPlain2@COMPANY", "X", ".", "allow-log") - - # aclKey: "a.*.b" - self.LookupPublish("uStar1@COMPANY", "X", "a.xx.b", "allow-log") - self.LookupPublish("uStar1@COMPANY", "X", "a.b", "deny-log") - # aclKey: "*.x" - self.LookupPublish("uStar2@COMPANY", "X", "y.x", "allow-log") - self.LookupPublish("uStar2@COMPANY", "X", ".x", "allow-log") - self.LookupPublish("uStar2@COMPANY", "X", "x", "deny-log") - # aclKey: "x.x.*" - self.LookupPublish("uStar3@COMPANY", "X", "x.x.y", "allow-log") - self.LookupPublish("uStar3@COMPANY", "X", "x.x.", "allow-log") - self.LookupPublish("uStar3@COMPANY", "X", "x.x", "deny-log") - self.LookupPublish("uStar3@COMPANY", "X", "q.x.y", "deny-log") - - # aclKey: "a.#.b" - self.LookupPublish("uHash1@COMPANY", "X", "a.b", "allow-log") - self.LookupPublish("uHash1@COMPANY", "X", "a.x.b", "allow-log") - self.LookupPublish("uHash1@COMPANY", "X", "a..x.y.zz.b", "allow-log") - self.LookupPublish("uHash1@COMPANY", "X", "a.b.", "deny-log") - self.LookupPublish("uHash1@COMPANY", "X", "q.x.b", "deny-log") - - # aclKey: "a.#" - self.LookupPublish("uHash2@COMPANY", "X", "a", "allow-log") - self.LookupPublish("uHash2@COMPANY", "X", "a.b", "allow-log") - self.LookupPublish("uHash2@COMPANY", "X", "a.b.c", "allow-log") - - # aclKey: "#.a" - self.LookupPublish("uHash3@COMPANY", "X", "a", "allow-log") - self.LookupPublish("uHash3@COMPANY", "X", "x.y.a", "allow-log") - - # aclKey: "a.#.b.#.c" - self.LookupPublish("uHash4@COMPANY", "X", "a.b.c", "allow-log") - self.LookupPublish("uHash4@COMPANY", "X", "a.x.b.y.c", "allow-log") - self.LookupPublish("uHash4@COMPANY", "X", "a.x.x.b.y.y.c", "allow-log") - - # aclKey: "*.x.#.y" - self.LookupPublish("uMixed1@COMPANY", "X", "a.x.y", "allow-log") - self.LookupPublish("uMixed1@COMPANY", "X", "a.x.p.qq.y", "allow-log") - self.LookupPublish("uMixed1@COMPANY", "X", "a.a.x.y", "deny-log") - self.LookupPublish("uMixed1@COMPANY", "X", "aa.x.b.c", "deny-log") - - # aclKey: "a.#.b.*" - self.LookupPublish("uMixed2@COMPANY", "X", "a.b.x", "allow-log") - self.LookupPublish("uMixed2@COMPANY", "X", "a.x.x.x.b.x", "allow-log") - - # aclKey: "*.*.*.#" - self.LookupPublish("uMixed3@COMPANY", "X", "x.y.z", "allow-log") - self.LookupPublish("uMixed3@COMPANY", "X", "x.y.z.a.b.c", "allow-log") - self.LookupPublish("uMixed3@COMPANY", "X", "x.y", "deny-log") - self.LookupPublish("uMixed3@COMPANY", "X", "x", "deny-log") - - # Repeat the keys with wildcard user spec - self.LookupPublish("uPlain1@COMPANY", "X", "MN.OP.Q", "allow-log") - self.LookupPublish("uStar1@COMPANY" , "X", "M.xx.N", "allow-log") - self.LookupPublish("uHash1@COMPANY" , "X", "M.N", "allow-log") - self.LookupPublish("uHash1@COMPANY" , "X", "M.x.N", "allow-log") - self.LookupPublish("uHash1@COMPANY" , "X", "M..x.y.zz.N", "allow-log") - self.LookupPublish("uMixed1@COMPANY", "X", "a.M.N", "allow-log") - self.LookupPublish("uMixed1@COMPANY", "X", "a.M.p.qq.N", "allow-log") - - self.LookupPublish("dev@QPID", "X", "MN.OP.Q", "allow-log") - self.LookupPublish("dev@QPID", "X", "M.xx.N", "allow-log") - self.LookupPublish("dev@QPID", "X", "M.N", "allow-log") - self.LookupPublish("dev@QPID", "X", "M.x.N", "allow-log") - self.LookupPublish("dev@QPID", "X", "M..x.y.zz.N", "allow-log") - self.LookupPublish("dev@QPID", "X", "a.M.N", "allow-log") - self.LookupPublish("dev@QPID", "X", "a.M.p.qq.N", "allow-log") - - def test_topic_exchange_other_tests(self): - """ - Test using QMF method hooks into ACL logic - """ - action_list = ['access','bind','unbind'] - - aclf = self.get_acl_file() - aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n') - aclf.write('acl allow-log anonymous create queue\n') - aclf.write('acl allow-log anonymous all exchange name=qmf.*\n') - aclf.write('acl allow-log anonymous all exchange name=amq.direct\n') - aclf.write('acl allow-log anonymous all exchange name=qpid.management\n') - aclf.write('acl allow-log anonymous access method name=*\n') - aclf.write('# end hack alert\n') - for action in action_list: - aclf.write('acl allow-log uPlain1@COMPANY ' + action + ' exchange name=X routingkey=ab.cd.e\n') - aclf.write('acl allow-log uPlain2@COMPANY ' + action + ' exchange name=X routingkey=.\n') - aclf.write('acl allow-log uStar1@COMPANY ' + action + ' exchange name=X routingkey=a.*.b\n') - aclf.write('acl allow-log uStar2@COMPANY ' + action + ' exchange name=X routingkey=*.x\n') - aclf.write('acl allow-log uStar3@COMPANY ' + action + ' exchange name=X routingkey=x.x.*\n') - aclf.write('acl allow-log uHash1@COMPANY ' + action + ' exchange name=X routingkey=a.#.b\n') - aclf.write('acl allow-log uHash2@COMPANY ' + action + ' exchange name=X routingkey=a.#\n') - aclf.write('acl allow-log uHash3@COMPANY ' + action + ' exchange name=X routingkey=#.a\n') - aclf.write('acl allow-log uHash4@COMPANY ' + action + ' exchange name=X routingkey=a.#.b.#.c\n') - aclf.write('acl allow-log uMixed1@COMPANY ' + action + ' exchange name=X routingkey=*.x.#.y\n') - aclf.write('acl allow-log uMixed2@COMPANY ' + action + ' exchange name=X routingkey=a.#.b.*\n') - aclf.write('acl allow-log uMixed3@COMPANY ' + action + ' exchange name=X routingkey=*.*.*.#\n') - - aclf.write('acl allow-log all ' + action + ' exchange name=X routingkey=MN.OP.Q\n') - aclf.write('acl allow-log all ' + action + ' exchange name=X routingkey=M.*.N\n') - aclf.write('acl allow-log all ' + action + ' exchange name=X routingkey=M.#.N\n') - aclf.write('acl allow-log all ' + action + ' exchange name=X routingkey=*.M.#.N\n') - - aclf.write('acl deny-log all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - for action in action_list: - # aclKey: "ab.cd.e" - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":"ab.cd.e"}, "allow-log") - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":"ab.cd.e"}, "allow-log") - - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":"ab.cd.e"}, "allow-log") - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":"abx.cd.e"}, "deny-log") - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":"ab.cd"}, "deny-log") - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":"ab.cd..e."}, "deny-log") - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":"ab.cd.e."}, "deny-log") - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":".ab.cd.e"}, "deny-log") - # aclKey: "." - self.Lookup("uPlain2@COMPANY", action, "exchange", "X", {"routingkey":"."}, "allow-log") - - # aclKey: "a.*.b" - self.Lookup("uStar1@COMPANY", action, "exchange", "X", {"routingkey":"a.xx.b"}, "allow-log") - self.Lookup("uStar1@COMPANY", action, "exchange", "X", {"routingkey":"a.b"}, "deny-log") - # aclKey: "*.x" - self.Lookup("uStar2@COMPANY", action, "exchange", "X", {"routingkey":"y.x"}, "allow-log") - self.Lookup("uStar2@COMPANY", action, "exchange", "X", {"routingkey":".x"}, "allow-log") - self.Lookup("uStar2@COMPANY", action, "exchange", "X", {"routingkey":"x"}, "deny-log") - # aclKey: "x.x.*" - self.Lookup("uStar3@COMPANY", action, "exchange", "X", {"routingkey":"x.x.y"}, "allow-log") - self.Lookup("uStar3@COMPANY", action, "exchange", "X", {"routingkey":"x.x."}, "allow-log") - self.Lookup("uStar3@COMPANY", action, "exchange", "X", {"routingkey":"x.x"}, "deny-log") - self.Lookup("uStar3@COMPANY", action, "exchange", "X", {"routingkey":"q.x.y"}, "deny-log") - - # aclKey: "a.#.b" - self.Lookup("uHash1@COMPANY", action, "exchange", "X", {"routingkey":"a.b"}, "allow-log") - self.Lookup("uHash1@COMPANY", action, "exchange", "X", {"routingkey":"a.x.b"}, "allow-log") - self.Lookup("uHash1@COMPANY", action, "exchange", "X", {"routingkey":"a..x.y.zz.b"}, "allow-log") - self.Lookup("uHash1@COMPANY", action, "exchange", "X", {"routingkey":"a.b."}, "deny-log") - self.Lookup("uHash1@COMPANY", action, "exchange", "X", {"routingkey":"q.x.b"}, "deny-log") - - # aclKey: "a.#" - self.Lookup("uHash2@COMPANY", action, "exchange", "X", {"routingkey":"a"}, "allow-log") - self.Lookup("uHash2@COMPANY", action, "exchange", "X", {"routingkey":"a.b"}, "allow-log") - self.Lookup("uHash2@COMPANY", action, "exchange", "X", {"routingkey":"a.b.c"}, "allow-log") - - # aclKey: "#.a" - self.Lookup("uHash3@COMPANY", action, "exchange", "X", {"routingkey":"a"}, "allow-log") - self.Lookup("uHash3@COMPANY", action, "exchange", "X", {"routingkey":"x.y.a"}, "allow-log") - - # aclKey: "a.#.b.#.c" - self.Lookup("uHash4@COMPANY", action, "exchange", "X", {"routingkey":"a.b.c"}, "allow-log") - self.Lookup("uHash4@COMPANY", action, "exchange", "X", {"routingkey":"a.x.b.y.c"}, "allow-log") - self.Lookup("uHash4@COMPANY", action, "exchange", "X", {"routingkey":"a.x.x.b.y.y.c"}, "allow-log") - - # aclKey: "*.x.#.y" - self.Lookup("uMixed1@COMPANY", action, "exchange", "X", {"routingkey":"a.x.y"}, "allow-log") - self.Lookup("uMixed1@COMPANY", action, "exchange", "X", {"routingkey":"a.x.p.qq.y"}, "allow-log") - self.Lookup("uMixed1@COMPANY", action, "exchange", "X", {"routingkey":"a.a.x.y"}, "deny-log") - self.Lookup("uMixed1@COMPANY", action, "exchange", "X", {"routingkey":"aa.x.b.c"}, "deny-log") - - # aclKey: "a.#.b.*" - self.Lookup("uMixed2@COMPANY", action, "exchange", "X", {"routingkey":"a.b.x"}, "allow-log") - self.Lookup("uMixed2@COMPANY", action, "exchange", "X", {"routingkey":"a.x.x.x.b.x"}, "allow-log") - - # aclKey: "*.*.*.#" - self.Lookup("uMixed3@COMPANY", action, "exchange", "X", {"routingkey":"x.y.z"}, "allow-log") - self.Lookup("uMixed3@COMPANY", action, "exchange", "X", {"routingkey":"x.y.z.a.b.c"}, "allow-log") - self.Lookup("uMixed3@COMPANY", action, "exchange", "X", {"routingkey":"x.y"}, "deny-log") - self.Lookup("uMixed3@COMPANY", action, "exchange", "X", {"routingkey":"x"}, "deny-log") - - # Repeat the keys with wildcard user spec - self.Lookup("uPlain1@COMPANY", action, "exchange", "X", {"routingkey":"MN.OP.Q"}, "allow-log") - self.Lookup("uStar1@COMPANY" , action, "exchange", "X", {"routingkey":"M.xx.N"}, "allow-log") - self.Lookup("uHash1@COMPANY" , action, "exchange", "X", {"routingkey":"M.N"}, "allow-log") - self.Lookup("uHash1@COMPANY" , action, "exchange", "X", {"routingkey":"M.x.N"}, "allow-log") - self.Lookup("uHash1@COMPANY" , action, "exchange", "X", {"routingkey":"M..x.y.zz.N"}, "allow-log") - self.Lookup("uMixed1@COMPANY", action, "exchange", "X", {"routingkey":"a.M.N"}, "allow-log") - self.Lookup("uMixed1@COMPANY", action, "exchange", "X", {"routingkey":"a.M.p.qq.N"}, "allow-log") - - self.Lookup("dev@QPID", action, "exchange", "X", {"routingkey": "MN.OP.Q"}, "allow-log") - self.Lookup("dev@QPID", action, "exchange", "X", {"routingkey": "M.xx.N"}, "allow-log") - self.Lookup("dev@QPID", action, "exchange", "X", {"routingkey": "M.N"}, "allow-log") - self.Lookup("dev@QPID", action, "exchange", "X", {"routingkey": "M.x.N"}, "allow-log") - self.Lookup("dev@QPID", action, "exchange", "X", {"routingkey": "M..x.y.zz.N"}, "allow-log") - self.Lookup("dev@QPID", action, "exchange", "X", {"routingkey": "a.M.N"}, "allow-log") - self.Lookup("dev@QPID", action, "exchange", "X", {"routingkey": "a.M.p.qq.N"}, "allow-log") - - #===================================== - # Connection limits - #===================================== - - def test_connection_limits_cli_sets_all(self): - - try: - sessiona1 = self.get_session_by_port('alice','alice', self.port_u()) - sessiona2 = self.get_session_by_port('alice','alice', self.port_u()) - except Exception, e: - self.fail("Could not create two connections for user alice: " + str(e)) - - # Third session should fail - try: - sessiona3 = self.get_session_by_port('alice','alice', self.port_u()) - self.fail("Should not be able to create third connection for user alice") - except Exception, e: - result = None - - - - def test_connection_limits_by_named_user(self): - """ - Test ACL control connection limits - """ - aclf = self.get_acl_file() - aclf.write('quota connections 2 aliceCL@QPID bobCL@QPID\n') - aclf.write('quota connections 0 evildude@QPID\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # By username should be able to connect twice per user - try: - conna1 = self.get_connection('aliceCL','aliceCL') - conna2 = self.get_connection('aliceCL','aliceCL') - except Exception, e: - self.fail("Could not create two connections for user aliceCL: " + str(e)) - - # Third session should fail - try: - conna3 = self.get_connection('aliceCL','aliceCL') - self.fail("Should not be able to create third connection for user aliceCL") - except Exception, e: - result = None - - # Disconnecting should allow another session. - conna1.close() - try: - conna3 = self.get_connection('aliceCL','aliceCL') - except Exception, e: - self.fail("Could not recreate second connection for user aliceCL: " + str(e)) - - # By username should be able to connect twice per user - try: - connb1 = self.get_connection('bobCL','bobCL') - connb2 = self.get_connection('bobCL','bobCL') - except Exception, e: - self.fail("Could not create two connections for user bobCL: " + str(e)) - - # Third session should fail - try: - connb3 = self.get_connection('bobCL','bobCL') - self.fail("Should not be able to create third connection for user bobCL") - except Exception, e: - result = None - - - # User with quota of 0 is denied - try: - conne1 = self.get_connection('evildude','evildude') - self.fail("Should not be able to create a connection for user evildude") - except Exception, e: - result = None - - - # User not named in quotas is denied - try: - connc1 = self.get_connection('charlie','charlie') - self.fail("Should not be able to create a connection for user charlie") - except Exception, e: - result = None - - # Clean up the connections - conna2.close() - conna3.close() - connb1.close() - connb2.close() - - - - def test_connection_limits_by_unnamed_all(self): - """ - Test ACL control connection limits - """ - aclf = self.get_acl_file() - aclf.write('quota connections 2 aliceUA@QPID bobUA@QPID\n') - aclf.write('quota connections 1 all\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # By username should be able to connect twice per user - try: - connectiona1 = self.get_connection('aliceUA','alice') - connectiona2 = self.get_connection('aliceUA','alice') - except Exception, e: - self.fail("Could not create two connections for user alice: " + str(e)) - - # Third connection should fail - try: - connectiona3 = self.get_connection('aliceUA','alice') - self.fail("Should not be able to create third connection for user alice") - except Exception, e: - result = None - - # By username should be able to connect twice per user - try: - connectionb1 = self.get_connection('bobUA','bob') - connectionb2 = self.get_connection('bobUA','bob') - except Exception, e: - self.fail("Could not create two connections for user bob: " + str(e)) - - # Third connection should fail - try: - connectionb3 = self.get_connection('bobUA','bob') - self.fail("Should not be able to create third connection for user bob") - except Exception, e: - result = None - - # User not named in quotas gets 'all' quota - try: - connectionc1 = self.get_connection('charlieUA','charlie') - except Exception, e: - self.fail("Could not create one connection for user charlie: " + str(e)) - - # Next connection should fail - try: - connectionc2 = self.get_connection('charlieUA','charlie') - self.fail("Should not be able to create second connection for user charlie") - except Exception, e: - result = None - - # Clean up the connections - connectiona1.close() - connectiona2.close() - connectionb1.close() - connectionb2.close() - connectionc1.close() - - - def test_connection_limits_by_group(self): - """ - Test ACL control connection limits - """ - aclf = self.get_acl_file() - aclf.write('group stooges moeGR@QPID larryGR@QPID curlyGR@QPID\n') - aclf.write('quota connections 2 aliceGR@QPID bobGR@QPID\n') - aclf.write('quota connections 2 stooges charlieGR@QPID\n') - aclf.write('# user and groups may be overwritten. Should use last value\n') - aclf.write('quota connections 3 bobGR@QPID stooges\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # Alice gets 2 - try: - connectiona1 = self.get_connection('aliceGR','alice') - connectiona2 = self.get_connection('aliceGR','alice') - except Exception, e: - self.fail("Could not create two connections for user alice: " + str(e)) - - # Third connection should fail - try: - connectiona3 = self.get_connection('aliceGR','alice') - self.fail("Should not be able to create third connection for user alice") - except Exception, e: - result = None - - # Bob gets 3 - try: - connectionb1 = self.get_connection('bobGR','bob') - connectionb2 = self.get_connection('bobGR','bob') - connectionb3 = self.get_connection('bobGR','bob') - except Exception, e: - self.fail("Could not create three connections for user bob: " + str(e)) - - # Fourth connection should fail - try: - connectionb4 = self.get_connection('bobGR','bob') - self.fail("Should not be able to create fourth connection for user bob") - except Exception, e: - result = None - - # Moe gets 3 - try: - connectionm1 = self.get_connection('moeGR','moe') - connectionm2 = self.get_connection('moeGR','moe') - connectionm3 = self.get_connection('moeGR','moe') - except Exception, e: - self.fail("Could not create three connections for user moe: " + str(e)) - - # Fourth connection should fail - try: - connectionb4 = self.get_connection('moeGR','moe') - self.fail("Should not be able to create fourth connection for user ,pe") - except Exception, e: - result = None - - # User not named in quotas is denied - try: - connections1 = self.get_connection('shempGR','shemp') - self.fail("Should not be able to create a connection for user shemp") - except Exception, e: - result = None - - # Clean up the connections - connectiona1.close() - connectiona2.close() - connectionb1.close() - connectionb2.close() - connectionb3.close() - connectionm1.close() - connectionm2.close() - connectionm3.close() - - - def test_connection_limits_by_ip_address(self): - """ - Test ACL control connection limits by ip address - """ - # By IP address should be able to connect twice per client address - try: - sessionb1 = self.get_session_by_port('alice','alice', self.port_i()) - sessionb2 = self.get_session_by_port('bob','bob', self.port_i()) - except Exception, e: - self.fail("Could not create two connections for client address: " + str(e)) - - # Third session should fail - try: - sessionb3 = self.get_session_by_port('charlie','charlie', self.port_i()) - self.fail("Should not be able to create third connection for client address") - except Exception, e: - result = None - - sessionb1.close() - sessionb2.close() - - #===================================== - # User name substitution - #===================================== - - def test_user_name_substitution(self): - """ - Test name substitution internals, limits, and edge cases. - """ - aclf = self.get_acl_file() - aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n') - aclf.write('acl allow-log anonymous create queue\n') - aclf.write('acl allow-log anonymous all exchange name=qmf.*\n') - aclf.write('acl allow-log anonymous all exchange name=amq.direct\n') - aclf.write('acl allow-log anonymous all exchange name=qpid.management\n') - aclf.write('acl allow-log anonymous access method name=*\n') - aclf.write('# end hack alert\n') - aclf.write('acl allow all create queue name=tmp-${userdomain}\n') - aclf.write('acl allow all create queue name=${userdomain}-tmp\n') - aclf.write('acl allow all create queue name=tmp-${userdomain}-tmp\n') - aclf.write('acl allow all create queue name=tmp-${userdomain}-tmp-${userdomain}\n') - aclf.write('acl allow all create queue name=temp0-${userdomain}\n') - aclf.write('acl allow all access queue name=temp0-${userdomain}\n') - aclf.write('acl allow all purge queue name=temp0-${userdomain}\n') - aclf.write('acl allow all consume queue name=temp0-${userdomain}\n') - aclf.write('acl allow all delete queue name=temp0-${userdomain}\n') - aclf.write('acl allow all create exchange name=temp0-${userdomain}\n') - aclf.write('acl allow all access exchange name=temp0-${userdomain}\n') - aclf.write('acl allow all bind exchange name=temp0-${userdomain}\n') - aclf.write('acl allow all unbind exchange name=temp0-${userdomain}\n') - aclf.write('acl allow all delete exchange name=temp0-${userdomain}\n') - aclf.write('acl allow all publish exchange name=temp0-${userdomain}\n') - - aclf.write('acl allow all publish exchange name=X routingkey=${userdomain}.cd.e\n') - aclf.write('acl allow all publish exchange name=X routingkey=a.*.${userdomain}\n') - aclf.write('acl allow all publish exchange name=X routingkey=b.#.${userdomain}\n') - aclf.write('acl allow all publish exchange name=X routingkey=*.${userdomain}.#.y\n') - - aclf.write('acl allow all create queue name=user-${user}\n') - aclf.write('acl allow all publish exchange name=U routingkey=${user}.cd.e\n') - aclf.write('acl allow all publish exchange name=U routingkey=a.*.${user}\n') - aclf.write('acl allow all publish exchange name=U routingkey=b.#.${user}\n') - aclf.write('acl allow all publish exchange name=U routingkey=*.${user}.#.y\n') - - aclf.write('acl allow all create queue name=domain-${domain}\n') - aclf.write('acl allow all publish exchange name=D routingkey=${domain}.cd.e\n') - aclf.write('acl allow all publish exchange name=D routingkey=a.*.${domain}\n') - aclf.write('acl allow all publish exchange name=D routingkey=b.#.${domain}\n') - aclf.write('acl allow all publish exchange name=D routingkey=*.${domain}.#.y\n') - - # Resolving ${user}_${domain} into ${userdomain} works for everything but routing keys - aclf.write('acl allow all create queue name=mixed-OK-${user}_${domain}\n') - # For routing keys ${user}_${domain} will be parsed into ${userdomain}. - # Routing keys not be found when the rule specifies ${user}_${domain}. - aclf.write('acl allow all publish exchange name=NOGO routingkey=${user}_${domain}.cd.e\n') - # This works since it is does not conflict with ${userdomain} - aclf.write('acl allow all publish exchange name=OK routingkey=${user}___${domain}.cd.e\n') - - aclf.write('acl deny-log all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - self.Lookup("alice@QPID", "create", "queue", "tmp-alice_QPID", {}, "allow") - self.Lookup("bob@QPID", "create", "queue", "bob_QPID-tmp", {}, "allow") - self.Lookup("charlie@QPID", "create", "queue", "tmp-charlie_QPID-tmp", {}, "allow") - self.Lookup("dave@QPID", "create", "queue", "tmp-dave_QPID-tmp-dave_QPID", {}, "allow") - self.Lookup("ed@BIG.COM", "create", "queue", "tmp-ed_BIG_COM", {}, "allow") - self.Lookup("c.e.r@BIG.GER.COM", "create", "queue", "tmp-c_e_r_BIG_GER_COM", {}, "allow") - self.Lookup("c@", "create", "queue", "tmp-c_", {}, "allow") - self.Lookup("someuser", "create", "queue", "tmp-someuser", {}, "allow") - - self.Lookup("alice@QPID", "create", "queue", "tmp-${user}", {}, "deny-log") - - self.Lookup("bob@QPID", "create", "exchange", "temp0-bob_QPID", {}, "allow") - self.Lookup("bob@QPID", "access", "exchange", "temp0-bob_QPID", {}, "allow") - self.Lookup("bob@QPID", "bind", "exchange", "temp0-bob_QPID", {}, "allow") - self.Lookup("bob@QPID", "unbind", "exchange", "temp0-bob_QPID", {}, "allow") - self.Lookup("bob@QPID", "delete", "exchange", "temp0-bob_QPID", {}, "allow") - self.LookupPublish("bob@QPID", "temp0-bob_QPID", "x", "allow") - - self.Lookup("bob@QPID", "create", "queue", "temp0-bob_QPID", {}, "allow") - self.Lookup("bob@QPID", "access", "queue", "temp0-bob_QPID", {}, "allow") - self.Lookup("bob@QPID", "purge", "queue", "temp0-bob_QPID", {}, "allow") - self.Lookup("bob@QPID", "consume", "queue", "temp0-bob_QPID", {}, "allow") - self.Lookup("bob@QPID", "delete", "queue", "temp0-bob_QPID", {}, "allow") - - self.Lookup("alice@QPID", "access", "queue", "temp0-bob_QPID", {}, "deny-log") - - # aclKey: "${userdomain}.cd.e" - self.LookupPublish("uPlain1@COMPANY", "X", "uPlain1_COMPANY.cd.e", "allow") - # aclKey: "a.*.${userdomain}" - self.LookupPublish("uStar1@COMPANY", "X", "a.xx.uStar1_COMPANY", "allow") - self.LookupPublish("uStar1@COMPANY", "X", "a.b", "deny-log") - # aclKey: "b.#.${userdomain}" - self.LookupPublish("uHash1@COMPANY", "X", "b.uHash1_COMPANY", "allow") - self.LookupPublish("uHash1@COMPANY", "X", "b.x.uHash1_COMPANY", "allow") - self.LookupPublish("uHash1@COMPANY", "X", "b..x.y.zz.uHash1_COMPANY", "allow") - self.LookupPublish("uHash1@COMPANY", "X", "b.uHash1_COMPANY.", "deny-log") - self.LookupPublish("uHash1@COMPANY", "X", "q.x.uHash1_COMPANY", "deny-log") - # aclKey: "*.${userdomain}.#.y" - self.LookupPublish("uMixed1@COMPANY", "X", "a.uMixed1_COMPANY.y", "allow") - self.LookupPublish("uMixed1@COMPANY", "X", "a.uMixed1_COMPANY.p.qq.y", "allow") - self.LookupPublish("uMixed1@COMPANY", "X", "a.a.uMixed1_COMPANY.y", "deny-log") - self.LookupPublish("uMixed1@COMPANY", "X", "aa.uMixed1_COMPANY.b.c", "deny-log") - self.LookupPublish("uMixed1@COMPANY.COM", "X", "a.uMixed1_COMPANY_COM.y", "allow") - - - self.Lookup("bob@QPID", "create", "queue", "user-bob", {}, "allow") - # aclKey: "${user}.cd.e" - self.LookupPublish("uPlain1@COMPANY", "U", "uPlain1.cd.e", "allow") - # aclKey: "a.*.${user}" - self.LookupPublish("uStar1@COMPANY", "U", "a.xx.uStar1", "allow") - self.LookupPublish("uStar1@COMPANY", "U", "a.b", "deny-log") - # aclKey: "b.#.${user}" - self.LookupPublish("uHash1@COMPANY", "U", "b.uHash1", "allow") - self.LookupPublish("uHash1@COMPANY", "U", "b.x.uHash1", "allow") - self.LookupPublish("uHash1@COMPANY", "U", "b..x.y.zz.uHash1", "allow") - self.LookupPublish("uHash1@COMPANY", "U", "b.uHash1.", "deny-log") - self.LookupPublish("uHash1@COMPANY", "U", "q.x.uHash1", "deny-log") - # aclKey: "*.${user}.#.y" - self.LookupPublish("uMixed1@COMPANY", "U", "a.uMixed1.y", "allow") - self.LookupPublish("uMixed1@COMPANY", "U", "a.uMixed1.p.qq.y", "allow") - self.LookupPublish("uMixed1@COMPANY", "U", "a.a.uMixed1.y", "deny-log") - self.LookupPublish("uMixed1@COMPANY", "U", "aa.uMixed1.b.c", "deny-log") - self.LookupPublish("uMixed1@COMPANY.COM", "U", "a.uMixed1.y", "allow") - - - self.Lookup("bob@QPID", "create", "queue", "domain-QPID", {}, "allow") - # aclKey: "${domain}.cd.e" - self.LookupPublish("uPlain1@COMPANY", "D", "COMPANY.cd.e", "allow") - # aclKey: "a.*.${domain}" - self.LookupPublish("uStar1@COMPANY", "D", "a.xx.COMPANY", "allow") - self.LookupPublish("uStar1@COMPANY", "D", "a.b", "deny-log") - # aclKey: "b.#.${domain}" - self.LookupPublish("uHash1@COMPANY", "D", "b.COMPANY", "allow") - self.LookupPublish("uHash1@COMPANY", "D", "b.x.COMPANY", "allow") - self.LookupPublish("uHash1@COMPANY", "D", "b..x.y.zz.COMPANY", "allow") - self.LookupPublish("uHash1@COMPANY", "D", "b.COMPANY.", "deny-log") - self.LookupPublish("uHash1@COMPANY", "D", "q.x.COMPANY", "deny-log") - # aclKey: "*.${domain}.#.y" - self.LookupPublish("uMixed1@COMPANY", "D", "a.COMPANY.y", "allow") - self.LookupPublish("uMixed1@COMPANY", "D", "a.COMPANY.p.qq.y", "allow") - self.LookupPublish("uMixed1@COMPANY", "D", "a.a.COMPANY.y", "deny-log") - self.LookupPublish("uMixed1@COMPANY", "D", "aa.COMPANY.b.c", "deny-log") - self.LookupPublish("uMixed1@COMPANY.COM", "D", "a.COMPANY_COM.y", "allow") - - self.Lookup("uPlain1@COMPANY", "create", "queue", "mixed-OK-uPlain1_COMPANY", {}, "allow") - self.LookupPublish("uPlain1@COMPANY", "NOGO", "uPlain1_COMPANY.cd.e", "deny-log") - self.LookupPublish("uPlain1@COMPANY", "OK", "uPlain1___COMPANY.cd.e", "allow") - - - #===================================== - # User name substitution details - #===================================== - # User name substitution allows for three flavors of keyword in the Acl file. - # Given a user name of bob.user@QPID.COM the keywords are normalized and resolve as follows: - # ${userdomain} - bob_user_QPID_COM - # ${user} - bob_user - # ${domain} - QPID_COM - # - # The following substitution tests are very similar but differ in the flavor of keyword used - # in the rules. The tests results using the different keywords differ slightly in how permissive - # the rules become. - # ${userdomain} limits access to one authenticated user - # ${user} limits access to a user name regardless of user's domain - # ${domain} limits access to a domain regardless of user name - # - - def test_user_name_substitution_userdomain(self): - """ - Test a setup where users can create, bind, and publish to a main exchange and queue. - Allow access to a single alternate exchange and queue. - """ - aclf = self.get_acl_file() - aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n') - aclf.write('acl allow-log anonymous create queue\n') - aclf.write('acl allow-log anonymous all exchange name=qmf.*\n') - aclf.write('acl allow-log anonymous all exchange name=amq.direct\n') - aclf.write('acl allow-log anonymous all exchange name=qpid.management\n') - aclf.write('acl allow-log anonymous access method name=*\n') - aclf.write('# end hack alert\n') - # Create primary queue and exchange: - # allow predefined alternate - # deny any other alternate - # allow no alternate - aclf.write('acl allow all create queue name=${userdomain}-work alternate=${userdomain}-work2\n') - aclf.write('acl deny all create queue name=${userdomain}-work alternate=*\n') - aclf.write('acl allow all create queue name=${userdomain}-work\n') - aclf.write('acl allow all create exchange name=${userdomain}-work alternate=${userdomain}-work2\n') - aclf.write('acl deny all create exchange name=${userdomain}-work alternate=*\n') - aclf.write('acl allow all create exchange name=${userdomain}-work\n') - # Create backup queue and exchange - # Deny any alternate - aclf.write('acl deny all create queue name=${userdomain}-work2 alternate=*\n') - aclf.write('acl allow all create queue name=${userdomain}-work2\n') - aclf.write('acl deny all create exchange name=${userdomain}-work2 alternate=*\n') - aclf.write('acl allow all create exchange name=${userdomain}-work2\n') - # Bind/unbind primary exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all bind exchange name=${userdomain}-work routingkey=${userdomain} queuename=${userdomain}-work\n') - aclf.write('acl allow all unbind exchange name=${userdomain}-work routingkey=${userdomain} queuename=${userdomain}-work\n') - # Bind/unbind backup exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all bind exchange name=${userdomain}-work2 routingkey=${userdomain} queuename=${userdomain}-work2\n') - aclf.write('acl allow all unbind exchange name=${userdomain}-work2 routingkey=${userdomain} queuename=${userdomain}-work2\n') - # Access primary exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all access exchange name=${userdomain}-work routingkey=${userdomain} queuename=${userdomain}-work\n') - # Access backup exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all access exchange name=${userdomain}-work2 routingkey=${userdomain} queuename=${userdomain}-work2\n') - # Publish primary exchange - # Use only predefined routingkey - aclf.write('acl allow all publish exchange name=${userdomain}-work routingkey=${userdomain}\n') - # Publish backup exchange - # Use only predefined routingkey - aclf.write('acl allow all publish exchange name=${userdomain}-work2 routingkey=${userdomain}\n') - # deny mode - aclf.write('acl deny all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # create queues - self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work", {}, "allow") - self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work2", {}, "allow") - self.Lookup("bob@QPID", "create", "queue", "joe_QPID-work", {}, "deny") - self.Lookup("bob@QPID", "create", "queue", "joe_QPID-work2", {}, "deny") - self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work3", {}, "deny") - self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work", {"alternate":"bob_QPID-work2"}, "allow") - self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work", {"alternate":"joe_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work2", {"alternate":"someexchange"}, "deny") - # create exchanges - self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work", {}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work2",{}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "joe_QPID-work", {}, "deny") - self.Lookup("bob@QPID", "create", "exchange", "joe_QPID-work2",{}, "deny") - self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work3",{}, "deny") - self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work", {"alternate":"bob_QPID-work2"}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work2",{"alternate":"someexchange"}, "deny") - # bind/unbind/access - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", { "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "allow") - self.Lookup("bob@QPID", "bind", "exchange", "joe_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work"}, "deny") - - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", { "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "allow") - self.Lookup("bob@QPID", "bind", "exchange", "joe_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work2"}, "deny") - - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", { "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "allow") - self.Lookup("bob@QPID", "unbind", "exchange", "joe_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work"}, "deny") - - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", { "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "allow") - self.Lookup("bob@QPID", "unbind", "exchange", "joe_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work2"}, "deny") - - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", { "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "allow") - self.Lookup("bob@QPID", "access", "exchange", "joe_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work"}, "deny") - - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", { "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "allow") - self.Lookup("bob@QPID", "access", "exchange", "joe_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work2"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work2"}, "deny") - # publish - self.LookupPublish("bob@QPID", "bob_QPID-work", "bob_QPID", "allow") - self.LookupPublish("bob@QPID", "bob_QPID-work2", "bob_QPID", "allow") - self.LookupPublish("bob@QPID", "joe_QPID-work", "bob_QPID", "deny") - self.LookupPublish("bob@QPID", "joe_QPID-work2", "bob_QPID", "deny") - self.LookupPublish("bob@QPID", "bob_QPID-work", "joe_QPID", "deny") - self.LookupPublish("bob@QPID", "bob_QPID-work2", "joe_QPID", "deny") - - - def test_user_name_substitution_user(self): - """ - Test a setup where users can create, bind, and publish to a main exchange and queue. - Allow access to a single backup exchange and queue. - """ - aclf = self.get_acl_file() - aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n') - aclf.write('acl allow-log anonymous create queue\n') - aclf.write('acl allow-log anonymous all exchange name=qmf.*\n') - aclf.write('acl allow-log anonymous all exchange name=amq.direct\n') - aclf.write('acl allow-log anonymous all exchange name=qpid.management\n') - aclf.write('acl allow-log anonymous access method name=*\n') - aclf.write('# end hack alert\n') - # Create primary queue and exchange - # allow predefined alternate - # deny any other alternate - # allow no alternate - aclf.write('acl allow all create queue name=${user}-work alternate=${user}-work2\n') - aclf.write('acl deny all create queue name=${user}-work alternate=*\n') - aclf.write('acl allow all create queue name=${user}-work\n') - aclf.write('acl allow all create exchange name=${user}-work alternate=${user}-work2\n') - aclf.write('acl deny all create exchange name=${user}-work alternate=*\n') - aclf.write('acl allow all create exchange name=${user}-work\n') - # Create backup queue and exchange - # Deny any alternate - aclf.write('acl deny all create queue name=${user}-work2 alternate=*\n') - aclf.write('acl allow all create queue name=${user}-work2\n') - aclf.write('acl deny all create exchange name=${user}-work2 alternate=*\n') - aclf.write('acl allow all create exchange name=${user}-work2\n') - # Bind/unbind primary exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all bind exchange name=${user}-work routingkey=${user} queuename=${user}-work\n') - aclf.write('acl allow all unbind exchange name=${user}-work routingkey=${user} queuename=${user}-work\n') - # Bind/unbind backup exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all bind exchange name=${user}-work2 routingkey=${user} queuename=${user}-work2\n') - aclf.write('acl allow all unbind exchange name=${user}-work2 routingkey=${user} queuename=${user}-work2\n') - # Access primary exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all access exchange name=${user}-work routingkey=${user} queuename=${user}-work\n') - # Access backup exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all access exchange name=${user}-work2 routingkey=${user} queuename=${user}-work2\n') - # Publish primary exchange - # Use only predefined routingkey - aclf.write('acl allow all publish exchange name=${user}-work routingkey=${user}\n') - # Publish backup exchange - # Use only predefined routingkey - aclf.write('acl allow all publish exchange name=${user}-work2 routingkey=${user}\n') - # deny mode - aclf.write('acl deny all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # create queues - self.Lookup("bob@QPID", "create", "queue", "bob-work", {}, "allow") - self.Lookup("bob@QPID", "create", "queue", "bob-work2", {}, "allow") - self.Lookup("bob@QPID", "create", "queue", "joe-work", {}, "deny") - self.Lookup("bob@QPID", "create", "queue", "joe-work2", {}, "deny") - self.Lookup("bob@QPID", "create", "queue", "bob-work3", {}, "deny") - self.Lookup("bob@QPID", "create", "queue", "bob-work", {"alternate":"bob-work2"}, "allow") - self.Lookup("bob@QPID", "create", "queue", "bob-work", {"alternate":"joe-work2"}, "deny") - self.Lookup("bob@QPID", "create", "queue", "bob-work2", {"alternate":"someexchange"},"deny") - # create exchanges - self.Lookup("bob@QPID", "create", "exchange", "bob-work", {}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "bob-work2",{}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "joe-work", {}, "deny") - self.Lookup("bob@QPID", "create", "exchange", "joe-work2",{}, "deny") - self.Lookup("bob@QPID", "create", "exchange", "bob-work3",{}, "deny") - self.Lookup("bob@QPID", "create", "exchange", "bob-work", {"alternate":"bob-work2"}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "bob-work2",{"alternate":"someexchange"},"deny") - # bind/unbind/access - self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {"routingkey":"bob"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work", { "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {"routingkey":"bob", "queuename":"bob-work"}, "allow") - self.Lookup("bob@QPID", "bind", "exchange", "joe-work", {"routingkey":"bob", "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {"routingkey":"joe", "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {"routingkey":"bob", "queuename":"joe-work"}, "deny") - - self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {"routingkey":"bob"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", { "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "allow") - self.Lookup("bob@QPID", "bind", "exchange", "joe-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {"routingkey":"joe", "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"joe-work2"}, "deny") - - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {"routingkey":"bob"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", { "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {"routingkey":"bob", "queuename":"bob-work"}, "allow") - self.Lookup("bob@QPID", "unbind", "exchange", "joe-work", {"routingkey":"bob", "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {"routingkey":"joe", "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {"routingkey":"bob", "queuename":"joe-work"}, "deny") - - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {"routingkey":"bob"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", { "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "allow") - self.Lookup("bob@QPID", "unbind", "exchange", "joe-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {"routingkey":"joe", "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"joe-work2"}, "deny") - - self.Lookup("bob@QPID", "access", "exchange", "bob-work", {}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work", {"routingkey":"bob"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work", { "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work", {"routingkey":"bob", "queuename":"bob-work"}, "allow") - self.Lookup("bob@QPID", "access", "exchange", "joe-work", {"routingkey":"bob", "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work", {"routingkey":"joe", "queuename":"bob-work"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work", {"routingkey":"bob", "queuename":"joe-work"}, "deny") - - self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {"routingkey":"bob"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work2", { "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "allow") - self.Lookup("bob@QPID", "access", "exchange", "joe-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {"routingkey":"joe", "queuename":"bob-work2"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"joe-work2"}, "deny") - # publish - self.LookupPublish("bob@QPID", "bob-work", "bob", "allow") - self.LookupPublish("bob@QPID", "bob-work2", "bob", "allow") - self.LookupPublish("bob@QPID", "joe-work", "bob", "deny") - self.LookupPublish("bob@QPID", "joe-work2", "bob", "deny") - self.LookupPublish("bob@QPID", "bob-work", "joe", "deny") - self.LookupPublish("bob@QPID", "bob-work2", "joe", "deny") - - - def test_user_name_substitution_domain(self): - """ - Test a setup where users can create, bind, and publish to a main exchange and queue. - Allow access to a single backup exchange and queue. - """ - aclf = self.get_acl_file() - aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n') - aclf.write('acl allow-log anonymous create queue\n') - aclf.write('acl allow-log anonymous all exchange name=qmf.*\n') - aclf.write('acl allow-log anonymous all exchange name=amq.direct\n') - aclf.write('acl allow-log anonymous all exchange name=qpid.management\n') - aclf.write('acl allow-log anonymous access method name=*\n') - aclf.write('# end hack alert\n') - # Create primary queue and exchange - # allow predefined alternate - # deny any other alternate - # allow no alternate - aclf.write('acl allow all create queue name=${domain}-work alternate=${domain}-work2\n') - aclf.write('acl deny all create queue name=${domain}-work alternate=*\n') - aclf.write('acl allow all create queue name=${domain}-work\n') - aclf.write('acl allow all create exchange name=${domain}-work alternate=${domain}-work2\n') - aclf.write('acl deny all create exchange name=${domain}-work alternate=*\n') - aclf.write('acl allow all create exchange name=${domain}-work\n') - # Create backup queue and exchange - # Deny any alternate - aclf.write('acl deny all create queue name=${domain}-work2 alternate=*\n') - aclf.write('acl allow all create queue name=${domain}-work2\n') - aclf.write('acl deny all create exchange name=${domain}-work2 alternate=*\n') - aclf.write('acl allow all create exchange name=${domain}-work2\n') - # Bind/unbind primary exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all bind exchange name=${domain}-work routingkey=${domain} queuename=${domain}-work\n') - aclf.write('acl allow all unbind exchange name=${domain}-work routingkey=${domain} queuename=${domain}-work\n') - # Bind/unbind backup exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all bind exchange name=${domain}-work2 routingkey=${domain} queuename=${domain}-work2\n') - aclf.write('acl allow all unbind exchange name=${domain}-work2 routingkey=${domain} queuename=${domain}-work2\n') - # Access primary exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all access exchange name=${domain}-work routingkey=${domain} queuename=${domain}-work\n') - # Access backup exchange - # Use only predefined routingkey and queuename - aclf.write('acl allow all access exchange name=${domain}-work2 routingkey=${domain} queuename=${domain}-work2\n') - # Publish primary exchange - # Use only predefined routingkey - aclf.write('acl allow all publish exchange name=${domain}-work routingkey=${domain}\n') - # Publish backup exchange - # Use only predefined routingkey - aclf.write('acl allow all publish exchange name=${domain}-work2 routingkey=${domain}\n') - # deny mode - aclf.write('acl deny all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # create queues - self.Lookup("bob@QPID", "create", "queue", "QPID-work", {}, "allow") - self.Lookup("bob@QPID", "create", "queue", "QPID-work2", {}, "allow") - self.Lookup("bob@QPID", "create", "queue", "QPID-work3", {}, "deny") - self.Lookup("bob@QPID", "create", "queue", "QPID-work", {"alternate":"QPID-work2"}, "allow") - self.Lookup("bob@QPID", "create", "queue", "QPID-work", {"alternate":"bob_QPID-work2"},"deny") - self.Lookup("bob@QPID", "create", "queue", "QPID-work", {"alternate":"joe_QPID-work2"},"deny") - self.Lookup("bob@QPID", "create", "queue", "QPID-work2", {"alternate":"someexchange"}, "deny") - # create exchanges - self.Lookup("bob@QPID", "create", "exchange", "QPID-work", {}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "QPID-work2",{}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "QPID-work3",{}, "deny") - self.Lookup("bob@QPID", "create", "exchange", "QPID-work", {"alternate":"QPID-work2"}, "allow") - self.Lookup("bob@QPID", "create", "exchange", "QPID-work2",{"alternate":"someexchange"}, "deny") - # bind/unbind/access - self.Lookup("bob@QPID", "bind", "exchange", "QPID-work", {}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "QPID-work", {"routingkey":"QPID"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "QPID-work", { "queuename":"QPID-work"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "QPID-work", {"routingkey":"QPID", "queuename":"QPID-work"}, "allow") - - self.Lookup("bob@QPID", "bind", "exchange", "QPID-work2", {}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "QPID-work2", {"routingkey":"QPID"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "QPID-work2", { "queuename":"QPID-work2"}, "deny") - self.Lookup("bob@QPID", "bind", "exchange", "QPID-work2", {"routingkey":"QPID", "queuename":"QPID-work2"}, "allow") - - self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work", {}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work", {"routingkey":"QPID"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work", { "queuename":"QPID-work"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work", {"routingkey":"QPID", "queuename":"QPID-work"}, "allow") - - self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work2", {}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work2", {"routingkey":"QPID"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work2", { "queuename":"QPID-work2"}, "deny") - self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work2", {"routingkey":"QPID", "queuename":"QPID-work2"}, "allow") - - self.Lookup("bob@QPID", "access", "exchange", "QPID-work", {}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "QPID-work", {"routingkey":"QPID"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "QPID-work", { "queuename":"QPID-work"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "QPID-work", {"routingkey":"QPID", "queuename":"QPID-work"}, "allow") - - self.Lookup("bob@QPID", "access", "exchange", "QPID-work2", {}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "QPID-work2", {"routingkey":"QPID"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "QPID-work2", { "queuename":"QPID-work2"}, "deny") - self.Lookup("bob@QPID", "access", "exchange", "QPID-work2", {"routingkey":"QPID", "queuename":"QPID-work2"}, "allow") - # publish - self.LookupPublish("bob@QPID", "QPID-work", "QPID", "allow") - self.LookupPublish("bob@QPID", "QPID-work2", "QPID", "allow") - self.LookupPublish("joe@QPID", "QPID-work", "QPID", "allow") - self.LookupPublish("joe@QPID", "QPID-work2", "QPID", "allow") - - #===================================== - # Queue per-user quota - #===================================== - - def queue_quota(self, user, passwd, count, byPort=None): - """ Helper method to: - - create a number of queues (should succeed) - - create too many queues (should fail) - - create another queue after deleting a queue (should succeed) - """ - - try: - if byPort: - session = self.get_session_by_port(user, passwd, byPort) - else: - session = self.get_session(user, passwd) - except Exception, e: - self.fail("Unexpected error creating session for %s: %s" % (user, str(e))) - - # Should be able to create count queues per user - try: - for i in range(count): - session.queue_declare(queue="%s%d" % (user, i)) - except Exception, e: - self.fail("Could not create %s for %s: %s" % ("%s%d" % (user, i), user, str(e))) - - # next queue should fail - try: - session.queue_declare(queue="%s%d" % (user, count)) - self.fail("Should not be able to create another queue for user %s" % user) - except Exception, e: - if byPort: - session = self.get_session_by_port(user, passwd, byPort) - else: - session = self.get_session(user, passwd) - - if count > 0: - # Deleting a queue should allow another queue. - session.queue_delete(queue="%s0" % user) - try: - session.queue_declare(queue="%s%d" % (user, count)) - except Exception, e: - self.fail("Could not recreate additional queue for user %s: %s " % (user, str(e))) - - # Clean up - for i in range(1, count+1): - session.queue_delete(queue="%s%d" % (user, i)) - try: - session.close() - except Exception, e: - pass - - def test_queue_per_named_user_quota(self): - """ - Test ACL queue counting limits per named user. - """ - aclf = self.get_acl_file() - aclf.write('quota queues 2 ted@QPID carrol@QPID\n') - aclf.write('quota queues 1 edward@QPID\n') - aclf.write('quota queues 0 mick@QPID\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # named users should be able to create specified number of queues - self.queue_quota("ted", 'ted', 2) - self.queue_quota("carrol", 'carrol', 2) - self.queue_quota("edward", 'edward', 1) - - # User with quota of 0 is denied - self.queue_quota("mick", 'mick', 0) - - # User not named in quotas is denied - self.queue_quota("dan", 'dan', 0) - - def test_queue_per_user_quota(self): - """ - Test ACL queue counting limits. - port_q has a limit of 2 - """ - # bob should be able to create two queues - self.queue_quota("bob", 'bob', 2, self.port_q()) - - # alice should be able to create two queues - self.queue_quota("alice", 'alice', 2, self.port_q()) - - - def test_queue_limits_by_unnamed_all(self): - """ - Test ACL control queue limits - """ - aclf = self.get_acl_file() - aclf.write('quota queues 2 aliceQUA@QPID bobQUA@QPID\n') - aclf.write('quota queues 1 all\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # By username should be able to connect twice per user - self.queue_quota('aliceQUA', 'alice', 2) - self.queue_quota('bobQUA', 'bob', 2) - - # User not named in quotas gets 'all' quota - self.queue_quota('charlieQUA', 'charlie', 1) - - - def test_queue_limits_by_group(self): - """ - Test ACL control queue limits - """ - aclf = self.get_acl_file() - aclf.write('group hobbits frodoGR@QPID samGR@QPID merryGR@QPID\n') - aclf.write('quota queues 2 gandalfGR@QPID aragornGR@QPID\n') - aclf.write('quota queues 2 hobbits rosieGR@QPID\n') - aclf.write('# user and groups may be overwritten. Should use last value\n') - aclf.write('quota queues 3 aragornGR@QPID hobbits\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - # gandalf gets 2 - self.queue_quota('gandalfGR', 'gandalf', 2) - - # aragorn gets 3 - self.queue_quota('aragornGR', 'aragorn', 3) - - # frodo gets 3 - self.queue_quota('frodoGR', 'frodo', 3) - - # User not named in quotas is denied - self.queue_quota('bilboGR', 'bilbo', 0) - - def test_queue_delete_with_properties(self): - """ - Test cases for queue delete with properties - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID access queue\n') - aclf.write('acl allow bob@QPID access exchange\n') - aclf.write('acl allow bob@QPID create queue name=qdaq1 durable=true\n') - aclf.write('acl allow bob@QPID create queue name=qdaq2 exclusive=true\n') - aclf.write('acl allow bob@QPID create queue name=qdaq3 policytype=ring\n') - aclf.write('acl allow bob@QPID create queue name=qdaq4 durable=false\n') - aclf.write('acl allow bob@QPID create queue name=qdaq5 exclusive=false\n') - aclf.write('acl allow bob@QPID create queue name=qdaq6 policytype=reject\n') - aclf.write('acl allow bob@QPID create queue name=qdaq7 autodelete=true\n') - aclf.write('acl allow bob@QPID create queue name=qdaq8 autodelete=false\n') - aclf.write('acl allow bob@QPID create queue name=qdaq9\n') - aclf.write('acl allow bob@QPID create exchange name=qdae9\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq1 durable=true\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq2 exclusive=true\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq3 policytype=ring\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq4 durable=false\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq5 exclusive=false\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq6 policytype=reject\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq7 autodelete=true\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq8 autodelete=false\n') - aclf.write('acl deny bob@QPID delete queue name=qdaq9 alternate=qdaq9a\n') - aclf.write('acl allow all access queue\n') - aclf.write('acl allow anonymous all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="qdaq1", durable=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qdaq1 durable=true"); - - try: - session.queue_delete(queue="qdaq1") - self.fail("ACL should deny queue delete request for qdaq1"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="qdaq2", exclusive=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qdaq2 exclusive=true"); - - try: - session.queue_delete(queue="qdaq2") - self.fail("ACL should deny queue delete request for qdaq2"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.policy_type"] = "ring" - session.queue_declare(queue="qdaq3", arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request for qdaq3 with policytype=ring"); - - try: - session.queue_delete(queue="qdaq3") - self.fail("ACL should deny queue delete request for qdaq3"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="qdaq4", durable=False) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qdaq4 durable=false"); - - try: - session.queue_delete(queue="qdaq4") - self.fail("ACL should deny queue delete request for qdaq4"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="qdaq5", exclusive=False) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qdaq5 exclusive=false"); - - try: - session.queue_delete(queue="qdaq5") - self.fail("ACL should deny queue delete request for qdaq5"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.policy_type"] = "reject" - session.queue_declare(queue="qdaq6", arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request for qdaq6 with policytype=reject"); - - try: - session.queue_delete(queue="qdaq6") - self.fail("ACL should deny queue delete request for qdaq6"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="qdaq7", auto_delete=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qdaq7 autodelete=true"); - - try: - session.queue_delete(queue="qdaq7") - self.fail("ACL should deny queue delete request for qdaq7"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="qdaq8", auto_delete=False) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qdaq8 autodelete=false"); - - try: - session.queue_delete(queue="qdaq8") - self.fail("ACL should deny queue delete request for qdaq8"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='qdae9', type='direct') - except qpid.session.SessionException, e: - self.fail("ACL should allow exchange create request with name=qdae9"); - - try: - session.queue_declare(queue="qdaq9", alternate_exchange="qdae9") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=qdaq9 alternate=qdaq9a"); - - try: - session.queue_delete(queue="qdaq9") - self.fail("ACL should deny queue delete request for qdaq9"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - - def test_exchange_delete_with_properties(self): - """ - Test cases for exchange delete with properties - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID access exchange\n') - aclf.write('acl allow bob@QPID create exchange\n') - aclf.write('acl deny bob@QPID delete exchange name=edae1 durable=true\n') - aclf.write('acl deny bob@QPID delete exchange name=edae2 alternate=edae2a\n') - aclf.write('acl deny bob@QPID delete exchange type=direct\n') - aclf.write('acl allow bob@QPID delete exchange type=headers\n') - aclf.write('acl allow anonymous all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='edae1', type='direct', durable=True) - except qpid.session.SessionException, e: - self.fail("ACL should allow exchange create request with name=edae1"); - - try: - session.exchange_delete(exchange="edae1") - self.fail("ACL should deny exchange delete request for edae1"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='edae2a', type='direct') - except qpid.session.SessionException, e: - self.fail("ACL should allow exchange create request with name=edae2a"); - - try: - session.exchange_declare(exchange='edae2', type='direct', alternate_exchange='edae2a') - except qpid.session.SessionException, e: - self.fail("ACL should allow exchange create request with name=edae2"); - - try: - session.exchange_delete(exchange="edae2") - self.fail("ACL should deny exchange delete request for edae2"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='edae3d', type='direct') - except qpid.session.SessionException, e: - self.fail("ACL should allow exchange create request with name=edae3d"); - - try: - session.exchange_declare(exchange='edae3h', type='headers') - except qpid.session.SessionException, e: - self.fail("ACL should allow exchange create request with name=eda3h"); - - try: - session.exchange_delete(exchange="edae3d") - self.fail("ACL should deny exchange delete request for edae3d"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_delete(exchange="edae3h") - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - self.fail("ACL should allow exchange delete request for edae3h"); - - #===================================== - # 'create connection' tests - #===================================== -# def test_connect_mode_file_rejects_two_defaults(self): -# """ -# Should reject a file with two connect mode statements -# """ -# aclf = self.get_acl_file() -# aclf.write('acl allow all create connection host=all\n') -# aclf.write('acl allow all create connection host=all\n') -# aclf.close() -# -# result = self.reload_acl() -# if (result): -# pass -# else: -# self.fail(result) - - def test_connect_mode_accepts_host_spec_formats(self): - """ - Should accept host specs of various forms - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID create connection host=all\n') - aclf.write('acl allow bob@QPID create connection host=1.1.1.1\n') - aclf.write('acl allow bob@QPID create connection host=1.1.1.1,2.2.2.2\n') - aclf.write('acl allow bob@QPID create connection host=localhost\n') - aclf.write('acl allow all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - def test_connect_mode_allow_all_mode(self): - """ - Should allow one 'all', 'all' - """ - aclf = self.get_acl_file() - aclf.write('acl allow all create connection host=all\n') - aclf.write('acl allow all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - - def test_connect_mode_allow_all_localhost(self): - """ - Should allow 'all' 'localhost' - """ - aclf = self.get_acl_file() - aclf.write('acl allow all create connection host=localhost\n') - aclf.write('acl deny all create connection host=all\n') - aclf.write('acl allow all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - - def test_connect_mode_global_deny(self): - """ - Should allow 'all' 'localhost' - """ - aclf = self.get_acl_file() - aclf.write('acl allow all create connection host=localhost\n') - aclf.write('acl deny all create connection host=all\n') - aclf.write('acl allow all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - self.Lookup("bob@QPID", "create", "connection", "", {"host":"127.0.0.1"}, "allow") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"127.0.0.2"}, "deny") - - - def test_connect_mode_global_range(self): - """ - Should allow 'all' 'localhost' - """ - aclf = self.get_acl_file() - aclf.write('acl allow all create connection host=10.0.0.0,10.255.255.255\n') - aclf.write('acl allow all create connection host=localhost\n') - aclf.write('acl deny all create connection host=all\n') - aclf.write('acl allow all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - self.Lookup("bob@QPID", "create", "connection", "", {"host":"0.0.0.0"}, "deny") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"9.255.255.255"}, "deny") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.0.0.0"}, "allow") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.255.255.255"}, "allow") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"11.0.0.0"}, "deny") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"255.255.255.255"},"deny") - - - def test_connect_mode_nested_ranges(self): - """ - Tests nested ranges for single user - """ - aclf = self.get_acl_file() - aclf.write('acl deny-log bob@QPID create connection host=10.0.1.0,10.0.1.255\n') - aclf.write('acl allow-log bob@QPID create connection host=10.0.0.0,10.255.255.255\n') - aclf.write('acl deny-log bob@QPID create connection host=all\n') - aclf.write('acl allow all create connection host=localhost\n') - aclf.write('acl allow all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - self.Lookup("bob@QPID", "create", "connection", "", {"host":"0.0.0.0"}, "deny-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"9.255.255.255"}, "deny-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.0.0.0"}, "allow-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.0.0.255"}, "allow-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.0.1.0"}, "deny-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.0.1.255"}, "deny-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.0.2.0"}, "allow-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.255.255.255"}, "allow-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"11.0.0.0"}, "deny-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"255.255.255.255"},"deny-log") - - - def test_connect_mode_user_ranges(self): - """ - Two user ranges should not interfere with each other - """ - aclf = self.get_acl_file() - aclf.write('acl allow-log bob@QPID create connection host=10.0.0.0,10.255.255.255\n') - aclf.write('acl deny-log bob@QPID create connection host=all\n') - aclf.write('acl allow-log cat@QPID create connection host=192.168.0.0,192.168.255.255\n') - aclf.write('acl deny-log cat@QPID create connection host=all\n') - aclf.write('acl allow all create connection host=localhost\n') - aclf.write('acl allow all all\n') - aclf.close() - - result = self.reload_acl() - if (result): - self.fail(result) - - session = self.get_session('bob','bob') - - self.Lookup("bob@QPID", "create", "connection", "", {"host":"0.0.0.0"}, "deny-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"9.255.255.255"}, "deny-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.0.0.0"}, "allow-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"10.255.255.255"}, "allow-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"11.0.0.0"}, "deny-log") - self.Lookup("bob@QPID", "create", "connection", "", {"host":"255.255.255.255"},"deny-log") - self.Lookup("cat@QPID", "create", "connection", "", {"host":"0.0.0.0"}, "deny-log") - self.Lookup("cat@QPID", "create", "connection", "", {"host":"192.167.255.255"},"deny-log") - self.Lookup("cat@QPID", "create", "connection", "", {"host":"192.168.0.0"}, "allow-log") - self.Lookup("cat@QPID", "create", "connection", "", {"host":"192.168.255.255"},"allow-log") - self.Lookup("cat@QPID", "create", "connection", "", {"host":"192.169.0.0"}, "deny-log") - self.Lookup("cat@QPID", "create", "connection", "", {"host":"255.255.255.255"},"deny-log") - - -class BrokerAdmin: - def __init__(self, broker, username=None, password=None): - self.connection = qpid.messaging.Connection(broker) - if username: - self.connection.username = username - self.connection.password = password - self.connection.sasl_mechanisms = "PLAIN" - self.connection.open() - self.session = self.connection.session() - self.sender = self.session.sender("qmf.default.direct/broker") - self.reply_to = "responses-#; {create:always}" - self.receiver = self.session.receiver(self.reply_to) - - def invoke(self, method, arguments): - content = { - "_object_id": {"_object_name": "org.apache.qpid.broker:broker:amqp-broker"}, - "_method_name": method, - "_arguments": arguments - } - request = qpid.messaging.Message(reply_to=self.reply_to, content=content) - request.properties["x-amqp-0-10.app-id"] = "qmf2" - request.properties["qmf.opcode"] = "_method_request" - self.sender.send(request) - response = self.receiver.fetch() - self.session.acknowledge() - if response.properties['x-amqp-0-10.app-id'] == 'qmf2': - if response.properties['qmf.opcode'] == '_method_response': - return response.content['_arguments'] - elif response.properties['qmf.opcode'] == '_exception': - raise Exception(response.content['_values']) - else: raise Exception("Invalid response received, unexpected opcode: %s" % response.properties['qmf.opcode']) - else: raise Exception("Invalid response received, not a qmfv2 method: %s" % response.properties['x-amqp-0-10.app-id']) - - def query(self, object_name=None, class_name=None): - content = { "_what": "OBJECT" } - if object_name is not None: - content["_object_id"] = {"_object_name": object_name } - if class_name is not None: - content["_schema_id"] = {"_class_name": class_name } - request = qpid.messaging.Message(reply_to=self.reply_to, content=content) - request.properties["x-amqp-0-10.app-id"] = "qmf2" - request.properties["qmf.opcode"] = "_query_request" - self.sender.send(request) - response = self.receiver.fetch() - self.session.acknowledge() - if response.properties['x-amqp-0-10.app-id'] == 'qmf2': - if response.properties['qmf.opcode'] == '_query_response': - return - elif response.properties['qmf.opcode'] == '_exception': - raise Exception(response.content['_values']) - else: raise Exception("Invalid response received, unexpected opcode: %s" % response.properties['qmf.opcode']) - else: raise Exception("Invalid response received, not a qmfv2 method: %s" % response.properties['x-amqp-0-10.app-id']) - - def create_exchange(self, name, exchange_type=None, options={}): - properties = options - if exchange_type: properties["exchange_type"] = exchange_type - self.invoke("create", {"type": "exchange", "name":name, "properties":properties}) - - def create_queue(self, name, properties={}): - self.invoke("create", {"type": "queue", "name":name, "properties":properties}) - - def delete_exchange(self, name): - self.invoke("delete", {"type": "exchange", "name":name}) - - def delete_queue(self, name): - self.invoke("delete", {"type": "queue", "name":name}) - - def get_timestamp_cfg(self): - return self.invoke("getTimestampConfig", {}) - - def set_timestamp_cfg(self, receive): - return self.invoke("getTimestampConfig", {"receive":receive}) diff --git a/qpid/cpp/src/tests/acl_1.py b/qpid/cpp/src/tests/acl_1.py deleted file mode 100644 index 79d87fdc6e..0000000000 --- a/qpid/cpp/src/tests/acl_1.py +++ /dev/null @@ -1,396 +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. -# - -from qpid.tests.messaging.implementation import * -from qpid.tests.messaging import VersionTest -from mgmt_1 import Mgmt - -class Policy(object): - def __init__(self): - self.lines = [] - - - def str(self): - return '\n'.join(lines) - -class AclCtrl(object): - def __init__(self, broker, path): - self.policy = path - self.original = self.read() - conn = Connection.establish(broker, protocol='amqp0-10', username='admin', password='admin', sasl_mechanism='PLAIN') - self.agent = Mgmt(conn) - self.agent.create('queue', 'acl_test_queue') - self.lines = [] - - def deny(self, user=None, *args): - self._add_rule('deny', user, *args) - return self - - def allow(self, user=None, *args): - self._add_rule('allow', user, *args) - return self - - def apply(self, allow_admin=True): - if allow_admin: - # admin users needs permission to send a qmf message to - # reload policy - self.lines.insert(0, 'acl allow admin@QPID all all') - self.specify("\n".join(self.lines)) - return self - - def dump(self): - print "\n".join(self.lines) - return self - - def clear(self): - self.lines = [] - return self - - def _add_rule(self, deny_or_allow, user=None, *args): - elements = ['acl', deny_or_allow] - if user: - elements.append("%s@QPID" % user) - else: - elements.append('all') - if len(args) > 0: - for a in args: - elements.append(a) - else: - elements.append('all') - self.lines.append(' '.join(elements)) - - def read(self): - f = open(self.policy,'r') - content = f.read() - f.close() - return content - - def specify(self, acl): - f = open(self.policy,'w') - f.write(acl) - f.close() - self.agent.reload_acl_file() - - def restore(self): - self.agent.delete('queue', 'acl_test_queue') - self.specify(self.original) - self.agent.close() - - -class Acl_AMQP1_Tests (VersionTest): - """ - Tests for acl when accessing qpidd via AMQP 1.0 - """ - def auth_session(self, user): - conn = Connection.establish(self.config.broker, protocol='amqp1.0', username=user, password=user, sasl_mechanism='PLAIN', container_id=user) - return conn.session() - - def setUp(self): - VersionTest.setup(self) - self.acl = AclCtrl(self.config.broker, self.config.defines.get("policy_file")) - self.alice = self.auth_session('alice') - self.bob = self.auth_session('bob') - - def tearDown(self): - self.bob.connection.close() - self.alice.connection.close() - self.acl.restore() - VersionTest.teardown(self) - - def test_deny_sender_to_exchange(self): - self.acl.allow('alice').deny().apply() - try: - self.ssn.sender("amq.topic") - assert False, "anonymous should not be allowed to create sender to amq.topic" - except UnauthorizedAccess: pass - try: - self.bob.sender("amq.topic") - assert False, "bob should not be allowed to create sender to amq.topic" - except UnauthorizedAccess: pass - self.alice.sender("amq.topic") - - def test_deny_sender_to_queue(self): - self.acl.allow('alice').deny().apply() - try: - self.ssn.sender("acl_test_queue") - assert False, "anonymous shound not be allowed to create sender to acl_test_queue" - except UnauthorizedAccess: pass - try: - self.bob.sender("acl_test_queue") - assert False, "bob should not be allowed to create sender to acl_test_queue" - except UnauthorizedAccess: pass - self.alice.sender("acl_test_queue") - - def test_deny_sender_to_unknown(self): - self.acl.allow('alice').deny().apply() - try: - self.ssn.sender("unknown") - assert False, "anonymous should not be allowed to create sender to non-existent node" - except UnauthorizedAccess: pass - try: - self.bob.sender("unknown") - assert False, "bob should not be allowed to create sender to unknown" - except UnauthorizedAccess: pass - try: - self.alice.sender("unknown") - except NotFound: pass - - def test_deny_receiver_to_exchange(self): - self.acl.allow('alice').deny().apply() - try: - self.ssn.receiver("amq.topic") - assert False, "anonymous should not be allowed to create receiver from amq.topic" - except UnauthorizedAccess: pass - try: - self.bob.receiver("amq.topic") - assert False, "bob should not be allowed to create receiver to amq.topic" - except UnauthorizedAccess: pass - self.alice.receiver("amq.topic") - - def test_deny_receiver_to_queue(self): - self.acl.allow('alice').deny().apply() - try: - self.ssn.receiver("acl_test_queue") - assert False, "anonymous should not be allowed to create receiver from acl_test_queue" - except UnauthorizedAccess: pass - try: - self.bob.receiver("acl_test_queue") - assert False, "bob should not be allowed to create receiver to acl_test_queue" - except UnauthorizedAccess: pass - self.alice.receiver("acl_test_queue") - - def test_deny_receiver_to_unknown(self): - self.acl.allow('alice').deny().apply() - try: - self.ssn.receiver("I_dont_exist") - assert False, "anonymous should not be allowed to create receiver from non-existent node" - except UnauthorizedAccess: pass - try: - self.bob.receiver("unknown") - assert False, "bob should not be allowed to create receiver to unknown" - except UnauthorizedAccess: pass - try: - self.alice.receiver("unknown") - except NotFound: pass - - def test_create_for_receiver_from_exchange(self): - self.acl.allow('bob', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'access', 'queue', 'name=amq.topic') - self.acl.allow('alice').deny().apply() - try: - self.ssn.receiver("amq.topic") - assert False, "anonymous should not be allowed to create receiver from amq.topic" - except UnauthorizedAccess: pass - try: - self.bob.receiver("amq.topic") - assert False, "bob should not be allowed to create receiver from amq.topic without create permission" - except UnauthorizedAccess: pass - self.alice.receiver("amq.topic") - - def test_bind_for_receiver_from_exchange(self): - self.acl.allow('bob', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'access', 'queue', 'name=amq.topic') - self.acl.allow('bob', 'create', 'queue', 'name=bob*') - self.acl.allow('alice').deny().apply() - try: - self.ssn.receiver("amq.topic") - assert False, "anonymous should not be allowed to create receiver from amq.topic" - except UnauthorizedAccess: pass - try: - self.bob.receiver("amq.topic") - assert False, "bob should not be allowed to create receiver from amq.topic without bind permission" - except UnauthorizedAccess: pass - self.alice.receiver("amq.topic") - - def test_consume_for_receiver_from_exchange(self): - self.acl.allow('bob', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'access', 'queue', 'name=amq.topic') - self.acl.allow('bob', 'create', 'queue', 'name=bob*') - self.acl.allow('bob', 'bind', 'exchange', 'name=amq.topic') - self.acl.allow('alice').deny().apply() - try: - self.ssn.receiver("amq.topic") - assert False, "anonymous should not be allowed to create receiver from amq.topic" - except UnauthorizedAccess: pass - try: - self.bob.receiver("amq.topic") - assert False, "bob should not be allowed to create receiver from amq.topic without consume permission" - except UnauthorizedAccess: pass - self.alice.receiver("amq.topic") - - def test_required_permissions_for_receiver_from_exchange(self): - self.acl.allow('bob', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'access', 'queue', 'name=amq.topic') - self.acl.allow('bob', 'create', 'queue', 'name=bob*') - self.acl.allow('bob', 'bind', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'consume', 'queue', 'name=bob*') - self.acl.allow('alice').deny().apply() - try: - self.ssn.receiver("amq.topic") - assert False, "anonymous should not be allowed to create receiver from amq.topic" - except UnauthorizedAccess: pass - self.bob.receiver("amq.topic") - try: - self.bob.receiver("amq.direct") - assert False, "bob should not be allowed to create receiver from amq.direct" - except UnauthorizedAccess: pass - - def test_publish_to_exchange(self): - self.acl.allow('bob', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'access', 'queue', 'name=amq.topic') - self.acl.allow('bob', 'publish', 'exchange', 'name=amq.topic', 'routingkey=abc') - self.acl.allow('alice').deny().apply() - - sender = self.bob.sender("amq.topic") - sender.send(Message("a message", subject="abc"), sync=True) - try: - sender.send(Message("another", subject="def"), sync=True) - assert False, "bob should not be allowed to send message to amq.topic with subject 'def'" - except UnauthorizedAccess: pass - sender = self.alice.sender("amq.topic") - sender.send(Message("alice's message", subject="abc"), sync=True) - sender.send(Message("another from alice", subject="def"), sync=True) - - def test_publish_to_anonymous_relay(self): - self.acl.allow('bob', 'access', 'exchange', 'name=ANONYMOUS-RELAY') - self.acl.allow('bob', 'access', 'queue', 'name=acl_test_queue') - self.acl.allow('bob', 'access', 'exchange', 'name=acl_test_queue') - self.acl.allow('bob', 'publish', 'exchange', 'routingkey=acl_test_queue') - self.acl.allow('bob', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'access', 'queue', 'name=amq.topic') - self.acl.allow('bob', 'publish', 'exchange', 'name=amq.topic', 'routingkey=abc') - self.acl.allow('bob', 'access', 'exchange', 'name=amq.direct') - self.acl.allow('bob', 'access', 'queue', 'name=amq.direct') - self.acl.allow('alice').deny().apply() - - sender = self.bob.sender("") - sender.send(Message("a message", properties={'x-amqp-to':'acl_test_queue'}), sync=True) - sender.send(Message("another", subject='abc', properties={'x-amqp-to':'amq.topic'}), sync=True) - try: - # have access permission, but publish not allowed for given key - sender.send(Message("a third", subject='def', properties={'x-amqp-to':'amq.topic'}), sync=True) - assert False, "bob should not be allowed to send message to amq.topic with key 'def'" - except UnauthorizedAccess: pass - sender = self.bob.sender("") - try: - # have access permission, but no publish - sender.send(Message("a fourth", subject='abc', properties={'x-amqp-to':'amq.direct'}), sync=True) - assert False, "bob should not be allowed to send message to amq.direct" - except UnauthorizedAccess: pass - sender = self.bob.sender("") - try: - # have no access permission - sender.send(Message("a fiftth", subject='abc', properties={'x-amqp-to':'amq.fanout'}), sync=True) - assert False, "bob should not be allowed to send message to amq.fanout" - except UnauthorizedAccess: pass - sender = self.bob.sender("") - try: - # have no access permission - sender.send(Message("a sixth", properties={'x-amqp-to':'somewhereelse'}), sync=True) - assert False, "bob should not be allowed to send message to somewhere else" - except UnauthorizedAccess: pass - sender = self.alice.sender("") - sender.send(Message("alice's message", properties={'x-amqp-to':'abc'}), sync=True) - sender.send(Message("another from alice", properties={'x-amqp-to':'def'}), sync=True) - - def test_resolution_for_sender_to_exchange(self): - self.acl.allow('alice', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('alice', 'access', 'queue', 'name=amq.topic') - self.acl.allow('bob', 'access', 'exchange', 'name=amq.topic') - self.acl.deny().apply() - try: - self.ssn.sender("amq.topic") - assert False, "anonymous should not be allowed to create sender to amq.topic" - except UnauthorizedAccess: pass - self.bob.sender("amq.topic; {node:{type:topic}}") - try: - self.bob.sender("amq.topic") - assert False, "bob should not be allowed to create sender to amq.topic without specifying the node type" - except UnauthorizedAccess: pass - self.alice.sender("amq.topic; {node:{type:topic}}") - self.alice.sender("amq.topic") - try: - self.alice.sender("amq.direct") - assert False, "alice should not be allowed to create sender to amq.direct" - except UnauthorizedAccess: pass - - def test_resolution_for_sender_to_queue(self): - self.acl.allow('alice', 'access', 'exchange', 'name=acl_test_queue') - self.acl.allow('alice', 'access', 'queue', 'name=acl_test_queue') - self.acl.allow('alice', 'publish', 'exchange', 'routingkey=acl_test_queue') - self.acl.allow('bob', 'access', 'queue', 'name=acl_test_queue') - self.acl.allow('bob', 'publish', 'exchange', 'routingkey=acl_test_queue') - self.acl.deny().apply() - try: - self.ssn.sender("acl_test_queue") - assert False, "anonymous should not be allowed to create sender to acl_test_queue" - except UnauthorizedAccess: pass - self.bob.sender("acl_test_queue; {node:{type:queue}}") - try: - self.bob.sender("acl_test_queue") - assert False, "bob should not be allowed to create sender to acl_test_queue without specifying the node type" - except UnauthorizedAccess: pass - self.alice.sender("acl_test_queue; {node:{type:queue}}") - self.alice.sender("acl_test_queue") - - def test_resolution_for_receiver_from_exchange(self): - self.acl.allow('alice', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('alice', 'access', 'queue', 'name=amq.topic') - self.acl.allow('alice', 'create', 'queue') - self.acl.allow('alice', 'consume', 'queue') - self.acl.allow('alice', 'bind', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'access', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'bind', 'exchange', 'name=amq.topic') - self.acl.allow('bob', 'create', 'queue', 'name=bob*', 'autodelete=true') - self.acl.allow('bob', 'consume', 'queue', 'name=bob*') - self.acl.deny().apply() - try: - self.ssn.receiver("amq.topic") - assert False, "anonymous should not be allowed to create receiver from amq.topic" - except UnauthorizedAccess: pass - self.bob.receiver("amq.topic; {node:{type:topic}}") - try: - self.bob.receiver("amq.topic") - assert False, "bob should not be allowed to create receiver from amq.topic without specifying the node type" - except UnauthorizedAccess: pass - self.alice.receiver("amq.topic; {node:{type:topic}}") - self.alice.receiver("amq.topic") - try: - self.alice.receiver("amq.direct") - assert False, "alice should not be allowed to create receiver from amq.direct" - except UnauthorizedAccess: pass - - def test_resolution_for_receiver_from_queue(self): - self.acl.allow('alice', 'access', 'exchange', 'name=acl_test_queue') - self.acl.allow('alice', 'access', 'queue', 'name=acl_test_queue') - self.acl.allow('alice', 'consume', 'queue', 'name=acl_test_queue') - self.acl.allow('bob', 'access', 'queue', 'name=acl_test_queue') - self.acl.allow('bob', 'consume', 'queue', 'name=acl_test_queue') - self.acl.deny().apply() - try: - self.ssn.receiver("acl_test_queue") - assert False, "anonymous should not be allowed to create receiver from acl_test_queue" - except UnauthorizedAccess: pass - self.bob.receiver("acl_test_queue; {node:{type:queue}}") - try: - self.bob.receiver("acl_test_queue") - assert False, "bob should not be allowed to create receiver from acl_test_queue without specifying the node type" - except UnauthorizedAccess: pass - self.alice.receiver("acl_test_queue; {node:{type:queue}}") - self.alice.receiver("acl_test_queue") diff --git a/qpid/cpp/src/tests/assertions.py b/qpid/cpp/src/tests/assertions.py deleted file mode 100644 index 179f4ed57d..0000000000 --- a/qpid/cpp/src/tests/assertions.py +++ /dev/null @@ -1,194 +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. -# - -from qpid.tests.messaging.implementation import * -from qpid.tests.messaging import VersionTest - -class AssertionTests (VersionTest): - """ - Tests for assertions with qpidd - """ - def test_queues_alternate_exchange1(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{properties:{alternate-exchange:amq.fanout}}}" % name) - self.ssn.sender("%s; {assert:always, node:{properties:{alternate-exchange:amq.fanout}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{properties:{alternate-exchange:amq.topic}}}" % name) - assert False, "Expected assertion to fail on alternate-exchange" - except AssertionFailed: None - except MessagingError: None - - def test_queues_alternate_exchange2(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{x-declare:{alternate-exchange:amq.fanout}}}" % name) - self.ssn.sender("%s; {assert:always, node:{x-declare:{alternate-exchange:amq.fanout}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{alternate-exchange:amq.topic}}}" % name) - assert False, "Expected assertion to fail on alternate-exchange" - except AssertionFailed: None - except MessagingError: None - - def test_queue_type(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always}" % name) - self.ssn.sender("%s; {assert:always, node:{type:queue}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{type:topic}}" % name) - assert False, "Expected assertion to fail on type" - except AssertionFailed: None - except MessagingError: None - - def test_queue_not_durable(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always}" % name) - self.ssn.sender("%s; {assert:always, node:{durable:False}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{durable:True}}" % name) - assert False, "Expected assertion to fail on durability" - except AssertionFailed: None - except MessagingError: None - - def test_queue_is_durable(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{durable:True}}" % name) - self.ssn.sender("%s; {assert:always, node:{durable:True}}" % name) - - def test_queue_is_autodelete(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{x-declare:{auto-delete:True}}}" % name) - self.ssn.sender("%s; {assert:always, node:{x-declare:{auto-delete:True}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{auto-delete:False}}}" % name) - assert False, "Expected assertion to fail for auto-delete" - except AssertionFailed: None - except MessagingError: None - - def do_test_queue_options(self, name): - self.ssn.sender("%s; {create:always, node:{x-declare:{arguments:{foo:bar,'qpid.last_value_queue_key':abc}}}}" % name) - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments:{'qpid.last_value_queue_key':abc}}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments:{foo:bar}}}}" % name) - assert False, "Expected assertion to fail on unrecognised option" - except AssertionFailed: None - except MessagingError: None - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments:{'qpid.max_count':10}}}}" % name) - assert False, "Expected assertion to fail on unspecified option" - except AssertionFailed: None - except MessagingError: None - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments:{'qpid.last_value_key':xyz}}}}" % name) - assert False, "Expected assertion to fail on option with different value" - except AssertionFailed: None - except MessagingError: None - - def test_queue_options(self): - self.do_test_queue_options(str(uuid4())) - - def test_queue_options_from_0_10(self): - name = str(uuid4()) - self.do_test_queue_options(name) - ssn_0_10 = self.create_connection("amqp0-10", True).session() - ssn_0_10.sender("%s; {assert:always, node:{x-declare:{arguments:{'qpid.last_value_queue_key':abc}}}}" % name) - try: - ssn_0_10.sender("%s; {assert:always, node:{x-declare:{arguments:{'qpid.last_value_key':xyz}}}}" % name) - assert False, "Expected assertion to fail on option with different value" - except AssertionFailed: None - except MessagingError: None - - - def test_exchanges_alternate_exchange1(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{type:topic, properties:{alternate-exchange:amq.fanout}}}" % name) - self.ssn.sender("%s; {assert:always, node:{type:topic, properties:{alternate-exchange:amq.fanout}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{properties:{alternate-exchange:amq.topic}}}" % name) - assert False, "Expected assertion to fail on alternate-exchange" - except AssertionFailed: None - except MessagingError: None - - def test_exchanges_alternate_exchange2(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{type:topic, x-declare:{alternate-exchange:amq.fanout}}}" % name) - self.ssn.sender("%s; {assert:always, node:{type:topic, x-declare:{alternate-exchange:amq.fanout}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{alternate-exchange:amq.topic}}}" % name) - assert False, "Expected assertion to fail on alternate-exchange" - except AssertionFailed: None - except MessagingError: None - - def test_exchange_type(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{type:topic}}" % name) - self.ssn.sender("%s; {assert:always, node:{type:topic}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{type:queue}}" % name) - assert False, "Expected assertion to fail on type" - except AssertionFailed: None - except MessagingError: None - - def test_exchange_durability(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{type:topic}}" % name) - self.ssn.sender("%s; {assert:always, node:{durable:False}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{durable:True}}" % name) - assert False, "Expected assertion to fail on durability" - except AssertionFailed: None - except MessagingError: None - - def test_exchange_is_autodelete(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{type:topic, x-declare:{auto-delete:True}}}" % name) - self.ssn.sender("%s; {assert:always, node:{x-declare:{auto-delete:True}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{auto-delete:False}}}" % name) - assert False, "Expected assertion to fail for auto-delete" - except AssertionFailed: None - except MessagingError: None - - def test_exchange_options(self): - name = str(uuid4()) - self.ssn.sender("%s; {create:always, node:{type:topic, x-declare:{arguments:{foo:bar,'qpid.msg_sequence':True}}}}" % name) - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments:{'qpid.msg_sequence':True}}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments:{foo:bar}}}}" % name) - assert False, "Expected assertion to fail on unrecognised option" - except AssertionFailed: None - except MessagingError: None - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments:{'qpid.ive':True}}}}" % name) - assert False, "Expected assertion to fail on unspecified option" - except AssertionFailed: None - except MessagingError: None - - def test_queue_autodelete_timeout(self): - name = str(uuid4()) - # create subscription queue with 0-10 to be sure of name - ssn_0_10 = self.create_connection("amqp0-10", True).session() - ssn_0_10.receiver("amq.direct; {link:{name:%s,timeout:120}}" % name) - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments: {qpid.auto_delete_timeout: 120}}}}" % name) - ssn_0_10_other = self.create_connection("amqp0-10", True).session() - ssn_0_10_other.sender("%s; {assert:always, node:{x-declare:{arguments: {qpid.auto_delete_timeout: 120}}}}" % name) - try: - self.ssn.sender("%s; {assert:always, node:{x-declare:{arguments: {qpid.auto_delete_timeout: 180}}}}" % name) - ssn_0_10_other.sender("%s; {assert:always, node:{x-declare:{arguments: {qpid.auto_delete_timeout: 180}}}}" % name) - assert False, "Expected assertion to fail for auto_delete_timeout" - except AssertionFailed: None - except MessagingError: None diff --git a/qpid/cpp/src/tests/background.ps1 b/qpid/cpp/src/tests/background.ps1 deleted file mode 100644 index 36e9e4e6e9..0000000000 --- a/qpid/cpp/src/tests/background.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run a PowerShell scriptblock in a background process. -param( - [scriptblock] $script # scriptblock to run -) - -# break out of the script on any errors -trap { break } - -# In order to pass a scriptblock to another powershell instance, it must -# be encoded to pass through the command line. -$encodedScript = [convert]::ToBase64String( - [Text.Encoding]::Unicode.GetBytes([string] $script)) - -#$p = new-object System.Diagnostics.Process -$si = new-object System.Diagnostics.ProcessStartInfo -$si.WorkingDirectory = $pwd -$si.FileName = (get-command powershell.exe).Definition -$si.Arguments = "-encodedCommand $encodedScript" - -###### debugging setup -#$si.CreateNoWindow = $true -# UseShellExecute false required for RedirectStandard(Error, Output) -#$si.UseShellExecute = $false -#$si.RedirectStandardError = $true -#$si.RedirectStandardOutput = $true -###### -$si.UseShellExecute = $true - -##### Debugging, instead of the plain Start() above. -#$output = [io.File]::AppendText("start.out") -#$error = [io.File]::AppendText("start.err") -$p = [System.Diagnostics.Process]::Start($si) -#$output.WriteLine($p.StandardOutput.ReadToEnd()) -#$error.WriteLine($p.StandardError.ReadToEnd()) -#$p.WaitForExit() -#$output.Close() diff --git a/qpid/cpp/src/tests/brokertest.py b/qpid/cpp/src/tests/brokertest.py deleted file mode 100644 index b40e953427..0000000000 --- a/qpid/cpp/src/tests/brokertest.py +++ /dev/null @@ -1,739 +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. -# - -# Support library for tests that start multiple brokers, e.g. HA or federation - -import os, signal, string, tempfile, subprocess, socket, threading, time, imp, re -import qpid, traceback, signal -from qpid import connection, util -from qpid.compat import format_exc -from unittest import TestCase -from copy import copy -from threading import Thread, Lock, Condition -from logging import getLogger -from qpidtoollibs import BrokerAgent - -# NOTE: Always import native client qpid.messaging, import swigged client -# qpid_messaging if possible. qpid_messaing is set to None if not available. -# -# qm is set to qpid_messaging if it is available, qpid.messaging if not. -# Use qm.X to specify names from the default messaging module. -# -# Set environment variable QPID_PY_NO_SWIG=1 to prevent qpid_messaging from loading. -# -# BrokerTest can be configured to determine which protocol is used by default: -# -# -DPROTOCOL="amqpX": Use protocol "amqpX". Defaults to amqp1.0 if available. -# -# The configured defaults can be over-ridden on BrokerTest.connect and some -# other methods by specifying native=True|False and protocol="amqpX" -# - -import qpid.messaging -qm = qpid.messaging -qpid_messaging = None - -def env_has_log_config(): - """True if there are qpid log configuratoin settings in the environment.""" - return "QPID_LOG_ENABLE" in os.environ or "QPID_TRACE" in os.environ - -if not os.environ.get("QPID_PY_NO_SWIG"): - try: - import qpid_messaging - from qpid.datatypes import uuid4 - qm = qpid_messaging - # Silence warnings from swigged messaging library unless enabled in environment. - if not env_has_log_config(): - qm.Logger.configure(["--log-enable=error"]) - except ImportError: - print "Cannot load python SWIG bindings, falling back to native qpid.messaging." - -log = getLogger("brokertest") - -# Values for expected outcome of process at end of test -EXPECT_EXIT_OK=1 # Expect to exit with 0 status before end of test. -EXPECT_EXIT_FAIL=2 # Expect to exit with non-0 status before end of test. -EXPECT_RUNNING=3 # Expect to still be running at end of test -EXPECT_UNKNOWN=4 # No expectation, don't check exit status. - -def find_exe(program): - """Find an executable in the system PATH""" - def is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - mydir, name = os.path.split(program) - if mydir: - if is_exe(program): return program - else: - for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, program) - if is_exe(exe_file): return exe_file - return None - -def is_running(pid): - try: - os.kill(pid, 0) - return True - except: - return False - -class BadProcessStatus(Exception): - pass - -def error_line(filename, n=1): - """Get the last n line(s) of filename for error messages""" - result = [] - try: - f = open(filename) - try: - for l in f: - if len(result) == n: result.pop(0) - result.append(" "+l) - finally: - f.close() - except: return "" - return ":\n" + "".join(result) - -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.""" - deadline = time.time() + timeout - ret = None - while True: - ret = function() - if ret: return ret - remaining = deadline - time.time() - if remaining <= 0: return False - delay = min(delay, remaining) - time.sleep(delay) - delay = min(delay*2, max_delay) - -class AtomicCounter: - def __init__(self): - self.count = 0 - self.lock = Lock() - - def next(self): - self.lock.acquire(); - ret = self.count - self.count += 1 - self.lock.release(); - return ret - -_popen_id = AtomicCounter() # Popen identifier for use in output file names. - -# Constants for file descriptor arguments to Popen -FILE = "FILE" # Write to file named after process -from subprocess import PIPE, STDOUT - -class Popen(subprocess.Popen): - """ - Can set and verify expectation of process status at end of test. - Dumps command line, stdout, stderr to data dir for debugging. - """ - - def __init__(self, cmd, expect=EXPECT_EXIT_OK, stdin=None, stdout=FILE, stderr=FILE): - """Run cmd (should be a list of program and arguments) - expect - if set verify expectation at end of test. - stdout, stderr - can have the same values as for subprocess.Popen as well as - FILE (the default) which means write to a file named after the process. - stdin - like subprocess.Popen but defauts to PIPE - """ - self._clean = False - self._clean_lock = Lock() - if type(cmd) is type(""): cmd = [cmd] # Make it a list. - self.cmd = [ str(x) for x in cmd ] - self.expect = expect - self.id = _popen_id.next() - self.pname = "%s-%d" % (os.path.split(self.cmd[0])[1], self.id) - if stdout == FILE: stdout = open(self.outfile("out"), "w") - if stderr == FILE: stderr = open(self.outfile("err"), "w") - subprocess.Popen.__init__(self, self.cmd, bufsize=0, executable=None, - stdin=stdin, stdout=stdout, stderr=stderr) - f = open(self.outfile("cmd"), "w") - try: f.write("%s\n%d"%(self.cmd_str(), self.pid)) - finally: f.close() - log.debug("Started process %s: %s" % (self.pname, " ".join(self.cmd))) - - def __repr__(self): return "Popen<%s>"%(self.pname) - - def outfile(self, ext): return "%s.%s" % (self.pname, ext) - - def unexpected(self,msg): - err = error_line(self.outfile("err")) or error_line(self.outfile("out")) - raise BadProcessStatus("%s %s%s" % (self.pname, msg, err)) - - def teardown(self): # Clean up at end of test. - if self.expect == EXPECT_UNKNOWN: - try: self.kill() # Just make sure its dead - except: pass - elif self.expect == EXPECT_RUNNING: - if self.poll() != None: - self.unexpected("expected running, exit code %d" % self.returncode) - else: - try: - self.kill() - except Exception,e: - self.unexpected("exception from kill: %s" % str(e)) - else: - retry(lambda: self.poll() is not None) - if self.returncode is None: # Still haven't stopped - self.kill() - self.unexpected("still running") - elif self.expect == EXPECT_EXIT_OK and self.returncode != 0: - self.unexpected("exit code %d" % self.returncode) - elif self.expect == EXPECT_EXIT_FAIL and self.returncode == 0: - self.unexpected("expected error") - self.wait() - - - def communicate(self, input=None): - ret = subprocess.Popen.communicate(self, input) - self._cleanup() - return ret - - def is_running(self): return self.poll() is None - - def assert_running(self): - if not self.is_running(): self.unexpected("Exit code %d" % self.returncode) - - def wait(self): - ret = subprocess.Popen.wait(self) - self._cleanup() - return ret - - def assert_exit_ok(self): - if self.wait() != 0: self.unexpected("Exit code %d" % self.returncode) - - def terminate(self): - try: subprocess.Popen.terminate(self) - except AttributeError: # No terminate method - try: - os.kill( self.pid , signal.SIGTERM) - except AttributeError: # no os.kill, using taskkill.. (Windows only) - os.popen('TASKKILL /PID ' +str(self.pid) + ' /F') - self.wait() - - def kill(self): - # Set to EXPECT_UNKNOWN, EXPECT_EXIT_FAIL creates a race condition - # if the process exits normally concurrent with the call to kill. - self.expect = EXPECT_UNKNOWN - try: subprocess.Popen.kill(self) - except AttributeError: # No terminate method - try: - os.kill( self.pid , signal.SIGKILL) - except AttributeError: # no os.kill, using taskkill.. (Windows only) - os.popen('TASKKILL /PID ' +str(self.pid) + ' /F') - self.wait() - - def _cleanup(self): - """Clean up after a dead process""" - self._clean_lock.acquire() - if not self._clean: - self._clean = True - try: self.stdin.close() - except: pass - try: self.stdout.close() - except: pass - try: self.stderr.close() - except: pass - self._clean_lock.release() - - def cmd_str(self): return " ".join([str(s) for s in self.cmd]) - - -def checkenv(name): - value = os.getenv(name) - if not value: raise Exception("Environment variable %s is not set" % name) - return value - -def find_in_file(str, filename): - if not os.path.exists(filename): return False - f = open(filename) - try: return str in f.read() - finally: f.close() - -class Broker(Popen): - "A broker process. Takes care of start, stop and logging." - _broker_count = 0 - _log_count = 0 - - def __repr__(self): return ""%(self.log, self.port()) - - def get_log(self): - return os.path.abspath(self.log) - - def __init__(self, test, args=[], test_store=False, name=None, expect=EXPECT_RUNNING, port=0, wait=None, show_cmd=False): - """Start a broker daemon. name determines the data-dir and log - file names.""" - - self.test = test - self._port=port - args = copy(args) - if BrokerTest.amqp_lib: args += ["--load-module", BrokerTest.amqp_lib] - if BrokerTest.store_lib and not test_store: - args += ['--load-module', BrokerTest.store_lib] - if BrokerTest.sql_store_lib: - args += ['--load-module', BrokerTest.sql_store_lib] - args += ['--catalog', BrokerTest.sql_catalog] - if BrokerTest.sql_clfs_store_lib: - args += ['--load-module', BrokerTest.sql_clfs_store_lib] - args += ['--catalog', BrokerTest.sql_catalog] - cmd = [BrokerTest.qpidd_exec, "--port", port, "--interface", "127.0.0.1", "--no-module-dir"] + args - if not "--auth" in args: cmd.append("--auth=no") - if wait != None: - cmd += ["--wait", str(wait)] - if name: self.name = name - else: - self.name = "broker%d" % Broker._broker_count - Broker._broker_count += 1 - - 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"] - - # Add default --log-enable arguments unless args already has --log arguments. - if not env_has_log_config() and not [l for l in args if l.startswith("--log")]: - args += ["--log-enable=info+"] - - if test_store: cmd += ["--load-module", BrokerTest.test_store_lib, - "--test-store-events", self.store_log] - - self.datadir = os.path.abspath(self.name) - cmd += ["--data-dir", self.datadir] - if show_cmd: print cmd - Popen.__init__(self, cmd, expect, stdout=PIPE) - test.teardown_add(self) - self._host = "127.0.0.1" - self._agent = None - - log.debug("Started broker %s" % self) - - def host(self): return self._host - - def port(self): - # Read port from broker process stdout if not already read. - if (self._port == 0): - try: self._port = int(self.stdout.readline()) - except ValueError, e: - raise Exception("Can't get port for broker %s (%s)%s: %s" % - (self.name, self.pname, error_line(self.log,5), e)) - return self._port - - def unexpected(self,msg): - raise BadProcessStatus("%s: %s (%s)" % (msg, self.name, self.pname)) - - def connect(self, timeout=5, native=False, **kwargs): - """New API connection to the broker. - @param native if True force use of the native qpid.messaging client - even if swig client is available. - """ - if native: connection_class = qpid.messaging.Connection - else: - connection_class = qm.Connection - if (self.test.protocol and qm == qpid_messaging): - kwargs.setdefault("protocol", self.test.protocol) - return connection_class.establish(self.host_port(), timeout=timeout, **kwargs) - - @property - def agent(self, **kwargs): - """Return a BrokerAgent for this broker""" - if not self._agent: self._agent = BrokerAgent(self.connect(**kwargs)) - return self._agent - - - def declare_queue(self, queue): - self.agent.addQueue(queue) - - def _prep_sender(self, queue, durable, xprops): - s = queue + "; {create:always, node:{durable:" + str(durable) - if xprops != None: s += ", x-declare:{" + xprops + "}" - return s + "}}" - - def send_message(self, queue, message, durable=True, xprops=None, session=None): - if session == None: - s = self.connect().session() - else: - s = session - s.sender(self._prep_sender(queue, durable, xprops)).send(message) - if session == None: - s.connection.close() - - def send_messages(self, queue, messages, durable=True, xprops=None, session=None): - if session == None: - s = self.connect().session() - else: - s = session - sender = s.sender(self._prep_sender(queue, durable, xprops)) - for m in messages: sender.send(m) - if session == None: - s.connection.close() - - def get_message(self, queue): - s = self.connect().session() - m = s.receiver(queue+"; {create:always}", capacity=1).fetch(timeout=1) - s.acknowledge() - s.connection.close() - return m - - def get_messages(self, queue, n): - s = self.connect().session() - receiver = s.receiver(queue+"; {create:always}", capacity=n) - m = [receiver.fetch(timeout=1) for i in range(n)] - s.acknowledge() - s.connection.close() - return m - - def host_port(self): return "%s:%s" % (self.host(), self.port()) - - def ready(self, timeout=10, **kwargs): - """Wait till broker is ready to serve clients""" - 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 assert_log_clean(self, ignore=None): - log = open(self.get_log()) - try: - error = re.compile("] error|] critical") - if ignore: ignore = re.compile(ignore) - else: ignore = re.compile("\000") # Won't match anything - for line in log.readlines(): - assert not error.search(line) or ignore.search(line), "Errors in log file %s: %s"%(log, line) - finally: log.close() - -def receiver_iter(receiver, timeout=0): - """Make an iterator out of a receiver. Returns messages till Empty is raised.""" - try: - while True: - yield receiver.fetch(timeout=timeout) - except qm.Empty: - pass - -def browse(session, queue, timeout=0, transform=lambda m: m.content): - """Return a list with the contents of each message on queue.""" - r = session.receiver("%s;{mode:browse}"%(queue)) - r.capacity = 100 - try: - return [transform(m) for m in receiver_iter(r, timeout)] - finally: - r.close() - -def assert_browse(session, queue, expect_contents, timeout=0, transform=lambda m: m.content, msg=None): - """Assert that the contents of messages on queue (as retrieved - using session and timeout) exactly match the strings in - expect_contents""" - if msg is None: msg = "browse '%s' failed" % queue - actual_contents = browse(session, queue, timeout, transform=transform) - 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=.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) - actual_contents = browse(session, queue, 0, transform=transform) - if msg: msg = "%s: %r != %r"%(msg, expect_contents, actual_contents) - assert expect_contents == actual_contents, msg - -class BrokerTest(TestCase): - """ - Tracks processes started by test and kills at end of test. - 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 = "qpidd" - ha_lib = os.getenv("HA_LIB") - xml_lib = os.getenv("XML_LIB") - amqp_lib = os.getenv("AMQP_LIB") - qpid_config_exec = "qpid-config" - qpid_route_exec = "qpid-route" - receiver_exec = "receiver" - sender_exec = "sender" - sql_store_lib = os.getenv("STORE_SQL_LIB") - sql_clfs_store_lib = os.getenv("STORE_SQL_CLFS_LIB") - sql_catalog = os.getenv("STORE_CATALOG") - store_lib = os.getenv("STORE_LIB") - test_store_lib = os.getenv("TEST_STORE_LIB") - rootdir = os.getcwd() - - try: - import proton - PN_VERSION = (proton.VERSION_MAJOR, proton.VERSION_MINOR) - except ImportError: - # proton not on path, can't determine version - PN_VERSION = (0, 0) - except AttributeError: - # prior to 0.8 proton did not expose version info - PN_VERSION = (0, 7) - - PN_TX_VERSION = (0, 9) - - amqp_tx_supported = PN_VERSION >= PN_TX_VERSION - - def configure(self, config): self.config=config - - def setUp(self): - defs = self.config.defines - outdir = defs.get("OUTDIR") or "brokertest.tmp" - self.dir = os.path.join(self.rootdir, outdir, self.id()) - os.makedirs(self.dir) - os.chdir(self.dir) - self.teardown_list = [] # things to tear down at end of test - if qpid_messaging and self.amqp_lib: default_protocol="amqp1.0" - else: default_protocol="amqp0-10" - self.protocol = defs.get("PROTOCOL") or default_protocol - self.tx_protocol = self.protocol - if not self.amqp_tx_supported: self.tx_protocol = "amqp0-10" - - def tearDown(self): - err = [] - self.teardown_list.reverse() # Tear down in reverse order - for p in self.teardown_list: - log.debug("Tearing down %s", p) - try: - # Call the first of the methods that is available on p. - for m in ["teardown", "close"]: - a = getattr(p, m, None) - if a: a(); break - else: raise Exception("Don't know how to tear down %s", p) - except Exception, e: - if m != "close": # Ignore connection close errors. - err.append("%s: %s"%(e.__class__.__name__, str(e))) - self.teardown_list = [] # reset in case more processes start - os.chdir(self.rootdir) - if err: raise Exception("Unexpected process status:\n "+"\n ".join(err)) - - def teardown_add(self, thing): - """Call thing.teardown() or thing.close() at end of test""" - self.teardown_list.append(thing) - - def popen(self, cmd, expect=EXPECT_EXIT_OK, stdin=None, stdout=FILE, stderr=FILE): - """Start a process that will be killed at end of test, in the test dir.""" - os.chdir(self.dir) - p = Popen(cmd, expect, stdin=stdin, stdout=stdout, stderr=stderr) - self.teardown_add(p) - return p - - def broker(self, args=[], name=None, expect=EXPECT_RUNNING, wait=True, port=0, show_cmd=False, **kw): - """Create and return a broker ready for use""" - b = Broker(self, args=args, name=name, expect=expect, port=port, show_cmd=show_cmd, **kw) - if (wait): - try: b.ready() - except Exception, e: - raise RethrownException("Failed to start broker %s(%s): %s" % (b.name, b.log, e)) - return b - - def check_output(self, args, stdin=None): - p = self.popen(args, stdout=PIPE, stderr=STDOUT) - out = p.communicate(stdin) - if p.returncode != 0: - raise Exception("%s exit code %s, output:\n%s" % (args, p.returncode, out[0])) - return out[0] - - def browse(self, *args, **kwargs): browse(*args, **kwargs) - def assert_browse(self, *args, **kwargs): assert_browse(*args, **kwargs) - def assert_browse_retry(self, *args, **kwargs): assert_browse_retry(*args, **kwargs) - - def protocol_option(self, connection_options=""): - if "protocol" in connection_options: return connection_options - else: return ",".join(filter(None, [connection_options,"protocol:'%s'"%self.protocol])) - - -def join(thread, timeout=30): - thread.join(timeout) - if thread.isAlive(): raise Exception("Timed out joining thread %s"%thread) - -class RethrownException(Exception): - """Captures the stack trace of the current exception to be thrown later""" - def __init__(self, msg=""): - Exception.__init__(self, msg+"\n"+format_exc()) - -class StoppableThread(Thread): - """ - Base class for threads that do something in a loop and periodically check - to see if they have been stopped. - """ - def __init__(self): - self.stopped = False - self.error = None - Thread.__init__(self) - - def stop(self): - self.stopped = True - join(self) - if self.error: raise self.error - -# Options for a client that wants to reconnect automatically. -RECONNECT_OPTIONS="reconnect:true,reconnect-timeout:10,reconnect-urls-replace:true" - -class NumberedSender(Thread): - """ - Thread to run a sender client and send numbered messages until stopped. - """ - - def __init__(self, broker, max_depth=None, queue="test-queue", - connection_options=RECONNECT_OPTIONS, - failover_updates=False, url=None, args=[]): - """ - max_depth: enable flow control, ensure sent - received <= max_depth. - Requires self.notify_received(n) to be called each time messages are received. - """ - Thread.__init__(self) - cmd = ["qpid-send", - "--broker", url or broker.host_port(), - "--address", "%s;{create:always}"%queue, - "--connection-options", "{%s}"%(broker.test.protocol_option(connection_options)), - "--content-stdin" - ] + args - if failover_updates: cmd += ["--failover-updates"] - self.sender = broker.test.popen( - cmd, expect=EXPECT_RUNNING, stdin=PIPE) - self.condition = Condition() - self.max = max_depth - self.received = 0 - self.stopped = False - self.error = None - self.queue = queue - - def write_message(self, n): - self.sender.stdin.write(str(n)+"\n") - self.sender.stdin.flush() - - def run(self): - try: - self.sent = 0 - while not self.stopped: - self.sender.assert_running() - if self.max: - self.condition.acquire() - while not self.stopped and self.sent - self.received > self.max: - self.condition.wait() - self.condition.release() - self.write_message(self.sent) - self.sent += 1 - except Exception, e: - self.error = RethrownException( - "%s: (%s)%s"%(self.sender.pname,e, - error_line(self.sender.outfile("err")))) - - - def notify_received(self, count): - """Called by receiver to enable flow control. count = messages received so far.""" - self.condition.acquire() - self.received = count - self.condition.notify() - self.condition.release() - - def stop(self): - self.condition.acquire() - try: - self.stopped = True - self.condition.notify() - finally: self.condition.release() - join(self) - self.write_message(-1) # end-of-messages marker. - if self.error: raise self.error - -class NumberedReceiver(Thread): - """ - Thread to run a receiver client and verify it receives - sequentially numbered messages. - """ - def __init__(self, broker, sender=None, queue="test-queue", - connection_options=RECONNECT_OPTIONS, - failover_updates=False, url=None, args=[]): - """ - sender: enable flow control. Call sender.received(n) for each message received. - """ - Thread.__init__(self) - self.test = broker.test - cmd = ["qpid-receive", - "--broker", url or broker.host_port(), - "--address", "%s;{create:always}"%queue, - "--connection-options", "{%s}"%(broker.test.protocol_option(connection_options)), - "--forever" - ] - if failover_updates: cmd += [ "--failover-updates" ] - cmd += args - self.receiver = self.test.popen( - cmd, expect=EXPECT_RUNNING, stdout=PIPE) - self.lock = Lock() - self.error = None - self.sender = sender - self.received = 0 - self.queue = queue - - def read_message(self): - n = int(self.receiver.stdout.readline()) - return n - - def run(self): - try: - m = self.read_message() - while m != -1: - self.receiver.assert_running() - assert m <= self.received, "%s missing message %s>%s"%(self.queue, m, self.received) - if (m == self.received): # Ignore duplicates - self.received += 1 - if self.sender: - self.sender.notify_received(self.received) - m = self.read_message() - except Exception, e: - self.error = RethrownException( - "%s: (%s)%s"%(self.receiver.pname,e, - error_line(self.receiver.outfile("err")))) - - def check(self): - """Raise an exception if there has been an error""" - if self.error: raise self.error - - def stop(self): - """Returns when termination message is received""" - join(self) - self.check() - -def import_script(path): - """ - Import executable script at path as a module. - Requires some trickery as scripts are not in standard module format - """ - f = open(path) - try: - name=os.path.split(path)[1].replace("-","_") - return imp.load_module(name, f, path, ("", "r", imp.PY_SOURCE)) - finally: f.close() diff --git a/qpid/cpp/src/tests/check_dependencies.py.in b/qpid/cpp/src/tests/check_dependencies.py.in deleted file mode 100755 index ef69fc1743..0000000000 --- a/qpid/cpp/src/tests/check_dependencies.py.in +++ /dev/null @@ -1,53 +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. -# - -import os -import sys - -def _message(error): - return """ -=============================================================================== -Error! {0} - -The tests require Qpid Python, version 1.33 or greater. Make sure -Qpid Python is installed and available on the Python path: - - - Linux distributions: Install 'python-qpid' - - Other: Install qpid-python from source and update PYTHONPATH - -See the Qpid website for more information: - - - Qpid downloads: http://qpid.apache.org/download.html - - Qpid packages: http://qpid.apache.org/packages.html -=============================================================================== -""".format(error) - -sys.path.insert(0, os.path.join("@CMAKE_SOURCE_DIR@", "management", "python", "lib")) - -try: - import qpid -except ImportError: - exit(_message("Can't find Python 'qpid' module")) - -try: - import qpid_tests -except ImportError: - exit(_message("Can't find Python 'qpid_tests' module")) diff --git a/qpid/cpp/src/tests/cli_tests.py b/qpid/cpp/src/tests/cli_tests.py deleted file mode 100755 index ae0f32d4d1..0000000000 --- a/qpid/cpp/src/tests/cli_tests.py +++ /dev/null @@ -1,482 +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. -# - -import sys -import os -import imp -from qpid.testlib import TestBase010 -from qpid.datatypes import Message -from qpid.queue import Empty -from time import sleep - -def import_script(path): - """ - Import executable script at path as a module. - Requires some trickery as scripts are not in standard module format - """ - f = open(path) - try: - name=os.path.split(path)[1].replace("-","_") - return imp.load_module(name, f, path, ("", "r", imp.PY_SOURCE)) - finally: f.close() - -def checkenv(name): - value = os.getenv(name) - if not value: raise Exception("Environment variable %s is not set" % name) - return value - -class CliTests(TestBase010): - - def remote_host(self): - return self.defines.get("remote-host", "localhost") - - def remote_port(self): - return int(self.defines["remote-port"]) - - def cli_dir(self): - return self.defines["cli-dir"] - - def makeQueue(self, qname, arguments, api=False): - if api: - ret = self.qpid_config_api(" add queue " + qname + " " + arguments) - else: - ret = os.system(self.qpid_config_command(" add queue " + qname + " " + arguments)) - - self.assertEqual(ret, 0) - queue = self.broker_access.getQueue(qname) - if queue: - return queue - assert False - - def test_queue_params(self): - 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 ring") - - LIMIT = "qpid.policy_type" - assert LIMIT not in queue1.arguments - self.assertEqual(queue2.arguments[LIMIT], "reject") - self.assertEqual(queue3.arguments[LIMIT], "ring") - - queue4 = self.makeQueue("test_queue_params4", "--lvq-key lkey") - - LVQKEY = "qpid.last_value_queue_key" - - 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 ring", True) - - LIMIT = "qpid.policy_type" - assert LIMIT not in queue1.arguments - self.assertEqual(queue2.arguments[LIMIT], "reject") - self.assertEqual(queue3.arguments[LIMIT], "ring") - - queue4 = self.makeQueue("test_queue_params_api4", "--lvq-key lkey") - - LVQKEY = "qpid.last_value_queue_key" - - assert LVQKEY not in queue3.arguments - assert LVQKEY in queue4.arguments - assert queue4.arguments[LVQKEY] == "lkey" - - - def test_qpid_config(self): - self.startBrokerAccess(); - qname = "test_qpid_config" - - ret = os.system(self.qpid_config_command(" add queue " + qname)) - self.assertEqual(ret, 0) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, False) - found = True - self.assertEqual(found, True) - - ret = os.system(self.qpid_config_command(" del queue " + qname)) - self.assertEqual(ret, 0) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - found = True - self.assertEqual(found, False) - - def test_qpid_config_del_nonempty_queue(self): - self.startBrokerAccess(); - qname = "test_qpid_config_del" - - ret = os.system(self.qpid_config_command(" add queue " + qname)) - self.assertEqual(ret, 0) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, False) - found = True - self.assertEqual(found, True) - - self.startBrokerAccess() - - sess = self.broker_conn.session() - tx = sess.sender(qname) - tx.send("MESSAGE") - - ret = os.system(self.qpid_config_command(" del queue " + qname)) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - found = True - self.assertEqual(found, True) - - ret = os.system(self.qpid_config_command(" del queue " + qname + " --force")) - self.assertEqual(ret, 0) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - found = True - self.assertEqual(found, False) - - - def test_qpid_config_api(self): - self.startBrokerAccess(); - qname = "test_qpid_config_api" - - ret = self.qpid_config_api(" add queue " + qname) - self.assertEqual(ret, 0) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, False) - found = True - self.assertEqual(found, True) - - ret = self.qpid_config_api(" del queue " + qname) - self.assertEqual(ret, 0) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - found = True - self.assertEqual(found, False) - - - def test_qpid_config_sasl_plain_expect_succeed(self): - self.startBrokerAccess(); - qname = "test_qpid_config_sasl_plain_expect_succeed" - cmd = " --sasl-mechanism PLAIN -b guest/guest@localhost:"+str(self.broker.port) + " add queue " + qname - ret = self.qpid_config_api(cmd) - self.assertEqual(ret, 0) - - def test_qpid_config_sasl_plain_expect_fail(self): - """Fails because no user name and password is supplied""" - self.startBrokerAccess(); - qname = "test_qpid_config_sasl_plain_expect_fail" - cmd = " --sasl-mechanism PLAIN -b localhost:"+str(self.broker.port) + " add queue " + qname - ret = self.qpid_config_api(cmd) - assert ret != 0 - - # helpers for some of the test methods - def helper_find_exchange(self, xchgname, typ, expected=True): - xchgs = self.broker_access.getAllExchanges() - found = False - for xchg in xchgs: - if xchg.name == xchgname: - if typ: - self.assertEqual(xchg.type, typ) - found = True - self.assertEqual(found, expected) - - def helper_create_exchange(self, xchgname, typ="direct", opts=""): - foo = self.qpid_config_command(opts + " add exchange " + typ + " " + xchgname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - self.helper_find_exchange(xchgname, typ, True) - - def helper_destroy_exchange(self, xchgname): - foo = self.qpid_config_command(" del exchange " + xchgname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - self.helper_find_exchange(xchgname, False, expected=False) - - def helper_find_queue(self, qname, expected=True): - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, False) - found = True - self.assertEqual(found, expected) - - def helper_create_queue(self, qname): - foo = self.qpid_config_command(" add queue " + qname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - self.helper_find_queue(qname, True) - - def helper_destroy_queue(self, qname): - foo = self.qpid_config_command(" del queue " + qname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - self.helper_find_queue(qname, False) - - # test the bind-queue-to-header-exchange functionality - def test_qpid_config_headers(self): - self.startBrokerAccess(); - qname = "test_qpid_config" - xchgname = "test_xchg" - - # first create a header xchg - self.helper_create_exchange(xchgname, typ="headers") - - # create the queue - self.helper_create_queue(qname) - - # now bind the queue to the xchg - foo = self.qpid_config_command(" bind " + xchgname + " " + qname + - " key all foo=bar baz=quux") - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - - # he likes it, mikey. Ok, now tear it all down. first the binding - ret = os.system(self.qpid_config_command(" unbind " + xchgname + " " + qname + - " key")) - self.assertEqual(ret, 0) - - # then the queue - self.helper_destroy_queue(qname) - - # then the exchange - self.helper_destroy_exchange(xchgname) - - - def test_qpid_config_xml(self): - self.startBrokerAccess(); - qname = "test_qpid_config" - xchgname = "test_xchg" - - # first create a header xchg - self.helper_create_exchange(xchgname, typ="xml") - - # create the queue - self.helper_create_queue(qname) - - # now bind the queue to the xchg - xquery_file = self.defines["xquery-file"] - foo = self.qpid_config_command("-f " + xquery_file + " bind " + xchgname + " " + qname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - - # he likes it, mikey. Ok, now tear it all down. first the binding - ret = os.system(self.qpid_config_command(" unbind " + xchgname + " " + qname + - " key")) - self.assertEqual(ret, 0) - - # then the queue - self.helper_destroy_queue(qname) - - # then the exchange - self.helper_destroy_exchange(xchgname) - - def test_qpid_config_durable(self): - self.startBrokerAccess(); - qname = "test_qpid_config" - - ret = os.system(self.qpid_config_command(" add queue --durable " + qname)) - self.assertEqual(ret, 0) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, True) - found = True - self.assertEqual(found, True) - - ret = os.system(self.qpid_config_command(" del queue " + qname)) - self.assertEqual(ret, 0) - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qname: - found = True - self.assertEqual(found, False) - - def test_qpid_config_altex(self): - self.startBrokerAccess(); - exName = "testalt" - qName = "testqalt" - altName = "amq.direct" - - ret = os.system(self.qpid_config_command(" add exchange topic %s --alternate-exchange=%s" % (exName, altName))) - self.assertEqual(ret, 0) - - exchanges = self.broker_access.getAllExchanges() - found = False - for exchange in exchanges: - if exchange.name == altName: - self.assertEqual(exchange.altExchange, None) - - if exchange.name == exName: - found = True - if not exchange.altExchange: - self.fail("Alternate exchange not set") - self.assertEqual(exchange.altExchange, altName) - self.assertEqual(found, True) - - ret = os.system(self.qpid_config_command(" add queue %s --alternate-exchange=%s" % (qName, altName))) - self.assertEqual(ret, 0) - - ret = os.system(self.qpid_config_command(" queues")) - self.assertEqual(ret, 0) - - queues = self.broker_access.getAllQueues() - found = False - for queue in queues: - if queue.name == qName: - found = True - if not queue.altExchange: - self.fail("Alternate exchange not set") - self.assertEqual(queue.altExchange, altName) - self.assertEqual(found, True) - - def test_qpid_config_list_queues_arguments(self): - """ - Test to verify that when the type of a policy limit is - actually a string (though still a valid value), it does not - upset qpid-config - """ - self.startBrokerAccess(); - - names = ["queue_capacity%s" % (i) for i in range(1, 6)] - for name in names: - self.session.queue_declare(queue=name, exclusive=True, - arguments={'qpid.max_count' : str(i), 'qpid.max_size': '100'}) - - output = os.popen(self.qpid_config_command(" queues")).readlines() - queues = [line.split()[0] for line in output[2:len(output)]] #ignore first two lines (header) - - for name in names: - assert name in queues, "%s not in %s" % (name, queues) - - def test_qpid_route(self): - self.startBrokerAccess(); - - command = self.cli_dir() + "/qpid-route dynamic add guest/guest@localhost:%d %s:%d amq.topic" %\ - (self.broker.port, self.remote_host(), self.remote_port()) - ret = os.system(command) - self.assertEqual(ret, 0) - - links = self.broker_access.getAllLinks() - found = False - for link in links: - if link.port == self.remote_port(): - found = True - self.assertEqual(found, True) - - def test_qpid_route_api(self): - self.startBrokerAccess(); - - ret = self.qpid_route_api("dynamic add " - + "guest/guest@localhost:"+str(self.broker.port) + " " - + str(self.remote_host())+":"+str(self.remote_port()) + " " - +"amq.direct") - - self.assertEqual(ret, 0) - - links = self.broker_access.getAllLinks() - found = False - for link in links: - if link.port == self.remote_port(): - found = True - self.assertEqual(found, True) - - - def test_qpid_route_api(self): - self.startBrokerAccess(); - - ret = self.qpid_route_api("dynamic add " - + " --client-sasl-mechanism PLAIN " - + "guest/guest@localhost:"+str(self.broker.port) + " " - + str(self.remote_host())+":"+str(self.remote_port()) + " " - +"amq.direct") - - self.assertEqual(ret, 0) - - links = self.broker_access.getAllLinks() - found = False - for link in links: - if link.port == self.remote_port(): - found = True - self.assertEqual(found, True) - - def test_qpid_route_api_expect_fail(self): - self.startBrokerAccess(); - - ret = self.qpid_route_api("dynamic add " - + " --client-sasl-mechanism PLAIN " - + "localhost:"+str(self.broker.port) + " " - + str(self.remote_host())+":"+str(self.remote_port()) + " " - +"amq.direct") - assert ret != 0 - - - def getProperty(self, msg, name): - for h in msg.headers: - if hasattr(h, name): return getattr(h, name) - return None - - def getAppHeader(self, msg, name): - headers = self.getProperty(msg, "application_headers") - if headers: - return headers[name] - return None - - def qpid_config_command(self, arg = ""): - return self.cli_dir() + "/qpid-config -b localhost:%d" % self.broker.port + " " + arg - - def qpid_config_api(self, arg = ""): - path = os.path.join(os.getenv("SOURCE_DIR"), "management", "python", - "bin", "qpid-config") - script = import_script(path) - broker = ["-b", "localhost:"+str(self.broker.port)] - return script.main(broker + arg.split()) - - def qpid_route_api(self, arg = ""): - path = os.path.join(os.getenv("SOURCE_DIR"), "management", "python", - "bin", "qpid-route") - script = import_script(path) - return script.main(arg.split()) diff --git a/qpid/cpp/src/tests/common.py b/qpid/cpp/src/tests/common.py deleted file mode 100644 index d6dc640c5a..0000000000 --- a/qpid/cpp/src/tests/common.py +++ /dev/null @@ -1,298 +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. -# - -from __future__ import print_function - -from env import * - -import atexit as _atexit -import os as _os -import re as _re -import shlex as _shlex -import shutil as _shutil -import signal as _signal -import subprocess as _subprocess -import time as _time -import uuid as _uuid - -def _unique_id(): - return str(_uuid.uuid4())[:4] - -def make_work_dir(): - prog = file_name(ARGS[0]) - name = "{0}_{1}".format(prog, _unique_id()) - - return make_dir(join(BUILD_DIR, name)) - -WORK_DIR = make_work_dir() - -notice("Created work dir '{0}'", WORK_DIR) - -def _init_valgrind_command(command): - if VALGRIND is None: - return command, None - - log_file = join(WORK_DIR, "valgrind_{0}.log".format(_unique_id())) - suppressions_file = join(BUILD_DIR, "src", "tests", ".valgrind.supp") - - valgrind_command = [ - VALGRIND, - "--leak-check=full --num-callers=25 --error-exitcode=100", - "--log-file={0}".format(log_file), - "--gen-suppressions=all", - "--suppressions={0}".format(suppressions_file), - "--", - command, - ] - - return " ".join(valgrind_command), log_file - -def call_with_valgrind(command, *args, **kwargs): - command, valgrind_log_file = _init_valgrind_command(command) - - try: - call(command, *args, **kwargs) - except _subprocess.CalledProcessError as e: - if e.returncode == 100: - error("Valgrind reported errors") - print(read(valgrind_log_file)) - - raise - -def call_for_output_with_valgrind(command, *args, **kwargs): - command, valgrind_log_file = _init_valgrind_command(command) - - try: - return call_for_output(command, *args, **kwargs) - except _subprocess.CalledProcessError as e: - if e.returncode == 100: - error("Valgrind reported errors") - print(read(valgrind_log_file)) - - raise - -_brokers = list() -_brokers_by_port = dict() -_broker_port_expr = _re.compile(r"Listening on TCP/TCP6 port ([0-9]+)") -_broker_config_file = join(BUILD_DIR, "src", "tests", "qpidd-empty.conf") - -class _Broker(object): - def __init__(self, dir): - self.dir = dir - - self.command_file = join(self.dir, "command") - self.log_file = join(self.dir, "log") - self.data_dir = join(self.dir, "data") - - self.port = None - self.proc = None - self.command = None - self.valgrind_log_file = None - - def __repr__(self): - args = self.port, self.proc.pid, self.proc.returncode - return "Broker(port={0}, pid={1}, exit={2})".format(*args) - - def start(self, args): - make_dir(self.dir) - - command = [ - "qpidd", - "--port", "0", - "--interface", "localhost", - "--no-module-dir", - "--log-enable", "info+", - "--log-source", "yes", - "--log-to-stderr", "no", - "--log-to-file", self.log_file, - "--config", _broker_config_file, - "--data-dir", self.data_dir, - ] - - if WINDOWS: - command += [ - "--ssl-cert-store-location", "LocalMachine", - "--ssl-cert-name", "localhost", - "--ssl-port", "0", - ] - - command += [x for x in args if x is not None] - command = " ".join(command) - command, valgrind_log_file = _init_valgrind_command(command) - - self.command = command - self.valgrind_log_file = valgrind_log_file - - notice("Calling '{0}'", self.command) - write(self.command_file, self.command) - - # XXX Workaround for problem terminating subprocesses that use shell=True - command_args = _shlex.split(self.command, posix=False) - - self.proc = _subprocess.Popen(command_args, stdout=_subprocess.PIPE) - self.port = self._wait_for_port() - - assert self.command is not None - assert self.proc is not None - assert self.port is not None - assert self.port not in _brokers_by_port, self.port - - _brokers.append(self) - _brokers_by_port[self.port] = self - - notice("Started {0}", self) - - def _wait_for_port(self): - port = None - - while port is None: - _time.sleep(0.4) - port = self._scan_port() - - return port - - def _scan_port(self): - if not exists(self.log_file): - return - - match = _re.search(_broker_port_expr, read(self.log_file)) - - if match: - return match.group(1) - - def stop(self): - if self.proc.poll() is not None: - return - - notice("Stopping {0}", self) - - if WINDOWS: - call("taskkill /f /t /pid {0}", self.proc.pid) - else: - self.proc.terminate() - - self.proc.wait() - - def check(self): - if WINDOWS: - # Taskkilled windows processes always return 1, so exit - # codes don't mean anything there - return 0 - - notice("Checking {0}", self) - - if self.proc.returncode == 0: - return 0 - - error("{0} exited with code {1}", self, self.proc.returncode) - - if self.proc.returncode == 100: - print("Valgrind reported errors:") - print(read(self.valgrind_log_file)) - else: - print("Last 100 lines of broker log:") - print(tail(self.log_file, 100)) - - flush() - - error("{0} exited with code {1}", self, self.proc.returncode) - - return self.proc.returncode - -def start_broker(dir, *args, **kwargs): - if not is_absolute(dir): - dir = join(WORK_DIR, dir) - - auth_disabled = kwargs.get("auth_disabled", True) - - if auth_disabled: - args = list(args) - args.append("--auth no") - - broker = _Broker(dir) - broker.start(args) - - return broker.port - -def stop_broker(port): - broker = _brokers_by_port[port] - broker.stop() - -def check_broker(port): - broker = _brokers_by_port[port] - - if broker.check() != 0: - exit("Broker failure") - -def check_results(): - for broker in _brokers: - broker.stop() - - errors = False - - for broker in _brokers: - code = broker.check() - - if code == 0: - continue - - errors = True - - if errors: - exit("Broker failure") - - remove(WORK_DIR) - - notice("Tests completed without error") - -def _exit_handler(): - if exists(WORK_DIR): - notice("Output saved in work dir '{0}'", WORK_DIR) - - for broker in _brokers: - broker.stop() - -_atexit.register(_exit_handler) - -def configure_broker(broker_port, *args): - command = [ - "qpid-config", - "--broker localhost:{0}".format(broker_port), - ] - - command += [x for x in args if x is not None] - - call(" ".join(command)) - -def run_broker_tests(broker_port, *args): - command = [ - "qpid-python-test", - "--broker localhost:{0}".format(broker_port), - "--time", - ] - - command += [x for x in args if x is not None] - - call(" ".join(command)) - -def connect_brokers(*args): - command = ["qpid-route"] - command += [x for x in args if x is not None] - - call(" ".join(command)) diff --git a/qpid/cpp/src/tests/consume.cpp b/qpid/cpp/src/tests/consume.cpp deleted file mode 100644 index 69110d151f..0000000000 --- a/qpid/cpp/src/tests/consume.cpp +++ /dev/null @@ -1,131 +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 -#include -#include -#include -#include - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using namespace std; - -namespace qpid { -namespace tests { - -typedef vector StringSet; - -struct Args : public qpid::TestOptions { - uint count; - uint ack; - string queue; - bool declare; - bool summary; - bool print; - bool durable; - - Args() : count(1000), ack(0), queue("publish-consume"), - declare(false), summary(false), print(false) - { - addOptions() - ("count", optValue(count, "N"), "number of messages to publish") - ("ack-frequency", optValue(ack, "N"), "ack every N messages (0 means use no-ack mode)") - ("queue", optValue(queue, ""), "queue to consume from") - ("declare", optValue(declare), "declare the queue") - ("durable", optValue(durable), "declare the queue durable, use with declare") - ("print-data", optValue(print), "Print the recieved data at info level") - ("s,summary", optValue(summary), "Print undecorated rate."); - } -}; - -Args opts; - -struct Client -{ - Connection connection; - Session session; - - Client() - { - opts.open(connection); - session = connection.newSession(); - } - - void consume() - { - if (opts.declare) - session.queueDeclare(arg::queue=opts.queue, arg::durable=opts.durable); - SubscriptionManager subs(session); - LocalQueue lq; - SubscriptionSettings settings; - settings.acceptMode = opts.ack > 0 ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE; - settings.flowControl = FlowControl(opts.count, SubscriptionManager::UNLIMITED,false); - Subscription sub = subs.subscribe(lq, opts.queue, settings); - Message msg; - AbsTime begin=now(); - for (size_t i = 0; i < opts.count; ++i) { - msg=lq.pop(); - QPID_LOG(info, "Received: " << msg.getMessageProperties().getCorrelationId()); - if (opts.print) QPID_LOG(info, "Data: " << msg.getData()); - } - if (opts.ack != 0) - sub.accept(sub.getUnaccepted()); // Cumulative ack for final batch. - AbsTime end=now(); - double secs(double(Duration(begin,end))/TIME_SEC); - if (opts.summary) cout << opts.count/secs << endl; - else cout << "Time: " << secs << "s Rate: " << opts.count/secs << endl; - } - - ~Client() - { - try{ - session.close(); - connection.close(); - } catch(const exception& e) { - cout << e.what() << endl; - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - Client client; - client.consume(); - return 0; - } catch(const exception& e) { - cout << e.what() << endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/datagen.cpp b/qpid/cpp/src/tests/datagen.cpp deleted file mode 100644 index acbc07d63c..0000000000 --- a/qpid/cpp/src/tests/datagen.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 -#include -#include -#include -#include "qpid/Options.h" - -namespace qpid { -namespace tests { - -struct Args : public qpid::Options -{ - uint count; - uint minSize; - uint maxSize; - uint minChar; - uint maxChar; - bool help; - - Args() : qpid::Options("Random data generator"), - count(1), minSize(8), maxSize(4096), - minChar(32), maxChar(126),//safely printable ascii chars - help(false) - { - addOptions() - ("count", qpid::optValue(count, "N"), "number of data strings to generate") - ("min-size", qpid::optValue(minSize, "N"), "minimum size of data string") - ("max-size", qpid::optValue(maxSize, "N"), "maximum size of data string") - ("min-char", qpid::optValue(minChar, "N"), "minimum char value used in data string") - ("max-char", qpid::optValue(maxChar, "N"), "maximum char value used in data string") - ("help", qpid::optValue(help), "print this usage statement"); - } - - bool parse(int argc, char** argv) { - try { - qpid::Options::parse(argc, argv); - if (maxSize < minSize) throw qpid::Options::Exception("max-size must be greater than min-size"); - if (maxChar < minChar) throw qpid::Options::Exception("max-char must be greater than min-char"); - - if (help) { - std::cerr << *this << std::endl << std::endl; - } else { - return true; - } - } catch (const std::exception& e) { - std::cerr << *this << std::endl << std::endl << e.what() << std::endl; - } - return false; - } - -}; - -uint random(uint min, uint max) -{ - return (rand() % (max-min+1)) + min; -} - -std::string generateData(uint size, uint min, uint max) -{ - std::string data; - for (uint i = 0; i < size; i++) { - data += (char) random(min, max); - } - return data; -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - Args opts; - if (opts.parse(argc, argv)) { - srand(time(0)); - for (uint i = 0; i < opts.count; i++) { - std::cout << generateData(random(opts.minSize, opts.maxSize), opts.minChar, opts.maxChar) << std::endl; - } - return 0; - } else { - return 1; - } -} diff --git a/qpid/cpp/src/tests/declare_queues.cpp b/qpid/cpp/src/tests/declare_queues.cpp deleted file mode 100644 index bf85b9c04b..0000000000 --- a/qpid/cpp/src/tests/declare_queues.cpp +++ /dev/null @@ -1,101 +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 -#include -#include -#include - -#include -#include -#include - -using namespace qpid::client; - -using namespace std; - -int -main(int argc, char ** argv) -{ - ConnectionSettings settings; - if ( argc != 6 ) - { - cerr << "Usage: declare_queues host port durability queue_name_prefix n_queues\n"; - return 1; - } - - settings.host = argv[1]; - settings.port = atoi(argv[2]); - int durability = atoi(argv[3]); - char const * queue_name_prefix = argv[4]; - int n_queues = atoi(argv[5]); - - FailoverManager connection(settings); - - int max_fail = 13; - for ( int i = 0; i < n_queues; ++ i ) { - stringstream queue_name; - queue_name << queue_name_prefix << '_' << i; - - bool queue_created = false; - int failure_count; - - // Any non-transport failure is Bad. - try - { - while ( ! queue_created ) { - Session session = connection.connect().newSession(); - // TransportFailures aren't too bad -- they might happen because - // we are doing a cluster failover test. But if we get too many, - // we will still bug out. - failure_count = 0; - try { - if ( durability ) - session.queueDeclare(arg::queue=queue_name.str(), arg::durable=true); - else - session.queueDeclare(arg::queue=queue_name.str()); - queue_created = true; - cout << "declare_queues: Created queue " << queue_name.str() << endl; - } - catch ( const qpid::TransportFailure& ) { - if ( ++ failure_count >= max_fail ) { - cerr << "declare_queues failed: too many transport errors.\n"; - cerr << " host: " << settings.host - << " port: " << settings.port << endl; - return 1; - } - qpid::sys::sleep ( 1 ); - } - } - } - catch ( const exception & error) { - cerr << "declare_queues failed:" << error.what() << endl; - cerr << " host: " << settings.host - << " port: " << settings.port << endl; - return 1; - } - } -} - - - - - diff --git a/qpid/cpp/src/tests/dlclose_noop.c b/qpid/cpp/src/tests/dlclose_noop.c deleted file mode 100644 index b78cf486d8..0000000000 --- a/qpid/cpp/src/tests/dlclose_noop.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * 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. - * - */ - -/* - * Loaded via LD_PRELOAD this will turn dlclose into a no-op. - * - * Allows valgrind to generate useful reports from programs that - * dynamically unload libraries before exit, such as CppUnit's - * DllPlugInTester. - * - */ - -#include -void* dlclose(void* handle) { return 0; } - diff --git a/qpid/cpp/src/tests/dynamic_log_hires_timestamp b/qpid/cpp/src/tests/dynamic_log_hires_timestamp deleted file mode 100755 index 606286d9c3..0000000000 --- a/qpid/cpp/src/tests/dynamic_log_hires_timestamp +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env 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 a simple test to verify dynamic log highres timestamp changes - -source ./env.sh - -LOG_FILE=hires_test.log -trap cleanup EXIT - -cleanup() { - test -n "$PORT" && qpidd --no-module-dir --quit --port $PORT -} - -error() { - echo $*; - exit 1; -} - -rm -rf $LOG_FILE -PORT=$(qpidd --auth=no --no-module-dir --daemon --port=0 --interface 127.0.0.1 --log-to-file $LOG_FILE) || error "Could not start broker" - -echo Broker for log highres timestamp test started on $PORT, pid is $(qpidd --no-module-dir --check --port $PORT) - -qpid-ctrl -b localhost:$PORT setLogLevel level='debug+:Broker' > /dev/null -qpid-ctrl -b localhost:$PORT echo sequence=1 body=LOWRES > /dev/null -qpid-ctrl -b localhost:$PORT setLogHiresTimestamp logHires='true' > /dev/null -qpid-ctrl -b localhost:$PORT echo sequence=2 body=HI_RES > /dev/null -qpid-ctrl -b localhost:$PORT setLogHiresTimestamp logHires='false' > /dev/null -qpid-ctrl -b localhost:$PORT echo sequence=3 body=LOWRES > /dev/null - -# Expect 3 log entries with 'echo' in them -if [[ $(grep echo $LOG_FILE | wc -l) -ne 3 ]]; then - cat $LOG_FILE - error "Log content error - expected 3 echo log entries" -fi - -# Lines 1 and 3 are length X -# Line 2 is length X+10 because of timestamp addition -LEN1=$(grep echo $LOG_FILE | grep \(1 | wc -m) -LEN2=$(grep echo $LOG_FILE | grep \(2 | wc -m) -LEN3=$(grep echo $LOG_FILE | grep \(3 | wc -m) -EXPECTED_LEN2=$(( $LEN1 + 10 )) - -if [ $LEN1 -ne $LEN3 ]; then - cat $LOG_FILE - error "Log content error - expected echo 3 to be same line length as echo 1" -fi - -if [ $LEN2 -ne $EXPECTED_LEN2 ]; then - cat $LOG_FILE - error "Log content error - expected echo 2 to be 10 characters longer than echo 1" -fi - -rm -rf $LOG_FILE -echo OK - diff --git a/qpid/cpp/src/tests/dynamic_log_level_test b/qpid/cpp/src/tests/dynamic_log_level_test deleted file mode 100755 index 0ea40d11b6..0000000000 --- a/qpid/cpp/src/tests/dynamic_log_level_test +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env 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 a simple test to verify dynamic log level changes - -source ./env.sh - -LOG_FILE=log_test.log -trap cleanup EXIT - -cleanup() { - test -n "$PORT" && qpidd --no-module-dir --quit --port $PORT -} - -error() { - echo $*; - exit 1; -} - -checklog() { - if [[ $(grep echo $LOG_FILE | wc -l) -ne $1 ]]; then - cat $LOG_FILE - error "Log contents not as expected - " $2 - fi -} - -rm -rf $LOG_FILE -PORT=$(qpidd --auth=no --no-module-dir --daemon --port=0 --interface 127.0.0.1 --log-to-file $LOG_FILE) || error "Could not start broker" - -echo Broker for log level test started on $PORT, pid is $(qpidd --no-module-dir --check --port $PORT) - -# Set level to notice+ and send an echo request -# The 'echo' in the log is hidden since it is at debug level. -qpid-ctrl -b localhost:$PORT setLogLevel level='notice+' > /dev/null -qpid-ctrl -b localhost:$PORT echo sequence=1 body=HIDDEN > /dev/null -checklog 0 "Step 1 Expected no echo log entries" - -# Next, enable all Broker logs at debug and higher levels and send another echo -# This 'echo' should be in the log. -qpid-ctrl -b localhost:$PORT setLogLevel level='debug+:Broker' > /dev/null -qpid-ctrl -b localhost:$PORT echo sequence=2 body=VISIBLE > /dev/null -checklog 1 "Step 2 Expected one echo log entry" - -# Now turn on Broker debug messages but specifically disable ManagementMethod logs -# The 'echo' should be hidden. -qpid-ctrl -b localhost:$PORT setLogLevel level='debug+:Broker !debug+:broker::Broker::ManagementMethod' > /dev/null -qpid-ctrl -b localhost:$PORT echo sequence=3 body=HIDDEN > /dev/null -checklog 1 "Step 3 Expected one echo log entry" - -# Verify that the management get returns what was just set -qpid-ctrl -b localhost:$PORT getLogLevel > dynamic_log_level.tmp -if [[ $(grep 'level=debug+:Broker,!debug+:broker::Broker::ManagementMethod' dynamic_log_level.tmp | wc -l) -ne 1 ]]; then - error "Step 4 getLogLevel returned unexpected value: " `cat dynamic_log_level.tmp` -fi -rm -rf dynamic_log_level.tmp - -cleanup - -# Start another broker with --log-disable settings and make sure the management string receives them -rm -rf $LOG_FILE -PORT=$(qpidd --auth=no --no-module-dir --daemon --port=0 --interface 127.0.0.1 --log-to-file $LOG_FILE --log-enable debug:foo --log-disable debug:bar) || error "Could not start broker" -echo Broker for log level test started on $PORT, pid is $(qpidd --no-module-dir --check --port $PORT) - -qpid-ctrl -b localhost:$PORT getLogLevel > dynamic_log_level.tmp -if [[ $(grep 'level=debug:foo,!debug:bar' dynamic_log_level.tmp | wc -l) -ne 1 ]]; then - error "Step 5 getLogLevel returned unexpected value: " `cat dynamic_log_level.tmp` -fi -rm -rf dynamic_log_level.tmp - -rm -rf $LOG_FILE -echo OK - diff --git a/qpid/cpp/src/tests/echotest.cpp b/qpid/cpp/src/tests/echotest.cpp deleted file mode 100644 index 7c30989098..0000000000 --- a/qpid/cpp/src/tests/echotest.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; -using namespace std; - -namespace qpid { -namespace tests { - -struct Args : public qpid::Options, - public qpid::client::ConnectionSettings -{ - bool help; - uint count; - uint size; - bool summary; - - Args() : qpid::Options("Simple latency test optins"), help(false), count(20), size(0), summary() - { - using namespace qpid; - addOptions() - ("help", optValue(help), "Print this usage statement") - ("count", optValue(count, "N"), "Number of messages to send") - ("size", optValue(count, "N"), "Size of messages") - ("broker,b", optValue(host, "HOST"), "Broker host to connect to") - ("port,p", optValue(port, "PORT"), "Broker port to connect to") - ("username", optValue(username, "USER"), "user name for broker log in.") - ("password", optValue(password, "PASSWORD"), "password for broker log in.") - ("mechanism", optValue(mechanism, "MECH"), "SASL mechanism to use when authenticating.") - ("tcp-nodelay", optValue(tcpNoDelay), "Turn on tcp-nodelay") - ("s,summary", optValue(summary), "Print only average latency."); - } -}; - -uint64_t current_time() -{ - return Duration::FromEpoch(); -} - -class Listener : public MessageListener -{ - private: - Session session; - SubscriptionManager subscriptions; - uint counter; - const uint limit; - std::string queue; - Message request; - double total, min, max; - bool summary; - - public: - Listener(Session& session, uint limit, bool summary); - void start(uint size); - void received(Message& message); -}; - -Listener::Listener(Session& s, uint l, bool summary_) : - session(s), subscriptions(s), counter(0), limit(l), - queue(session.getId().getName()), total(), - min(std::numeric_limits::max()), max(), summary(summary_) -{} - -void Listener::start(uint size) -{ - session.queueDeclare(arg::queue=queue, arg::exclusive=true, arg::autoDelete=true); - request.getDeliveryProperties().setRoutingKey(queue); - subscriptions.subscribe(*this, queue, SubscriptionSettings(FlowControl::unlimited(), ACCEPT_MODE_NONE)); - - request.getDeliveryProperties().setTimestamp(current_time()); - if (size) request.setData(std::string(size, 'X')); - async(session).messageTransfer(arg::content=request); - subscriptions.run(); -} - -void Listener::received(Message& response) -{ - //extract timestamp and compute latency: - uint64_t sentAt = response.getDeliveryProperties().getTimestamp(); - uint64_t receivedAt = current_time(); - - double latency = ((double) (receivedAt - sentAt)) / TIME_MSEC; - if (!summary) cout << "Latency: " << latency << "ms" << endl; - min = std::min(latency, min); - max = std::max(latency, max); - total += latency; - - if (++counter < limit) { - request.getDeliveryProperties().setTimestamp(current_time()); - async(session).messageTransfer(arg::content=request); - } else { - subscriptions.cancel(queue); - if (summary) cout << min << "\t" << max << "\t" << total/limit << endl; - else cout << "min: " << min << " max: " << max << " average: " << total/limit << endl; - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - Args opts; - opts.parse(argc, argv); - - if (opts.help) { - std::cout << opts << std::endl; - return 0; - } - - Connection connection; - try { - connection.open(opts); - Session session = connection.newSession(); - Listener listener(session, opts.count, opts.summary); - listener.start(opts.size); - - connection.close(); - return 0; - } catch(const std::exception& error) { - std::cout << error.what() << std::endl; - } - return 1; -} - - diff --git a/qpid/cpp/src/tests/env.ps1.in b/qpid/cpp/src/tests/env.ps1.in deleted file mode 100644 index 94834a4b5e..0000000000 --- a/qpid/cpp/src/tests/env.ps1.in +++ /dev/null @@ -1,77 +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. -# - -# Environment variables substituted by configure/cmake. -$abs_srcdir="@abs_srcdir@" -$abs_builddir="@abs_builddir@" -$top_srcdir="@abs_top_srcdir@" -$top_builddir="@abs_top_builddir@" -$moduledir="$top_builddir\src@builddir_lib_suffix@" -$testmoduledir="$builddir@builddir_lib_suffix@" -$BOOST_LIBRARYDIR="@BOOST_LIBRARYDIR@" - -# Python paths and directories -$PYTHON_EXE="@PYTHON_EXECUTABLE@" -$PYTHON_DIR="$builddir\python" -$QPID_PYTHON_TEST="$PYTHON_DIR\commands\qpid-python-test" -if ( !(Test-Path "$PYTHON_DIR") -and (Test-Path "$top_srcdir\..\python")) { - $PYTHON_DIR="$top_srcdir\..\python" - $QPID_PYTHON_TEST="$PYTHON_DIR\qpid-python-test" -} -$QPID_TESTS="$top_srcdir\..\tests" -$QPID_TESTS_PY="$QPID_TESTS\src\py" -$QPID_TOOLS="$top_srcdir\..\tools" -$QPID_TOOLS_LIBS="$QPID_TOOLS\src\py" -$QMF_LIB="$top_srcdir\..\extras\qmf\src\py" -$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_HA_TOOL_EXEC="$PYTHON_COMMANDS\qpid-ha-tool" - -# Executables -$env:QPIDD_EXEC="$top_builddir\src\@CMAKE_BUILD_TYPE@\qpidd.exe" -$env:QPID_WATCHDOG_EXEC="$top_builddir\src\qpidd_watchdog" - -# Test executables -$QPID_TEST_EXEC_DIR="$builddir\@CMAKE_BUILD_TYPE@" -$RECEIVER_EXEC="$QPID_TEST_EXEC_DIR\receiver" -$SENDER_EXEC="$QPID_TEST_EXEC_DIR\sender" - -# Path -$env:PATH="$top_builddir\src\@CMAKE_BUILD_TYPE@;$builddir\@CMAKE_BUILD_TYPE@;$srcdir;$PYTHON_COMMANDS;$QPID_TEST_EXEC_DIR;@BOOST_LIBRARYDIR@;$env:PATH" - -# Modules -$env:TEST_STORE_LIB="$testmoduledir\test_store.so" - -#exportmodule() { test -f $moduledir/$2 && eval "export $1=$moduledir/$2"; } -#exportmodule ACL_LIB acl.so -#exportmodule CLUSTER_LIB cluster.so -#exportmodule SSLCONNECTOR_LIB sslconnector.so -#exportmodule SSL_LIB ssl.so -#exportmodule WATCHDOG_LIB watchdog.so -#exportmodule XML_LIB xml.so - -# Qpid options -$env:QPID_NO_MODULE_DIR="1" # Don't accidentally load installed modules -$env:QPID_DATA_DIR= # Default to no data dir, not ~/.qpidd - -# Options for boost test framework -$env:BOOST_TEST_SHOW_PROGRESS="yes" -$env:BOOST_TEST_CATCH_SYSTEM_ERRORS="no" diff --git a/qpid/cpp/src/tests/env.py.in b/qpid/cpp/src/tests/env.py.in deleted file mode 100644 index 29b8c8739c..0000000000 --- a/qpid/cpp/src/tests/env.py.in +++ /dev/null @@ -1,116 +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. -# - -from __future__ import print_function - -from plano import * - -import platform as _platform - -WINDOWS = _platform.system() == "Windows" - -def _export(name, value): - globals()[name] = value - - if value is not None: - ENV[name] = value - -def _export_module(name, path): - _export(name, None) - - if exists(path): - _export(name, path) - -_cmake_build_type = "RelWithDebInfo" # XXX - -# Variables substituted by cmake - -_export("BUILD_DIR", normalize_path("@CMAKE_BINARY_DIR@")) -_export("SOURCE_DIR", normalize_path("@CMAKE_SOURCE_DIR@")) -_export("SASLPASSWD2", normalize_path("@SASLPASSWD2_EXECUTABLE@")) -_export("PYTHON", normalize_path("@PYTHON_EXECUTABLE@")) -_export("VALGRIND", None) - -if "@ENABLE_VALGRIND@" == "ON": - _export("VALGRIND", normalize_path("@VALGRIND_EXECUTABLE@")) - -# Python path - -_python_path = [ - join(BUILD_DIR, "src", "tests"), - join(BUILD_DIR, "bindings", "qpid", "python"), - join(BUILD_DIR, "management", "python", "lib"), -] - -if "PYTHONPATH" in ENV: - _python_path.extend(ENV["PYTHONPATH"].split(PATH_VAR_SEP)) - -ENV["PYTHONPATH"] = PATH_VAR_SEP.join(_python_path) - -# Path - -_build_src_dir = join(BUILD_DIR, "src") -_build_tests_dir = join(BUILD_DIR, "src", "tests") - -if WINDOWS: - _build_src_dir = join(_build_src_dir, _cmake_build_type) - _build_tests_dir = join(_build_tests_dir, _cmake_build_type) - -_path = [ - _build_src_dir, - _build_tests_dir, - join(BUILD_DIR, "management", "python", "bin"), -] - -if "PATH" in ENV: - _path.extend(ENV["PATH"].split(PATH_VAR_SEP)) - -ENV["PATH"] = PATH_VAR_SEP.join(_path) - -# Modules - -_module_prefix = join(BUILD_DIR, "src") - -if WINDOWS: - _module_prefix = join(_module_prefix, _cmake_build_type) - -_export_module("HA_LIB", join(_module_prefix, "ha@CMAKE_SHARED_LIBRARY_SUFFIX@")) -_export_module("XML_LIB", join(_module_prefix, "xml@CMAKE_SHARED_LIBRARY_SUFFIX@")) -_export_module("AMQP_LIB", join(_module_prefix, "amqp@CMAKE_SHARED_LIBRARY_SUFFIX@")) -_export_module("TEST_STORE_LIB", join(_module_prefix, "tests", "test_store@CMAKE_SHARED_LIBRARY_SUFFIX@")) -_export_module("STORE_LIB", join(_module_prefix, "linearstore@CMAKE_SHARED_LIBRARY_SUFFIX@")) - -if STORE_LIB is None: - _export_module("STORE_LIB", join(_module_prefix, "legacystore@CMAKE_SHARED_LIBRARY_SUFFIX@")) - -# Summarize - -print("PWD: {0}".format(current_dir())) -print("SOURCE_DIR: {0}".format(SOURCE_DIR)) -print("BUILD_DIR: {0}".format(BUILD_DIR)) - -print("PATH:") - -for item in _path: - print(" {0}".format(item)) - -print("PYTHONPATH:") - -for item in _python_path: - print(" {0}".format(item)) diff --git a/qpid/cpp/src/tests/env.sh.in b/qpid/cpp/src/tests/env.sh.in deleted file mode 100644 index 7ff42df1b7..0000000000 --- a/qpid/cpp/src/tests/env.sh.in +++ /dev/null @@ -1,76 +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. -# - -# Environment variables substituted by cmake - -export BUILD_DIR=@CMAKE_BINARY_DIR@ -export SOURCE_DIR=@CMAKE_SOURCE_DIR@ - -export SASLPASSWD2=@SASLPASSWD2_EXECUTABLE@ -export PYTHON=@PYTHON_EXECUTABLE@ - -if [[ "@ENABLE_VALGRIND@" == "ON" ]]; then - export VALGRIND=@VALGRIND_EXECUTABLE@ -fi - -# Python path - -export PYTHONPATH=$BUILD_DIR/src/tests:$BUILD_DIR/bindings/qpid/python:$BUILD_DIR/management/python/lib:${PYTHONPATH-} - -# Path - -export PATH=$BUILD_DIR/src:$BUILD_DIR/src/tests:$BUILD_DIR/management/python/bin:${PATH-} - -# Modules - -function export_module { - if [[ -f $BUILD_DIR/src/$2 ]]; then - export $1=$BUILD_DIR/src/$2 - fi -} - -export_module HA_LIB ha.so -export_module XML_LIB xml.so -export_module AMQP_LIB amqp.so - -[[ ${STORE_LIB-} ]] || export_module STORE_LIB linearstore.so -[[ ${STORE_LIB-} ]] || export_module STORE_LIB legacystore.so - -export TEST_STORE_LIB=$BUILD_DIR/src/tests/test_store.so - -# Qpidd options - Eliminate - -export QPID_NO_MODULE_DIR=1 # Don't accidentally load installed modules -export QPID_DATA_DIR= # Disable persistence -export QPID_CONFIG=$SOURCE_DIR/src/tests/qpidd-empty.conf - -# Options for boost test framework - -[[ ${BOOST_TEST_SHOW_PROGRESS-} ]] || export BOOST_TEST_SHOW_PROGRESS=yes -[[ ${BOOST_TEST_CATCH_SYSTEM_ERRORS-} ]] || export BOOST_TEST_CATCH_SYSTEM_ERRORS=no - -echo "PWD: $PWD" -echo "SOURCE_DIR: ${SOURCE_DIR}" -echo "BUILD_DIR: ${BUILD_DIR}" - -echo "PATH:" -echo -n " "; echo $PATH | sed 's/:/\n /g' - -echo "PYTHONPATH:" -echo -n " "; echo $PYTHONPATH | sed 's/:/\n /g' diff --git a/qpid/cpp/src/tests/exception_test.cpp b/qpid/cpp/src/tests/exception_test.cpp deleted file mode 100644 index b880069575..0000000000 --- a/qpid/cpp/src/tests/exception_test.cpp +++ /dev/null @@ -1,125 +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 "unit_test.h" -#include "test_tools.h" -#include "BrokerFixture.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/MessageListener.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/framing/reply_exceptions.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(exception_test) - -// FIXME aconway 2008-06-12: need to update our exception handling to -// 0-10 handling and extend this test to provoke all the exceptional -// conditions we know of and verify the correct exception is thrown. - -using namespace std; -using namespace qpid; -using namespace sys; -using namespace client; -using namespace framing; - -using qpid::broker::Broker; -using boost::bind; -using boost::function; - -template -struct Catcher : public Runnable { - function f; - bool caught; - Thread thread; - - Catcher(function f_) : f(f_), caught(false), thread(this) {} - ~Catcher() { join(); } - - void run() { - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f(); - } - catch(const Ex& e) { - caught=true; - BOOST_TEST_MESSAGE(string("Caught expected exception: ")+e.what()+"["+typeid(e).name()+"]"); - } - catch(const std::exception& e) { - BOOST_ERROR(string("Bad exception: ")+e.what()+"["+typeid(e).name()+"] expected: "+typeid(Ex).name()); - } - catch(...) { - BOOST_ERROR(string("Bad exception: unknown")); - } - } - - bool join() { - if (thread) { - thread.join(); - thread=Thread(); - } - return caught; - } -}; - -QPID_AUTO_TEST_CASE(TestSessionBusy) { - SessionFixture f; - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f.connection.newSession(f.session.getId().getName()); - BOOST_FAIL("Expected SessionBusyException for " << f.session.getId().getName()); - } catch (const SessionBusyException&) {} // FIXME aconway 2008-09-22: client is not throwing correct exception. -} - -QPID_AUTO_TEST_CASE(DisconnectedPop) { - SessionFixture fix; - fix.session.queueDeclare(arg::queue="q"); - fix.subs.subscribe(fix.lq, "q"); - Catcher pop(bind(&LocalQueue::pop, &fix.lq, sys::TIME_SEC)); - fix.shutdownBroker(); - BOOST_CHECK(pop.join()); -} - -QPID_AUTO_TEST_CASE(DisconnectedListen) { - SessionFixture fix; - struct NullListener : public MessageListener { - void received(Message&) { BOOST_FAIL("Unexpected message"); } - } l; - fix.session.queueDeclare(arg::queue="q"); - fix.subs.subscribe(l, "q"); - - Catcher runner(bind(&SubscriptionManager::run, boost::ref(fix.subs))); - fix.shutdownBroker(); - runner.join(); - BOOST_CHECK_THROW(fix.session.queueDeclare(arg::queue="x"), TransportFailure); -} - -QPID_AUTO_TEST_CASE(NoSuchQueueTest) { - SessionFixture fix; - ScopedSuppressLogging sl; // Suppress messages for expected errors. - BOOST_CHECK_THROW(fix.subs.subscribe(fix.lq, "no such queue"), NotFoundException); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/failing-amqp0-10-python-tests b/qpid/cpp/src/tests/failing-amqp0-10-python-tests deleted file mode 100644 index afa263217f..0000000000 --- a/qpid/cpp/src/tests/failing-amqp0-10-python-tests +++ /dev/null @@ -1,32 +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. -# - -#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 - -# The following test fails because the swig client throws an error -# when creating a sender with a node name that is ambiguous and no -# type specified. By contrast the pure python client defaults to the -# queue in this case. -qpid_tests.broker_0_10.new_api.GeneralTests.test_node_disambiguation_2 diff --git a/qpid/cpp/src/tests/failing-amqp1.0-python-tests b/qpid/cpp/src/tests/failing-amqp1.0-python-tests deleted file mode 100644 index e76d05d7be..0000000000 --- a/qpid/cpp/src/tests/failing-amqp1.0-python-tests +++ /dev/null @@ -1,25 +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. -# - -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 -qpid_tests.broker_0_10.new_api.GeneralTests.test_nolocal_rerouted -qpid_tests.broker_0_10.new_api.GeneralTests.test_ambiguous_delete_1 -qpid_tests.broker_0_10.new_api.GeneralTests.test_ambiguous_delete_2 -qpid_tests.broker_0_10.new_api.GeneralTests.test_node_disambiguation_2 diff --git a/qpid/cpp/src/tests/federated_topic_test b/qpid/cpp/src/tests/federated_topic_test deleted file mode 100755 index b8356b4b9d..0000000000 --- a/qpid/cpp/src/tests/federated_topic_test +++ /dev/null @@ -1,127 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 topic test on a federated setup - -# Clean up old log files -rm -f subscriber_*.log - -# Defaults values -SUBSCRIBERS=2 -MESSAGES=1000 -BATCHES=1 -VERBOSE=1 - -while getopts "s:m:b:" opt ; do - case $opt in - s) SUBSCRIBERS=$OPTARG ;; - m) MESSAGES=$OPTARG ;; - b) BATCHES=$OPTARG ;; - ?) - echo "Usage: %0 [-s ] [-m ]" - exit 1 - ;; - esac -done - -source ./env.sh - -trap stop_brokers EXIT - -start_broker() { - qpidd --daemon --port 0 --interface 127.0.0.1 --no-module-dir --no-data-dir --auth no > qpidd.port -} - -start_brokers() { - start_broker - PORT_A=`cat qpidd.port` - start_broker - PORT_B=`cat qpidd.port` - start_broker - PORT_C=`cat qpidd.port` -} - -stop_brokers() { - for p in $PORT_A $PORT_B $PORT_C; do - qpidd --no-module-dir -q --port $p - done -} - -subscribe() { - #which broker should we connect to? - if (( $1 % 2 )); then - MY_PORT=$PORT_C; - else - MY_PORT=$PORT_A; - fi - - echo Subscriber $1 connecting on $MY_PORT - LOG="subscriber_$1.log" - qpid-topic-listener -p $MY_PORT > $LOG 2>&1 && rm -f $LOG -} - -publish() { - qpid-topic-publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS -p $PORT_A -} - -setup_routes() { - BROKER_A="daffodil:$PORT_A" - BROKER_B="daffodil:$PORT_B" - BROKER_C="daffodil:$PORT_C" - if (($VERBOSE)); then - echo "Establishing routes for topic..." - fi - qpid-route route add $BROKER_B $BROKER_A amq.topic topic_control B B - qpid-route route add $BROKER_C $BROKER_B amq.topic topic_control C C - if (($VERBOSE)); then - echo "linked A->B->C" - fi - qpid-route route add $BROKER_B $BROKER_C amq.topic topic_control B B - qpid-route route add $BROKER_A $BROKER_B amq.topic topic_control A A - if (($VERBOSE)); then - echo "linked C->B->A" - echo "Establishing routes for response queue..." - fi - - qpid-route route add $BROKER_B $BROKER_C amq.direct response B B - qpid-route route add $BROKER_A $BROKER_B amq.direct response A A - if (($VERBOSE)); then - echo "linked C->B->A" - for b in $BROKER_A $BROKER_B $BROKER_C; do - echo "Routes for $b" - qpid-route route list $b - done - fi -} - -start_brokers - -if (($VERBOSE)); then - echo "Running federated topic test against brokers on ports $PORT_A $PORT_B $PORT_C" -fi - -for ((i=$SUBSCRIBERS ; i--; )); do - subscribe $i & -done - -setup_routes - -publish || exit 1 diff --git a/qpid/cpp/src/tests/federation.py b/qpid/cpp/src/tests/federation.py deleted file mode 100755 index f5b62019e5..0000000000 --- a/qpid/cpp/src/tests/federation.py +++ /dev/null @@ -1,2793 +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. -# - -import sys -from qpid.testlib import TestBase010 -from qpid.datatypes import Message -from qpid.queue import Empty -from qpid.util import URL -import qpid.messaging -from time import sleep, time - - -class _FedBroker(object): - """ - A proxy object for a remote broker. Contains connection and management - state. - """ - def __init__(self, host, port, - conn=None, session=None, qmf_broker=None): - self.host = host - self.port = port - self.url = "%s:%d" % (host, port) - self.client_conn = None - self.client_session = None - self.qmf_broker = None - self.qmf_object = None - if conn is not None: - self.client_conn = conn - if session is not None: - self.client_session = session - if qmf_broker is not None: - self.qmf_broker = qmf_broker - - -class FederationTests(TestBase010): - - def remote_host(self): - return self.defines.get("remote-host", "localhost") - - def remote_port(self): - return int(self.defines["remote-port"]) - - def verify_cleanup(self): - attempts = 0 - total = len(self.qmf.getObjects(_class="bridge")) + len(self.qmf.getObjects(_class="link")) - while total > 0: - attempts += 1 - if attempts >= 10: - self.fail("Bridges and links didn't clean up") - return - sleep(1) - total = len(self.qmf.getObjects(_class="bridge")) + len(self.qmf.getObjects(_class="link")) - - def _setup_brokers(self): - ports = [self.remote_port()] - extra = self.defines.get("extra-brokers") - if extra: - for p in extra.split(): - ports.append(int(p)) - - # broker[0] has already been set up. - self._brokers = [_FedBroker(self.broker.host, - self.broker.port, - self.conn, - self.session, - self.qmf_broker)] - self._brokers[0].qmf_object = self.qmf.getObjects(_class="broker")[0] - - # setup remaining brokers - for _p in ports: - _b = _FedBroker(self.remote_host(), _p) - _b.client_conn = self.connect(host=self.remote_host(), port=_p) - _b.client_session = _b.client_conn.session("Fed_client_session_" + str(_p)) - _b.qmf_broker = self.qmf.addBroker(_b.url) - for _bo in self.qmf.getObjects(_class="broker"): - if _bo.getBroker().getUrl() == _b.qmf_broker.getUrl(): - _b.qmf_object = _bo - break - self._brokers.append(_b) - - # add a new-style messaging connection to each broker - for _b in self._brokers: - _b.connection = qpid.messaging.Connection(_b.url) - _b.connection.open() - - def _teardown_brokers(self): - """ Un-does _setup_brokers() - """ - # broker[0] is configured at test setup, so it must remain configured - for _b in self._brokers[1:]: - self.qmf.delBroker(_b.qmf_broker) - if not _b.client_session.error(): - _b.client_session.close(timeout=10) - _b.client_conn.close(timeout=10) - _b.connection.close() - - def test_bridge_create_and_close(self): - self.startQmf(); - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0, result) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "amq.direct", "amq.direct", "my-key", "", - "", False, False, False, 0, 0) - self.assertEqual(result.status, 0, result) - - bridge = qmf.getObjects(_class="bridge")[0] - result = bridge.close() - self.assertEqual(result.status, 0, result) - - result = link.close() - self.assertEqual(result.status, 0, result) - - self.verify_cleanup() - - def test_pull_from_exchange(self): - """ This test uses an alternative method to manage links and bridges - via the broker object. - """ - session = self.session - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - - # create link - link_args = {"host":self.remote_host(), "port":self.remote_port(), "durable":False, - "authMechanism":"PLAIN", "username":"guest", "password":"guest", - "transport":"tcp"} - result = broker.create("link", "test-link-1", link_args, False) - self.assertEqual(result.status, 0, result) - link = qmf.getObjects(_class="link")[0] - - # create bridge - bridge_args = {"link":"test-link-1", "src":"amq.direct", "dest":"amq.fanout", - "key":"my-key"} - result = broker.create("bridge", "test-bridge-1", bridge_args, False); - self.assertEqual(result.status, 0, result) - bridge = qmf.getObjects(_class="bridge")[0] - - #setup queue to receive messages from local broker - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - sleep(6) - - #send messages to remote broker and confirm it is routed to local broker - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_pull_from_exchange") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="my-key") - r_session.message_transfer(destination="amq.direct", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - - result = broker.delete("bridge", "test-bridge-1", {}) - self.assertEqual(result.status, 0, result) - - result = broker.delete("link", "test-link-1", {}) - self.assertEqual(result.status, 0, result) - - self.verify_cleanup() - - def test_push_to_exchange(self): - session = self.session - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0, result) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "", "", False, True, False, 0, 0) - self.assertEqual(result.status, 0, result) - - bridge = qmf.getObjects(_class="bridge")[0] - - #setup queue to receive messages from remote broker - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_push_to_exchange") - r_session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - r_session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(session=r_session, queue="fed1", destination="f1") - queue = r_session.incoming("f1") - sleep(6) - - #send messages to local broker and confirm it is routed to remote broker - for i in range(1, 11): - dp = session.delivery_properties(routing_key="my-key") - session.message_transfer(destination="amq.direct", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0, result) - result = link.close() - self.assertEqual(result.status, 0, result) - - self.verify_cleanup() - - def test_pull_from_queue(self): - session = self.session - - #setup queue on remote broker and add some messages - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_pull_from_queue") - r_session.queue_declare(queue="my-bridge-queue", auto_delete=True) - for i in range(1, 6): - dp = r_session.delivery_properties(routing_key="my-bridge-queue") - r_session.message_transfer(message=Message(dp, "Message %d" % i)) - - #setup queue to receive messages from local broker - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0, result) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "my-bridge-queue", "amq.fanout", "my-key", "", "", True, False, False, 1, 0) - self.assertEqual(result.status, 0, result) - - bridge = qmf.getObjects(_class="bridge")[0] - sleep(3) - - #add some more messages (i.e. after bridge was created) - for i in range(6, 11): - dp = r_session.delivery_properties(routing_key="my-bridge-queue") - r_session.message_transfer(message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - try: - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - except Empty: - self.fail("Failed to find expected message containing 'Message %d'" % i) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0, result) - result = link.close() - self.assertEqual(result.status, 0, result) - - self.verify_cleanup() - - def test_pull_from_queue_recovery(self): - session = self.session - - #setup queue on remote broker and add some messages - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_pull_from_queue_recovery") - # disable auto-delete otherwise the detach of the fed session may - # delete the queue right after this test re-creates it. - r_session.queue_declare(queue="my-bridge-queue", auto_delete=False) - for i in range(1, 6): - dp = r_session.delivery_properties(routing_key="my-bridge-queue") - r_session.message_transfer(message=Message(dp, "Message %d" % i)) - - #setup queue to receive messages from local broker - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0, result) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "my-bridge-queue", "amq.fanout", "my-key", "", "", True, False, False, 1, 0) - self.assertEqual(result.status, 0, result) - - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - #recreate the remote bridge queue to invalidate the bridge session - r_session.queue_delete (queue="my-bridge-queue", if_empty=False, if_unused=False) - r_session.queue_declare(queue="my-bridge-queue", auto_delete=False) - - #add some more messages (i.e. after bridge was created) - for i in range(6, 11): - dp = r_session.delivery_properties(routing_key="my-bridge-queue") - r_session.message_transfer(message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - try: - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - except Empty: - self.fail("Failed to find expected message containing 'Message %d'" % i) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - self.verify_cleanup() - r_session.queue_delete (queue="my-bridge-queue", if_empty=False, if_unused=False) - - def test_tracing_automatic(self): - remoteUrl = "%s:%d" % (self.remote_host(), self.remote_port()) - self.startQmf() - l_broker = self.qmf_broker - r_broker = self.qmf.addBroker(remoteUrl) - - l_brokerObj = self.qmf.getObjects(_class="broker", _broker=l_broker)[0] - r_brokerObj = self.qmf.getObjects(_class="broker", _broker=r_broker)[0] - - l_res = l_brokerObj.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - r_res = r_brokerObj.connect(self.broker.host, self.broker.port, False, "PLAIN", "guest", "guest", "tcp") - - self.assertEqual(l_res.status, 0) - self.assertEqual(r_res.status, 0) - - l_link = self.qmf.getObjects(_class="link", _broker=l_broker)[0] - r_link = self.qmf.getObjects(_class="link", _broker=r_broker)[0] - - l_res = l_link.bridge(False, "amq.direct", "amq.direct", "key", "", "", False, False, False, 0, 0) - r_res = r_link.bridge(False, "amq.direct", "amq.direct", "key", "", "", False, False, False, 0, 0) - - self.assertEqual(l_res.status, 0) - self.assertEqual(r_res.status, 0) - - count = 0 - while l_link.state != "Operational" or r_link.state != "Operational": - count += 1 - if count > 10: - self.fail("Fed links didn't become operational after 10 seconds") - sleep(1) - l_link = self.qmf.getObjects(_class="link", _broker=l_broker)[0] - r_link = self.qmf.getObjects(_class="link", _broker=r_broker)[0] - sleep(3) - - #setup queue to receive messages from local broker - session = self.session - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.direct", binding_key="key") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - #setup queue on remote broker and add some messages - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_trace") - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="key") - r_session.message_transfer(destination="amq.direct", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - try: - msg = queue.get(timeout=5) - mp = msg.get("message_properties").application_headers - self.assertEqual(mp.__class__, dict) - self.assertEqual(mp['x-qpid.trace'], 'REMOTE') # check that the federation-tag override works - self.assertEqual("Message %d" % i, msg.body) - except Empty: - self.fail("Failed to find expected message containing 'Message %d'" % i) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - def test_tracing(self): - session = self.session - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "my-bridge-id", - "exclude-me,also-exclude-me", False, False, False, 0, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - - #setup queue to receive messages from local broker - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - sleep(6) - - #send messages to remote broker and confirm it is routed to local broker - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_tracing") - - trace = [None, "exclude-me", "a,exclude-me,b", "also-exclude-me,c", "dont-exclude-me"] - body = ["yes", "first-bad", "second-bad", "third-bad", "yes"] - for b, t in zip(body, trace): - headers = {} - if (t): headers["x-qpid.trace"]=t - dp = r_session.delivery_properties(routing_key="my-key", ttl=1000*60*5) - mp = r_session.message_properties(application_headers=headers) - r_session.message_transfer(destination="amq.direct", message=Message(dp, mp, b)) - - for e in ["my-bridge-id", "dont-exclude-me,my-bridge-id"]: - msg = queue.get(timeout=5) - self.assertEqual("yes", msg.body) - self.assertEqual(e, self.getAppHeader(msg, "x-qpid.trace")) - assert(msg.get("delivery_properties").ttl > 0) - assert(msg.get("delivery_properties").ttl < 1000*60*50) - - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_fanout(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_fanout") - - session.exchange_declare(exchange="fed.fanout", type="fanout") - r_session.exchange_declare(exchange="fed.fanout", type="fanout") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.fanout", "fed.fanout", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties() - r_session.message_transfer(destination="fed.fanout", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - - def test_dynamic_direct(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_direct") - - session.exchange_declare(exchange="fed.direct", type="direct") - r_session.exchange_declare(exchange="fed.direct", type="direct") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.direct", "fed.direct", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.direct", binding_key="fd-key") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="fd-key") - r_session.message_transfer(destination="fed.direct", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_topic(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_topic") - - session.exchange_declare(exchange="fed.topic", type="topic") - r_session.exchange_declare(exchange="fed.topic", type="topic") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.topic", "fed.topic", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.topic", binding_key="ft-key.#") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="ft-key.one.two") - r_session.message_transfer(destination="fed.topic", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_topic_reorigin(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_topic_reorigin") - - session.exchange_declare(exchange="fed.topic_reorigin", type="topic") - r_session.exchange_declare(exchange="fed.topic_reorigin", type="topic") - - session.exchange_declare(exchange="fed.topic_reorigin_2", type="topic") - r_session.exchange_declare(exchange="fed.topic_reorigin_2", type="topic") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - session.queue_declare(queue="fed2", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed2", exchange="fed.topic_reorigin_2", binding_key="ft-key.one.#") - self.subscribe(queue="fed2", destination="f2") - queue2 = session.incoming("f2") - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.topic_reorigin", "fed.topic_reorigin", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - result = link.bridge(False, "fed.topic_reorigin_2", "fed.topic_reorigin_2", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - bridge2 = qmf.getObjects(_class="bridge")[1] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.topic_reorigin", binding_key="ft-key.#") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="ft-key.one.two") - r_session.message_transfer(destination="fed.topic_reorigin", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = bridge2.close() - self.assertEqual(result.status, 0) - - # extra check: verify we don't leak bridge objects - keep the link - # around and verify the bridge count has gone to zero - - attempts = 0 - bridgeCount = len(qmf.getObjects(_class="bridge")) - while bridgeCount > 0: - attempts += 1 - if attempts >= 5: - self.fail("Bridges didn't clean up") - return - sleep(1) - bridgeCount = len(qmf.getObjects(_class="bridge")) - - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_direct_reorigin(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_direct_reorigin") - - session.exchange_declare(exchange="fed.direct_reorigin", type="direct") - r_session.exchange_declare(exchange="fed.direct_reorigin", type="direct") - - session.exchange_declare(exchange="fed.direct_reorigin_2", type="direct") - r_session.exchange_declare(exchange="fed.direct_reorigin_2", type="direct") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - session.queue_declare(queue="fed2", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed2", exchange="fed.direct_reorigin_2", binding_key="ft-key.two") - self.subscribe(queue="fed2", destination="f2") - queue2 = session.incoming("f2") - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.direct_reorigin", "fed.direct_reorigin", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - result = link.bridge(False, "fed.direct_reorigin_2", "fed.direct_reorigin_2", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - bridge2 = qmf.getObjects(_class="bridge")[1] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.direct_reorigin", binding_key="ft-key.one") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="ft-key.one") - r_session.message_transfer(destination="fed.direct_reorigin", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - - # Extra test: don't explicitly close() bridge2. When the link is closed, - # it should clean up bridge2 automagically. verify_cleanup() will detect - # if bridge2 isn't cleaned up and will fail the test. - # - #result = bridge2.close() - #self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_any(self): - self.do_test_dynamic_headers('any') - - def test_dynamic_headers_all(self): - self.do_test_dynamic_headers('all') - - - def do_test_dynamic_headers(self, match_mode): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_%s" % match_mode) - - session.exchange_declare(exchange="fed.headers", type="headers") - r_session.exchange_declare(exchange="fed.headers", type="headers") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.headers", "fed.headers", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.headers", binding_key="key1", arguments={'x-match':match_mode, 'class':'first'}) - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - props = r_session.message_properties(application_headers={'class':'first'}) - for i in range(1, 11): - r_session.message_transfer(destination="fed.headers", message=Message(props, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - content = msg.body - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_reorigin(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_reorigin") - - session.exchange_declare(exchange="fed.headers_reorigin", type="headers") - r_session.exchange_declare(exchange="fed.headers_reorigin", type="headers") - - session.exchange_declare(exchange="fed.headers_reorigin_2", type="headers") - r_session.exchange_declare(exchange="fed.headers_reorigin_2", type="headers") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - session.queue_declare(queue="fed2", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed2", exchange="fed.headers_reorigin_2", binding_key="key2", arguments={'x-match':'any', 'class':'second'}) - self.subscribe(queue="fed2", destination="f2") - queue2 = session.incoming("f2") - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.headers_reorigin", "fed.headers_reorigin", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - result = link.bridge(False, "fed.headers_reorigin_2", "fed.headers_reorigin_2", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - bridge2 = qmf.getObjects(_class="bridge")[1] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.headers_reorigin", binding_key="key1", arguments={'x-match':'any', 'class':'first'}) - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - props = r_session.message_properties(application_headers={'class':'first'}) - for i in range(1, 11): - r_session.message_transfer(destination="fed.headers_reorigin", message=Message(props, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - - # Extra test: don't explicitly close() bridge2. When the link is closed, - # it should clean up bridge2 automagically. verify_cleanup() will detect - # if bridge2 isn't cleaned up and will fail the test. - # - #result = bridge2.close() - #self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_unbind(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_unbind") - - session.exchange_declare(exchange="fed.headers_unbind", type="headers") - r_session.exchange_declare(exchange="fed.headers_unbind", type="headers") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.headers_unbind", "fed.headers_unbind", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - queue = qmf.getObjects(_class="queue", name="fed1")[0] - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - session.exchange_bind(queue="fed1", exchange="fed.headers_unbind", binding_key="key1", arguments={'x-match':'any', 'class':'first'}) - queue.update() - self.assertEqual(queue.bindingCount, 2, - "bindings not accounted for (expected 2, got %d)" % queue.bindingCount) - - session.exchange_unbind(queue="fed1", exchange="fed.headers_unbind", binding_key="key1") - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - - def test_dynamic_headers_xml(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_xml") - - session.exchange_declare(exchange="fed.xml", type="xml") - r_session.exchange_declare(exchange="fed.xml", type="xml") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.xml", "fed.xml", "", "", "", False, False, True, 0, 0) - - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.xml", binding_key="key1", arguments={'xquery':'true()'}) - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - props = r_session.delivery_properties(routing_key="key1") - for i in range(1, 11): - r_session.message_transfer(destination="fed.xml", message=Message(props, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - content = msg.body - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_reorigin_xml(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_reorigin_xml") - - session.exchange_declare(exchange="fed.xml_reorigin", type="xml") - r_session.exchange_declare(exchange="fed.xml_reorigin", type="xml") - - session.exchange_declare(exchange="fed.xml_reorigin_2", type="xml") - r_session.exchange_declare(exchange="fed.xml_reorigin_2", type="xml") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - session.queue_declare(queue="fed2", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed2", exchange="fed.xml_reorigin_2", binding_key="key2", arguments={'xquery':'true()'}) - self.subscribe(queue="fed2", destination="f2") - queue2 = session.incoming("f2") - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.xml_reorigin", "fed.xml_reorigin", "", "", "", False, False, True, 0, 0) - - self.assertEqual(result.status, 0) - result = link.bridge(False, "fed.xml_reorigin_2", "fed.xml_reorigin_2", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - bridge2 = qmf.getObjects(_class="bridge")[1] - sleep(5) - - foo=qmf.getObjects(_class="link") - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.xml_reorigin", binding_key="key1", arguments={'xquery':'true()'}) - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - props = r_session.delivery_properties(routing_key="key1") - for i in range(1, 11): - r_session.message_transfer(destination="fed.xml_reorigin", message=Message(props, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - - # Extra test: don't explicitly close() bridge2. When the link is closed, - # it should clean up bridge2 automagically. verify_cleanup() will detect - # if bridge2 isn't cleaned up and will fail the test. - # - #result = bridge2.close() - #self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_unbind_xml(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_xml_unbind") - - session.exchange_declare(exchange="fed.xml_unbind", type="xml") - r_session.exchange_declare(exchange="fed.xml_unbind", type="xml") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.xml_unbind", "fed.xml_unbind", "", "", "", False, False, True, 0, 0) - - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - queue = qmf.getObjects(_class="queue", name="fed1")[0] - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - session.exchange_bind(queue="fed1", exchange="fed.xml_unbind", binding_key="key1", arguments={'xquery':'true()'}) - queue.update() - self.assertEqual(queue.bindingCount, 2, - "bindings not accounted for (expected 2, got %d)" % queue.bindingCount) - - session.exchange_unbind(queue="fed1", exchange="fed.xml_unbind", binding_key="key1") - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - - def test_dynamic_topic_nodup(self): - """Verify that a message whose routing key matches more than one - binding does not get duplicated to the same queue. - """ - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_topic_nodup") - - session.exchange_declare(exchange="fed.topic", type="topic") - r_session.exchange_declare(exchange="fed.topic", type="topic") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.topic", "fed.topic", "", "", "", False, False, True, 0, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.topic", binding_key="red.*") - session.exchange_bind(queue="fed1", exchange="fed.topic", binding_key="*.herring") - - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="red.herring") - r_session.message_transfer(destination="fed.topic", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - - def test_dynamic_direct_route_prop(self): - """ Set up a tree of uni-directional routes across the direct exchange. - Bind the same key to the same queues on the leaf nodes. Verify a - message sent with the routing key transverses the tree an arrives at - each leaf. Remove one leaf's queue, and verify that messages still - reach the other leaf. - - Route Topology: - - +---> B2 queue:"test-queue", binding key:"spudboy" - B0 --> B1 --+ - +---> B3 queue:"test-queue", binding key:"spudboy" - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create direct exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers: - _b.client_session.exchange_declare(exchange="fedX.direct", type="direct") - self.assertEqual(_b.client_session.exchange_query(name="fedX.direct").type, - "direct", "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - while my_exchange is None: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX.direct": - my_exchange = ooo - break - if my_exchange is None: - retries += 1 - self.failIfEqual(retries, 10, - "QMF failed to find new exchange!") - sleep(1) - exchanges.append(my_exchange) - - self.assertEqual(len(exchanges), len(self._brokers), "Exchange creation failed!") - - # connect B0 --> B1 - result = self._brokers[1].qmf_object.connect(self._brokers[0].host, - self._brokers[0].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B2 - result = self._brokers[2].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B3 - result = self._brokers[3].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # for each link, bridge the "fedX.direct" exchanges: - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX.direct", # src - "fedX.direct", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0, # sync - 0) # credit - self.assertEqual(result.status, 0) - - # wait for the inter-broker links to become operational - retries = 0 - operational = False - while not operational: - operational = True - for _l in qmf.getObjects(_class="link"): - #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - if not operational: - retries += 1 - self.failIfEqual(retries, 10, - "inter-broker links failed to become operational.") - sleep(1) - - # @todo - There is no way to determine when the bridge objects become - # active. Hopefully, this is long enough! - sleep(6) - - # create a queue on B2, bound to "spudboy" - self._brokers[2].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[2].client_session.exchange_bind(queue="fedX1", exchange="fedX.direct", binding_key="spudboy") - - # create a queue on B3, bound to "spudboy" - self._brokers[3].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[3].client_session.exchange_bind(queue="fedX1", exchange="fedX.direct", binding_key="spudboy") - - # subscribe to messages arriving on B2's queue - self.subscribe(self._brokers[2].client_session, queue="fedX1", destination="f1") - queue_2 = self._brokers[2].client_session.incoming("f1") - - # subscribe to messages arriving on B3's queue - self.subscribe(self._brokers[3].client_session, queue="fedX1", destination="f1") - queue_3 = self._brokers[3].client_session.incoming("f1") - - # wait until the binding key has propagated to each broker (twice at - # broker B1). Work backwards from binding brokers. - - binding_counts = [1, 2, 1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(3,-1,-1): - retries = 0 - exchanges[i].update() - while exchanges[i].bindingCount < binding_counts[i]: - retries += 1 - self.failIfEqual(retries, 10, - "binding failed to propagate to broker %d" - % i) - sleep(3) - exchanges[i].update() - - # send 10 msgs from B0 - for i in range(1, 11): - dp = self._brokers[0].client_session.delivery_properties(routing_key="spudboy") - self._brokers[0].client_session.message_transfer(destination="fedX.direct", message=Message(dp, "Message_drp %d" % i)) - - # wait for 10 messages to be forwarded from B0->B1, - # 10 messages from B1->B2, - # and 10 messages from B1->B3 - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 10 or exchanges[0].msgRoutes != 10 or - exchanges[1].msgReceives != 10 or exchanges[1].msgRoutes != 20 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 10 or exchanges[3].msgRoutes != 10): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B2 and B3 - for i in range(1, 11): - msg = queue_2.get(timeout=5) - self.assertEqual("Message_drp %d" % i, msg.body) - msg = queue_3.get(timeout=5) - self.assertEqual("Message_drp %d" % i, msg.body) - - try: - extra = queue_2.get(timeout=1) - self.fail("Got unexpected message in queue_2: " + extra.body) - except Empty: None - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - - # tear down the queue on B2 - self._brokers[2].client_session.exchange_unbind(queue="fedX1", exchange="fedX.direct", binding_key="spudboy") - self._brokers[2].client_session.message_cancel(destination="f1") - self._brokers[2].client_session.queue_delete(queue="fedX1") - - # @todo - restore code when QPID-2499 fixed!! - sleep(6) - # wait for the binding count on B1 to drop from 2 to 1 - retries = 0 - exchanges[1].update() - while exchanges[1].bindingCount != 1: - retries += 1 - self.failIfEqual(retries, 10, - "unbinding failed to propagate to broker B1: %d" - % exchanges[1].bindingCount) - sleep(1) - exchanges[1].update() - - # send 10 msgs from B0 - for i in range(11, 21): - dp = self._brokers[0].client_session.delivery_properties(routing_key="spudboy") - self._brokers[0].client_session.message_transfer(destination="fedX.direct", message=Message(dp, "Message_drp %d" % i)) - - # verify messages are forwarded to B3 only - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 20 or exchanges[0].msgRoutes != 20 or - exchanges[1].msgReceives != 20 or exchanges[1].msgRoutes != 30 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 20 or exchanges[3].msgRoutes != 20): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route more msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B3 only - for i in range(11, 21): - msg = queue_3.get(timeout=5) - self.assertEqual("Message_drp %d" % i, msg.body) - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # cleanup - - self._brokers[3].client_session.exchange_unbind(queue="fedX1", exchange="fedX.direct", binding_key="spudboy") - self._brokers[3].client_session.message_cancel(destination="f1") - self._brokers[3].client_session.queue_delete(queue="fedX1") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers: - _b.client_session.exchange_delete(exchange="fedX.direct") - - self._teardown_brokers() - - self.verify_cleanup() - - def test_dynamic_topic_route_prop(self): - """ Set up a tree of uni-directional routes across a topic exchange. - Bind the same key to the same queues on the leaf nodes. Verify a - message sent with the routing key transverses the tree an arrives at - each leaf. Remove one leaf's queue, and verify that messages still - reach the other leaf. - - Route Topology: - - +---> B2 queue:"test-queue", binding key:"spud.*" - B0 --> B1 --+ - +---> B3 queue:"test-queue", binding key:"spud.*" - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers: - _b.client_session.exchange_declare(exchange="fedX.topic", type="topic") - self.assertEqual(_b.client_session.exchange_query(name="fedX.topic").type, - "topic", "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - while my_exchange is None: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX.topic": - my_exchange = ooo - break - if my_exchange is None: - retries += 1 - self.failIfEqual(retries, 10, - "QMF failed to find new exchange!") - sleep(1) - exchanges.append(my_exchange) - - self.assertEqual(len(exchanges), len(self._brokers), "Exchange creation failed!") - - # connect B0 --> B1 - result = self._brokers[1].qmf_object.connect(self._brokers[0].host, - self._brokers[0].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B2 - result = self._brokers[2].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B3 - result = self._brokers[3].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # for each link, bridge the "fedX.topic" exchanges: - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX.topic", # src - "fedX.topic", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0, # sync - 0) # credit - self.assertEqual(result.status, 0) - - # wait for the inter-broker links to become operational - retries = 0 - operational = False - while not operational: - operational = True - for _l in qmf.getObjects(_class="link"): - #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - if not operational: - retries += 1 - self.failIfEqual(retries, 10, - "inter-broker links failed to become operational.") - sleep(1) - - # @todo - There is no way to determine when the bridge objects become - # active. - sleep(6) - - # create a queue on B2, bound to "spudboy" - self._brokers[2].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[2].client_session.exchange_bind(queue="fedX1", exchange="fedX.topic", binding_key="spud.*") - - # create a queue on B3, bound to "spudboy" - self._brokers[3].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[3].client_session.exchange_bind(queue="fedX1", exchange="fedX.topic", binding_key="spud.*") - - # subscribe to messages arriving on B2's queue - self.subscribe(self._brokers[2].client_session, queue="fedX1", destination="f1") - queue_2 = self._brokers[2].client_session.incoming("f1") - - # subscribe to messages arriving on B3's queue - self.subscribe(self._brokers[3].client_session, queue="fedX1", destination="f1") - queue_3 = self._brokers[3].client_session.incoming("f1") - - # wait until the binding key has propagated to each broker (twice at - # broker B1). Work backwards from binding brokers. - - binding_counts = [1, 2, 1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(3,-1,-1): - retries = 0 - exchanges[i].update() - while exchanges[i].bindingCount < binding_counts[i]: - retries += 1 - self.failIfEqual(retries, 10, - "binding failed to propagate to broker %d" - % i) - sleep(3) - exchanges[i].update() - - # send 10 msgs from B0 - for i in range(1, 11): - dp = self._brokers[0].client_session.delivery_properties(routing_key="spud.boy") - self._brokers[0].client_session.message_transfer(destination="fedX.topic", message=Message(dp, "Message_trp %d" % i)) - - # wait for 10 messages to be forwarded from B0->B1, - # 10 messages from B1->B2, - # and 10 messages from B1->B3 - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 10 or exchanges[0].msgRoutes != 10 or - exchanges[1].msgReceives != 10 or exchanges[1].msgRoutes != 20 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 10 or exchanges[3].msgRoutes != 10): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B2 and B3 - for i in range(1, 11): - msg = queue_2.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - msg = queue_3.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - - try: - extra = queue_2.get(timeout=1) - self.fail("Got unexpected message in queue_2: " + extra.body) - except Empty: None - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # tear down the queue on B2 - self._brokers[2].client_session.exchange_unbind(queue="fedX1", exchange="fedX.topic", binding_key="spud.*") - self._brokers[2].client_session.message_cancel(destination="f1") - self._brokers[2].client_session.queue_delete(queue="fedX1") - - # wait for the binding count on B1 to drop from 2 to 1 - retries = 0 - exchanges[1].update() - while exchanges[1].bindingCount != 1: - retries += 1 - self.failIfEqual(retries, 10, - "unbinding failed to propagate to broker B1: %d" - % exchanges[1].bindingCount) - sleep(1) - exchanges[1].update() - - # send 10 msgs from B0 - for i in range(11, 21): - dp = self._brokers[0].client_session.delivery_properties(routing_key="spud.boy") - self._brokers[0].client_session.message_transfer(destination="fedX.topic", message=Message(dp, "Message_trp %d" % i)) - - # verify messages are forwarded to B3 only - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 20 or exchanges[0].msgRoutes != 20 or - exchanges[1].msgReceives != 20 or exchanges[1].msgRoutes != 30 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 20 or exchanges[3].msgRoutes != 20): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route more msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B3 only - for i in range(11, 21): - msg = queue_3.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # cleanup - - self._brokers[3].client_session.exchange_unbind(queue="fedX1", exchange="fedX.topic", binding_key="spud.*") - self._brokers[3].client_session.message_cancel(destination="f1") - self._brokers[3].client_session.queue_delete(queue="fedX1") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers: - _b.client_session.exchange_delete(exchange="fedX.topic") - - self._teardown_brokers() - - self.verify_cleanup() - - - def test_dynamic_fanout_route_prop(self): - """ Set up a tree of uni-directional routes across a fanout exchange. - Bind the same key to the same queues on the leaf nodes. Verify a - message sent with the routing key transverses the tree an arrives at - each leaf. Remove one leaf's queue, and verify that messages still - reach the other leaf. - - Route Topology: - - +---> B2 queue:"test-queue", binding key:"spud.*" - B0 --> B1 --+ - +---> B3 queue:"test-queue", binding key:"spud.*" - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create fanout exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers: - _b.client_session.exchange_declare(exchange="fedX.fanout", type="fanout") - self.assertEqual(_b.client_session.exchange_query(name="fedX.fanout").type, - "fanout", "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - while my_exchange is None: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX.fanout": - my_exchange = ooo - break - if my_exchange is None: - retries += 1 - self.failIfEqual(retries, 10, - "QMF failed to find new exchange!") - sleep(1) - exchanges.append(my_exchange) - - self.assertEqual(len(exchanges), len(self._brokers), "Exchange creation failed!") - - # connect B0 --> B1 - result = self._brokers[1].qmf_object.connect(self._brokers[0].host, - self._brokers[0].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B2 - result = self._brokers[2].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B3 - result = self._brokers[3].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # for each link, bridge the "fedX.fanout" exchanges: - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX.fanout", # src - "fedX.fanout", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0, # sync - 0) # credit - self.assertEqual(result.status, 0) - - # wait for the inter-broker links to become operational - retries = 0 - operational = False - while not operational: - operational = True - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - if not operational: - retries += 1 - self.failIfEqual(retries, 10, - "inter-broker links failed to become operational.") - sleep(1) - - # @todo - There is no way to determine when the bridge objects become - # active. - sleep(6) - - # create a queue on B2, bound to the exchange - self._brokers[2].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[2].client_session.exchange_bind(queue="fedX1", exchange="fedX.fanout") - - # create a queue on B3, bound to the exchange - self._brokers[3].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[3].client_session.exchange_bind(queue="fedX1", exchange="fedX.fanout") - - # subscribe to messages arriving on B2's queue - self.subscribe(self._brokers[2].client_session, queue="fedX1", destination="f1") - queue_2 = self._brokers[2].client_session.incoming("f1") - - # subscribe to messages arriving on B3's queue - self.subscribe(self._brokers[3].client_session, queue="fedX1", destination="f1") - queue_3 = self._brokers[3].client_session.incoming("f1") - - # wait until the binding key has propagated to each broker (twice at - # broker B1). Work backwards from binding brokers. - - binding_counts = [1, 2, 1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(3,-1,-1): - retries = 0 - exchanges[i].update() - while exchanges[i].bindingCount < binding_counts[i]: - retries += 1 - self.failIfEqual(retries, 10, - "binding failed to propagate to broker %d" - % i) - sleep(3) - exchanges[i].update() - - # send 10 msgs from B0 - for i in range(1, 11): - dp = self._brokers[0].client_session.delivery_properties() - self._brokers[0].client_session.message_transfer(destination="fedX.fanout", message=Message(dp, "Message_frp %d" % i)) - - # wait for 10 messages to be forwarded from B0->B1, - # 10 messages from B1->B2, - # and 10 messages from B1->B3 - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 10 or exchanges[0].msgRoutes != 10 or - exchanges[1].msgReceives != 10 or exchanges[1].msgRoutes != 20 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 10 or exchanges[3].msgRoutes != 10): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B2 and B3 - for i in range(1, 11): - msg = queue_2.get(timeout=5) - self.assertEqual("Message_frp %d" % i, msg.body) - msg = queue_3.get(timeout=5) - self.assertEqual("Message_frp %d" % i, msg.body) - - try: - extra = queue_2.get(timeout=1) - self.fail("Got unexpected message in queue_2: " + extra.body) - except Empty: None - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # tear down the queue on B2 - self._brokers[2].client_session.exchange_unbind(queue="fedX1", exchange="fedX.fanout") - self._brokers[2].client_session.message_cancel(destination="f1") - self._brokers[2].client_session.queue_delete(queue="fedX1") - - # wait for the binding count on B1 to drop from 2 to 1 - retries = 0 - exchanges[1].update() - while exchanges[1].bindingCount != 1: - retries += 1 - self.failIfEqual(retries, 10, - "unbinding failed to propagate to broker B1: %d" - % exchanges[1].bindingCount) - sleep(1) - exchanges[1].update() - - # send 10 msgs from B0 - for i in range(11, 21): - dp = self._brokers[0].client_session.delivery_properties() - self._brokers[0].client_session.message_transfer(destination="fedX.fanout", message=Message(dp, "Message_frp %d" % i)) - - # verify messages are forwarded to B3 only - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 20 or exchanges[0].msgRoutes != 20 or - exchanges[1].msgReceives != 20 or exchanges[1].msgRoutes != 30 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 20 or exchanges[3].msgRoutes != 20): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route more msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B3 only - for i in range(11, 21): - msg = queue_3.get(timeout=5) - self.assertEqual("Message_frp %d" % i, msg.body) - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # cleanup - - self._brokers[3].client_session.exchange_unbind(queue="fedX1", exchange="fedX.fanout") - self._brokers[3].client_session.message_cancel(destination="f1") - self._brokers[3].client_session.queue_delete(queue="fedX1") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers: - _b.client_session.exchange_delete(exchange="fedX.fanout") - - self._teardown_brokers() - - self.verify_cleanup() - - - def getProperty(self, msg, name): - for h in msg.headers: - if hasattr(h, name): return getattr(h, name) - return None - - def getAppHeader(self, msg, name): - headers = self.getProperty(msg, "application_headers") - if headers: - return headers[name] - return None - - def test_dynamic_topic_bounce(self): - """ Bounce the connection between federated Topic Exchanges. - """ - class Params: - def exchange_type(self): return "topic" - def bind_queue(self, ssn, qname, ename): - ssn.exchange_bind(queue=qname, exchange=ename, - binding_key="spud.*") - def unbind_queue(self, ssn, qname, ename): - ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud.*") - def delivery_properties(self, ssn): - return ssn.delivery_properties(routing_key="spud.boy") - - self.generic_dynamic_bounce_test(Params()) - - def test_dynamic_direct_bounce(self): - """ Bounce the connection between federated Direct Exchanges. - """ - class Params: - def exchange_type(self): return "direct" - def bind_queue(self, ssn, qname, ename): - ssn.exchange_bind(queue=qname, exchange=ename, binding_key="spud") - def unbind_queue(self, ssn, qname, ename): - ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud") - def delivery_properties(self, ssn): - return ssn.delivery_properties(routing_key="spud") - self.generic_dynamic_bounce_test(Params()) - - def test_dynamic_fanout_bounce(self): - """ Bounce the connection between federated Fanout Exchanges. - """ - class Params: - def exchange_type(self): return "fanout" - def bind_queue(self, ssn, qname, ename): - ssn.exchange_bind(queue=qname, exchange=ename) - def unbind_queue(self, ssn, qname, ename): - ssn.exchange_unbind(queue=qname, exchange=ename) - def delivery_properties(self, ssn): - return ssn.delivery_properties(routing_key="spud") - self.generic_dynamic_bounce_test(Params()) - - def test_dynamic_headers_bounce(self): - """ Bounce the connection between federated Headers Exchanges. - """ - class Params: - def exchange_type(self): return "headers" - def bind_queue(self, ssn, qname, ename): - ssn.exchange_bind(queue=qname, exchange=ename, - binding_key="spud", arguments={'x-match':'any', 'class':'first'}) - def unbind_queue(self, ssn, qname, ename): - ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud") - def delivery_properties(self, ssn): - return ssn.message_properties(application_headers={'class':'first'}) - ## @todo KAG - re-enable once federation bugs with headers exchanges - ## are fixed. - #self.generic_dynamic_bounce_test(Params()) - return - - - def generic_dynamic_bounce_test(self, params): - """ Verify that a federated broker can maintain a binding to a local - queue using the same key as a remote binding. Destroy and reconnect - the federation link, and verify routes are restored correctly. - See QPID-3170. - Topology: - - Queue1 <---"Key"---B0<==[Federated Exchange]==>B1---"Key"--->Queue2 - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers[0:2]: - _b.client_session.exchange_declare(exchange="fedX", type=params.exchange_type()) - self.assertEqual(_b.client_session.exchange_query(name="fedX").type, - params.exchange_type(), "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - timeout = time() + 10 - while my_exchange is None and time() <= timeout: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX": - my_exchange = ooo - break - if my_exchange is None: - self.fail("QMF failed to find new exchange!") - exchanges.append(my_exchange) - - # - # on each broker, create a local queue bound to the exchange with the - # same key value. - # - - self._brokers[0].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - params.bind_queue(self._brokers[0].client_session, "fedX1", "fedX") - self.subscribe(self._brokers[0].client_session, queue="fedX1", destination="f1") - queue_0 = self._brokers[0].client_session.incoming("f1") - - self._brokers[1].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - params.bind_queue(self._brokers[1].client_session, "fedX1", "fedX") - self.subscribe(self._brokers[1].client_session, queue="fedX1", destination="f1") - queue_1 = self._brokers[1].client_session.incoming("f1") - - # now federate the two brokers - - # connect B0 --> B1 - result = self._brokers[1].qmf_object.connect(self._brokers[0].host, - self._brokers[0].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B0 - result = self._brokers[0].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # for each link, bridge the "fedX" exchanges: - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX", # src - "fedX", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0, # sync - 0) # credit - self.assertEqual(result.status, 0) - - # wait for all the inter-broker links to become operational - operational = False - timeout = time() + 10 - while not operational and time() <= timeout: - operational = True - for _l in qmf.getObjects(_class="link"): - #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - self.failUnless(operational, "inter-broker links failed to become operational.") - - # @todo - There is no way to determine when the bridge objects become - # active. - - # wait until the binding key has propagated to each broker - each - # broker should see 2 bindings (1 local, 1 remote) - - binding_counts = [2, 2] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(2): - exchanges[i].update() - timeout = time() + 10 - while exchanges[i].bindingCount < binding_counts[i] and time() <= timeout: - exchanges[i].update() - self.failUnless(exchanges[i].bindingCount == binding_counts[i]) - - # send 10 msgs to B0 - for i in range(1, 11): - # dp = self._brokers[0].client_session.delivery_properties(routing_key=params.routing_key()) - dp = params.delivery_properties(self._brokers[0].client_session) - self._brokers[0].client_session.message_transfer(destination="fedX", message=Message(dp, "Message_trp %d" % i)) - - # get exactly 10 msgs on B0's local queue and B1's queue - for i in range(1, 11): - try: - msg = queue_0.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - msg = queue_1.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - except Empty: - self.fail("Only got %d msgs - expected 10" % i) - try: - extra = queue_0.get(timeout=1) - self.fail("Got unexpected message in queue_0: " + extra.body) - except Empty: None - - try: - extra = queue_1.get(timeout=1) - self.fail("Got unexpected message in queue_1: " + extra.body) - except Empty: None - - # - # Tear down the bridges between the two exchanges, then wait - # for the bindings to be cleaned up - # - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - binding_counts = [1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(2): - exchanges[i].update() - timeout = time() + 10 - while exchanges[i].bindingCount != binding_counts[i] and time() <= timeout: - exchanges[i].update() - self.failUnless(exchanges[i].bindingCount == binding_counts[i]) - - # - # restore the bridges between the two exchanges, and wait for the - # bindings to propagate. - # - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX", # src - "fedX", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0, # sync - 0) # credit - self.assertEqual(result.status, 0) - - binding_counts = [2, 2] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(2): - exchanges[i].update() - timeout = time() + 10 - while exchanges[i].bindingCount != binding_counts[i] and time() <= timeout: - exchanges[i].update() - self.failUnless(exchanges[i].bindingCount == binding_counts[i]) - - # - # verify traffic flows correctly - # - - for i in range(1, 11): - #dp = self._brokers[1].client_session.delivery_properties(routing_key=params.routing_key()) - dp = params.delivery_properties(self._brokers[1].client_session) - self._brokers[1].client_session.message_transfer(destination="fedX", message=Message(dp, "Message_trp %d" % i)) - - # get exactly 10 msgs on B0's queue and B1's queue - for i in range(1, 11): - try: - msg = queue_0.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - msg = queue_1.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - except Empty: - self.fail("Only got %d msgs - expected 10" % i) - try: - extra = queue_0.get(timeout=1) - self.fail("Got unexpected message in queue_0: " + extra.body) - except Empty: None - - try: - extra = queue_1.get(timeout=1) - self.fail("Got unexpected message in queue_1: " + extra.body) - except Empty: None - - - # - # cleanup - # - params.unbind_queue(self._brokers[0].client_session, "fedX1", "fedX") - self._brokers[0].client_session.message_cancel(destination="f1") - self._brokers[0].client_session.queue_delete(queue="fedX1") - - params.unbind_queue(self._brokers[1].client_session, "fedX1", "fedX") - self._brokers[1].client_session.message_cancel(destination="f1") - self._brokers[1].client_session.queue_delete(queue="fedX1") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers[0:2]: - _b.client_session.exchange_delete(exchange="fedX") - - self._teardown_brokers() - - self.verify_cleanup() - - - def test_multilink_direct(self): - """ Verify that two distinct links can be created between federated - brokers. - """ - self.startQmf() - qmf = self.qmf - self._setup_brokers() - src_broker = self._brokers[0] - dst_broker = self._brokers[1] - - # create a direct exchange on each broker - for _b in [src_broker, dst_broker]: - _b.client_session.exchange_declare(exchange="fedX.direct", type="direct") - self.assertEqual(_b.client_session.exchange_query(name="fedX.direct").type, - "direct", "exchange_declare failed!") - - # create destination queues - for _q in [("HiQ", "high"), ("MedQ", "medium"), ("LoQ", "low")]: - dst_broker.client_session.queue_declare(queue=_q[0], auto_delete=True) - dst_broker.client_session.exchange_bind(queue=_q[0], exchange="fedX.direct", binding_key=_q[1]) - - # create two connections, one for high priority traffic - for _q in ["HiPri", "Traffic"]: - result = dst_broker.qmf_object.create("link", _q, - {"host":src_broker.host, - "port":src_broker.port}, - False) - self.assertEqual(result.status, 0); - - links = qmf.getObjects(_broker=dst_broker.qmf_broker, _class="link") - for _l in links: - if _l.name == "HiPri": - hi_link = _l - elif _l.name == "Traffic": - data_link = _l - else: - self.fail("Unexpected Link found: " + _l.name) - - # now create a route for messages sent with key "high" to use the - # hi_link - result = dst_broker.qmf_object.create("bridge", "HiPriBridge", - {"link":hi_link.name, - "src":"fedX.direct", - "dest":"fedX.direct", - "key":"high"}, False) - self.assertEqual(result.status, 0); - - - # create routes for the "medium" and "low" links to use the normal - # data_link - for _b in [("MediumBridge", "medium"), ("LowBridge", "low")]: - result = dst_broker.qmf_object.create("bridge", _b[0], - {"link":data_link.name, - "src":"fedX.direct", - "dest":"fedX.direct", - "key":_b[1]}, False) - self.assertEqual(result.status, 0); - - # now wait for the links to become operational - for _l in [hi_link, data_link]: - expire_time = time() + 30 - while _l.state != "Operational" and time() < expire_time: - _l.update() - self.assertEqual(_l.state, "Operational", "Link failed to become operational") - - # verify each link uses a different connection - self.assertNotEqual(hi_link.connectionRef, data_link.connectionRef, - "Different links using the same connection") - - hi_conn = qmf.getObjects(_broker=dst_broker.qmf_broker, - _objectId=hi_link.connectionRef)[0] - data_conn = qmf.getObjects(_broker=dst_broker.qmf_broker, - _objectId=data_link.connectionRef)[0] - - - # send hi data, verify only goes over hi link - - r_ssn = dst_broker.connection.session() - hi_receiver = r_ssn.receiver("HiQ"); - med_receiver = r_ssn.receiver("MedQ"); - low_receiver = r_ssn.receiver("LoQ"); - - for _c in [hi_conn, data_conn]: - _c.update() - self.assertEqual(_c.msgsToClient, 0, "Unexpected messages received") - - s_ssn = src_broker.connection.session() - hi_sender = s_ssn.sender("fedX.direct/high") - med_sender = s_ssn.sender("fedX.direct/medium") - low_sender = s_ssn.sender("fedX.direct/low") - - try: - hi_sender.send(qpid.messaging.Message(content="hi priority")) - msg = hi_receiver.fetch(timeout=10) - r_ssn.acknowledge() - self.assertEqual(msg.content, "hi priority"); - except: - self.fail("Hi Pri message failure") - - hi_conn.update() - data_conn.update() - self.assertEqual(hi_conn.msgsToClient, 1, "Expected 1 hi pri message") - self.assertEqual(data_conn.msgsToClient, 0, "Expected 0 data messages") - - # send low and medium, verify it does not go over hi link - - try: - med_sender.send(qpid.messaging.Message(content="medium priority")) - msg = med_receiver.fetch(timeout=10) - r_ssn.acknowledge() - self.assertEqual(msg.content, "medium priority"); - except: - self.fail("Medium Pri message failure") - - hi_conn.update() - data_conn.update() - self.assertEqual(hi_conn.msgsToClient, 1, "Expected 1 hi pri message") - self.assertEqual(data_conn.msgsToClient, 1, "Expected 1 data message") - - try: - low_sender.send(qpid.messaging.Message(content="low priority")) - msg = low_receiver.fetch(timeout=10) - r_ssn.acknowledge() - self.assertEqual(msg.content, "low priority"); - except: - self.fail("Low Pri message failure") - - hi_conn.update() - data_conn.update() - self.assertEqual(hi_conn.msgsToClient, 1, "Expected 1 hi pri message") - self.assertEqual(data_conn.msgsToClient, 2, "Expected 2 data message") - - # cleanup - - for _b in qmf.getObjects(_broker=dst_broker.qmf_broker,_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_broker=dst_broker.qmf_broker,_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _q in [("HiQ", "high"), ("MedQ", "medium"), ("LoQ", "low")]: - dst_broker.client_session.exchange_unbind(queue=_q[0], exchange="fedX.direct", binding_key=_q[1]) - dst_broker.client_session.queue_delete(queue=_q[0]) - - for _b in [src_broker, dst_broker]: - _b.client_session.exchange_delete(exchange="fedX.direct") - - self._teardown_brokers() - - self.verify_cleanup() - - - def test_multilink_shared_queue(self): - """ Verify that two distinct links can be created between federated - brokers. - """ - self.startQmf() - qmf = self.qmf - self._setup_brokers() - src_broker = self._brokers[0] - dst_broker = self._brokers[1] - - # create a topic exchange on the destination broker - dst_broker.client_session.exchange_declare(exchange="fedX.topic", type="topic") - self.assertEqual(dst_broker.client_session.exchange_query(name="fedX.topic").type, - "topic", "exchange_declare failed!") - - # create a destination queue - dst_broker.client_session.queue_declare(queue="destQ", auto_delete=True) - dst_broker.client_session.exchange_bind(queue="destQ", exchange="fedX.topic", binding_key="srcQ") - - # create a single source queue - src_broker.client_session.queue_declare(queue="srcQ", auto_delete=True) - - # create two connections - for _q in ["Link1", "Link2"]: - result = dst_broker.qmf_object.create("link", _q, - {"host":src_broker.host, - "port":src_broker.port}, - False) - self.assertEqual(result.status, 0); - - links = qmf.getObjects(_broker=dst_broker.qmf_broker, _class="link") - self.assertEqual(len(links), 2) - - # now create two "parallel" queue routes from the source queue to the - # destination exchange. - result = dst_broker.qmf_object.create("bridge", "Bridge1", - {"link":"Link1", - "src":"srcQ", - "dest":"fedX.topic", - "srcIsQueue": True}, - False) - self.assertEqual(result.status, 0); - result = dst_broker.qmf_object.create("bridge", "Bridge2", - {"link":"Link2", - "src":"srcQ", - "dest":"fedX.topic", - "srcIsQueue": True}, - False) - self.assertEqual(result.status, 0); - - - # now wait for the links to become operational - for _l in links: - expire_time = time() + 30 - while _l.state != "Operational" and time() < expire_time: - _l.update() - self.assertEqual(_l.state, "Operational", "Link failed to become operational") - - # verify each link uses a different connection - self.assertNotEqual(links[0].connectionRef, links[1].connectionRef, - "Different links using the same connection") - - conn1 = qmf.getObjects(_broker=dst_broker.qmf_broker, - _objectId=links[0].connectionRef)[0] - conn2 = qmf.getObjects(_broker=dst_broker.qmf_broker, - _objectId=links[1].connectionRef)[0] - - # verify messages sent to the queue are pulled by each connection - - r_ssn = dst_broker.connection.session() - receiver = r_ssn.receiver("destQ"); - - for _c in [conn1, conn2]: - _c.update() - self.assertEqual(_c.msgsToClient, 0, "Unexpected messages received") - - s_ssn = src_broker.connection.session() - sender = s_ssn.sender("srcQ") - - try: - for x in range(5): - sender.send(qpid.messaging.Message(content="hello")) - for x in range(5): - msg = receiver.fetch(timeout=10) - self.assertEqual(msg.content, "hello"); - r_ssn.acknowledge() - except: - self.fail("Message failure") - - # expect messages to be split over each connection. - conn1.update() - conn2.update() - self.assertNotEqual(conn1.msgsToClient, 0, "No messages sent") - self.assertNotEqual(conn2.msgsToClient, 0, "No messages sent") - self.assertEqual(conn2.msgsToClient + conn1.msgsToClient, 5, - "Expected 5 messages total") - - for _b in qmf.getObjects(_broker=dst_broker.qmf_broker,_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_broker=dst_broker.qmf_broker,_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - dst_broker.client_session.exchange_unbind(queue="destQ", exchange="fedX.topic", binding_key="srcQ") - dst_broker.client_session.exchange_delete(exchange="fedX.topic") - - self._teardown_brokers() - - self.verify_cleanup() - - - def test_dynamic_direct_shared_queue(self): - """ - Route Topology: - - +<--- B1 - B0 <---+<--- B2 - +<--- B3 - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create direct exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers: - _b.client_session.exchange_declare(exchange="fedX.direct", type="direct") - self.assertEqual(_b.client_session.exchange_query(name="fedX.direct").type, - "direct", "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - while my_exchange is None: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX.direct": - my_exchange = ooo - break - if my_exchange is None: - retries += 1 - self.failIfEqual(retries, 10, - "QMF failed to find new exchange!") - sleep(1) - exchanges.append(my_exchange) - - self.assertEqual(len(exchanges), len(self._brokers), "Exchange creation failed!") - - # Create 2 links per each source broker (1,2,3) to the downstream - # broker 0: - for _b in range(1,4): - for _l in ["dynamic", "queue"]: - result = self._brokers[0].qmf_object.create( "link", - "Link-%d-%s" % (_b, _l), - {"host":self._brokers[_b].host, - "port":self._brokers[_b].port}, False) - self.assertEqual(result.status, 0) - - # create queue on source brokers for use by the dynamic route - self._brokers[_b].client_session.queue_declare(queue="fedSrcQ", exclusive=False, auto_delete=True) - - for _l in range(1,4): - # for each dynamic link, create a dynamic bridge for the "fedX.direct" - # exchanges, using the fedSrcQ on each upstream source broker - result = self._brokers[0].qmf_object.create("bridge", - "Bridge-%d-dynamic" % _l, - {"link":"Link-%d-dynamic" % _l, - "src":"fedX.direct", - "dest":"fedX.direct", - "dynamic":True, - "queue":"fedSrcQ"}, False) - self.assertEqual(result.status, 0) - - # create a queue route that shares the queue used by the dynamic route - result = self._brokers[0].qmf_object.create("bridge", - "Bridge-%d-queue" % _l, - {"link":"Link-%d-queue" % _l, - "src":"fedSrcQ", - "dest":"fedX.direct", - "srcIsQueue":True}, False) - self.assertEqual(result.status, 0) - - - # wait for the inter-broker links to become operational - retries = 0 - operational = False - while not operational: - operational = True - for _l in qmf.getObjects(_class="link"): - #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - if not operational: - retries += 1 - self.failIfEqual(retries, 10, - "inter-broker links failed to become operational.") - sleep(1) - - # @todo - There is no way to determine when the bridge objects become - # active. Hopefully, this is long enough! - sleep(6) - - # create a queue on B0, bound to "spudboy" - self._brokers[0].client_session.queue_declare(queue="DestQ", exclusive=True, auto_delete=True) - self._brokers[0].client_session.exchange_bind(queue="DestQ", exchange="fedX.direct", binding_key="spudboy") - - # subscribe to messages arriving on B2's queue - self.subscribe(self._brokers[0].client_session, queue="DestQ", destination="f1") - queue = self._brokers[0].client_session.incoming("f1") - - # wait until the binding key has propagated to each broker - - binding_counts = [1, 1, 1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(3,-1,-1): - retries = 0 - exchanges[i].update() - while exchanges[i].bindingCount < binding_counts[i]: - retries += 1 - self.failIfEqual(retries, 10, - "binding failed to propagate to broker %d" - % i) - sleep(3) - exchanges[i].update() - - for _b in range(1,4): - # send 3 msgs from each source broker - for i in range(3): - dp = self._brokers[_b].client_session.delivery_properties(routing_key="spudboy") - self._brokers[_b].client_session.message_transfer(destination="fedX.direct", message=Message(dp, "Message_drp %d" % i)) - - # get exactly 9 (3 per broker) on B0 - for i in range(9): - msg = queue.get(timeout=5) - - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - # verify that messages went across every link - for _l in qmf.getObjects(_broker=self._brokers[0].qmf_broker, - _class="link"): - for _c in qmf.getObjects(_broker=self._brokers[0].qmf_broker, - _objectId=_l.connectionRef): - self.assertNotEqual(_c.msgsToClient, 0, "Messages did not pass over link as expected.") - - # cleanup - - self._brokers[0].client_session.exchange_unbind(queue="DestQ", exchange="fedX.direct", binding_key="spudboy") - self._brokers[0].client_session.message_cancel(destination="f1") - self._brokers[0].client_session.queue_delete(queue="DestQ") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers: - _b.client_session.exchange_delete(exchange="fedX.direct") - - self._teardown_brokers() - - self.verify_cleanup() - - def test_dynamic_bounce_unbinds_named_queue(self): - """ Verify that a propagated binding is removed when the connection is - bounced - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers[0:2]: - _b.client_session.exchange_declare(exchange="fedX", type="direct") - self.assertEqual(_b.client_session.exchange_query(name="fedX").type, - "direct", "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - timeout = time() + 10 - while my_exchange is None and time() <= timeout: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX": - my_exchange = ooo - break - if my_exchange is None: - self.fail("QMF failed to find new exchange!") - exchanges.append(my_exchange) - - # on the destination broker, create a binding for propagation - self._brokers[0].client_session.queue_declare(queue="fedDstQ") - self._brokers[0].client_session.exchange_bind(queue="fedDstQ", exchange="fedX", binding_key="spud") - - # on the source broker, create a bridge queue - self._brokers[1].client_session.queue_declare(queue="fedSrcQ") - - # connect B1 --> B0 - result = self._brokers[0].qmf_object.create( "link", - "Link-dynamic", - {"host":self._brokers[1].host, - "port":self._brokers[1].port}, False) - self.assertEqual(result.status, 0) - - # bridge the "fedX" exchange: - result = self._brokers[0].qmf_object.create("bridge", - "Bridge-dynamic", - {"link":"Link-dynamic", - "src":"fedX", - "dest":"fedX", - "dynamic":True, - "queue":"fedSrcQ"}, False) - self.assertEqual(result.status, 0) - - # wait for the inter-broker links to become operational - operational = False - timeout = time() + 10 - while not operational and time() <= timeout: - operational = True - for _l in qmf.getObjects(_class="link"): - #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - self.failUnless(operational, "inter-broker links failed to become operational.") - - # wait until the binding key has propagated to the src broker - exchanges[1].update() - timeout = time() + 10 - while exchanges[1].bindingCount < 1 and time() <= timeout: - exchanges[1].update() - self.failUnless(exchanges[1].bindingCount == 1) - - # - # Tear down the bridges between the two exchanges, then wait - # for the bindings to be cleaned up - # - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - exchanges[1].update() - timeout = time() + 10 - while exchanges[1].bindingCount != 0 and time() <= timeout: - exchanges[1].update() - self.failUnless(exchanges[1].bindingCount == 0) - - self._brokers[1].client_session.queue_delete(queue="fedSrcQ") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers[0:2]: - _b.client_session.exchange_delete(exchange="fedX") - - self._teardown_brokers() - - self.verify_cleanup() - - def test_credit(self): - """ Test a federation link configured to use explict acks and a credit - limit - """ - session = self.session - - # setup queue on remote broker and add some messages - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_credit") - r_session.queue_declare(queue="my-bridge-queue", auto_delete=True) - - #setup queue to receive messages from local broker - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0, result) - - link = qmf.getObjects(_class="link")[0] - - # now wait for Link to go operational - retries = 0 - operational = False - while not operational: - link.update() - if link.state == "Operational": - operational = True; - if not operational: - retries += 1 - self.failIfEqual(retries, 10, - "inter-broker links failed to become operational.") - sleep(1) - - # create the subscription - result = link.bridge(False, "my-bridge-queue", "amq.fanout", "my-key", - "", "", True, False, False, - 3, # explicit ack, with sync every 3 msgs - 7) # msg credit - self.assertEqual(result.status, 0, result) - bridge = qmf.getObjects(_class="bridge")[0] - - # generate enough traffic to trigger flow control and syncs - for i in range(1000): - dp = r_session.delivery_properties(routing_key="my-bridge-queue") - r_session.message_transfer(message=Message(dp, "Message %d" % i)) - - for i in range(1000): - try: - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - except Empty: - self.fail("Failed to find expected message containing 'Message %d'" % i) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0, result) - result = link.close() - self.assertEqual(result.status, 0, result) - - r_session.close() - r_conn.close() - - self.verify_cleanup() - diff --git a/qpid/cpp/src/tests/federation_sys.py b/qpid/cpp/src/tests/federation_sys.py deleted file mode 100755 index be9613bb9f..0000000000 --- a/qpid/cpp/src/tests/federation_sys.py +++ /dev/null @@ -1,977 +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. -# - -from inspect import stack -from qpid import messaging -from qpid.messaging import Message -from qpid.messaging.exceptions import Empty -from qpid.testlib import TestBase010 -from random import randint -from sys import stdout -from time import sleep - - -class Enum(object): - def __init__(self, **entries): - self.__dict__.update(entries) - def __repr__(self): - args = ['%s=%s' % (k, repr(v)) for (k,v) in vars(self).items()] - return 'Enum(%s)' % ', '.join(args) - - -class QmfTestBase010(TestBase010): - - _brokers = [] - _links = [] - _bridges = [] - _alt_exch_ops = Enum(none=0, create=1, delete=2) - - class _Broker(object): - """ - This broker proxy object holds the Qmf proxy to a broker of known address as well as the QMF broker - object, connection and sessions to the broker. - """ - def __init__(self, url): - self.url = url # format: "host:port" - url_parts = url.split(':') - self.host = url_parts[0] - self.port = int(url_parts[1]) - self.qmf_broker = None - self.connection = messaging.Connection.establish(self.url) - self.sessions = [] - def __str__(self): - return "_Broker %s:%s (%d open sessions)" % (self.host, self.port, len(self.sessions)) - def destroy(self, qmf = None): - if qmf is not None: - qmf.delBroker(self.qmf_broker.getBroker()) - for session in self.sessions: - try: # Session may have been closed by broker error - session.close() - except Exception, e: print "WARNING: %s: Unable to close session %s (%s): %s %s" % (self, session, hex(id(session)), type(e), e) - try: # Connection may have been closed by broker error - self.connection.close() - except Exception, e: print "WARNING: %s: Unable to close connection %s (%s): %s %s" % (self, self.connection, hex(id(self.connection)), type(e), e) - def session(self, name, transactional_flag = False): - session = self.connection.session(name, transactional_flag) - self.sessions.append(session) - return session - - def setUp(self): - """ - Called one before each test starts - """ - TestBase010.setUp(self) - self.startQmf(); - - def tearDown(self): - """ - Called once after each test competes. Close all Qmf objects (bridges, links and brokers) - """ - while len(self._bridges): - self._bridges.pop().close() - while len(self._links): - self._links.pop().close() - while len(self._brokers): - b = self._brokers.pop() - if len(self._brokers) <= 1: - b.destroy(None) - else: - b.destroy(self.qmf) - TestBase010.tearDown(self) - self.qmf.close() - - #--- General test utility functions - - def _get_name(self): - """ - Return the name of method which called this method stripped of "test_" prefix. Used for naming - queues and exchanges on a per-test basis. - """ - return stack()[1][3][5:] - - def _get_broker_port(self, key): - """ - Get the port of a broker defined in the environment using -D=portno - """ - return int(self.defines[key]) - - def _get_send_address(self, exch_name, queue_name): - """ - Get an address to which to send messages based on the exchange name and queue name, but taking into account - that the exchange name may be "" (the default exchange), in whcih case the format changes slightly. - """ - if len(exch_name) == 0: # Default exchange - return queue_name - return "%s/%s" % (exch_name, queue_name) - - def _get_broker(self, broker_port_key): - """ - Read the port numbers for pre-started brokers from the environment using keys, then find or create and return - the Qmf broker proxy for the appropriate broker - """ - port = self._get_broker_port(broker_port_key) - return self._find_create_broker("localhost:%s" % port) - ################ - def _get_msg_subject(self, topic_key): - """ - Return an appropriate subject for sending a message to a known topic. Return None if there is no topic. - """ - if len(topic_key) == 0: return None - if "*" in topic_key: return topic_key.replace("*", "test") - if "#" in topic_key: return topic_key.replace("#", "multipart.test") - return topic_key - - def _send_msgs(self, session_name, broker, addr, msg_count, msg_content = "Message_%03d", topic_key = "", - msg_durable_flag = False, enq_txn_size = 0): - """ - Send messages to a broker using address addr - """ - send_session = broker.session(session_name, transactional_flag = enq_txn_size > 0) - sender = send_session.sender(addr) - txn_cnt = 0 - for i in range(0, msg_count): - sender.send(Message(msg_content % (i + 1), subject = self._get_msg_subject(topic_key), durable = msg_durable_flag)) - if enq_txn_size > 0: - txn_cnt += 1 - if txn_cnt >= enq_txn_size: - send_session.commit() - txn_cnt = 0 - if enq_txn_size > 0 and txn_cnt > 0: - send_session.commit() - sender.close() - send_session.close() - - def _receive_msgs(self, session_name, broker, addr, msg_count, msg_content = "Message_%03d", deq_txn_size = 0, - timeout = 0): - """ - Receive messages from a broker - """ - receive_session = broker.session(session_name, transactional_flag = deq_txn_size > 0) - receiver = receive_session.receiver(addr) - txn_cnt = 0 - for i in range(0, msg_count): - try: - msg = receiver.fetch(timeout = timeout) - if deq_txn_size > 0: - txn_cnt += 1 - if txn_cnt >= deq_txn_size: - receive_session.commit() - txn_cnt = 0 - receive_session.acknowledge() - except Empty: - if deq_txn_size > 0: receive_session.rollback() - receiver.close() - receive_session.close() - if i == 0: - self.fail("Broker %s queue \"%s\" is empty" % (broker.qmf_broker.getBroker().getUrl(), addr)) - else: - self.fail("Unable to receive message %d from broker %s queue \"%s\"" % (i, broker.qmf_broker.getBroker().getUrl(), addr)) - if msg.content != msg_content % (i + 1): - receiver.close() - receive_session.close() - self.fail("Unexpected message \"%s\", was expecting \"%s\"." % (msg.content, msg_content % (i + 1))) - try: - msg = receiver.fetch(timeout = 0) - if deq_txn_size > 0: receive_session.rollback() - receiver.close() - receive_session.close() - self.fail("Extra message \"%s\" found on broker %s address \"%s\"" % (msg.content, broker.qmf_broker.getBroker().getUrl(), addr)) - except Empty: - pass - if deq_txn_size > 0 and txn_cnt > 0: - receive_session.commit() - receiver.close() - receive_session.close() - - #--- QMF-specific utility functions - - def _get_qmf_property(self, props, key): - """ - Get the value of a named property key kj from a property list [(k0, v0), (k1, v1), ... (kn, vn)]. - """ - for k,v in props: - if k.name == key: - return v - return None - - def _check_qmf_return(self, method_result): - """ - Check the result of a Qmf-defined method call - """ - self.assertTrue(method_result.status == 0, method_result.text) - - def _check_optional_qmf_property(self, qmf_broker, type, qmf_object, key, expected_val, obj_ref_flag): - """ - Optional Qmf properties don't show up in the properties list when they are not specified. Checks for - these property types involve searching the properties list and making sure it is present or not as - expected. - """ - val = self._get_qmf_property(qmf_object.getProperties(), key) - if val is None: - if len(expected_val) > 0: - self.fail("%s %s exists, but has does not have %s property. Expected value: \"%s\"" % - (type, qmf_object.name, key, expected_val)) - else: - if len(expected_val) > 0: - if obj_ref_flag: - obj = self.qmf.getObjects(_objectId = val, _broker = qmf_broker.getBroker()) - self.assertEqual(len(obj), 1, "More than one object with the same objectId: %s" % obj) - val = obj[0].name - self.assertEqual(val, expected_val, "%s %s exists, but has incorrect %s property. Found \"%s\", expected \"%s\"" % - (type, qmf_object.name, key, val, expected_val)) - else: - self.fail("%s %s exists, but has an unexpected %s property \"%s\" set." % (type, qmf_object.name, key, val)) - - #--- Find/create Qmf broker objects - - def _find_qmf_broker(self, url): - """ - Find the Qmf broker object for the given broker URL. The broker must have been previously added to Qmf through - addBroker() - """ - for b in self.qmf.getObjects(_class="broker"): - if b.getBroker().getUrl() == url: - return b - return None - - def _find_create_broker(self, url): - """ - Find a running broker through Qmf. If it does not exist, add it (assuming the broker is already running). - """ - broker = self._Broker(url) - self._brokers.append(broker) - if self.qmf is not None: - qmf_broker = self._find_qmf_broker(broker.url) - if qmf_broker is None: - self.qmf.addBroker(broker.url) - broker.qmf_broker = self._find_qmf_broker(broker.url) - else: - broker.qmf_broker = qmf_broker - return broker - - #--- Find/create/delete exchanges - - def _find_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete): - """ - Find Qmf exchange object - """ - for e in self.qmf.getObjects(_class="exchange", _broker = qmf_broker.getBroker()): - if e.name == name: - if len(name) == 0 or (len(name) >= 4 and name[:4] == "amq."): return e # skip checks for special exchanges - self.assertEqual(e.type, type, - "Exchange \"%s\" exists, but is of unexpected type %s; expected type %s." % - (name, e.type, type)) - self._check_optional_qmf_property(qmf_broker, "Exchange", e, "altExchange", alternate, True) - self.assertEqual(e.durable, durable, - "Exchange \"%s\" exists, but has incorrect durability. Found durable=%s, expected durable=%s" % - (name, e.durable, durable)) - self.assertEqual(e.autoDelete, auto_delete, - "Exchange \"%s\" exists, but has incorrect auto-delete property. Found %s, expected %s" % - (name, e.autoDelete, auto_delete)) - return e - return None - - def _find_create_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete, args): - """ - Find Qmf exchange object if exchange exists, create exchange and return its Qmf object if not - """ - e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete) - if e is not None: return e - # Does not exist, so create it - props = dict({"exchange-type": type, "type": type, "durable": durable, "auto-delete": auto_delete, "alternate-exchange": alternate}, **args) - self._check_qmf_return(qmf_broker.create(type="exchange", name=name, properties=props, strict=True)) - e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete) - self.assertNotEqual(e, None, "Creation of exchange %s on broker %s failed" % (name, qmf_broker.getBroker().getUrl())) - return e - - def _find_delete_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete): - """ - Find and delete Qmf exchange object if it exists - """ - e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete) - if e is not None and not auto_delete: - self._check_qmf_return(qmf_broker.delete(type="exchange", name=name, options={})) - - #--- Find/create/delete queues - - def _find_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete): - """ - Find a Qmf queue object - """ - for q in self.qmf.getObjects(_class="queue", _broker = qmf_broker.getBroker()): - if q.name == name: - self._check_optional_qmf_property(qmf_broker, "Queue", q, "altExchange", alternate_exchange, True) - self.assertEqual(q.durable, durable, - "Queue \"%s\" exists, but has incorrect durable property. Found %s, expected %s" % - (name, q.durable, durable)) - self.assertEqual(q.exclusive, exclusive, - "Queue \"%s\" exists, but has incorrect exclusive property. Found %s, expected %s" % - (name, q.exclusive, exclusive)) - self.assertEqual(q.autoDelete, auto_delete, - "Queue \"%s\" exists, but has incorrect auto-delete property. Found %s, expected %s" % - (name, q.autoDelete, auto_delete)) - return q - return None - - def _find_create_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete, args): - """ - Find Qmf queue object if queue exists, create queue and return its Qmf object if not - """ - q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete) - if q is not None: return q - # Queue does not exist, so create it - props = dict({"durable": durable, "auto-delete": auto_delete, "exclusive": exclusive, "alternate-exchange": alternate_exchange}, **args) - self._check_qmf_return(qmf_broker.create(type="queue", name=name, properties=props, strict=True)) - q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete) - self.assertNotEqual(q, None, "Creation of queue %s on broker %s failed" % (name, qmf_broker.getBroker().getUrl())) - return q - - def _find_delete_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete, args): - """ - Find and delete Qmf queue object if it exists - """ - q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete) - if q is not None and not auto_delete: - self._check_qmf_return(qmf_broker.delete(type="queue", name=name, options={})) - - #--- Find/create/delete bindings (between an exchange and a queue) - - def _find_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args): - """ - Find a Qmf binding object - """ - for b in self.qmf.getObjects(_class="binding", _broker = qmf_broker.getBroker()): - if b.exchangeRef == qmf_exchange.getObjectId() and b.queueRef == qmf_queue.getObjectId(): - if qmf_exchange.type != "fanout": # Fanout ignores the binding key, and always returns "" as the key - self.assertEqual(b.bindingKey, binding_key, - "Binding between exchange %s and queue %s exists, but has mismatching binding key: Found %s, expected %s." % - (qmf_exchange.name, qmf_queue.name, b.bindingKey, binding_key)) - self.assertEqual(b.arguments, binding_args, - "Binding between exchange %s and queue %s exists, but has mismatching arguments: Found %s, expected %s" % - (qmf_exchange.name, qmf_queue.name, b.arguments, binding_args)) - return b - return None - - def _find_create_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args): - """ - Find Qmf binding object if it exists, create binding and return its Qmf object if not - """ - b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args) - if b is not None: return b - # Does not exist, so create it - self._check_qmf_return(qmf_broker.create(type="binding", name="%s/%s/%s" % (qmf_exchange.name, qmf_queue.name, binding_key), properties=binding_args, strict=True)) - b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args) - self.assertNotEqual(b, None, "Creation of binding between exchange %s and queue %s with key %s failed" % - (qmf_exchange.name, qmf_queue.name, binding_key)) - return b - - def _find_delete_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args): - """ - Find and delete Qmf binding object if it exists - """ - b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args) - if b is not None: - if len(qmf_exchange.name) > 0: # not default exchange - self._check_qmf_return(qmf_broker.delete(type="binding", name="%s/%s/%s" % (qmf_exchange.name, qmf_queue.name, binding_key), options={})) - - #--- Find/create a link - - def _find_qmf_link(self, qmf_from_broker_proxy, host, port): - """ - Find a Qmf link object - """ - for l in self.qmf.getObjects(_class="link", _broker=qmf_from_broker_proxy): - if l.host == host and l.port == port: - return l - return None - - def _find_create_qmf_link(self, qmf_from_broker, qmf_to_broker_proxy, link_durable_flag, auth_mechanism, user_id, - password, transport, pause_interval, link_ready_timeout): - """ - Find a Qmf link object if it exists, create it and return its Qmf link object if not - """ - to_broker_host = qmf_to_broker_proxy.host - to_broker_port = qmf_to_broker_proxy.port - l = self._find_qmf_link(qmf_from_broker.getBroker(), to_broker_host, to_broker_port) - if l is not None: return l - # Does not exist, so create it - self._check_qmf_return(qmf_from_broker.connect(to_broker_host, to_broker_port, link_durable_flag, auth_mechanism, user_id, password, transport)) - l = self._find_qmf_link(qmf_from_broker.getBroker(), to_broker_host, to_broker_port) - self.assertNotEqual(l, None, "Creation of link from broker %s to broker %s failed" % - (qmf_from_broker.getBroker().getUrl(), qmf_to_broker_proxy.getUrl())) - self._wait_for_link(l, pause_interval, link_ready_timeout) - return l - - def _wait_for_link(self, link, pause_interval, link_ready_timeout): - """ - Wait for link to become active (state=Operational) - """ - tot_time = 0 - link.update() - while link.state != "Operational" and tot_time < link_ready_timeout: - sleep(pause_interval) - tot_time += pause_interval - link.update() - self.assertEqual(link.state, "Operational", "Timeout: Link not operational, state=%s" % link.state) - - #--- Find/create a bridge - - def _find_qmf_bridge(self, qmf_broker_proxy, qmf_link, source, destination, key): - """ - Find a Qmf link object - """ - for b in self.qmf.getObjects(_class="bridge", _broker=qmf_broker_proxy): - if b.linkRef == qmf_link.getObjectId() and b.src == source and b.dest == destination and b.key == key: - return b - return None - - def _find_create_qmf_bridge(self, qmf_broker_proxy, qmf_link, queue_name, exch_name, topic_key, - queue_route_type_flag, bridge_durable_flag): - """ - Find a Qmf bridge object if it exists, create it and return its Qmf object if not - """ - if queue_route_type_flag: - src = queue_name - dest = exch_name - key = "" - else: - src = exch_name - dest = exch_name - if len(topic_key) > 0: - key = topic_key - else: - key = queue_name - b = self._find_qmf_bridge(qmf_broker_proxy, qmf_link, src, dest, key) - if b is not None: - return b - # Does not exist, so create it - self._check_qmf_return(qmf_link.bridge(bridge_durable_flag, src, dest, key, "", "", queue_route_type_flag, False, False, 1, 0)) - b = self._find_qmf_bridge(qmf_broker_proxy, qmf_link, src, dest, key) - self.assertNotEqual(b, None, "Bridge creation failed: src=%s dest=%s key=%s" % (src, dest, key)) - return b - - def _wait_for_bridge(self, bridge, src_broker, dest_broker, exch_name, queue_name, topic_key, pause_interval, - bridge_ready_timeout): - """ - Wait for bridge to become active by sending messages over the bridge at 1 sec intervals until they are - observed at the destination. - """ - tot_time = 0 - active = False - send_session = src_broker.session("tx") - sender = send_session.sender(self._get_send_address(exch_name, queue_name)) - src_receive_session = src_broker.session("src_rx") - src_receiver = src_receive_session.receiver(queue_name) - dest_receive_session = dest_broker.session("dest_rx") - dest_receiver = dest_receive_session.receiver(queue_name) - while not active and tot_time < bridge_ready_timeout: - sender.send(Message("xyz123", subject = self._get_msg_subject(topic_key))) - try: - src_receiver.fetch(timeout = 0) - src_receive_session.acknowledge() - # Keep receiving msgs, as several may have accumulated - while True: - dest_receiver.fetch(timeout = 0) - dest_receive_session.acknowledge() - sleep(1) - active = True - except Empty: - sleep(pause_interval) - tot_time += pause_interval - dest_receiver.close() - dest_receive_session.close() - src_receiver.close() - src_receive_session.close() - sender.close() - send_session.close() - self.assertTrue(active, "Bridge failed to become active after %ds: %s" % (bridge_ready_timeout, bridge)) - - #--- Find/create/delete utility functions - - def _create_and_bind(self, qmf_broker, exchange_args, queue_args, binding_args): - """ - Create a binding between a named exchange and queue on a broker - """ - e = self._find_create_qmf_exchange(qmf_broker, **exchange_args) - q = self._find_create_qmf_queue(qmf_broker, **queue_args) - return self._find_create_qmf_binding(qmf_broker, e, q, **binding_args) - - def _check_alt_exchange(self, qmf_broker, alt_exch_name, alt_exch_type, alt_exch_op): - """ - Check for existence of alternate exchange. Return the Qmf exchange proxy object for the alternate exchange - """ - if len(alt_exch_name) == 0: return None - if alt_exch_op == _alt_exch_ops.create: - return self._find_create_qmf_exchange(qmf_broker=qmf_broker, name=alt_exch_name, type=alt_exch_type, - alternate="", durable=False, auto_delete=False, args={}) - if alt_exch_op == _alt_exch_ops.delete: - return self._find_delete_qmf_exchange(qmf_broker=qmf_broker, name=alt_exch_name, type=alt_exch_type, - alternate="", durable=False, auto_delete=False) - return self._find_qmf_exchange(qmf_broker=qmf_broker, name=alt_exchange_name, type=alt_exchange_type, - alternate="", durable=False, auto_delete=False) - - def _delete_queue_binding(self, qmf_broker, exchange_args, queue_args, binding_args): - """ - Delete a queue and the binding between it and the exchange - """ - e = self._find_qmf_exchange(qmf_broker, exchange_args["name"], exchange_args["type"], exchange_args["alternate"], exchange_args["durable"], exchange_args["auto_delete"]) - q = self._find_qmf_queue(qmf_broker, queue_args["name"], queue_args["alternate_exchange"], queue_args["durable"], queue_args["exclusive"], queue_args["auto_delete"]) - self._find_delete_qmf_binding(qmf_broker, e, q, **binding_args) - self._find_delete_qmf_queue(qmf_broker, **queue_args) - - def _create_route(self, queue_route_type_flag, src_broker, dest_broker, exch_name, queue_name, topic_key, - link_durable_flag, bridge_durable_flag, auth_mechanism, user_id, password, transport, - pause_interval = 1, link_ready_timeout = 20, bridge_ready_timeout = 20): - """ - Create a route from a source broker to a destination broker - """ - l = self._find_create_qmf_link(dest_broker.qmf_broker, src_broker.qmf_broker.getBroker(), link_durable_flag, - auth_mechanism, user_id, password, transport, pause_interval, link_ready_timeout) - self._links.append(l) - b = self._find_create_qmf_bridge(dest_broker.qmf_broker.getBroker(), l, queue_name, exch_name, topic_key, - queue_route_type_flag, bridge_durable_flag) - self._bridges.append(b) - self._wait_for_bridge(b, src_broker, dest_broker, exch_name, queue_name, topic_key, pause_interval, bridge_ready_timeout) - - # Parameterized test - entry point for tests - - def _do_test(self, - test_name, # Name of test - exch_name = "amq.direct", # Remote exchange name - exch_type = "direct", # Remote exchange type - exch_alt_exch = "", # Remote exchange alternate exchange - exch_alt_exch_type = "direct", # Remote exchange alternate exchange type - exch_durable_flag = False, # Remote exchange durability - exch_auto_delete_flag = False, # Remote exchange auto-delete property - exch_x_args = {}, # Remote exchange args - queue_alt_exch = "", # Remote queue alternate exchange - queue_alt_exch_type = "direct", # Remote queue alternate exchange type - queue_durable_flag = False, # Remote queue durability - queue_exclusive_flag = False, # Remote queue exclusive property - queue_auto_delete_flag = False, # Remote queue auto-delete property - queue_x_args = {}, # Remote queue args - binding_durable_flag = False, # Remote binding durability - binding_x_args = {}, # Remote binding args - topic_key = "", # Binding key For remote topic exchanges only - msg_count = 10, # Number of messages to send - msg_durable_flag = False, # Message durability - link_durable_flag = False, # Route link durability - bridge_durable_flag = False, # Route bridge durability - queue_route_type_flag = False, # Route type: false = bridge route, true = queue route - enq_txn_size = 0, # Enqueue transaction size, 0 = no transactions - deq_txn_size = 0, # Dequeue transaction size, 0 = no transactions - alt_exch_op = _alt_exch_ops.create,# Op on alt exch [create (ensure present), delete (ensure not present), none (neither create nor delete)] - auth_mechanism = "", # Authorization mechanism for linked broker - user_id = "", # User ID for authorization on linked broker - password = "", # Password for authorization on linked broker - transport = "tcp" # Transport for route to linked broker - ): - """ - Parameterized federation test. Sets up a federated link between a source broker and a destination broker and - checks that messages correctly pass over the link to the destination. Where appropriate (non-queue-routes), also - checks for the presence of messages on the source broker. - - In these tests, the concept is to create a LOCAL broker, then create a link to a REMOTE broker using federation. - In other words, the messages sent to the LOCAL broker will be replicated on the REMOTE broker, and tests are - performed on the REMOTE broker to check that the required messages are present. In the case of regular routes, - the LOCAL broker will also retain the messages, and a similar test is performed on this broker. - - TODO: There are several items to improve here: - 1. _do_test() is rather general. Rather create a version for each exchange type and test the exchange/queue - interaction in more detail based on the exchange type - 2. Add a headers and an xml exchange type - 3. Restructure the tests to start and stop brokers directly rather than relying on previously - started brokers. Then persistence can be checked by stopping and restarting the brokers. In particular, - test the persistence of links and bridges, both of which take a persistence flag. - 4. Test the behavior of the alternate exchanges when messages are sourced through a link. Also check behavior - when the alternate exchange is not present or is deleted after the reference is made. - 5. Test special queue types (eg LVQ) - """ - local_broker = self._get_broker("local-port") - remote_broker = self._get_broker("remote-port") - - # Check alternate exchanges exist (and create them if not) on both local and remote brokers - self._check_alt_exchange(local_broker.qmf_broker, exch_alt_exch, exch_alt_exch_type, alt_exch_op) - self._check_alt_exchange(local_broker.qmf_broker, queue_alt_exch, queue_alt_exch_type, alt_exch_op) - self._check_alt_exchange(remote_broker.qmf_broker, exch_alt_exch, exch_alt_exch_type, alt_exch_op) - self._check_alt_exchange(remote_broker.qmf_broker, queue_alt_exch, queue_alt_exch_type, alt_exch_op) - - queue_name = "queue_%s" % test_name - exchange_args = {"name": exch_name, "type": exch_type, "alternate": exch_alt_exch, - "durable": exch_durable_flag, "auto_delete": exch_auto_delete_flag, "args": exch_x_args} - queue_args = {"name": queue_name, "alternate_exchange": queue_alt_exch, "durable": queue_durable_flag, - "exclusive": queue_exclusive_flag, "auto_delete": queue_auto_delete_flag, "args": queue_x_args} - binding_args = {"binding_args": binding_x_args} - if exch_type == "topic": - self.assertTrue(len(topic_key) > 0, "Topic exchange selected, but no topic key was set.") - binding_args["binding_key"] = topic_key - elif exch_type == "direct": - binding_args["binding_key"] = queue_name - else: - binding_args["binding_key"] = "" - self._create_and_bind(qmf_broker=local_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args) - self._create_and_bind(qmf_broker=remote_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args) - self._create_route(queue_route_type_flag, local_broker, remote_broker, exch_name, queue_name, topic_key, - link_durable_flag, bridge_durable_flag, auth_mechanism, user_id, password, transport) - - self._send_msgs("send_session", local_broker, addr = self._get_send_address(exch_name, queue_name), - msg_count = msg_count, topic_key = topic_key, msg_durable_flag = msg_durable_flag, enq_txn_size = enq_txn_size) - if not queue_route_type_flag: - self._receive_msgs("local_receive_session", local_broker, addr = queue_name, msg_count = msg_count, deq_txn_size = deq_txn_size) - self._receive_msgs("remote_receive_session", remote_broker, addr = queue_name, msg_count = msg_count, deq_txn_size = deq_txn_size, timeout = 5) - - # Clean up - self._delete_queue_binding(qmf_broker=local_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args) - self._delete_queue_binding(qmf_broker=remote_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args) - -class A_ShortTests(QmfTestBase010): - - def test_route_defaultExch(self): - self._do_test(self._get_name()) - - def test_queueRoute_defaultExch(self): - self._do_test(self._get_name(), queue_route_type_flag=True) - - -class A_LongTests(QmfTestBase010): - - def test_route_amqDirectExch(self): - self._do_test(self._get_name(), exch_name="amq.direct") - - def test_queueRoute_amqDirectExch(self): - self._do_test(self._get_name(), exch_name="amq.direct", queue_route_type_flag=True) - - - def test_route_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange") - - def test_queueRoute_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True) - - - def test_route_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout") - - def test_queueRoute_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True) - - - def test_route_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#") - - def test_queueRoute_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True) - - -class B_ShortTransactionTests(QmfTestBase010): - - def test_txEnq01_route_defaultExch(self): - self._do_test(self._get_name(), enq_txn_size=1) - - def test_txEnq01_queueRoute_defaultExch(self): - self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq01_txDeq01_route_defaultExch(self): - self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_defaultExch(self): - self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - -class B_LongTransactionTests(QmfTestBase010): - - def test_txEnq10_route_defaultExch(self): - self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_defaultExch(self): - self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - - - - def test_txEnq01_route_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1) - - def test_txEnq01_queueRoute_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq10_route_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq01_txDeq01_route_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - - def test_txEnq01_route_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1) - - def test_txEnq01_queueRoute_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq10_route_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq01_txDeq01_route_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - - def test_txEnq01_route_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1) - - def test_txEnq01_queueRoute_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq10_route_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq01_txDeq01_route_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - -class E_ShortPersistenceTests(QmfTestBase010): - - def test_route_durQueue_defaultExch(self): - self._do_test(self._get_name(), queue_durable_flag=True) - - def test_route_durMsg_durQueue_defaultExch(self): - self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True) - - def test_queueRoute_durQueue_defaultExch(self): - self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True) - - def test_queueRoute_durMsg_durQueue_defaultExch(self): - self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True) - - -class E_LongPersistenceTests(QmfTestBase010): - - - def test_route_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True) - - def test_route_durMsg_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True) - - def test_queueRoute_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True) - - def test_queueRoute_durMsg_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True) - - - def test_route_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True) - - def test_route_durMsg_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True) - - def test_queueRoute_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True) - - def test_queueRoute_durMsg_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True) - - - def test_route_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True) - - def test_route_durMsg_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True) - - def test_queueRoute_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True) - - def test_queueRoute_durMsg_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True) - - -class F_ShortPersistenceTransactionTests(QmfTestBase010): - - def test_txEnq01_route_durQueue_defaultExch(self): - self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1) - - def test_txEnq01_route_durMsg_durQueue_defaultExch(self): - self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1) - - def test_txEnq01_queueRoute_durQueue_defaultExch(self): - self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq01_queueRoute_durMsg_durQueue_defaultExch(self): - self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq01_txDeq01_route_durQueue_defaultExch(self): - self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_route_durMsg_durQueue_defaultExch(self): - self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_durQueue_defaultExch(self): - self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_defaultExch(self): - self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - -class F_LongPersistenceTransactionTests(QmfTestBase010): - - def test_txEnq10_route_durQueue_defaultExch(self): - self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_route_durMsg_durQueue_defaultExch(self): - self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_durQueue_defaultExch(self): - self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_durMsg_durQueue_defaultExch(self): - self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - - - - def test_txEnq01_route_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1) - - def test_txEnq01_route_durMsg_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1) - - def test_txEnq01_queueRoute_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq01_queueRoute_durMsg_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq10_route_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_route_durMsg_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_durMsg_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq01_txDeq01_route_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_route_durMsg_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_directExch(self): - self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - - def test_txEnq01_route_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1) - - def test_txEnq01_route_durMsg_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1) - - def test_txEnq01_queueRoute_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq01_queueRoute_durMsg_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq10_route_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_route_durMsg_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_durMsg_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq01_txDeq01_route_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_route_durMsg_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_fanoutExch(self): - self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - - def test_txEnq01_route_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1) - - def test_txEnq01_route_durMsg_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1) - - def test_txEnq01_queueRoute_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq01_queueRoute_durMsg_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1) - - def test_txEnq10_route_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_route_durMsg_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq10_queueRoute_durMsg_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103) - - def test_txEnq01_txDeq01_route_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_route_durMsg_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_topicExch(self): - self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1) - - diff --git a/qpid/cpp/src/tests/find_prog.ps1 b/qpid/cpp/src/tests/find_prog.ps1 deleted file mode 100644 index 5c482debbf..0000000000 --- a/qpid/cpp/src/tests/find_prog.ps1 +++ /dev/null @@ -1,36 +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. -# - -# Locate the subdirectory where the specified program resides; the program -# must have a directory and a file name, even if the directory is . -param( - [string] $prog # program to look for somewhere below cwd -) - -$dir = Split-Path $prog -$exe = Split-Path $prog -leaf -$sub = "" -$subs = "Debug","Release","MinSizeRel","RelWithDebInfo" -foreach ($try in $subs) { - $prog = "$dir\$try\$exe" - if (Test-Path $prog) { - $sub = $try - break - } -} diff --git a/qpid/cpp/src/tests/ha_test.py b/qpid/cpp/src/tests/ha_test.py deleted file mode 100755 index 3659185140..0000000000 --- a/qpid/cpp/src/tests/ha_test.py +++ /dev/null @@ -1,401 +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. -# - -import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil, math, unittest, random -import traceback -from brokertest import * -from threading import Thread, Lock, Condition -from logging import getLogger, WARN, ERROR, DEBUG, INFO -from qpidtoollibs import BrokerAgent -from qpid.harness import Skipped - -log = getLogger(__name__) - -class LogLevel: - """ - Temporarily change the log settings on the root logger. - Used to suppress expected WARN messages from the python client. - """ - def __init__(self, level): - self.save_level = getLogger().getEffectiveLevel() - getLogger().setLevel(level) - - def restore(self): - getLogger().setLevel(self.save_level) - -class QmfAgent(object): - """Access to a QMF broker agent.""" - def __init__(self, address, **kwargs): - self._connection = qm.Connection.establish( - 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 = self.getSession(sub.sessionRef) - if not session: return None - 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 - -class Credentials(object): - """SASL credentials: username, password, and mechanism""" - def __init__(self, username, password, mechanism): - (self.username, self.password, self.mechanism) = (username, password, mechanism) - - def __str__(self): return "Credentials%s"%(self.tuple(),) - - def tuple(self): return (self.username, self.password, self.mechanism) - - def add_user(self, url): return "%s/%s@%s"%(self.username, self.password, url) - -class HaPort: - """Many HA tests need to allocate a broker port dynamically and then kill - and restart a broker on that same port multiple times. qpidd --port=0 only - ensures the port for the initial broker process, subsequent brokers re-using - the same port may fail with "address already in use". - - HaPort binds and listens to the port and returns a file descriptor to pass - to qpidd --socket-fd. It holds on to the port untill the end of the test so - the broker can restart multiple times. - """ - - def __init__(self, test, port=0): - """Bind and listen to port. port=0 allocates a port dynamically. - self.port is the allocated port, self.fileno is the file descriptor for - qpid --socket-fd.""" - - self.test = test - self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.socket.bind(("", port)) - self.socket.listen(5) - self.port = self.socket.getsockname()[1] - self.fileno = self.socket.fileno() - self.stopped = False - test.teardown_add(self) # Stop during test.tearDown - - def teardown(self): # Called in tearDown - if not self.stopped: - self.stopped = True - self.socket.shutdown(socket.SHUT_RDWR) - self.socket.close() - - def __str__(self): return "HaPort"%(self.port, self.fileno) - - -class HaBroker(Broker): - """Start a broker with HA enabled - @param client_cred: (user, password, mechanism) for admin clients started by the HaBroker. - """ - - heartbeat=5 - - 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" - ha_port = ha_port or HaPort(test) - args = copy(args) - args += ["--load-module", BrokerTest.ha_lib, - # Non-standard settings for faster tests. - "--link-maintenance-interval=0.1", - "--ha-cluster=%s"%ha_cluster] - # Add default --log-enable arguments unless args already has --log arguments. - if not env_has_log_config() and not [l for l in args if l.startswith("--log")]: - args += ["--log-enable=info+", "--log-enable=debug+:ha::"] - if not [h for h in args if h.startswith("--link-heartbeat-interval")]: - args += ["--link-heartbeat-interval=%s"%(HaBroker.heartbeat)] - - if ha_replicate is not None: - args += [ "--ha-replicate=%s"%ha_replicate ] - if brokers_url: args += [ "--ha-brokers-url", brokers_url ] - # Set up default ACL - acl=os.path.join(os.getcwd(), "unrestricted.acl") - if not os.path.exists(acl): - aclf=file(acl,"w") - aclf.write(""" -acl allow all all - """) - aclf.close() - if not "--acl-file" in args: - args += [ "--acl-file", acl, ] - args += ["--socket-fd=%s"%ha_port.fileno, "--listen-disable=tcp"] - self._agent = None - self.client_credentials = client_credentials - self.ha_port = ha_port - Broker.__init__(self, test, args, port=ha_port.port, **kwargs) - - # Do some static setup to locate the qpid-config and qpid-ha tools. - @property - def qpid_ha_script(self): - if not hasattr(self, "_qpid_ha_script"): - qpid_ha_exec = os.path.join(os.getenv("SOURCE_DIR"), "management", - "python", "bin", "qpid-ha") - self._qpid_ha_script = import_script(qpid_ha_exec) - return self._qpid_ha_script - - def __repr__(self): return ""%(self.log, self.port()) - - def qpid_ha(self, args): - if not self.qpid_ha_script: - raise Skipped("qpid-ha not available") - 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", "--cluster-manager"]) - def replicate(self, from_broker, queue): self.qpid_ha(["replicate", from_broker, queue]) - @property - def agent(self): - if not self._agent: - cred = self.client_credentials - if cred: - self._agent = QmfAgent(cred.add_user(self.host_port()), sasl_mechanisms=cred.mechanism) - else: - self._agent = QmfAgent(self.host_port()) - return self._agent - - def qmf(self): - hb = self.agent.getHaBroker() - hb.update() - return hb - - def ha_status(self): return self.qmf().status - - def wait_status(self, status, timeout=10): - - def try_get_status(): - self._status = "" - try: - self._status = self.ha_status() - except qm.ConnectionError, e: - # Record the error but don't raise, the broker may not be up yet. - self._status = "%s: %s" % (type(e).__name__, e) - return self._status == status; - assert retry(try_get_status, timeout=timeout), "%s expected=%r, actual=%r"%( - self, status, self._status) - - def wait_queue(self, queue, timeout=10, msg="wait_queue"): - """ Wait for queue to be visible via QMF""" - agent = self.agent - assert retry(lambda: agent.getQueue(queue) is not None, timeout=timeout), \ - "%s queue %s not present" % (msg, queue) - - def wait_no_queue(self, queue, timeout=10, msg="wait_no_queue"): - """ Wait for queue to be invisible via QMF""" - agent = self.agent - assert retry(lambda: agent.getQueue(queue) is None, timeout=timeout), "%s: queue %s still present"%(msg,queue) - - def qpid_config(self, args): - assert subprocess.call( - ["qpid-config", "--broker", self.host_port()]+args, stdout=1, stderr=subprocess.STDOUT - ) == 0, "qpid-config failed" - - def config_replicate(self, from_broker, queue): - self.qpid_config(["add", "queue", "--start-replica", from_broker, queue]) - - def config_declare(self, queue, replication): - self.qpid_config(["add", "queue", queue, "--replicate", replication]) - - def connect_admin(self, **kwargs): - cred = self.client_credentials - if cred: - return Broker.connect( - self, client_properties={"qpid.ha-admin":1}, - username=cred.username, password=cred.password, sasl_mechanisms=cred.mechanism, - **kwargs) - else: - return Broker.connect(self, client_properties={"qpid.ha-admin":1}, **kwargs) - - def wait_address(self, address): - """Wait for address to become valid on the broker.""" - c = self.connect_admin() - try: wait_address(c, address) - finally: c.close() - - wait_backup = wait_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_backup(self, queue, expected, **kwargs): - """Combines wait_backup and assert_browse_retry.""" - c = self.connect_admin() - try: - wait_address(c, queue) - if not "msg" in kwargs: - kwargs["msg"]=str(self) - assert_browse_retry(c.session(), queue, expected, **kwargs) - finally: c.close() - - assert_browse = assert_browse_backup - - def assert_connect_fail(self): - try: - self.connect() - self.test.fail("Expected qm.ConnectionError") - except qm.ConnectionError: pass - - def try_connect(self): - try: return self.connect() - except qm.ConnectionError: return None - - 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.teardown() - self._agent = None - return Broker.kill(self) - - -class HaCluster(object): - _cluster_count = 0 - - 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 = copy(args) - self.s_args = copy(s_args) - self.kwargs = kwargs - self._ports = [HaPort(test) for i in xrange(n)] - self._set_url() - self._brokers = [] - self.id = HaCluster._cluster_count - self.broker_id = 0 - HaCluster._cluster_count += 1 - for i in xrange(n): self.start() - if promote: - self[0].promote() - if wait: - self[0].wait_status("active") - for b in self[1:]: b.wait_status("ready") - - def next_name(self): - name="cluster%s-%s"%(self.id, self.broker_id) - self.broker_id += 1 - return 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=args, **self.kwargs) - b.ready(timeout=10) - return b - - def start(self): - """Start a new broker in the cluster""" - i = len(self) - assert i <= len(self._ports) - if i == len(self._ports): # Adding new broker after cluster init - self._ports.append(HaPort(self.test)) - self._set_url() - b = self._ha_broker(i, self.next_name()) - self._brokers.append(b) - return b - - def _set_url(self): - self.url = ",".join("127.0.0.1:%s"%(p.port) for p in self._ports) - - def connect(self, i, **kwargs): - """Connect with reconnect_urls""" - c = self[i].connect(reconnect=True, reconnect_urls=self.url.split(","), **kwargs) - self.test.teardown_add(c) # Clean up - return c - - def kill(self, i, promote_next=True, final=True): - """Kill broker i, promote broker i+1""" - self[i].kill(final=final) - if promote_next: self[(i+1) % len(self)].promote() - - def restart(self, i): - """Start a broker with the same port, name and data directory. It will get - 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(i, b.name) - self._brokers[i].ready() - - def bounce(self, i, promote_next=True): - """Stop and restart a broker in a cluster.""" - if (len(self) == 1): - self.kill(i, promote_next=False, final=False) - self.restart(i) - self[i].ready() - if promote_next: self[i].promote() - else: - self.kill(i, promote_next, final=False) - self.restart(i) - - # Behave like a list of brokers. - def __len__(self): return len(self._brokers) - def __getitem__(self,index): return self._brokers[index] - def __iter__(self): return self._brokers.__iter__() - - -def wait_address(connection, address): - """Wait for an address to become valid.""" - assert retry(lambda: valid_address(connection, address)), "Timed out waiting for address %s"%(address) - -def valid_address(connection, address): - """Test if an address is valid""" - try: - s = connection.session().receiver(address) - s.session.close() - return True - except qm.NotFound: - return False - - diff --git a/qpid/cpp/src/tests/ha_test_max_queues.cpp b/qpid/cpp/src/tests/ha_test_max_queues.cpp deleted file mode 100644 index fcce4c3151..0000000000 --- a/qpid/cpp/src/tests/ha_test_max_queues.cpp +++ /dev/null @@ -1,67 +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 -#include -#include -#include -#include -#include - -using namespace qpid::client; -using namespace std; - -int main(int argc, char** argv) { - if (argc != 2) { - cerr << "Expecing URL of broker as argument" << endl; - exit(1); - } - try { - // We need to create a large number of queues quickly, so we - // use the old API for it's asynchronous commands. - // The qpid::messaging API does not allow async queue creation. - // - Connection c; - c.open(qpid::Url(argv[1])); - AsyncSession s = async(c.newSession()); - // Generate too many queues, make sure we get an exception. - for (uint64_t i = 0; i < 100000; ++i) { - ostringstream os; - os << "q" << i; - string q = os.str(); - s.queueDeclare(q, arg::sync=false); - if (i && i % 1000 == 0) { - s.sync(); // Check for exceptions. - cout << "Declared " << q << endl; - } - } - cout << "Expected resource-limit-exceeded exception" << endl; - return 1; - } - catch (const qpid::framing::ResourceLimitExceededException& e) { - cout << "Resource limit exceeded: " << e.what() << endl; - return 0; - } - catch (const std::exception& e) { - cout << "Error: " << e.what() << endl; - return 1; - } -} diff --git a/qpid/cpp/src/tests/ha_tests.py b/qpid/cpp/src/tests/ha_tests.py deleted file mode 100755 index fdcb314751..0000000000 --- a/qpid/cpp/src/tests/ha_tests.py +++ /dev/null @@ -1,1458 +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. -# - -import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil, math, unittest -import traceback -from qpid.datatypes import uuid4, UUID -from brokertest import * -from ha_test import * -from threading import Thread, Lock, Condition -from logging import getLogger, WARN, ERROR, DEBUG, INFO -from qpidtoollibs import BrokerAgent, EventHelper - -log = getLogger(__name__) - -class HaBrokerTest(BrokerTest): - """Base class for HA broker tests""" - -class ReplicationTests(HaBrokerTest): - """Correctness tests for HA replication.""" - - def test_replication(self): - """Test basic replication of configuration and messages before and - after backup has connected""" - - def setup(prefix, primary): - """Create config, send messages on the primary p""" - a = primary.agent - - def queue(name, replicate): - a.addQueue(name, options={'qpid.replicate':replicate}) - return name - - def exchange(name, replicate, bindq, key): - a.addExchange("fanout", name, options={'qpid.replicate':replicate}) - a.bind(name, bindq, key) - return name - - # Test replication of messages - p = primary.connect().session() - s = p.sender(queue(prefix+"q1", "all")) - for m in ["a", "b", "1"]: s.send(qm.Message(m)) - # Test replication of dequeue - self.assertEqual(p.receiver(prefix+"q1").fetch(timeout=0).content, "a") - p.acknowledge() - - p.sender(queue(prefix+"q2", "configuration")).send(qm.Message("2")) - p.sender(queue(prefix+"q3", "none")).send(qm.Message("3")) - p.sender(exchange(prefix+"e1", "all", prefix+"q1", "key1")).send(qm.Message("4")) - p.sender(exchange(prefix+"e2", "configuration", prefix+"q2", "key2")).send(qm.Message("5")) - # Test unbind - p.sender(queue(prefix+"q4", "all")).send(qm.Message("6")) - s3 = p.sender(exchange(prefix+"e4", "all", prefix+"q4", "key4")) - s3.send(qm.Message("7")) - a.unbind(prefix+"e4", prefix+"q4", "key4") - p.sender(prefix+"e4").send(qm.Message("drop1")) # Should be dropped - - # Test replication of deletes - queue(prefix+"dq", "all") - exchange(prefix+"de", "all", prefix+"dq", "") - a.delQueue(prefix+"dq") - a.delExchange(prefix+"de") - - # Need a marker so we can wait till sync is done. - queue(prefix+"x", "configuration") - - def verify(b, prefix, p): - """Verify setup was replicated to backup b""" - # Wait for configuration to replicate. - wait_address(b.connection, prefix+"x"); - self.assert_browse_retry(b, prefix+"q1", ["b", "1", "4"]) - - self.assertEqual(p.receiver(prefix+"q1").fetch(timeout=0).content, "b") - p.acknowledge() - self.assert_browse_retry(b, prefix+"q1", ["1", "4"]) - - self.assert_browse_retry(b, prefix+"q2", []) # configuration only - assert not valid_address(b.connection, prefix+"q3") - - # Verify exchange with replicate=all - b.sender(prefix+"e1/key1").send(qm.Message(prefix+"e1")) - self.assert_browse_retry(b, prefix+"q1", ["1", "4", prefix+"e1"]) - - # Verify exchange with replicate=configuration - b.sender(prefix+"e2/key2").send(qm.Message(prefix+"e2")) - self.assert_browse_retry(b, prefix+"q2", [prefix+"e2"]) - - b.sender(prefix+"e4/key4").send(qm.Message("drop2")) # Verify unbind. - self.assert_browse_retry(b, prefix+"q4", ["6","7"]) - - # Verify deletes - assert not valid_address(b.connection, prefix+"dq") - assert not valid_address(b.connection, prefix+"de") - - l = LogLevel(ERROR) # Hide expected WARNING log messages from failover. - try: - cluster = HaCluster(self, 2) - primary = cluster[0] - backup = cluster[1] - - # Send messages before re-starting the backup, test catch-up replication. - cluster.kill(1, promote_next=False, final=False) - setup("1", primary) - cluster.restart(1) - - # Send messages after re-starting the backup, to test steady-state replication. - setup("2", primary) - - p = primary.connect().session() - - # Verify the data on the backup - b = backup.connect_admin().session() - verify(b, "1", p) - verify(b, "2", p) - # Test a series of messages, enqueue all then dequeue all. - primary.agent.addQueue("foo") - s = p.sender("foo") - wait_address(b.connection, "foo") - msgs = [str(i) for i in range(10)] - for m in msgs: s.send(qm.Message(m)) - self.assert_browse_retry(p, "foo", msgs) - self.assert_browse_retry(b, "foo", msgs) - r = p.receiver("foo") - for m in msgs: self.assertEqual(m, r.fetch(timeout=0).content) - p.acknowledge() - self.assert_browse_retry(p, "foo", []) - self.assert_browse_retry(b, "foo", []) - - # Another series, this time verify each dequeue individually. - for m in msgs: s.send(qm.Message(m)) - self.assert_browse_retry(p, "foo", msgs) - self.assert_browse_retry(b, "foo", msgs) - for i in range(len(msgs)): - self.assertEqual(msgs[i], r.fetch(timeout=0).content) - p.acknowledge() - self.assert_browse_retry(p, "foo", msgs[i+1:]) - self.assert_browse_retry(b, "foo", msgs[i+1:]) - finally: l.restore() - - def test_sync(self): - primary = HaBroker(self, name="primary") - primary.promote() - p = primary.connect().session() - s = p.sender("q;{create:always}") - for m in [str(i) for i in range(0,10)]: s.send(m) - s.sync() - backup1 = HaBroker(self, name="backup1", brokers_url=primary.host_port()) - for m in [str(i) for i in range(10,20)]: s.send(m) - s.sync() - backup2 = HaBroker(self, name="backup2", brokers_url=primary.host_port()) - for m in [str(i) for i in range(20,30)]: s.send(m) - s.sync() - - msgs = [str(i) for i in range(30)] - b1 = backup1.connect_admin().session() - backup1.assert_browse_backup("q", msgs) - backup2.assert_browse_backup("q", msgs) - - def test_send_receive(self): - """Verify sequence numbers of messages sent by qpid-send""" - l = LogLevel(ERROR) # Hide expected WARNING log messages from failover. - try: - brokers = HaCluster(self, 3) - sender = self.popen( - ["qpid-send", - "--broker", brokers[0].host_port(), - "--address", "q;{create:always}", - "--messages=1000", - "--content-string=x", - "--connection-options={%s}"%self.protocol_option() - ]) - receiver = self.popen( - ["qpid-receive", - "--broker", brokers[0].host_port(), - "--address", "q;{create:always}", - "--messages=990", - "--timeout=10", - "--connection-options={%s}"%self.protocol_option() - ]) - self.assertEqual(sender.wait(), 0) - self.assertEqual(receiver.wait(), 0) - expect = [long(i) for i in range(991, 1001)] - sn = lambda m: m.properties["sn"] - brokers[1].assert_browse_backup("q", expect, transform=sn) - brokers[2].assert_browse_backup("q", expect, transform=sn) - finally: l.restore() - - def test_failover_python(self): - """Verify that backups rejects connections and that fail-over works in python client""" - l = LogLevel(ERROR) # Hide expected WARNING log messages from failover. - try: - primary = HaBroker(self, name="primary") - primary.promote() - backup = HaBroker(self, name="backup", brokers_url=primary.host_port()) - # Check that backup rejects normal connections - try: - backup.connect().session() - self.fail("Expected connection to backup to fail") - except qm.ConnectionError: pass - # Check that admin connections are allowed to backup. - 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) - s = c.session() - sender = s.sender("q;{create:always}") - sender.send("foo", sync=True) - s.sync() - primary.kill() - assert retry(lambda: not is_running(primary.pid)) - backup.promote() - sender.send("bar") - self.assert_browse_retry(s, "q", ["foo", "bar"]) - c.close() - finally: l.restore() - - - def test_heartbeat_python(self): - """Verify that a python client with a heartbeat specified disconnects - from a stalled broker and does not hang indefinitely.""" - - broker = Broker(self) - broker_addr = broker.host_port() - - # Case 1: Connect before stalling the broker, use the connection after stalling. - c = qm.Connection(broker_addr, heartbeat=1) - c.open() - os.kill(broker.pid, signal.SIGSTOP) # Stall the broker - - def make_sender(): c.session().sender("foo") - self.assertRaises(qm.ConnectionError, make_sender) - - # Case 2: Connect to a stalled broker - c = qm.Connection(broker_addr, heartbeat=1) - self.assertRaises(qm.ConnectionError, c.open) - - # Case 3: Re-connect to a stalled broker. - broker2 = Broker(self) - c = qm.Connection(broker2.host_port(), heartbeat=1, reconnect_limit=1, - reconnect=True, reconnect_urls=[broker_addr], - reconnect_log=False) # Hide expected warnings - c.open() - broker2.kill() # Cause re-connection to broker - self.assertRaises(qm.ConnectionError, make_sender) - - def test_failover_cpp(self): - """Verify that failover works in the C++ client.""" - cluster = HaCluster(self, 2) - cluster[0].connect().session().sender("q;{create:always}") - cluster[1].wait_backup("q") - # FIXME aconway 2014-02-21: using 0-10, there is a failover problem with 1.0 - sender = NumberedSender(cluster[0], url=cluster.url, queue="q", - connection_options="reconnect:true,protocol:'amqp0-10'") - receiver = NumberedReceiver(cluster[0], url=cluster.url, queue="q", - connection_options="reconnect:true,protocol:'amqp0-10'") - receiver.start() - sender.start() - assert retry(lambda: receiver.received > 10) # Wait for some messages to get thru - cluster.kill(0) - n = receiver.received - assert retry(lambda: receiver.received > n + 10) # Verify we are still going - sender.stop() - receiver.stop() - - def test_backup_failover(self): - """Verify that a backup broker fails over and recovers queue state""" - brokers = HaCluster(self, 3) - brokers[0].connect().session().sender("q;{create:always}").send("a") - brokers.kill(0) - brokers[1].connect().session().sender("q").send("b") - brokers[2].assert_browse_backup("q", ["a","b"]) - s = brokers[1].connect().session() - self.assertEqual("a", s.receiver("q").fetch().content) - s.acknowledge() - brokers[2].assert_browse_backup("q", ["b"]) - - def test_empty_backup_failover(self): - """Verify that a new primary becomes active with no queues. - Regression test for QPID-5430""" - brokers = HaCluster(self, 3) - brokers.kill(0) - brokers[1].wait_status("active") - - def test_qpid_config_replication(self): - """Set up replication via qpid-config""" - brokers = HaCluster(self,2) - brokers[0].config_declare("q","all") - brokers[0].connect().session().sender("q").send("foo") - brokers[1].assert_browse_backup("q", ["foo"]) - - def test_standalone_queue_replica(self): - """Test replication of individual queues outside of cluster mode""" - primary = HaBroker(self, name="primary", ha_cluster=False, - args=["--ha-queue-replication=yes"]); - pc = primary.connect() - ps = pc.session().sender("q;{create:always}") - pr = pc.session().receiver("q;{create:always}") - backup = HaBroker(self, name="backup", ha_cluster=False, - args=["--ha-queue-replication=yes"]) - bs = backup.connect().session() - br = bs.receiver("q;{create:always}") - - def srange(*args): return [str(i) for i in xrange(*args)] - - for m in srange(3): ps.send(m) - # Set up replication with qpid-ha - backup.replicate(primary.host_port(), "q") - backup.assert_browse_backup("q", srange(3)) - for m in srange(3,6): ps.send(str(m)) - backup.assert_browse_backup("q", srange(6)) - self.assertEqual("0", pr.fetch().content) - pr.session.acknowledge() - backup.assert_browse_backup("q", srange(1,6)) - - # Set up replication with qpid-config - ps2 = pc.session().sender("q2;{create:always}") - backup.config_replicate(primary.host_port(), "q2"); - ps2.send("x") - backup.assert_browse_backup("q2", ["x"]) - - - def test_standalone_queue_replica_failover(self): - """Test individual queue replication from a cluster to a standalone - backup broker, verify it fails over.""" - l = LogLevel(ERROR) # Hide expected WARNING log messages from failover. - try: - cluster = HaCluster(self, 2) - primary = cluster[0] - pc = cluster.connect(0) - ps = pc.session().sender("q;{create:always}") - pr = pc.session().receiver("q;{create:always}") - backup = HaBroker(self, name="backup", ha_cluster=False, - args=["--ha-queue-replication=yes"]) - br = backup.connect().session().receiver("q;{create:always}") - backup.replicate(cluster.url, "q") - ps.send("a") - ps.sync() - backup.assert_browse_backup("q", ["a"]) - cluster.bounce(0) - backup.assert_browse_backup("q", ["a"]) - ps.send("b") - backup.assert_browse_backup("q", ["a", "b"]) - cluster[0].wait_status("ready") - cluster.bounce(1) - # FIXME aconway 2014-02-20: pr does not fail over with 1.0/swig - if qm == qpid_messaging: - print "WARNING: Skipping SWIG client failover bug" - return - self.assertEqual("a", pr.fetch().content) - pr.session.acknowledge() - backup.assert_browse_backup("q", ["b"]) - pc.close() - br.close() - finally: l.restore() - - def test_lvq(self): - """Verify that we replicate to an LVQ correctly""" - cluster = HaCluster(self, 2) - s = cluster[0].connect().session().sender("lvq; {create:always, node:{x-declare:{arguments:{'qpid.last_value_queue_key':lvq-key}}}}") - - def send(key,value,expect): - s.send(qm.Message(content=value,properties={"lvq-key":key})) - cluster[1].assert_browse_backup("lvq", expect) - - send("a", "a-1", ["a-1"]) - send("b", "b-1", ["a-1", "b-1"]) - send("a", "a-2", ["b-1", "a-2"]) - send("a", "a-3", ["b-1", "a-3"]) - send("c", "c-1", ["b-1", "a-3", "c-1"]) - send("c", "c-2", ["b-1", "a-3", "c-2"]) - send("b", "b-2", ["a-3", "c-2", "b-2"]) - send("c", "c-3", ["a-3", "b-2", "c-3"]) - send("d", "d-1", ["a-3", "b-2", "c-3", "d-1"]) - - def test_ring(self): - """Test replication with the ring queue policy""" - """Verify that we replicate to an LVQ correctly""" - cluster = HaCluster(self, 2) - s = cluster[0].connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':ring, 'qpid.max_count':5}}}}") - for i in range(10): s.send(qm.Message(str(i))) - cluster[1].assert_browse_backup("q", [str(i) for i in range(5,10)]) - - def test_reject(self): - """Test replication with the reject queue policy""" - cluster = HaCluster(self, 2) - primary, backup = cluster - s = primary.connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':reject, 'qpid.max_count':5}}}}") - try: - for i in range(10): s.send(qm.Message(str(i)), sync=False) - except qm.LinkError: pass - backup.assert_browse_backup("q", [str(i) for i in range(0,5)]) - try: s.session.connection.close() - except: pass # Expect exception from broken session - - def test_priority(self): - """Verify priority queues replicate correctly""" - cluster = HaCluster(self, 2) - session = cluster[0].connect().session() - s = session.sender("priority-queue; {create:always, node:{x-declare:{arguments:{'qpid.priorities':10}}}}") - priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2] - for p in priorities: s.send(qm.Message(priority=p)) - # Can't use browse_backup as browser sees messages in delivery order not priority. - cluster[1].wait_backup("priority-queue") - r = cluster[1].connect_admin().session().receiver("priority-queue") - received = [r.fetch().priority for i in priorities] - self.assertEqual(sorted(priorities, reverse=True), received) - - def test_priority_fairshare(self): - """Verify priority queues replicate correctly""" - cluster = HaCluster(self, 2) - primary, backup = cluster - session = primary.connect().session() - levels = 8 - priorities = [4,5,3,7,8,8,2,8,2,8,8,16,6,6,6,6,6,6,8,3,5,8,3,5,5,3,3,8,8,3,7,3,7,7,7,8,8,8,2,3] - limits={7:0,6:4,5:3,4:2,3:2,2:2,1:2} - limit_policy = ",".join(["'qpid.fairshare':5"] + ["'qpid.fairshare-%s':%s"%(i[0],i[1]) for i in limits.iteritems()]) - s = session.sender("priority-queue; {create:always, node:{x-declare:{arguments:{'qpid.priorities':%s, %s}}}}"%(levels,limit_policy)) - messages = [qm.Message(content=str(uuid4()), priority = p) for p in priorities] - for m in messages: s.send(m) - backup.wait_backup(s.target) - r = backup.connect_admin().session().receiver("priority-queue") - received = [r.fetch().content for i in priorities] - sort = sorted(messages, key=lambda m: priority_level(m.priority, levels), reverse=True) - fair = [m.content for m in fairshare(sort, lambda l: limits.get(l,0), levels)] - self.assertEqual(received, fair) - - def test_priority_ring(self): - cluster = HaCluster(self, 2) - primary, backup = cluster - s = primary.connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':ring, 'qpid.max_count':5, 'qpid.priorities':10}}}}") - priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2] - for p in priorities: s.send(qm.Message(priority=p)) - expect = sorted(priorities,reverse=True)[0:5] - primary.assert_browse("q", expect, transform=lambda m: m.priority) - backup.assert_browse_backup("q", expect, transform=lambda m: m.priority) - - def test_backup_acquired(self): - """Verify that acquired messages are backed up, for all queue types.""" - class Test: - def __init__(self, queue, arguments, expect): - self.queue = queue - self.address = "%s;{create:always,node:{x-declare:{arguments:{%s}}}}"%( - self.queue, ",".join(arguments)) - self.expect = [str(i) for i in expect] - - def send(self, connection): - """Send messages, then acquire one but don't acknowledge""" - s = connection.session() - for m in range(10): s.sender(self.address).send(str(m)) - s.receiver(self.address).fetch() - - def verify(self, brokertest, backup): - backup.assert_browse_backup(self.queue, self.expect, msg=self.queue) - - tests = [ - Test("plain",[],range(10)), - Test("ring", ["'qpid.policy_type':ring", "'qpid.max_count':5"], range(5,10)), - Test("priority",["'qpid.priorities':10"], range(10)), - Test("fairshare", ["'qpid.priorities':10,'qpid.fairshare':5"], range(10)), - Test("lvq", ["'qpid.last_value_queue_key':lvq-key"], [9]) - ] - - cluster = HaCluster(self, 3) - cluster.kill(2, final=False) # restart after messages are sent to test catch-up - - c = cluster[0].connect() - for t in tests: t.send(c) # Send messages, leave one unacknowledged. - - cluster.restart(2) - cluster[2].wait_status("ready") - - # Verify acquired message was replicated - for t in tests: t.verify(self, cluster[1]) - for t in tests: t.verify(self, cluster[2]) - - def test_replicate_default(self): - """Make sure we don't replicate if ha-replicate is unspecified or none""" - cluster1 = HaCluster(self, 2, ha_replicate=None) - cluster1[1].wait_status("ready") - c1 = cluster1[0].connect().session().sender("q;{create:always}") - cluster2 = HaCluster(self, 2, ha_replicate="none") - cluster2[1].wait_status("ready") - cluster2[0].connect().session().sender("q;{create:always}") - time.sleep(.1) # Give replication a chance. - # Expect queues not to be found - self.assertRaises(qm.NotFound, cluster1[1].connect_admin().session().receiver, "q") - self.assertRaises(qm.NotFound, cluster2[1].connect_admin().session().receiver, "q") - - def test_replicate_binding(self): - """Verify that binding replication can be disabled""" - cluster = HaCluster(self, 2) - primary, backup = cluster[0], cluster[1] - ps = primary.connect().session() - a = primary.agent - a.addExchange("fanout", "ex") - a.addQueue("q") - a.bind("ex", "q", options={'qpid.replicate':'none'}) - backup.wait_backup("q") - - primary.kill() - assert retry(lambda: not is_running(primary.pid)) # Wait for primary to die - backup.promote() - bs = backup.connect_admin().session() - bs.sender("ex").send(qm.Message("msg")) - self.assert_browse_retry(bs, "q", []) - - def test_invalid_replication(self): - """Verify that we reject an attempt to declare a queue with invalid replication value.""" - cluster = HaCluster(self, 1, ha_replicate="all") - self.assertRaises(Exception, cluster[0].connect().session().sender, - "q;{create:always, node:{x-declare:{arguments:{'qpid.replicate':XXinvalidXX}}}}") - - def test_exclusive_queue(self): - """Ensure that we can back-up exclusive queues, i.e. the replicating - subscriptions are exempt from the exclusivity""" - cluster = HaCluster(self, 2) - def test(addr): - c = cluster[0].connect() - q = addr.split(";")[0] - r = c.session().receiver(addr) - self.assertRaises(qm.LinkError, c.session().receiver, addr) - s = c.session().sender(q).send(q) - cluster[1].assert_browse_backup(q, [q]) - test("excl_queue;{create:always, node:{x-declare:{exclusive:True}}}") - if qm == qpid.messaging: # FIXME aconway 2014-02-20: swig client no exclusive subscribe - test("excl_sub;{create:always, link:{x-subscribe:{exclusive:True}}}"); - - def test_auto_delete_exclusive(self): - """Verify that we ignore auto-delete, exclusive, non-auto-delete-timeout queues""" - cluster = HaCluster(self, 2) - s0 = cluster[0].connect().session() - s0.receiver("exad;{create:always,node:{x-declare:{exclusive:True,auto-delete:True}}}") - s0.receiver("ex;{create:always,node:{x-declare:{exclusive:True}}}") - ad = s0.receiver("ad;{create:always,node:{x-declare:{auto-delete:True}}}") - s0.receiver("time;{create:always,node:{x-declare:{exclusive:True,auto-delete:True,arguments:{'qpid.auto_delete_timeout':1}}}}") - s0.receiver("q;{create:always}") - - s1 = cluster[1].connect_admin().session() - cluster[1].wait_backup("q") - assert not valid_address(s1.connection, "exad") - assert valid_address(s1.connection, "ex") - assert valid_address(s1.connection, "ad") - assert valid_address(s1.connection, "time") - - # Verify that auto-delete queues are not kept alive by - # replicating subscriptions - ad.close() - s0.sync() - assert not valid_address(s0.connection, "ad") - - def test_broker_info(self): - """Check that broker information is correctly published via management""" - cluster = HaCluster(self, 3) - - def ha_broker(broker): - ha_broker = broker.agent.getHaBroker(); - ha_broker.update() - return ha_broker - - for broker in cluster: # Make sure HA system-id matches broker's - self.assertEqual(ha_broker(broker).systemId, UUID(broker.agent.getBroker().systemRef)) - - # Check that all brokers have the same membership as the cluster - def check_ids(broker): - cluster_ids = set([ ha_broker(b).systemId for b in cluster]) - broker_ids = set([m["system-id"] for m in ha_broker(broker).members]) - assert retry(lambda: cluster_ids == broker_ids, 1), "%s != %s on %s"%(cluster_ids, broker_ids, broker) - - for broker in cluster: check_ids(broker) - - # Add a new broker, check it is updated everywhere - b = cluster.start() - for broker in cluster: check_ids(broker) - - def test_auth(self): - """Verify that authentication does not interfere with replication.""" - # TODO aconway 2012-07-09: generate test sasl config portably for cmake - sasl_config=os.path.join(self.rootdir, "sasl_config") - if not os.path.exists(sasl_config): - print "WARNING: Skipping test, SASL test configuration %s not found."%sasl_config - return - acl=os.path.join(os.getcwd(), "policy.acl") - aclf=file(acl,"w") - # 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 -acl allow zag@QPID delete queue -acl allow zag@QPID access exchange -acl allow zag@QPID create exchange -acl allow zag@QPID bind exchange -acl allow zag@QPID publish exchange -acl allow zag@QPID delete exchange -acl allow zag@QPID access method -acl allow zag@QPID create link -acl allow zag@QPID access query -# Normal user -acl allow zig@QPID all all -acl deny all all - """) - aclf.close() - cluster = HaCluster( - self, 2, - args=["--auth", "yes", "--sasl-config", sasl_config, - "--acl-file", acl, - "--ha-username=zag", "--ha-password=zag", "--ha-mechanism=PLAIN" - ], - client_credentials=Credentials("zag", "zag", "PLAIN")) - c = cluster[0].connect(username="zig", password="zig") - s0 = c.session(); - a = cluster[0].agent - a.addQueue("q") - a.addExchange("fanout", "ex") - a.bind("ex", "q", "") - s0.sender("ex").send("foo"); - - # Transactions should be done over the tx_protocol - c = cluster[0].connect(protocol=self.tx_protocol, username="zig", password="zig") - 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 - to new members of a cluster. """ - cluster = HaCluster(self, 2) - s = cluster[0].connect().session() - # altex exchange: acts as alternate exchange - a = cluster[0].agent - a.addExchange("fanout", "altex") - # altq queue bound to altex, collect re-routed messages. - a.addQueue("altq") - a.bind("altex", "altq", "") - # ex exchange with alternate-exchange altex and no queues bound - a.addExchange("direct", "ex", {"alternate-exchange":"altex"}) - # create queue q with alternate-exchange altex - a.addQueue("q", {"alternate-exchange":"altex"}) - # create a bunch of exchanges to ensure we don't clean up prematurely if the - # response comes in multiple fragments. - for i in xrange(200): s.sender("ex.%s;{create:always,node:{type:topic}}"%i) - - def verify(broker): - c = broker.connect() - s = c.session() - # Verify unmatched message goes to ex's alternate. - s.sender("ex").send("foo") - altq = s.receiver("altq") - self.assertEqual("foo", altq.fetch(timeout=0).content) - s.acknowledge() - # Verify rejected message goes to q's alternate. - s.sender("q").send("bar") - msg = s.receiver("q").fetch(timeout=0) - self.assertEqual("bar", msg.content) - s.acknowledge(msg, qm.Disposition(qm.REJECTED)) # Reject the message - self.assertEqual("bar", altq.fetch(timeout=0).content) - s.acknowledge() - s.sync() # Make sure backups are caught-up. - c.close() - - # Sanity check: alternate exchanges on original broker - verify(cluster[0]) - a = cluster[0].agent - # Altex is in use as an alternate exchange, we should get an exception - self.assertRaises(Exception, a.delExchange, "altex") - # Check backup that was connected during setup. - def wait(broker): - broker.wait_status("ready") - for a in ["q", "ex", "altq", "altex"]: - broker.wait_backup(a) - wait(cluster[1]) - cluster.bounce(0) - verify(cluster[1]) - - # Check a newly started backup. - cluster.start() - wait(cluster[2]) - cluster.bounce(1) - verify(cluster[2]) - - # Check that alt-exchange in-use count is replicated - a = cluster[2].agent - self.assertRaises(Exception, a.delExchange, "altex") - a.delQueue("q") - self.assertRaises(Exception, a.delExchange, "altex") - a.delExchange("ex") - a.delExchange("altex") - - def test_priority_reroute(self): - """Regression test for QPID-4262, rerouting messages from a priority queue - to itself causes a crash""" - cluster = HaCluster(self, 2) - primary = cluster[0] - session = primary.connect().session() - a = primary.agent - a.addQueue("pq", {'qpid.priorities':10}) - a.bind("amq.fanout", "pq") - s = session.sender("pq") - for m in xrange(100): s.send(qm.Message(str(m), priority=m%10)) - pq = QmfAgent(primary.host_port()).getQueue("pq") - pq.reroute(request=0, useAltExchange=False, exchange="amq.fanout") - # Verify that consuming is in priority order - expect = [str(10*i+p) for p in xrange(9,-1,-1) for i in xrange(0,10) ] - actual = [m.content for m in primary.get_messages("pq", 100)] - self.assertEqual(expect, actual) - - def test_delete_missing_response(self): - """Check that a backup correctly deletes leftover queues and exchanges that are - missing from the initial reponse set.""" - # This test is a bit contrived, we set up the situation on backup brokers - # and then promote one. - cluster = HaCluster(self, 2, promote=False) - - # cluster[0] Will be the primary - s = cluster[0].connect_admin().session() - s.sender("q1;{create:always}") - s.sender("e1;{create:always, node:{type:topic}}") - - # cluster[1] will be the backup, has extra queues/exchanges - xdecl = "x-declare:{arguments:{'qpid.replicate':'all'}}" - node = "node:{%s}"%(xdecl) - s = cluster[1].connect_admin().session() - s.sender("q1;{create:always, %s}"%(node)) - s.sender("q2;{create:always, %s}"%(node)) - s.sender("e1;{create:always, node:{type:topic, %s}}"%(xdecl)) - s.sender("e2;{create:always, node:{type:topic, %s}}"%(xdecl)) - for a in ["q1", "q2", "e1", "e2"]: cluster[1].wait_backup(a) - - cluster[0].promote() - # Verify the backup deletes the surplus queue and exchange - cluster[1].wait_status("ready") - s = cluster[1].connect_admin().session() - self.assertRaises(qm.NotFound, s.receiver, ("q2")); - self.assertRaises(qm.NotFound, s.receiver, ("e2")); - - - def test_delete_qpid_4285(self): - """Regression test for QPID-4285: on deleting a queue it gets stuck in a - partially deleted state and causes replication errors.""" - cluster = HaCluster(self,2) - s = cluster[0].connect().session() - s.receiver("q;{create:always}") - cluster[1].wait_backup("q") - cluster.kill(0) # Make the backup take over. - s = cluster[1].connect().session() - cluster[1].agent.delQueue("q") # Delete q on new primary - self.assertRaises(qm.NotFound, s.receiver, "q") - assert not cluster[1].agent.getQueue("q") # Should not be in QMF - - def test_auto_delete_failover(self): - """Test auto-delete queues. Verify that: - - queues auto-deleted on the primary are deleted on the backup. - - auto-delete queues with/without timeout are deleted after a failover correctly - - auto-delete queues never used (subscribe to) to are not deleted - - messages are correctly routed to the alternate exchange. - """ - cluster = HaCluster(self, 3) - s = cluster[0].connect().session() - a = cluster[0].agent - - def setup(q, timeout=None): - # Create alternate exchange, auto-delete queue and queue bound to alt. ex. - a.addExchange("fanout", q+"-altex") - args = {"auto-delete":True, "alternate-exchange":q+"-altex"} - if timeout is not None: args['qpid.auto_delete_timeout'] = timeout - a.addQueue(q, args) - a.addQueue(q+"-altq") - a.bind("%s-altex"%q, "%s-altq"%q) - - for args in [["q1"],["q2",0],["q3",1],["q4"],["q5"]]: setup(*args) - receivers = [] - for i in xrange(1,5): # Don't use q5 - q = "q%s"%i - receivers.append(s.receiver(q)) # Subscribe - qs = s.sender(q); qs.send(q); qs.close() # Send q name as message - - receivers[3].close() # Trigger auto-delete for q4 - for b in cluster[1:3]: b.wait_no_queue("q4") # Verify deleted on backups - - cluster[0].kill(final=False) # Kill primary - cluster[2].promote() - cluster.restart(0) - cluster[2].wait_queue("q3") # Not yet auto-deleted, 1 sec timeout. - for b in cluster: - for q in ["q%s"%i for i in xrange(1,5)]: - b.wait_no_queue(q,timeout=2, msg=str(b)) # auto-deleted - b.assert_browse_backup("%s-altq"%q, [q]) # Routed to alternate - cluster[2].wait_queue("q5") # Not auto-deleted, never subscribed - cluster[2].connect().session().receiver("q5").close() - cluster[2].wait_no_queue("q5") - - def test_auto_delete_close(self): - """Verify auto-delete queues are deleted on backup if auto-deleted - on primary""" - cluster=HaCluster(self, 2) - - # Create altex to use as alternate exchange, with altq bound to it - a = cluster[0].agent - a.addExchange("fanout", "altex") - a.addQueue("altq", {"auto-delete":True}) - a.bind("altex", "altq") - - p = cluster[0].connect().session() - r = p.receiver("adq1;{create:always,node:{x-declare:{auto-delete:True,alternate-exchange:'altex'}}}") - s = p.sender("adq1") - for m in ["aa","bb","cc"]: s.send(m) - s.close() - cluster[1].wait_queue("adq1") - r.close() # trigger auto-delete of adq1 - cluster[1].wait_no_queue("adq1") - cluster[1].assert_browse_backup("altq", ["aa","bb","cc"]) - - def test_expired(self): - """Regression test for QPID-4379: HA does not properly handle expired messages""" - # Race between messages expiring and HA replicating consumer. - cluster = HaCluster(self, 2) - s = cluster[0].connect().session().sender("q;{create:always}", capacity=2) - def send_ttl_messages(): - for i in xrange(100): s.send(qm.Message(str(i), ttl=0.001)) - send_ttl_messages() - cluster.start() - send_ttl_messages() - - def test_missed_recreate(self): - """If a queue or exchange is destroyed and one with the same name re-created - while a backup is disconnected, the backup should also delete/recreate - the object when it re-connects""" - cluster = HaCluster(self, 3) - sn = cluster[0].connect().session() - # Create a queue with messages - s = sn.sender("qq;{create:always}") - msgs = [str(i) for i in xrange(3)] - for m in msgs: s.send(m) - cluster[1].assert_browse_backup("qq", msgs) - cluster[2].assert_browse_backup("qq", msgs) - # Set up an exchange with a binding. - a = cluster[0].agent - a.addExchange("fanout", "xx") - a.addQueue("xxq") - a.bind("xx", "xxq", "xxq") - cluster[1].wait_address("xx") - self.assertEqual(cluster[1].agent.getExchange("xx").values["bindingCount"], 1) - cluster[2].wait_address("xx") - self.assertEqual(cluster[2].agent.getExchange("xx").values["bindingCount"], 1) - - # Simulate the race by re-creating the objects before promoting the new primary - cluster.kill(0, promote_next=False) - xdecl = "x-declare:{arguments:{'qpid.replicate':'all'}}" - node = "node:{%s}"%(xdecl) - sn = cluster[1].connect_admin().session() - a = cluster[1].agent - a.delQueue("qq", if_empty=False) - s = sn.sender("qq;{create:always, %s}"%(node)) - s.send("foo") - a.delExchange("xx") - sn.sender("xx;{create:always,node:{type:topic,%s}}"%(xdecl)) - cluster[1].promote() - cluster[1].wait_status("active") - # Verify we are not still using the old objects on cluster[2] - cluster[2].assert_browse_backup("qq", ["foo"]) - cluster[2].wait_address("xx") - self.assertEqual(cluster[2].agent.getExchange("xx").values["bindingCount"], 0) - - def test_resource_limit_bug(self): - """QPID-5666 Regression test: Incorrect resource limit exception for queue creation.""" - cluster = HaCluster(self, 3) - qs = ["q%s"%i for i in xrange(10)] - a = cluster[0].agent - a.addQueue("q") - cluster[1].wait_backup("q") - cluster.kill(0) - cluster[1].promote() - cluster[1].wait_status("active") - a = cluster[1].agent - a.delQueue("q") - a.addQueue("q") - -def fairshare(msgs, limit, levels): - """ - Generator to return prioritised messages in expected order for a given fairshare limit - """ - count = 0 - last_priority = None - postponed = [] - while msgs or postponed: - if not msgs: - msgs = postponed - count = 0 - last_priority = None - postponed = [ ] - msg = msgs.pop(0) - if last_priority and priority_level(msg.priority, levels) == last_priority: - count += 1 - else: - last_priority = priority_level(msg.priority, levels) - count = 1 - l = limit(last_priority) - if (l and count > l): - postponed.append(msg) - else: - yield msg - return - -def priority_level(value, levels): - """ - Method to determine which of a distinct number of priority levels - a given value falls into. - """ - offset = 5-math.ceil(levels/2.0) - return min(max(value - offset, 0), levels-1) - -class LongTests(HaBrokerTest): - """Tests that can run for a long time if -DDURATION= is set""" - - def duration(self): - d = self.config.defines.get("DURATION") - if d: return float(d)*60 - else: return 3 # Default is to be quick - - 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=50, - queue="test%s"%(i), args=["--capacity=10"]) for i in xrange(n)] - - receivers = [ - NumberedReceiver( - brokers[0], url=brokers.url, sender=senders[i], - queue="test%s"%(i), args=["--capacity=10"]) for i in xrange(n)] - - for r in receivers: r.start() - for s in senders: s.start() - - def wait_passed(r, n): - """Wait for receiver r to pass n""" - def check(): - r.check() # Verify no exceptions - return r.received > n + 100 - assert retry(check), "Stalled %s waiting for %s, sent %s"%( - r.queue, n, [s for s in senders if s.queue==r.queue][0].sent) - - for r in receivers: wait_passed(r, 0) - - # Kill and restart brokers in a cycle: - endtime = time.time() + self.duration() - i = 0 - primary = 0 - try: - try: - while time.time() < endtime or i < 3: # At least 3 iterations - # Precondition: All 3 brokers running, - # primary = index of promoted primary - # one or two backups are running, - for s in senders: s.sender.assert_running() - for r in receivers: r.receiver.assert_running() - checkpoint = [ r.received+10 for r in receivers ] - victim = random.choice([0,1,2,primary]) # Give the primary a better chance. - if victim == primary: - # Don't kill primary till it is active and the next - # backup is ready, otherwise we can lose messages. - brokers[victim].wait_status("active") - next = (victim+1)%3 - brokers[next].wait_status("ready") - brokers.bounce(victim) # Next one is promoted - primary = next - else: - brokers.bounce(victim, promote_next=False) - - # Make sure we are not stalled - map(wait_passed, receivers, checkpoint) - # Run another checkpoint to ensure things work in this configuration - checkpoint = [ r.received+10 for r in receivers ] - map(wait_passed, receivers, checkpoint) - i += 1 - except: - traceback.print_exc() - raise - finally: - for s in senders: s.stop() - for r in receivers: r.stop() - dead = filter(lambda b: not b.is_running(), brokers) - if dead: raise Exception("Brokers not running: %s"%dead) - - def test_tx_send_receive(self): - brokers = HaCluster(self, 3) - sender = self.popen( - ["qpid-send", - "--broker", brokers[0].host_port(), - "--address", "q;{create:always}", - "--messages=1000", - "--tx=10", - "--connection-options={protocol:%s}" % self.tx_protocol - ]) - receiver = self.popen( - ["qpid-receive", - "--broker", brokers[0].host_port(), - "--address", "q;{create:always}", - "--messages=990", - "--timeout=10", - "--tx=10", - "--connection-options={protocol:%s}" % self.tx_protocol - ]) - self.assertEqual(sender.wait(), 0) - self.assertEqual(receiver.wait(), 0) - expect = [long(i) for i in range(991, 1001)] - sn = lambda m: m.properties["sn"] - brokers[0].assert_browse("q", expect, transform=sn) - brokers[1].assert_browse_backup("q", expect, transform=sn) - brokers[2].assert_browse_backup("q", expect, transform=sn) - - - def test_qmf_order(self): - """QPID 4402: HA QMF events can be out of order. - This test mimics the test described in the JIRA. Two threads repeatedly - declare the same auto-delete queue and close their connection. - """ - broker = Broker(self) - class Receiver(Thread): - def __init__(self, qname): - Thread.__init__(self) - self.qname = qname - self.stopped = False - - def run(self): - while not self.stopped: - self.connection = broker.connect() - try: - self.connection.session().receiver( - self.qname+";{create:always,node:{x-declare:{auto-delete:True}}}") - except qm.NotFound: pass # Can occur occasionally, not an error. - try: self.connection.close() - except: pass - - class QmfObject(object): - """Track existance of an object and validate QMF events""" - def __init__(self, type_name, name_field, name): - self.type_name, self.name_field, self.name = type_name, name_field, name - self.exists = False - - def qmf_event(self, event): - content = event.content[0] - event_type = content['_schema_id']['_class_name'] - values = content['_values'] - if event_type == self.type_name+"Declare" and values[self.name_field] == self.name: - disp = values['disp'] - log.debug("Event %s: disp=%s exists=%s"%( - event_type, values['disp'], self.exists)) - if self.exists: assert values['disp'] == 'existing' - else: assert values['disp'] == 'created' - self.exists = True - elif event_type == self.type_name+"Delete" and values[self.name_field] == self.name: - log.debug("Event %s: exists=%s"%(event_type, self.exists)) - assert self.exists - self.exists = False - - # Verify order of QMF events. - helper = EventHelper() - r = broker.connect().session().receiver(helper.eventAddress()) - threads = [Receiver("qq"), Receiver("qq")] - for t in threads: t.start() - queue = QmfObject("queue", "qName", "qq") - finish = time.time() + self.duration() - try: - while time.time() < finish: - queue.qmf_event(r.fetch()) - finally: - for t in threads: t.stopped = True; t.join() - - def test_max_queues(self): - """Verify that we behave properly if we try to exceed the max number - of replicated queues - currently limited by the max number of channels - in the replication link""" - # This test is very slow (3 mins), skip it unless duration() > 1 minute. - if self.duration() < 60: return - # This test is written in C++ for speed, it takes a long time - # to create 64k queues in python. See ha_test_max_queues.cpp. - cluster = HaCluster(self, 2) - test = self.popen(["ha_test_max_queues", cluster[0].host_port()]) - self.assertEqual(test.wait(), 0) - -class RecoveryTests(HaBrokerTest): - """Tests for recovery after a failure.""" - - def test_queue_hold(self): - """Verify that the broker holds queues without sufficient backup, - i.e. does not complete messages sent to those queues.""" - - l = LogLevel(ERROR) # Hide expected WARNING log messages from failover. - try: - # We don't want backups to time out for this test, set long timeout. - cluster = HaCluster(self, 4, args=["--ha-backup-timeout=120"]); - # Wait for the primary to be ready - cluster[0].wait_status("active") - for b in cluster[1:4]: b.wait_status("ready") - # Create a queue before the failure. - # FIXME aconway 2014-02-20: SWIG client doesn't respect sync=False - s1 = cluster.connect(0, native=True).session().sender("q1;{create:always}") - for b in cluster: b.wait_backup("q1") - for i in xrange(10): s1.send(str(i), timeout=0.1) - - # Kill primary and 2 backups - cluster[3].wait_status("ready") - for i in [0,1,2]: cluster.kill(i, promote_next=False, final=False) - cluster[3].promote() # New primary, backups will be 1 and 2 - cluster[3].wait_status("recovering") - - def assertSyncTimeout(s): - self.assertRaises(qpid.messaging.Timeout, s.sync, timeout=.01) - - # Create a queue after the failure - # FIXME aconway 2014-02-20: SWIG client doesn't respect sync=False - s2 = cluster.connect(3, native=True).session().sender("q2;{create:always}") - - # Verify that messages sent are not completed - for i in xrange(10,20): - s1.send(str(i), sync=False, timeout=0.1); - s2.send(str(i), sync=False, timeout=0.1) - - assertSyncTimeout(s1) - self.assertEqual(s1.unsettled(), 10) - assertSyncTimeout(s2) - self.assertEqual(s2.unsettled(), 10) - - # Verify we can receive even if sending is on hold: - cluster[3].assert_browse("q1", [str(i) for i in range(10)]) - - # Restart backups, verify queues are released only when both backups are up - cluster.restart(1) - assertSyncTimeout(s1) - self.assertEqual(s1.unsettled(), 10) - assertSyncTimeout(s2) - self.assertEqual(s2.unsettled(), 10) - cluster.restart(2) - cluster.restart(0) - - # Verify everything is up to date and active - def settled(sender): sender.sync(timeout=1); return sender.unsettled() == 0; - assert retry(lambda: settled(s1)), "Unsetttled=%s"%(s1.unsettled()) - assert retry(lambda: settled(s2)), "Unsetttled=%s"%(s2.unsettled()) - cluster[1].assert_browse_backup("q1", [str(i) for i in range(10)+range(10,20)]) - cluster[1].assert_browse_backup("q2", [str(i) for i in range(10,20)]) - cluster[3].wait_status("active"), - s1.session.connection.close() - s2.session.connection.close() - finally: l.restore() - - def test_expected_backup_timeout(self): - """Verify that we time-out expected backups and release held queues - after a configured interval. Verify backup is demoted to catch-up, - but can still rejoin. - """ - cluster = HaCluster(self, 3, args=["--ha-backup-timeout=0.5"]); - for i in [0,1]: cluster.kill(i, False) - cluster[2].promote() # New primary, expected backup will be 1 - # Should not go active till the expected backup connects or times out. - cluster[2].wait_status("recovering") - # Messages should be held till expected backup times out - ss = cluster[2].connect().session() - s = ss.sender("q;{create:always}") - s.send("foo", sync=False) - self.assertEqual(s.unsettled(), 1) # Verify message not settled immediately. - s.sync(timeout=1) # And settled after timeout. - cluster[2].wait_status("active") - - def test_join_ready_cluster(self): - """If we join a cluster where the primary is dead, the new primary is - not yet promoted and there are ready backups then we should refuse - promotion so that one of the ready backups can be chosen.""" - cluster = HaCluster(self, 2) - cluster[0].wait_status("active") - cluster[1].wait_status("ready") - cluster.bounce(0, promote_next=False) - self.assertRaises(Exception, cluster[0].promote) - os.kill(cluster[1].pid, signal.SIGSTOP) # Test for timeout if unresponsive. - cluster.bounce(0, promote_next=False) - cluster[0].promote() - - def test_stalled_backup(self): - """Make sure that a stalled backup broker does not stall the primary""" - cluster = HaCluster(self, 3, args=["--link-heartbeat-interval=1"]) - os.kill(cluster[1].pid, signal.SIGSTOP) - s = cluster[0].connect().session() - s.sender("q;{create:always}").send("x") - self.assertEqual("x", s.receiver("q").fetch(0).content) - -class StoreTests(HaBrokerTest): - """Test for HA with persistence.""" - - def check_skip(self): - if not BrokerTest.store_lib: - print "WARNING: skipping HA+store tests, no store lib found." - return not BrokerTest.store_lib - - def test_store_recovery(self): - """Verify basic store and recover functionality""" - if self.check_skip(): return - cluster = HaCluster(self, 1) - sn = cluster[0].connect().session() - # Create queue qq, exchange exx and binding between them - s = sn.sender("qq;{create:always,node:{durable:true}}") - sk = sn.sender("exx/k;{create:always,node:{type:topic, durable:true, x-declare:{type:'direct'}}}") - cluster[0].agent.bind("exx", "qq", "k") - for m in ["foo", "bar", "baz"]: s.send(qm.Message(m, durable=True)) - r = cluster[0].connect().session().receiver("qq") - self.assertEqual(r.fetch().content, "foo") - r.session.acknowledge() - # Sending this message is a hack to flush the dequeue operation on qq. - s.send(qm.Message("flush", durable=True)) - - def verify(broker, x_count): - sn = broker.connect().session() - assert_browse(sn, "qq", [ "bar", "baz", "flush" ]+ (x_count)*["x"]) - sn.sender("exx/k").send(qm.Message("x", durable=True)) - assert_browse(sn, "qq", [ "bar", "baz", "flush" ]+ (x_count+1)*["x"]) - - verify(cluster[0], 0) # Sanity check - cluster.bounce(0) - cluster[0].wait_status("active") - verify(cluster[0], 1) # Loaded from store - cluster.start() - cluster[1].wait_status("ready") - cluster.kill(0) - cluster[1].wait_status("active") - verify(cluster[1], 2) - cluster.bounce(1, promote_next=False) - cluster[1].promote() - cluster[1].wait_status("active") - verify(cluster[1], 3) - - def test_catchup_store(self): - """Verify that a backup erases queue data from store recovery before - doing catch-up from the primary.""" - if self.check_skip(): return - cluster = HaCluster(self, 2) - sn = cluster[0].connect(heartbeat=HaBroker.heartbeat).session() - s1 = sn.sender("q1;{create:always,node:{durable:true}}") - for m in ["foo","bar"]: s1.send(qm.Message(m, durable=True)) - s2 = sn.sender("q2;{create:always,node:{durable:true}}") - sk2 = sn.sender("ex/k2;{create:always,node:{type:topic, durable:true, x-declare:{type:'direct'}}}") - cluster[0].agent.bind("ex", "q2", "k2") - sk2.send(qm.Message("hello", durable=True)) - # Wait for backup to catch up. - cluster[1].assert_browse_backup("q1", ["foo","bar"]) - 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=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(qm.Message(m, durable=True)) - cluster[0].agent.unbind("ex", "q2", "k2") - cluster[0].agent.bind("ex", "q1", "k1") - # Restart both brokers from store to get inconsistent sequence numbering. - cluster.bounce(0, promote_next=False) - cluster[0].promote() - cluster[0].wait_status("active") - cluster.restart(1) - cluster[1].wait_status("ready") - - # Verify state - cluster[0].assert_browse("q1", ["x","y","z"]) - cluster[1].assert_browse_backup("q1", ["x","y","z"]) - - 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"]) - sn.sender("ex/k2").send("hoo") # q2 was unbound so this should be dropped. - sn.sender("q2").send("end") # mark the end of the queue for assert_browse - 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): - - def tx_simple_setup(self, cluster, broker=0): - """Start a transaction, remove messages from queue a, add messages to queue b""" - c = cluster.connect(broker, protocol=self.tx_protocol) - # 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(qm.Message(content=m, durable=True)) - sa.close() - - # 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) - sb.close() - return tx - - def test_tx_simple_commit(self): - cluster = HaCluster(self, 2, test_store=True, wait=True) - tx = self.tx_simple_setup(cluster) - tx.sync() - tx.acknowledge() - # Pre transaction - messages are acquired on primary but not yet dequeued - # so still there on backup. - cluster[0].assert_browse_backup("a", []) - cluster[1].assert_browse_backup("a", ['x', 'y', 'z']) - for b in cluster: - b.assert_browse_backup("b", ['0', '1', '2']) - tx.commit() - tx.sync() - tx.close() - - # Post transaction: all synced. - for b in cluster: - b.assert_browse_backup("a", []) - b.assert_browse_backup("b", ['0', '1', '2', "x","y","z"]) - - # Verify non-tx dequeue is replicated correctly - c = cluster.connect(0, protocol=self.tx_protocol) - r = c.session().receiver("b") - ri = receiver_iter(r, timeout=1) - self.assertEqual(['0', '1', '2', 'x', 'y', 'z'], [m.content for m in ri]) - r.session.acknowledge() - for b in cluster: b.assert_browse_backup("b", [], msg=b) - c.close() - tx.connection.close() - - def test_tx_simple_rollback(self): - cluster = HaCluster(self, 2, test_store=True) - tx = self.tx_simple_setup(cluster) - tx.sync() - tx.acknowledge() - tx.rollback() - - for b in cluster: - b.assert_browse_backup("a", ["x","y","z"]) - b.assert_browse_backup("b", ['0', '1', '2']) - - tx.close() - tx.connection.close() - - - def test_tx_simple_failure(self): - """Verify we throw TransactionAborted if there is a fail-over during a transaction""" - cluster = HaCluster(self, 3, test_store=True) - tx = self.tx_simple_setup(cluster) - tx.sync() - tx_queues = cluster[0].agent.tx_queues() - tx.acknowledge() - l = LogLevel(ERROR) # Hide expected WARNING log messages from failover. - try: - cluster.bounce(0) # Should cause roll-back - tx.connection.session() # Wait for reconnect - self.assertRaises(qm.TransactionAborted, tx.sync) - self.assertRaises(qm.TransactionAborted, tx.commit) - try: tx.connection.close() - except qm.TransactionAborted: pass # Occasionally get exception on close. - for b in cluster: - b.assert_browse_backup("a", ["x","y","z"]) - b.assert_browse_backup("b", ['0', '1', '2']) - finally: l.restore() - - 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(protocol=self.tx_protocol).session(transactional=True) - s = tx.sender("q;{create:always}") - s.send("a", sync=True) - cluster[1].kill(final=False) - s.send("b") - tx.commit() - tx.connection.close() - for b in [cluster[0],cluster[2]]: - b.assert_browse_backup("q", ["a","b"], msg=b) - # Joining - tx = cluster[0].connect(protocol=self.tx_protocol).session(transactional=True) - s = tx.sender("q;{create:always}") - s.send("foo") - cluster.restart(1) # Not a part of the current transaction. - tx.commit() - tx.connection.close() - # The new member is not in the tx but receives the results normal replication. - for b in cluster: b.assert_browse_backup("q", ["a", "b", "foo"], msg=b) - - def test_tx_block_threads(self): - """Verify that TXs blocked in commit don't deadlock.""" - cluster = HaCluster(self, 2, args=["--worker-threads=2"], test_store=True) - n = 10 # Number of concurrent transactions - sessions = [cluster.connect(0, protocol=self.tx_protocol).session(transactional=True) for i in xrange(n)] - # Have the store delay the response for 10s - for s in sessions: - sn = s.sender("qq;{create:always,node:{durable:true}}") - sn.send(qm.Message("foo", durable=True)) - threads = [ Thread(target=s.commit) for s in sessions] - for t in threads: t.start() - cluster[0].ready(timeout=1) # Check for deadlock - for b in cluster: b.assert_browse_backup('qq', ['foo']*n) - for t in threads: t.join() - for s in sessions: s.connection.close() - - def test_other_tx_tests(self): - try: - import qpid_tests.broker_0_10 - except ImportError: - raise Skipped("Tests not found") - cluster = HaCluster(self, 3) - if "QPID_PORT" in os.environ: del os.environ["QPID_PORT"] - self.popen(["qpid-txtest2", "--broker", cluster[0].host_port()]).assert_exit_ok() - print - self.popen(["qpid-python-test", - "-m", "qpid_tests.broker_0_10", - "-m", "qpid_tests.broker_1_0", - "-b", "localhost:%s"%(cluster[0].port()), - "*.tx.*"], stdout=None, stderr=None).assert_exit_ok() - -if __name__ == "__main__": - outdir = "ha_tests.tmp" - shutil.rmtree(outdir, True) - os.execvp("qpid-python-test", - ["qpid-python-test", "-m", "ha_tests", "-DOUTDIR=%s"%outdir] - + sys.argv[1:]) - diff --git a/qpid/cpp/src/tests/header_test.cpp b/qpid/cpp/src/tests/header_test.cpp deleted file mode 100644 index c36b4f3bc3..0000000000 --- a/qpid/cpp/src/tests/header_test.cpp +++ /dev/null @@ -1,59 +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 - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" - -using namespace qpid; -using namespace qpid::client; -using namespace std; - -int main(int argc, char** argv) -{ - TestOptions opts; - try { - opts.parse(argc, argv); - Connection connection; - connection.open(opts.con); - Session session = connection.newSession(); - std::string q("header_interop_test_queue"); - session.queueDeclare(arg::queue=q); - double pi = 3.14159265; - float e = 2.71828f; - Message msg("", q); - msg.getMessageProperties().getApplicationHeaders().setDouble("pi", pi); - msg.getMessageProperties().getApplicationHeaders().setFloat("e", e); - session.messageTransfer(arg::content=msg); - - session.close(); - connection.close(); - - return 0; - } catch(const exception& e) { - cout << e.what() << endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/header_test.py b/qpid/cpp/src/tests/header_test.py deleted file mode 100755 index d5a2c16c01..0000000000 --- a/qpid/cpp/src/tests/header_test.py +++ /dev/null @@ -1,86 +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. -# - -import qpid -import sys -import os -from qpid.util import connect -from qpid.connection import Connection -from qpid.datatypes import Message, RangedSet, uuid4 -from qpid.queue import Empty -from math import fabs - -def getApplicationHeaders(msg): - for h in msg.headers: - if hasattr(h, 'application_headers'): return getattr(h, 'application_headers') - return None - -# Set parameters for login - -host="127.0.0.1" -port=5672 -user="guest" -password="guest" - -if len(sys.argv) > 1 : - host=sys.argv[1] -if len(sys.argv) > 2 : - port=int(sys.argv[2]) - -# Create a connection. -socket = connect(host, port) -connection = Connection (sock=socket) -connection.start() -session = connection.session(str(uuid4())) - -q = "header_interop_test_queue" -session.queue_declare(queue=q) - -session.message_subscribe(queue=q, destination="received") -queue = session.incoming("received") -queue.start() - -msg = queue.get(timeout=10) -pi = 3.14159265 -e = 2.71828 - -headers = getApplicationHeaders(msg) -pi_ = headers["pi"] -e_ = headers["e"] -session.close(timeout=10) - -failed = False - -if pi != pi_: - print "got incorrect value for pi: ", pi_, " expected:", pi - failed = True - -if fabs(e - e_) > 0.0001: - print "got incorrect value for e: ", e_, " expected:", e - failed = True - -if failed: - sys.exit(1) -else: - print "Correct header values received." - sys.exit(0) - - - diff --git a/qpid/cpp/src/tests/headers_federation.py b/qpid/cpp/src/tests/headers_federation.py deleted file mode 100644 index 60cff1da54..0000000000 --- a/qpid/cpp/src/tests/headers_federation.py +++ /dev/null @@ -1,99 +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. -# - -import sys -from qpid.testlib import TestBase010 -from qpid.datatypes import Message -from qpid.queue import Empty -from time import sleep - -class HeadersFederationTests(TestBase010): - - def remote_host(self): - return self.defines.get("remote-host", "localhost") - - def remote_port(self): - return int(self.defines["remote-port"]) - - def verify_cleanup(self): - attempts = 0 - total = len(self.qmf.getObjects(_class="bridge")) + len(self.qmf.getObjects(_class="link")) - while total > 0: - attempts += 1 - if attempts >= 10: - self.fail("Bridges and links didn't clean up") - return - sleep(1) - total = len(self.qmf.getObjects(_class="bridge")) + len(self.qmf.getObjects(_class="link")) - - def test_dynamic_headers_unbind(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_unbind") - - session.exchange_declare(exchange="fed.headers_unbind", type="headers") - r_session.exchange_declare(exchange="fed.headers_unbind", type="headers") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.headers_unbind", "fed.headers_unbind", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - queue = qmf.getObjects(_class="queue", name="fed1")[0] - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - session.exchange_bind(queue="fed1", exchange="fed.headers_unbind", binding_key="key1", arguments={'x-match':'any', 'class':'first'}) - queue.update() - self.assertEqual(queue.bindingCount, 2, - "bindings not accounted for (expected 2, got %d)" % queue.bindingCount) - - session.exchange_unbind(queue="fed1", exchange="fed.headers_unbind", binding_key="key1") - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def getProperty(self, msg, name): - for h in msg.headers: - if hasattr(h, name): return getattr(h, name) - return None - - def getAppHeader(self, msg, name): - headers = self.getProperty(msg, "application_headers") - if headers: - return headers[name] - return None diff --git a/qpid/cpp/src/tests/idle_timeout_tests.py b/qpid/cpp/src/tests/idle_timeout_tests.py deleted file mode 100755 index 877ec19164..0000000000 --- a/qpid/cpp/src/tests/idle_timeout_tests.py +++ /dev/null @@ -1,96 +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. -# - -import os -import shutil -import signal -import sys - -from brokertest import * -from qpid.harness import Skipped - -class AmqpIdleTimeoutTest(BrokerTest): - """ - Test AMQP 1.0 idle-timeout support - """ - def setUp(self): - BrokerTest.setUp(self) - if not BrokerTest.amqp_lib: - raise Skipped("AMQP 1.0 library not found") - if qm != qpid_messaging: - raise Skipped("AMQP 1.0 client not found") - self._broker = self.broker() - - def test_client_timeout(self): - """Ensure that the client disconnects should the broker stop - responding. - """ - conn = self._broker.connect(native=False, timeout=None, - protocol="amqp1.0", heartbeat=1) - self.assertTrue(conn.isOpen()) - # should disconnect within 2 seconds of broker stop - deadline = time.time() + 8 - os.kill(self._broker.pid, signal.SIGSTOP) - while time.time() < deadline: - if not conn.isOpen(): - break; - self.assertTrue(not conn.isOpen()) - os.kill(self._broker.pid, signal.SIGCONT) - - - def test_broker_timeout(self): - """By default, the broker will adopt the same timeout as the client - (mimics the 0-10 timeout behavior). Verify the broker disconnects - unresponsive clients. - """ - - count = len(self._broker.agent.getAllConnections()) - - # Create a new connection to the broker: - receiver_cmd = ["qpid-receive", - "--broker", self._broker.host_port(), - "--address=amq.fanout", - "--connection-options={protocol:amqp1.0, heartbeat:1}", - "--forever"] - receiver = self.popen(receiver_cmd, stdout=PIPE, stderr=PIPE, - expect=EXPECT_UNKNOWN) - start = time.time() - deadline = time.time() + 10 - while time.time() < deadline: - if count < len(self._broker.agent.getAllConnections()): - break; - self.assertTrue(count < len(self._broker.agent.getAllConnections())) - - # now 'hang' the client, the broker should disconnect - start = time.time() - os.kill(receiver.pid, signal.SIGSTOP) - deadline = time.time() + 10 - while time.time() < deadline: - if count == len(self._broker.agent.getAllConnections()): - break; - self.assertEqual(count, len(self._broker.agent.getAllConnections())) - os.kill(receiver.pid, signal.SIGCONT) - receiver.teardown() - - -if __name__ == "__main__": - shutil.rmtree("brokertest.tmp", True) - os.execvp("qpid-python-test", - ["qpid-python-test", "-m", "idle_timeout_tests"] + sys.argv[1:]) diff --git a/qpid/cpp/src/tests/interlink_tests.py b/qpid/cpp/src/tests/interlink_tests.py deleted file mode 100755 index 8833f06af5..0000000000 --- a/qpid/cpp/src/tests/interlink_tests.py +++ /dev/null @@ -1,331 +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. -# - -import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil, math, unittest, random -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 BrokerObject - -class Domain(BrokerObject): - def __init__(self, broker, values): - BrokerObject.__init__(self, broker, values) - -class Config: - def __init__(self, broker, address="q;{create:always}", version="amqp1.0"): - self.url = broker.host_port() - self.address = address - self.version = version - - def __str__(self): - return "url: %s, address: %s, version: %s" % (self.url, self.address, self.version) - -class AmqpBrokerTest(BrokerTest): - """ - Tests using AMQP 1.0 support - """ - def setUp(self): - BrokerTest.setUp(self) - self.port_holder = HaPort(self) - self.broker = self.amqp_broker(port_holder=self.port_holder) - self.default_config = Config(self.broker) - self.agent = self.broker.agent - - def sender(self, config, reply_to=None): - cmd = ["qpid-send", - "--broker", config.url, - "--address", config.address, - "--connection-options", "{protocol:%s}" % config.version, - "--content-stdin", "--send-eos=1" - ] - if reply_to: - cmd.append( "--reply-to=%s" % reply_to) - return self.popen(cmd, stdin=PIPE) - - def receiver(self, config): - cmd = ["qpid-receive", - "--broker", config.url, - "--address", config.address, - "--connection-options", "{protocol:%r}" % config.version, - "--timeout=10" - ] - return self.popen(cmd, stdout=PIPE) - - def ready_receiver(self, config): - s = self.broker.connect().session() - r = s.receiver("readyq; {create:always}") - cmd = ["qpid-receive", - "--broker", config.url, - "--address", config.address, - "--connection-options", "{protocol:%r}" % config.version, - "--timeout=10", "--ready-address=readyq;{create:always}" - ] - result = self.popen(cmd, stdout=PIPE) - r.fetch(timeout=1) # wait until receiver is actually ready - s.acknowledge() - r.close() - s.close() - return result - - def send_and_receive(self, send_config=None, recv_config=None, count=1000, reply_to=None, wait_for_receiver=False, debug=False): - if debug: - print "sender config is %s" % (send_config or self.default_config) - print "receiver config is %s" % (recv_config or self.default_config) - sender = self.sender(send_config or self.default_config, reply_to) - sender._set_cloexec_flag(sender.stdin) #required for older python, see http://bugs.python.org/issue4112 - if wait_for_receiver: - receiver = self.ready_receiver(recv_config or self.default_config) - else: - receiver = self.receiver(recv_config or self.default_config) - - messages = ["message-%s" % (i+1) for i in range(count)] - for m in messages: - sender.stdin.write(m + "\n") - sender.stdin.flush() - sender.stdin.close() - if debug: - c = send_config or self.default_config - print "sent %s messages to %s sn %s" % (len(messages), c.address, c.url) - - if debug: - c = recv_config or self.default_config - print "reading messages from %s sn %s" % (c.address, c.url) - for m in messages: - l = receiver.stdout.readline().rstrip() - if debug: - print l - assert m == l, (m, l) - - sender.wait() - receiver.wait() - - def test_simple(self): - self.send_and_receive() - - def test_translate1(self): - self.send_and_receive(recv_config=Config(self.broker, version="amqp0-10")) - - 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 - send_cmd = ["qpid-send", - "--broker", sconfig.url, - "--address=%s" % sconfig.address, - "--connection-options={protocol:%s}" % sconfig.version, - "--content-size=0", - "--messages=1", - "-P", "my-header=abc" - ] - sender = self.popen(send_cmd) - sender.wait() - receive_cmd = ["qpid-receive", - "--broker", rconfig.url, - "--address=%s" % rconfig.address, - "--connection-options={protocol:%s}" % rconfig.version, - "--messages=1", - "--print-content=false", "--print-headers=true" - ] - receiver = self.popen(receive_cmd, stdout=PIPE) - l = receiver.stdout.read() - assert "my-header:abc" in l - receiver.wait() - - def test_translate_empty_1(self): - self.send_and_receive_empty(recv_config=Config(self.broker, version="amqp0-10")) - - def test_translate_empty_2(self): - self.send_and_receive_empty(send_config=Config(self.broker, version="amqp0-10")) - - def request_response(self, reply_to, send_config=None, request_config=None, response_config=None, count=1000, wait_for_receiver=False): - rconfig = request_config or self.default_config - echo_cmd = ["qpid-receive", - "--broker", rconfig.url, - "--address=%s" % rconfig.address, - "--connection-options={protocol:%s}" % rconfig.version, - "--timeout=10", "--print-content=false", "--print-headers=false" - ] - requests = self.popen(echo_cmd) - self.send_and_receive(send_config, response_config, count, reply_to=reply_to, wait_for_receiver=wait_for_receiver) - requests.wait() - - def request_response_local(self, request_address, response_address, wait_for_receiver=False, request_version="amqp1.0", echo_version="amqp1.0"): - self.request_response(response_address, send_config=Config(self.broker, address=request_address, version=request_version), request_config=Config(self.broker, address=request_address, version=echo_version), response_config=Config(self.broker, address=response_address, version=request_version), wait_for_receiver=wait_for_receiver) - - def test_request_reponse_queue(self): - self.agent.create("queue", "q1") - self.agent.create("queue", "q2") - self.request_response_local("q1", "q2") - - def test_request_reponse_queue_translated1(self): - self.agent.create("queue", "q1") - self.agent.create("queue", "q2") - self.request_response_local("q1", "q2", request_version="amqp0-10", echo_version="amqp1.0") - - def test_request_reponse_queue_translated2(self): - self.agent.create("queue", "q1") - self.agent.create("queue", "q2") - self.request_response_local("q1", "q2", request_version="amqp1.0", echo_version="amqp0-10") - - def test_request_reponse_exchange(self): - self.agent.create("queue", "q1") - self.request_response_local("q1", "amq.fanout", wait_for_receiver=True) - - def test_request_reponse_exchange_translated1(self): - self.agent.create("queue", "q1") - self.request_response_local("q1", "amq.fanout", wait_for_receiver=True, request_version="amqp0-10", echo_version="amqp1.0") - - def test_request_reponse_exchange_translated2(self): - self.agent.create("queue", "q1") - self.request_response_local("q1", "amq.fanout", wait_for_receiver=True, request_version="amqp1.0", echo_version="amqp0-10") - - def test_request_reponse_exchange_with_subject(self): - self.agent.create("queue", "q1") - self.request_response_local("q1", "amq.topic/abc; {node:{type:topic}}", wait_for_receiver=True) - - def test_request_reponse_exchange_with_subject_translated1(self): - self.agent.create("queue", "q1") - self.request_response_local("q1", "amq.topic/abc; {node:{type:topic}}", wait_for_receiver=True, request_version="amqp0-10", echo_version="amqp1.0") - - def test_request_reponse_exchange_with_subject_translated2(self): - self.agent.create("queue", "q1") - self.request_response_local("q1", "amq.topic/abc; {node:{type:topic}}", wait_for_receiver=True, request_version="amqp1.0", echo_version="amqp0-10") - - def test_domain(self): - brokerB = self.amqp_broker() - self.agent.create("domain", "BrokerB", {"url":brokerB.host_port()}) - domains = self.agent._getAllBrokerObjects(Domain) - assert len(domains) == 1 - assert domains[0].name == "BrokerB" - - def incoming_link(self, mechanism): - brokerB = self.amqp_broker() - agentB = brokerB.agent - self.agent.create("queue", "q") - agentB.create("queue", "q") - 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 = brokerB.agent - self.agent.create("queue", "q") - agentB.create("queue", "q") - self.agent.create("domain", "BrokerB", {"url":brokerB.host_port(), "sasl_mechanisms":"NONE"}) - self.agent.create("outgoing", "Link1", {"domain":"BrokerB","source":"q","target":"q"}) - #send to brokerA, receive from brokerB - self.send_and_receive(recv_config=Config(brokerB)) - - def test_relay(self): - brokerB = self.amqp_broker() - agentB = brokerB.agent - agentB.create("queue", "q") - self.agent.create("domain", "BrokerB", {"url":brokerB.host_port(), "sasl_mechanisms":"NONE"}) - #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, - "--socket-fd=%s" % self.port_holder.fileno, - "--listen-disable=tcp", - "--log-enable=trace+:Protocol", - "--log-enable=info+"] - 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) - os.execvp("qpid-python-test", - ["qpid-python-test", "-m", "interlink_tests"] + sys.argv[1:]) diff --git a/qpid/cpp/src/tests/interop_tests.py b/qpid/cpp/src/tests/interop_tests.py deleted file mode 100755 index 31182f324a..0000000000 --- a/qpid/cpp/src/tests/interop_tests.py +++ /dev/null @@ -1,217 +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. -# - -""" -A set of tests that can be run against a foreign AMQP 1.0 broker. - -RUNNING WITH A FOREIGN BROKER: - -1. Start the broker -2. Create persistent queues named: interop-a interop-b interop-q tx-1 tx-2 -3. Export the environment variable QPID_INTEROP_URL with the URL to connect to your broker - in the form [user[:password]@]host[:port] -4. From the build directory run this test: - ctest -VV -R interop_tests - -If QPID_INTEROP_URL is not set, a qpidd broker will be started for the test. -""" - -import os, sys, shutil, subprocess -import qpid_messaging as qm -from brokertest import * - -URL='QPID_INTEROP_URL' - -class InteropTest(BrokerTest): - - def setUp(self): - super(InteropTest, self).setUp() - self.url = os.environ[URL] - self.connect_opts = ['--broker', self.url, '--connection-options', '{protocol:amqp1.0}'] - - def connect(self, **kwargs): - """Python connection to interop URL""" - c = qm.Connection.establish(self.url, protocol='amqp1.0', **kwargs) - self.teardown_add(c) - return c - - def drain(self, queue, connection=None): - """ - Drain a queue to make sure it is empty. Throw away the messages. - """ - c = connection or self.connect() - r = c.session().receiver(queue) - try: - while True: - r.fetch(timeout=0) - r.session.acknowledge() - except qm.Empty: - pass - r.close() - - def clear_queue(self, queue, connection=None, properties=None, durable=False): - """ - Make empty queue, prefix with self.id(). Create if needed, drain if needed - @return queue name. - """ - queue = "interop-%s" % queue - c = connection or self.connect() - props = {'create':'always'} - if durable: props['node'] = {'durable':True} - if properties: props.update(properties) - self.drain("%s;%s" % (queue, props), c) - return queue - - -class SimpleTest(InteropTest): - """Simple test to check the broker is responding.""" - - def test_send_receive_python(self): - c = self.connect() - q = self.clear_queue('q', c) - s = c.session() - s.sender(q).send('foo') - self.assertEqual('foo', s.receiver(q).fetch().content) - - def test_send_receive_cpp(self): - q = self.clear_queue('q') - args = ['-b', self.url, '-a', q] - self.check_output(['qpid-send', '--content-string=cpp_foo'] + args) - self.assertEqual('cpp_foo', self.check_output(['qpid-receive'] + args).strip()) - - -class PythonTxTest(InteropTest): - - def tx_simple_setup(self): - """Start a transaction, remove messages from queue a, add messages to queue b""" - c = self.connect() - qa, qb = self.clear_queue('a', c, durable=True), self.clear_queue('b', c, durable=True) - - # Send messages to a, no transaction. - sa = c.session().sender(qa+";{create:always,node:{durable:true}}") - tx_msgs = ['x', 'y', 'z'] - for m in tx_msgs: sa.send(qm.Message(content=m, durable=True)) - - # Receive messages from a, in transaction. - tx = c.session(transactional=True) - txr = tx.receiver(qa) - self.assertEqual(tx_msgs, [txr.fetch(1).content for i in xrange(3)]) - tx.acknowledge() - - # Send messages to b, transactional, mixed with non-transactional. - sb = c.session().sender(qb+";{create:always,node:{durable:true}}") - txs = tx.sender(qb) - msgs = [str(i) for i in xrange(3)] - for tx_m, m in zip(tx_msgs, msgs): - txs.send(tx_m); - sb.send(m) - tx.sync() - return tx, qa, qb - - def test_tx_simple_commit(self): - tx, qa, qb = self.tx_simple_setup() - s = self.connect().session() - assert_browse(s, qa, []) - assert_browse(s, qb, ['0', '1', '2']) - tx.commit() - assert_browse(s, qa, []) - assert_browse(s, qb, ['0', '1', '2', 'x', 'y', 'z']) - - def test_tx_simple_rollback(self): - tx, qa, qb = self.tx_simple_setup() - s = self.connect().session() - assert_browse(s, qa, []) - assert_browse(s, qb, ['0', '1', '2']) - tx.rollback() - assert_browse(s, qa, ['x', 'y', 'z']) - assert_browse(s, qb, ['0', '1', '2']) - - def test_tx_sequence(self): - tx = self.connect().session(transactional=True) - notx = self.connect().session() - q = self.clear_queue('q', tx.connection, durable=True) - s = tx.sender(q) - r = tx.receiver(q) - s.send('a') - tx.commit() - assert_browse(notx, q, ['a']) - s.send('b') - tx.commit() - assert_browse(notx, q, ['a', 'b']) - self.assertEqual('a', r.fetch().content) - tx.acknowledge(); - tx.commit() - assert_browse(notx, q, ['b']) - s.send('z') - tx.rollback() - assert_browse(notx, q, ['b']) - self.assertEqual('b', r.fetch().content) - tx.acknowledge(); - tx.rollback() - assert_browse(notx, q, ['b']) - - -class CppTxTest(InteropTest): - - def test_txtest2(self): - self.popen(["qpid-txtest2"] + self.connect_opts).assert_exit_ok() - - def test_send_receive(self): - q = self.clear_queue('q', durable=True) - sender = self.popen(["qpid-send", - "--address", q, - "--messages=100", - "--tx=10", - "--durable=yes"] + self.connect_opts) - receiver = self.popen(["qpid-receive", - "--address", q, - "--messages=90", - "--timeout=10", - "--tx=10"] + self.connect_opts) - sender.assert_exit_ok() - receiver.assert_exit_ok() - expect = [long(i) for i in range(91, 101)] - sn = lambda m: m.properties["sn"] - assert_browse(self.connect().session(), q, expect, transform=sn) - - -if __name__ == "__main__": - from env import * - outdir = "interop_tests.tmp" - shutil.rmtree(outdir, True) - cmd = ["qpid-python-test", "-m", "interop_tests", "-DOUTDIR=%s"%outdir] + sys.argv[1:] - if "QPID_PORT" in os.environ: del os.environ["QPID_PORT"] - if os.environ.get(URL): - os.execvp(cmd[0], cmd) - else: - dir = os.getcwd() - class StartBroker(BrokerTest): - def start_qpidd(self): pass - test = StartBroker('start_qpidd') - class Config: - def __init__(self): - self.defines = { 'OUTDIR': outdir } - test.configure(Config()) - test.setUp() - os.environ[URL] = test.broker().host_port() - os.chdir(dir) - p = subprocess.Popen(cmd) - status = p.wait() - test.tearDown() - sys.exit(status) diff --git a/qpid/cpp/src/tests/legacystore/.valgrind.supp b/qpid/cpp/src/tests/legacystore/.valgrind.supp deleted file mode 100644 index 5c1c5377bf..0000000000 --- a/qpid/cpp/src/tests/legacystore/.valgrind.supp +++ /dev/null @@ -1,35 +0,0 @@ -{ - - Memcheck:Leak - fun:_Znwm - fun:_ZNSs4_Rep9_S_createEmmRKSaIcE - fun:_ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag - fun:_ZNSsC1EPKcRKSaIcE -} - -{ - - Memcheck:Leak - fun:_Znwm - fun:_ZNSs4_Rep9_S_createEmmRKSaIcE - fun:_ZNSs4_Rep8_M_cloneERKSaIcEm - fun:_ZNSs7reserveEm -} - -{ - - Memcheck:Leak - fun:_Znwm - fun:_ZNSs4_Rep9_S_createEmmRKSaIcE - fun:_ZNSs9_M_mutateEmmm - fun:_ZNSs15_M_replace_safeEmmPKcm -} - -{ - - Memcheck:Leak - fun:_Znwm - fun:_ZNSs4_Rep9_S_createEmmRKSaIcE - fun:_ZNSsC1IPcEET_S1_RKSaIcE -} - diff --git a/qpid/cpp/src/tests/legacystore/.valgrindrc b/qpid/cpp/src/tests/legacystore/.valgrindrc deleted file mode 100644 index 4aba7661de..0000000000 --- a/qpid/cpp/src/tests/legacystore/.valgrindrc +++ /dev/null @@ -1,7 +0,0 @@ ---gen-suppressions=all ---leak-check=full ---demangle=yes ---suppressions=.valgrind.supp ---num-callers=25 ---trace-children=yes - diff --git a/qpid/cpp/src/tests/legacystore/CMakeLists.txt b/qpid/cpp/src/tests/legacystore/CMakeLists.txt deleted file mode 100644 index 20a242b415..0000000000 --- a/qpid/cpp/src/tests/legacystore/CMakeLists.txt +++ /dev/null @@ -1,130 +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. -# - -if(BUILD_LEGACYSTORE AND BUILD_TESTING) - -message(STATUS "Building legacystore tests") - -# If we're linking Boost for DLLs, turn that on for the tests too. -if (QPID_LINK_BOOST_DYNAMIC) - add_definitions(-DBOOST_TEST_DYN_LINK) -endif (QPID_LINK_BOOST_DYNAMIC) - -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) - -if (BUILD_TESTING_UNITTESTS) - -# Like this to work with cmake 2.4 on Unix -set (qpid_test_boost_libs - ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${Boost_SYSTEM_LIBRARY}) - -# Journal tests -MACRO (define_journal_test mainSourceFile) -if ("${ARGV1}" STREQUAL "LONG") - set (testname "journal_long_${mainSourceFile}") -else () - set (testname "journal_${mainSourceFile}") -endif () -add_executable (${testname} - jrnl/${mainSourceFile} - unit_test - ${platform_test_additions}) -target_link_libraries (${testname} - ${qpid_test_boost_libs} - ${clock_gettime_LIB} legacystore_shared) -if ("${ARGV1}" STREQUAL "LONG") - set_target_properties(${testname} PROPERTIES COMPILE_DEFINITIONS LONG_TEST) -endif () -add_test (NAME ${testname} COMMAND ${CMAKE_BINARY_DIR}/src/tests/run.sh $) -unset (testname) -ENDMACRO (define_journal_test) - -define_journal_test (_ut_time_ns) -define_journal_test (_ut_jexception) -define_journal_test (_ut_jerrno) -define_journal_test (_ut_rec_hdr) -define_journal_test (_ut_jinf) -define_journal_test (_ut_jdir) -define_journal_test (_ut_enq_map) -define_journal_test (_ut_txn_map) -define_journal_test (_ut_lpmgr) -define_journal_test (_st_basic) -define_journal_test (_st_basic_txn) -define_journal_test (_st_read) -define_journal_test (_st_read_txn) -define_journal_test (_st_auto_expand) -define_journal_test (_ut_lpmgr LONG) -define_journal_test (_st_basic LONG) -define_journal_test (_st_read LONG) - -add_executable (jtt__ut - jrnl/jtt/_ut_data_src.cpp - jrnl/jtt/_ut_jrnl_init_params.cpp - jrnl/jtt/_ut_read_arg.cpp - jrnl/jtt/_ut_jrnl_instance.cpp - jrnl/jtt/_ut_test_case.cpp - jrnl/jtt/_ut_test_case_result.cpp - jrnl/jtt/_ut_test_case_result_agregation.cpp - jrnl/jtt/_ut_test_case_set.cpp - jrnl/jtt/args.cpp - jrnl/jtt/data_src.cpp - jrnl/jtt/jrnl_init_params.cpp - jrnl/jtt/jrnl_instance.cpp - jrnl/jtt/read_arg.cpp - jrnl/jtt/test_case.cpp - jrnl/jtt/test_case_set.cpp - jrnl/jtt/test_case_result.cpp - jrnl/jtt/test_case_result_agregation.cpp - unit_test.cpp) - -target_link_libraries (jtt__ut - ${qpid_test_boost_libs} - ${Boost_PROGRAM_OPTIONS_LIBRARY} - ${clock_gettime_LIB} legacystore_shared) - -add_test(journal_jtt_ut ${CMAKE_BINARY_DIR}/src/tests/run.sh ${CMAKE_CURRENT_BINARY_DIR}/jtt__ut) - -endif (BUILD_TESTING_UNITTESTS) - -# -# Other test programs -# - -add_executable(jtt - jrnl/jtt/args.cpp - jrnl/jtt/data_src.cpp - jrnl/jtt/jrnl_init_params.cpp - jrnl/jtt/jrnl_instance.cpp - jrnl/jtt/main.cpp - jrnl/jtt/read_arg.cpp - jrnl/jtt/test_case.cpp - jrnl/jtt/test_case_result.cpp - jrnl/jtt/test_case_result_agregation.cpp - jrnl/jtt/test_case_set.cpp - jrnl/jtt/test_mgr.cpp) - -target_link_libraries (jtt - ${Boost_PROGRAM_OPTIONS_LIBRARY} - ${clock_gettime_LIB} legacystore_shared) - -add_test(journal_jtt ${CMAKE_CURRENT_BINARY_DIR}/jtt -c ${CMAKE_CURRENT_SOURCE_DIR}/jrnl/jtt/jtt.csv) - -add_test(legacystore_python_tests ${PYTHON_EXECUTABLE} run_python_tests) - -endif (BUILD_LEGACYSTORE AND BUILD_TESTING) diff --git a/qpid/cpp/src/tests/legacystore/MessageUtils.h b/qpid/cpp/src/tests/legacystore/MessageUtils.h deleted file mode 100644 index cd23244293..0000000000 --- a/qpid/cpp/src/tests/legacystore/MessageUtils.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include -#include -#include -#include -#include -#include - -using namespace qpid::broker; -using namespace qpid::framing; - -struct MessageUtils -{ - static Message createMessage(const std::string& exchange, const std::string& routingKey, - const Uuid& messageId=Uuid(), const bool durable = false, - const uint64_t contentSize = 0, const std::string& correlationId = std::string()) - { - boost::intrusive_ptr msg(new qpid::broker::amqp_0_10::MessageTransfer()); - - AMQFrame method(( MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - - msg->getFrames().append(method); - msg->getFrames().append(header); - MessageProperties* props = msg->getFrames().getHeaders()->get(true); - props->setContentLength(contentSize); - props->setMessageId(messageId); - props->setCorrelationId(correlationId); - msg->getFrames().getHeaders()->get(true)->setRoutingKey(routingKey); - if (durable) - msg->getFrames().getHeaders()->get(true)->setDeliveryMode(PERSISTENT); - return Message(msg, msg); - } - - static void addContent(Message msg, const std::string& data) - { - AMQFrame content((AMQContentBody(data))); - qpid::broker::amqp_0_10::MessageTransfer::get(msg).getFrames().append(content); - } - - struct MessageRetriever : public Consumer - { - MessageRetriever(Queue& q) : Consumer("test", CONSUMER), queue(q) {}; - - bool deliver(const QueueCursor& c, const Message& m) - { - message = m; - cursor = c; - return true; - }; - void notify() {} - void cancel() {} - void acknowledged(const DeliveryRecord&) {} - OwnershipToken* getSession() { return 0; } - - const Queue& queue; - Message message; - QueueCursor cursor; - }; - - static Message get(Queue& queue, QueueCursor* cursor = 0) - { - boost::shared_ptr consumer(new MessageRetriever(queue)); - if (!queue.dispatch(consumer))throw qpid::Exception("No message found!"); - if (cursor) *cursor = consumer->cursor; - return consumer->message; - } - - static Uuid getMessageId(const Message& message) - { - return qpid::broker::amqp_0_10::MessageTransfer::get(message).getProperties()->getMessageId(); - } - - static std::string getCorrelationId(const Message& message) - { - return qpid::broker::amqp_0_10::MessageTransfer::get(message).getProperties()->getCorrelationId(); - } - - static void deliver(Message& msg, FrameHandler& h, uint16_t framesize) - { - qpid::broker::amqp_0_10::MessageTransfer::get(msg).sendHeader(h, framesize, false, 0, qpid::types::Variant::Map()); - qpid::broker::amqp_0_10::MessageTransfer::get(msg).sendContent(h, framesize); - } - -}; diff --git a/qpid/cpp/src/tests/legacystore/TestFramework.cpp b/qpid/cpp/src/tests/legacystore/TestFramework.cpp deleted file mode 100644 index 2f7faf7682..0000000000 --- a/qpid/cpp/src/tests/legacystore/TestFramework.cpp +++ /dev/null @@ -1,30 +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. - * - */ - -// Defines broker to be used by tests - -#include "unit_test.h" -#include "TestFramework.h" -#include "qpid/broker/Broker.h" - -#include - -//BOOST_GLOBAL_FIXTURE( testBroker ) diff --git a/qpid/cpp/src/tests/legacystore/TestFramework.h b/qpid/cpp/src/tests/legacystore/TestFramework.h deleted file mode 100644 index f3066db602..0000000000 --- a/qpid/cpp/src/tests/legacystore/TestFramework.h +++ /dev/null @@ -1,37 +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. - * - */ - -// Defines broker to be used by tests - -#include "unit_test.h" - -#include - -namespace { - // test broker - qpid::broker::Broker::Options opts; - qpid::broker::Broker br(opts); -/* - struct testBroker { - testBroker() {} - ~testBroker() {} - };*/ -} diff --git a/qpid/cpp/src/tests/legacystore/clean.sh b/qpid/cpp/src/tests/legacystore/clean.sh deleted file mode 100644 index 838f246232..0000000000 --- a/qpid/cpp/src/tests/legacystore/clean.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env 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. -# - -# This script cleans up any previous database and journal files, and should -# be run prior to the store system tests, as these are prone to crashing or -# hanging under some circumstances if the database is old or inconsistent. - -if [ -d ${TMP_DATA_DIR} ]; then - rm -rf ${TMP_DATA_DIR} -fi -if [ -d ${TMP_PYTHON_TEST_DIR} ]; then - rm -rf ${TMP_PYTHON_TEST_DIR} -fi -rm -f ${abs_srcdir}/*.vglog* diff --git a/qpid/cpp/src/tests/legacystore/federation/Makefile.am b/qpid/cpp/src/tests/legacystore/federation/Makefile.am deleted file mode 100644 index c48e861a65..0000000000 --- a/qpid/cpp/src/tests/legacystore/federation/Makefile.am +++ /dev/null @@ -1,46 +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. -# - - -abs_srcdir=@abs_srcdir@ - -TMP_DATA_DIR=$(abs_srcdir)/../tmp_data_dir - -TESTS = \ - run_federation_sys_tests - -LONG_TESTS = \ - run_long_federation_sys_tests - -EXTRA_DIST = \ - federation_tests_env.sh \ - run_federation_sys_tests \ - run_long_federation_sys_tests - -TESTS_ENVIRONMENT = \ - QPID_DIR=$(QPID_DIR) \ - QPID_BLD=$(QPID_BLD) \ - TMP_DATA_DIR=$(TMP_DATA_DIR) \ - abs_srcdir=$(abs_srcdir) - -check-long: all - $(MAKE) check TESTS="$(LONG_TESTS)" SUBDIRS=. - -# END - diff --git a/qpid/cpp/src/tests/legacystore/federation/federation_tests_env.sh b/qpid/cpp/src/tests/legacystore/federation/federation_tests_env.sh deleted file mode 100755 index be4504f3bf..0000000000 --- a/qpid/cpp/src/tests/legacystore/federation/federation_tests_env.sh +++ /dev/null @@ -1,313 +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. -# - - -# --- Function definitions --- - -func_check_required_env () -#------------------------- -# Check that EITHER: -# QPID_DIR is set (for running against svn QPID) -# OR -# QPID_PREFIX is set (for running against installed QPID -# Will exit with error code 1 if neither of these is defined. -# Params: None -# Returns: 0 if env vars ok, 1 otherwise -{ - if test -z "${QPID_DIR}" -a -z "${QPID_PREFIX}"; then - # Try to find qpidd in the normal installed location - if test -x /usr/sbin/qpidd; then - QPID_PREFIX=/usr - else - echo "ERROR: Could not find installed Qpid" - echo "Either of the following must be set in the environment for this script to run:" - echo " QPID_DIR for running against a Qpid svn build" - echo " QPID_PREFIX for running against an installed Qpid" - return 1 - fi - fi - return 0 -} - - -func_check_clustering () -#----------------------- -# Check openAIS/corosync is running and user has correct privileges -# Params: None -# Returns: 0 if openAIS/corosync is running, 1 otherwise -# Sets env var COROSYNC to 1 if corosync is running, not set otherwise -{ - # Check either aisexec or corosync is running as root - cluster_prog=`ps -u root | grep 'aisexec\|corosync'` - test -n "$cluster_prog" || NODAEMON="Neither aisexec nor corosync is running as root" - if test -z "$NODAEMON"; then - # Test for corosync running - echo $cluster_prog | grep "aisexec" > /dev/null || COROSYNC=1 - if test -n "$COROSYNC"; then - # Corosync auth test - user=`whoami` - ls /etc/corosync/uidgid.d | grep $user > /dev/null || NOAUTH="You are not authorized to use corosync." - else - # OpenAis auth test - id -nG | grep '\' >/dev/null || NOAUTH="You are not a member of the ais group." - fi - fi - - if test -n "$NODAEMON" -o -n "$NOAUTH"; then - cat < qpidd.port - PORT=`cat qpidd.port` - eval "$3=${PORT}" - } - start_broker ${TMP_DATA_DIR}/local "${MODULES} --log-enable info+ --log-to-file ${TMP_DATA_DIR}/qpidd.log.local" LOCAL_PORT - start_broker ${TMP_DATA_DIR}/remote "${MODULES} --log-enable info+ --log-to-file ${TMP_DATA_DIR}/qpidd.log.remote" REMOTE_PORT - if [ -n "$CLUSTERING_ENABLED" ]; then - start_broker ${TMP_DATA_DIR}/cluster/c1.1 "${MODULES} ${CLUSTER_MODULE} --cluster-name test-cluster-1 --log-enable info+ --log-to-file ${TMP_DATA_DIR}/qpidd.log.cluster1.1" CLUSTER_C1_1 - start_broker ${TMP_DATA_DIR}/cluster/c1.2 "${MODULES} ${CLUSTER_MODULE} --cluster-name test-cluster-1 --log-enable info+ --log-to-file ${TMP_DATA_DIR}/qpidd.log.cluster1.2" CLUSTER_C1_2 - start_broker ${TMP_DATA_DIR}/cluster/c2.1 "${MODULES} ${CLUSTER_MODULE} --cluster-name test-cluster-2 --log-enable info+ --log-to-file ${TMP_DATA_DIR}/qpidd.log.cluster2.1" CLUSTER_C2_1 - start_broker ${TMP_DATA_DIR}/cluster/c2.2 "${MODULES} ${CLUSTER_MODULE} --cluster-name test-cluster-2 --log-enable info+ --log-to-file ${TMP_DATA_DIR}/qpidd.log.cluster2.2" CLUSTER_C2_2 - fi - rm qpidd.port -} - -stop_brokers() { - ${QPIDD_EXEC} -q --port ${LOCAL_PORT} - ${QPIDD_EXEC} -q --port ${REMOTE_PORT} - if [ -n "${CLUSTERING_ENABLED}" ]; then - ${QPID_CLUSTER_EXEC} --all-stop --force localhost:${CLUSTER_C1_1} - ${QPID_CLUSTER_EXEC} --all-stop --force localhost:${CLUSTER_C2_1} - fi -} - -if test -d ${PYTHON_DIR} ; then - start_brokers - if [ -z ${CLUSTERING_ENABLED} ]; then - echo "Running federation tests using brokers on local port ${LOCAL_PORT}, remote port ${REMOTE_PORT} (NOTE: clustering is DISABLED)" - else - echo "Running federation tests using brokers on local port ${LOCAL_PORT}, remote port ${REMOTE_PORT}, local cluster nodes ${CLUSTER_C1_1} ${CLUSTER_C1_2}, remote cluster nodes ${CLUSTER_C2_1} ${CLUSTER_C2_2}" - fi - if [ -z ${USE_LONG_TEST} ]; then - echo "NOTE: To run a full set of federation system tests, use \"make check-long\"." - fi - ${QPID_PYTHON_TEST} -m ${MODULENAME} ${SKIPTESTS} -b localhost:$REMOTE_PORT -Dlocal-port=$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dlocal-cluster-ports="$CLUSTER_C1_1 $CLUSTER_C1_2" -Dremote-cluster-ports="$CLUSTER_C2_1 $CLUSTER_C2_2" $@ - RETCODE=$? - stop_brokers - if test x$RETCODE != x0; then - echo "FAIL federation tests"; exit 1; - fi -fi diff --git a/qpid/cpp/src/tests/legacystore/federation/run_long_federation_sys_tests b/qpid/cpp/src/tests/legacystore/federation/run_long_federation_sys_tests deleted file mode 100755 index 012c8d8f18..0000000000 --- a/qpid/cpp/src/tests/legacystore/federation/run_long_federation_sys_tests +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env 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 federation system tests (long version). - -./run_federation_sys_tests LONG_TEST $@ diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_st_auto_expand.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_st_auto_expand.cpp deleted file mode 100644 index fb5c1f1742..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_st_auto_expand.cpp +++ /dev/null @@ -1,140 +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 "../unit_test.h" -#include -#include -#include "qpid/legacystore/jrnl/jcntl.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(journal_auto_expand) - -const string test_filename("_st_auto_expand"); - -#include "_st_helper_fns.h" - -// === Test suite === - -QPID_AUTO_TEST_CASE(no_ae_threshold) -{ - string test_name = get_test_name(test_filename, "no_ae_threshold"); - try - { - string msg; - - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - jc.initialize(NUM_DEFAULT_JFILES, false, 0, DEFAULT_JFSIZE_SBLKS); - unsigned m; - - // Fill journal to just below threshold - u_int32_t t = num_msgs_to_threshold(NUM_DEFAULT_JFILES, - DEFAULT_JFSIZE_SBLKS * JRNL_SBLK_SIZE, LARGE_MSG_REC_SIZE_DBLKS); - for (m=0; m -#include -#include "qpid/legacystore/jrnl/jcntl.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(journal_basic) - -const string test_filename("_st_basic"); - -#include "_st_helper_fns.h" - -// === Test suite === - -#ifndef LONG_TEST -/* - * ============================================== - * NORMAL TESTS - * This section contains normal "make check" tests - * for building/packaging. These are built when - * LONG_TEST is _not_ defined. - * ============================================== - */ - -QPID_AUTO_TEST_CASE(instantiation) -{ - string test_name = get_test_name(test_filename, "instantiation"); - try - { - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - BOOST_CHECK_EQUAL(jc.is_ready(), false); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(initialization) -{ - string test_name = get_test_name(test_filename, "initialization"); - try - { - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - BOOST_CHECK_EQUAL(jc.is_ready(), false); - jc.initialize(NUM_TEST_JFILES, false, 0, TEST_JFSIZE_SBLKS); - BOOST_CHECK_EQUAL(jc.is_ready(), true); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(enqueue_dequeue_block) -{ - string test_name = get_test_name(test_filename, "enqueue_dequeue_block"); - try - { - string msg; - - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - jc.initialize(NUM_TEST_JFILES, false, 0, TEST_JFSIZE_SBLKS); - for (int m=0; m -#include -#include "qpid/legacystore/jrnl/jcntl.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(journal_basic_txn) - -const string test_filename("_st_basic_txn"); - -#include "_st_helper_fns.h" - -// === Test suite === - -QPID_AUTO_TEST_CASE(enqueue_commit_dequeue_block) -{ - string test_name = get_test_name(test_filename, "enqueue_commit_dequeue_block"); - try - { - string msg; - string xid; - - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - jc.initialize(NUM_TEST_JFILES, false, 0, TEST_JFSIZE_SBLKS); - create_xid(xid, 0, XID_SIZE); - for (int m=0; m 0 ? string(tdp) + "/" + test_filename : "/var/tmp/jrnl_test"); - -class test_dtok : public data_tok -{ -private: - bool flag; -public: - test_dtok() : data_tok(), flag(false) {} - virtual ~test_dtok() {} - bool done() { if (flag || _wstate == NONE) return true; else { flag = true; return false; } } -}; - -class test_jrnl_cb : public aio_callback { - virtual void wr_aio_cb(std::vector& dtokl) - { - for (std::vector::const_iterator i=dtokl.begin(); i!=dtokl.end(); i++) - { - test_dtok* dtp = static_cast(*i); - if (dtp->done()) - delete dtp; - } - } - virtual void rd_aio_cb(std::vector& /*pil*/) {} -}; - -class test_jrnl : public jcntl -{ -test_jrnl_cb* cb; - -public: - test_jrnl(const std::string& jid, const std::string& jdir, const std::string& base_filename, test_jrnl_cb& cb0) : - jcntl(jid, jdir, base_filename), - cb(&cb0) {} - virtual ~test_jrnl() {} - void initialize(const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles, - const u_int32_t jfsize_sblks) - { - jcntl::initialize(num_jfiles, ae, ae_max_jfiles, jfsize_sblks, JRNL_WMGR_DEF_PAGES, JRNL_WMGR_DEF_PAGE_SIZE, - cb); - _jdir.create_dir(); - } - void recover(const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles, const u_int32_t jfsize_sblks, - vector* txn_list, u_int64_t& highest_rid) - { jcntl::recover(num_jfiles, ae, ae_max_jfiles, jfsize_sblks, JRNL_WMGR_DEF_PAGES, JRNL_WMGR_DEF_PAGE_SIZE, cb, - txn_list, highest_rid); } -}; - -/* -* This class is for testing recover functionality by maintaining an internal lfid-pfid map, then creating physical -* journal file stubs (just the fhdr section of the journal) and jinf file. This allows the recover functionality (which -* analyzes these components to determine recover order). -* -* First set up a map or "blueprint" of what the journal should look like for recovery, then have the class create the -* physical files. The jinf object under test then reads and analyzes the created journal, and it's analysis is checked -* against what is expected. -* -* General usage pattern: -* 1. Create instance of lfid_pfid_map. -* 2. Call lfid_pfid_map::journal_create() to simulate initial journal creation. -* 3. (optional) Call lfid_pfid_map::journal_insert() one or more times to simulate the addition of journal files. -* 4. Call lfid_pfid_map::write_journal() to create dummy journal files (files containing only file headers) -* 5. Create and initialize the jinf object under test -* 6. Call jinf::analyze() to determine the pfid order - and thus also first and last lids -* 7. Call lfid_pfid_map::check_analysis() to check the conclusions of the analysis -* 8. Call lfid_pfid_map::destroy_journal() to delete the journal files and reset the lfid_pfid_map object. -* 9. (optional) Back to step 2 for more tests -* -* See the individual methods below for more details. -*/ -class lfid_pfid_map -{ - public: - typedef pair lppair; // Used for loading the map - typedef multimap lpmap; // Stores the journal "plan" before it is created on-disk - typedef lpmap::const_iterator lpmap_citr; // General purpose iterator - typedef pair lpmap_range; // Range of values returned by multimap's equal_range() fn - - private: - string _jid; // Journal id - string _base_filename; // Base filename - lpmap _map; // Stores the journal "blueprint" before it is created on-disk - u_int16_t _num_used_files; // number of files which contain jorunals - u_int16_t _oldest_lfid; // lfid where owi flips; always 0 if !_full - u_int16_t _last_pfid; // last pfid (ie last file added) - - public: - lfid_pfid_map(const string& jid, const string& base_filename) : - _jid(jid), _base_filename(base_filename), _num_used_files(0), _oldest_lfid(0), _last_pfid(0) - {} - virtual ~lfid_pfid_map() {} - - // Mainly used for debugging - void print() - { - int cnt = 0; - for (lpmap_citr i=_map.begin(); i!=_map.end(); i++, cnt++) - { - const file_hdr fh = i->second; - cout << " " << cnt << ": owi=" << (fh.get_owi()?"t":"f") << hex << " frid=0x" << fh._rid; - cout << " pfid=0x" << fh._pfid << " lfid=0x" << fh._lfid << " fro=0x" << fh._fro << dec << endl; - } - } - - std::size_t size() - { - return _map.size(); - } - - /* - * Method journal_create(): Used to simulate the initial creation of a journal before file insertions - * take place. - * - * num_jfiles: The initial journal file count. - * num_used_jfiles: If this number is less than num_jfiles, it indicates a clean journal that has not yet - * completed its first rotation, and some files are empty (ie all null). The first - * num_used_jfiles will contain file headers, the remainder will be blank. - * oldest_lfid: The lfid (==pfid, see note 1 below) at which the owi flag flips. During normal operation, - * each time the journal rotates back to file 0, a flag (called the overwrite indicator or owi) - * is flipped. This flag is saved in the file header. During recovery, if scanning from logical - * file 0 upwards, the file at which this flag reverses from its value in file 0 is the file - * that was to have been overwritten next, and is thus the "oldest" file. Recovery analysis must - * start with this file. oldest_lfid sets the file at which this flag will flip value for the - * simulated recovery analysis. Note that this will be ignored if num_used_jfiles < num_jfiles, - * as it is not possible for an overwrite to have occurred if not all the files have been used. - * first_owi: Sets the value of the owi flag in file 0. If set to false, then the flip will be found with - * a true flag (and visa versa). - * - * NOTES: - * 1. By definition, the lfids and pfids coincide for a journal containing no inserted files. Thus pfid == lfid - * for all journals created after using initial_journal_create() alone. - * 2. By definition, if a journal is not full (num_used_jfiles < num_jfiles), then all owi flags for those files - * that are used must be the same. It is not possible for an overwrite situation to arise if a journal is not - * full. - * 3. This function acts on map _map only, and does not create any test files. Call write_journal() to do that. - * 4. This function must be called on a clean test object or on one where the previous test data has been - * cleared by calling journal_destroy(). Running this function more than once on existing data will - * result in invalid journals which cannot be recovered. - */ - void journal_create(const u_int16_t num_jfiles, // Total number of files - const u_int16_t num_used_jfiles, // Number of used files, rest empty at end - const u_int16_t oldest_lfid = 0, // Fid where owi reverses - const u_int16_t bad_lfid = 0, // Fid where owi reverses again (must be > oldest_lifd), - // used for testing bad owi detection - const bool first_owi = false) // Value of first owi flag (ie pfid=0) - { - const bool full = num_used_jfiles == num_jfiles; - bool owi = first_owi; - _oldest_lfid = full ? oldest_lfid : 0; - for (u_int16_t lfid = 0; lfid < num_jfiles; lfid++) - { - const u_int16_t pfid = lfid; - file_hdr fh; - if (pfid < num_used_jfiles) - { - _num_used_files = num_used_jfiles; - /* - * Invert the owi flag from its current value (initially given by first_owi param) only if: - * 1. The journal is full (ie all files are used) - * AND - * 2. oldest_lfid param is non-zero (this is default, but lfid 0 being inverted is logically - * inconsistent with first_owi parameter being present) - * AND - * 3. Either: - * * current lfid == oldest_lfid (ie we are preparing the oldest lfid) - * OR - * * current lfid == bad_lfid AND bad_lfid > oldest (ie we are past the oldest and preparing the - * bad lfid) - */ - if (full && oldest_lfid > 0 && - (lfid == oldest_lfid || (bad_lfid > oldest_lfid && lfid == bad_lfid))) - owi = !owi; - const u_int64_t frid = u_int64_t(random()); - init_fhdr(fh, frid, pfid, lfid, owi); - } - _map.insert(lppair(lfid, fh)); - } - } - - /* - * Method journal_insert(): Used to simulate the insertion of journal files into an existing journal. - * - * after_lfid: The logical file id (lfid) after which the new file is to be inserted. - * num_files: The number of files to be inserted. - * adjust_lids: Flag indicating that the lids of files _following_ the inserted files are to be adjusted upwards - * by the number of inserted files. Not doing so simulates a recovery immediately after insertion - * but before the following files are overwritten with their new lids. If this is set false, then: - * a) after_lfid MUST be the most recent file (_oldest_lfid-1 ie last lfid before owi changes). - * b) This call must be the last insert call. - * - * NOTES: - * 1. It is not possible to insert before lfid/pfid 0; thus these are always coincidental. This operation is - * logically equivalent to inserting after the last lfid, which is possible. - * 2. It is not possible to insert into a journal that is not full. Doing so will result in an unrecoverable - * journal (one that is logically inconsistent that can never occur in reality). - * 3. If a journal is stopped/interrupted immediately after a file insertion, there could be duplicate lids in - * play at recovery, as the following file lids in their headers are only overwritten when the file is - * eventually written to during normal operation. The owi flags, however, are used to determine which of the - * ambiguous lids are the inserted files. - * 4. This function acts on map _map only, and does not create any test files. Call write_journal() to do that. - */ - void journal_insert(const u_int16_t after_lfid, // Insert files after this lfid - const u_int16_t num_files = 1, // Number of files to insert - const bool adjust_lids = true) // Adjust lids following inserted files - { - if (num_files == 0) return; - _num_used_files += num_files; - const u_int16_t num_jfiles_before_append = _map.size(); - lpmap_citr i = _map.find(after_lfid); - if (i == _map.end()) BOOST_FAIL("Unable to find lfid=" << after_lfid << " in map."); - const file_hdr fh_before = (*i).second; - - // Move overlapping lids (if req'd) - if (adjust_lids && after_lfid < num_jfiles_before_append - 1) - { - for (u_int16_t lfid = num_jfiles_before_append - 1; lfid > after_lfid; lfid--) - { - lpmap_citr itr = _map.find(lfid); - if (itr == _map.end()) BOOST_FAIL("Unable to find lfid=" << after_lfid << " in map."); - file_hdr fh = itr->second; - _map.erase(lfid); - fh._lfid += num_files; - if (lfid == _oldest_lfid) - _oldest_lfid += num_files; - _map.insert(lppair(fh._lfid, fh)); - } - } - - // Add new file headers - u_int16_t pfid = num_jfiles_before_append; - u_int16_t lfid = after_lfid + 1; - while (pfid < num_jfiles_before_append + num_files) - { - const u_int64_t frid = u_int64_t(random()); - const size_t fro = 0x200; - const file_hdr fh(RHM_JDAT_FILE_MAGIC, RHM_JDAT_VERSION, frid, pfid, lfid, fro, fh_before.get_owi(), - true); - _map.insert(lppair(lfid, fh)); - _last_pfid = pfid; - pfid++; - lfid++; - } - } - - /* - * Get the list of pfids in the map in order of lfid. The pfids are appended to the supplied vector. Only - * as many headers as are in the map are appended. - * NOTE: will clear any contents from supplied vector before appending pfid list. - */ - void get_pfid_list(vector& pfid_list) - { - pfid_list.clear(); - for (lpmap_citr i = _map.begin(); i != _map.end(); i++) - pfid_list.push_back(i->second._pfid); - } - - /* - * Get the list of lfids in the map. The lfids are appended to the supplied vector in the order they appear - * in the map (which is not necessarily the natural or sorted order). - * NOTE: will clear any contents from supplied vector before appending lfid list. - */ - void get_lfid_list(vector& lfid_list) - { - lfid_list.clear(); - lfid_list.assign(_map.size(), 0); - for (lpmap_citr i = _map.begin(); i != _map.end(); i++) - lfid_list[i->second._pfid] = i->first; - } - - /* - * Method check_analysis(): Used to check the result of the test jinf object analysis by comparing the pfid order - * array it produces against the internal map. - * - * ji: A ref to the jinf object under test. - */ - void check_analysis(jinf& ji) // jinf object under test after analyze() has been called - { - BOOST_CHECK_EQUAL(ji.get_first_pfid(), get_first_pfid()); - BOOST_CHECK_EQUAL(ji.get_last_pfid(), get_last_pfid()); - - jinf::pfid_list& pfidl = ji.get_pfid_list(); - const u_int16_t num_jfiles = _map.size(); - const bool all_used = _num_used_files == num_jfiles; - BOOST_CHECK_EQUAL(pfidl.size(), _num_used_files); - - const u_int16_t lfid_start = all_used ? _oldest_lfid : 0; - // Because a simulated failure would leave lfid dups in map and last_fid would not exist in map in this - // case, we must find lfid_stop via pfid instead. Search for pfid == num_files. - lpmap_citr itr = _map.begin(); - while (itr != _map.end() && itr->second._pfid != _num_used_files - 1) itr++; - if (itr == _map.end()) - BOOST_FAIL("check(): Unable to find pfid=" << (_num_used_files - 1) << " in map."); - const u_int16_t lfid_stop = itr->second._lfid; - - std::size_t fidl_index = 0; - for (u_int16_t lfid_cnt = lfid_start; lfid_cnt < lfid_stop; lfid_cnt++, fidl_index++) - { - const u_int16_t lfid = lfid_cnt % num_jfiles; - lpmap_citr itr = _map.find(lfid); - if (itr == _map.end()) - BOOST_FAIL("check(): Unable to find lfid=" << lfid << " in map."); - BOOST_CHECK_EQUAL(itr->second._pfid, pfidl[fidl_index]); - } - } - - /* - * Method get_pfid(): Look up a pfid from a known lfid. - */ - u_int16_t get_pfid(const u_int16_t lfid, const bool initial_owi = false) - { - switch (_map.count(lfid)) - { - case 1: - return _map.find(lfid)->second._pfid; - case 2: - for (lpmap_citr itr = _map.lower_bound(lfid); itr != _map.upper_bound(lfid); itr++) - { - if (itr->second.get_owi() != initial_owi) - return itr->second._pfid; - } - default:; - } - BOOST_FAIL("get_pfid(): lfid=" << lfid << " not found in map."); - return 0xffff; - } - - /* - * Method get_first_pfid(): Look up the first (oldest, or next-to-be-overwritten) pfid in the analysis sequence. - */ - u_int16_t get_first_pfid() - { - return get_pfid(_oldest_lfid); - } - - /* - * Method get_last_pfid(): Look up the last (newest, or most recently written) pfid in the analysis sequence. - */ - u_int16_t get_last_pfid() - { - u_int16_t flfid = 0; - if (_num_used_files == _map.size()) // journal full? - { - if (_oldest_lfid) - { - // if failed insert, cycle past duplicate lids - while (_map.count(_oldest_lfid) == 2) - _oldest_lfid++; - while (_map.find(_oldest_lfid) != _map.end() && _map.find(_oldest_lfid)->second.get_owi() == false) - _oldest_lfid++; - flfid = _oldest_lfid - 1; - } - else - flfid = _map.size() - 1; - } - else - flfid = _num_used_files - 1; - return get_pfid(flfid, true); - } - - /* - * Method write_journal(): Used to create the dummy journal files from the built-up map created by calling - * initial_journal_create() and optionally journal_append() one or more times. Since the jinf object reads the - * jinf file and the file headers only, the create object creates a dummy journal file containing only a file - * header (512 bytes each) and a single jinf file which contains the journal metadata required for recovery - * analysis. - */ - void write_journal(const bool ae, const u_int16_t ae_max_jfiles, const u_int32_t fsize_sblks = JFSIZE_SBLKS) - { - create_jinf(ae, ae_max_jfiles); - u_int16_t pfid = 0; - for (lpmap_citr itr = _map.begin(); itr != _map.end(); itr++, pfid++) - { - if (itr->second._pfid == 0 && itr->second._magic == 0) // empty header, use pfid counter instead - create_journal_file(pfid, itr->second, _base_filename, fsize_sblks); - else - create_journal_file(itr->second._pfid, itr->second, _base_filename, fsize_sblks); - } - } - - /* - * Method destroy_journal(): Destroy the files created by create_journal() and reset the lfid_pfid_map test - * object. A new test may be started using the same lfid_pfid_map test object once this call has been made. - */ - void destroy_journal() - { - for (u_int16_t pfid = 0; pfid < _map.size(); pfid++) - { - string fn = create_journal_filename(pfid, _base_filename); - BOOST_WARN_MESSAGE(::unlink(fn.c_str()) == 0, "destroy_journal(): Failed to remove file " << fn); - } - clean_journal_info_file(_base_filename); - _map.clear(); - _num_used_files = 0; - _oldest_lfid = 0; - _last_pfid = 0; - } - - /* - * Method create_new_jinf(): This static call creates a default jinf file only. This is used to test the read - * constructor of a jinf test object which reads a jinf file at instantiation. - */ - static void create_new_jinf(const string jid, const string base_filename, const bool ae) - { - if (jdir::exists(test_dir)) - jdir::delete_dir(test_dir); - create_jinf(NUM_JFILES, ae, (ae ? 5 * NUM_JFILES : 0), jid, base_filename); - } - - /* - * Method clean_journal_info_file(): This static method deletes only a jinf file without harming any other - * journal file or its directory. This is used to clear those tests which rely only on the existence of a - * jinf file. - */ - static void clean_journal_info_file(const string base_filename) - { - stringstream fn; - fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION; - BOOST_WARN_MESSAGE(::unlink(fn.str().c_str()) == 0, "clean_journal_info_file(): Failed to remove file " << - fn.str()); - } - - static string create_journal_filename(const u_int16_t pfid, const string base_filename) - { - stringstream fn; - fn << test_dir << "/" << base_filename << "."; - fn << setfill('0') << hex << setw(4) << pfid << "." << JRNL_DATA_EXTENSION; - return fn.str(); - } - - private: - static void init_fhdr(file_hdr& fh, - const u_int64_t frid, - const u_int16_t pfid, - const u_int16_t lfid, - const bool owi, - const bool no_enq = false) - { - fh._magic = RHM_JDAT_FILE_MAGIC; - fh._version = RHM_JDAT_VERSION; -#if defined(JRNL_BIG_ENDIAN) - fh._eflag = RHM_BENDIAN_FLAG; -#else - fh._eflag = RHM_LENDIAN_FLAG; -#endif - fh._uflag = owi ? rec_hdr::HDR_OVERWRITE_INDICATOR_MASK : 0; - fh._rid = frid; - fh._pfid = pfid; - fh._lfid = lfid; - fh._fro = no_enq ? 0 : 0x200; - timespec ts; - ::clock_gettime(CLOCK_REALTIME, &ts); - fh._ts_sec = ts.tv_sec; - fh._ts_nsec = ts.tv_nsec; - } - - void create_jinf(const bool ae, const u_int16_t ae_max_jfiles) - { - if (jdir::exists(test_dir)) - jdir::delete_dir(test_dir); - create_jinf(_map.size(), ae, ae_max_jfiles, _jid, _base_filename); - } - - static void create_jinf(u_int16_t num_files, const bool ae, const u_int16_t ae_max_jfiles, const string jid, - const string base_filename) - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - timespec ts; - ::clock_gettime(CLOCK_REALTIME, &ts); - jinf ji(jid, test_dir, base_filename, num_files, ae, ae_max_jfiles, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE, - JRNL_WMGR_DEF_PAGES, ts); - ji.write(); - } - - static void create_journal_file(const u_int16_t pfid, - const file_hdr& fh, - const string base_filename, - const u_int32_t fsize_sblks = JFSIZE_SBLKS, - const char fill_char = 0) - { - const std::string filename = create_journal_filename(pfid, base_filename); - ofstream of(filename.c_str(), ofstream::out | ofstream::trunc); - if (!of.good()) - BOOST_FAIL("Unable to open test journal file \"" << filename << "\" for writing."); - - write_file_header(filename, of, fh, fill_char); - write_file_body(of, fsize_sblks, fill_char); - - of.close(); - if (of.fail() || of.bad()) - BOOST_FAIL("Error closing test journal file \"" << filename << "\"."); - } - - static void write_file_header(const std::string& filename, - ofstream& of, - const file_hdr& fh, - const char fill_char) - { - // write file header - u_int32_t cnt = sizeof(file_hdr); - of.write((const char*)&fh, cnt); - if (of.fail() || of.bad()) - BOOST_FAIL("Error writing file header to test journal file \"" << filename << "\"."); - - // fill remaining sblk with fill char - while (cnt++ < JRNL_DBLK_SIZE * JRNL_SBLK_SIZE) - { - of.put(fill_char); - if (of.fail() || of.bad()) - BOOST_FAIL("Error writing filler to test journal file \"" << filename << "\"."); - } - } - - static void write_file_body(ofstream& of, const u_int32_t fsize_sblks, const char fill_char) - { - if (fsize_sblks > 1) - { - std::vector sblk_buffer(JRNL_DBLK_SIZE * JRNL_SBLK_SIZE, fill_char); - u_int32_t fwritten_sblks = 0; // hdr - while (fwritten_sblks++ < fsize_sblks) - of.write(&sblk_buffer[0], JRNL_DBLK_SIZE * JRNL_SBLK_SIZE); - } - } -}; - -const string -get_test_name(const string& file, const string& test_name) -{ - cout << test_filename << "." << test_name << ": " << flush; - return file + "." + test_name; -} - -bool -check_iores(const string& ctxt, const iores ret, const iores exp_ret, test_dtok* dtp) -{ - if (ret != exp_ret) - { - delete dtp; - BOOST_FAIL(ctxt << ": Expected " << iores_str(exp_ret) << "; got " << iores_str(ret)); - } - return false; -} - -bool -handle_jcntl_response(const iores res, jcntl& jc, unsigned& aio_sleep_cnt, const std::string& ctxt, const iores exp_ret, - test_dtok* dtp) -{ - if (res == RHM_IORES_PAGE_AIOWAIT) - { - if (++aio_sleep_cnt <= MAX_AIO_SLEEPS) - { - jc.get_wr_events(0); // *** GEV2 - usleep(AIO_SLEEP_TIME); - } - else - return check_iores(ctxt, res, exp_ret, dtp); - } - else - return check_iores(ctxt, res, exp_ret, dtp); - return true; -} - -u_int64_t -enq_msg(jcntl& jc, - const u_int64_t rid, - const string& msg, - const bool transient, - const iores exp_ret = RHM_IORES_SUCCESS) -{ - ostringstream ctxt; - ctxt << "enq_msg(" << rid << ")"; - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_rid(rid); - dtp->set_external_rid(true); - try - { - iores res = jc.enqueue_data_record(msg.c_str(), msg.size(), msg.size(), dtp, transient); - check_iores(ctxt.str(), res, exp_ret, dtp); - u_int64_t dtok_rid = dtp->rid(); - if (dtp->done()) delete dtp; - return dtok_rid; - } - catch (exception& e) { delete dtp; throw; } -} - -u_int64_t -enq_extern_msg(jcntl& jc, const u_int64_t rid, const std::size_t msg_size, const bool transient, - const iores exp_ret = RHM_IORES_SUCCESS) -{ - ostringstream ctxt; - ctxt << "enq_extern_msg(" << rid << ")"; - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_rid(rid); - dtp->set_external_rid(true); - try - { - iores res = jc.enqueue_extern_data_record(msg_size, dtp, transient); - check_iores(ctxt.str(), res, exp_ret, dtp); - u_int64_t dtok_rid = dtp->rid(); - if (dtp->done()) delete dtp; - return dtok_rid; - } - catch (exception& e) { delete dtp; throw; } -} - -u_int64_t -enq_txn_msg(jcntl& jc, const u_int64_t rid, const string& msg, const string& xid, const bool transient, - const iores exp_ret = RHM_IORES_SUCCESS) -{ - ostringstream ctxt; - ctxt << "enq_txn_msg(" << rid << ")"; - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_rid(rid); - dtp->set_external_rid(true); - try - { - iores res = jc.enqueue_txn_data_record(msg.c_str(), msg.size(), msg.size(), dtp, xid, - transient); - check_iores(ctxt.str(), res, exp_ret, dtp); - u_int64_t dtok_rid = dtp->rid(); - if (dtp->done()) delete dtp; - return dtok_rid; - } - catch (exception& e) { delete dtp; throw; } -} - -u_int64_t -enq_extern_txn_msg(jcntl& jc, const u_int64_t rid, const std::size_t msg_size, const string& xid, const bool transient, - const iores exp_ret = RHM_IORES_SUCCESS) -{ - ostringstream ctxt; - ctxt << "enq_extern_txn_msg(" << rid << ")"; - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_rid(rid); - dtp->set_external_rid(true); - try - { - iores res = jc.enqueue_extern_txn_data_record(msg_size, dtp, xid, transient); - check_iores(ctxt.str(), res, exp_ret, dtp); - u_int64_t dtok_rid = dtp->rid(); - if (dtp->done()) delete dtp; - return dtok_rid; - } - catch (exception& e) { delete dtp; throw; } -} - -u_int64_t -deq_msg(jcntl& jc, const u_int64_t drid, const u_int64_t rid, const iores exp_ret = RHM_IORES_SUCCESS) -{ - ostringstream ctxt; - ctxt << "deq_msg(" << drid << ")"; - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_rid(rid); - dtp->set_dequeue_rid(drid); - dtp->set_external_rid(true); - dtp->set_wstate(data_tok::ENQ); - try - { - iores res = jc.dequeue_data_record(dtp); - check_iores(ctxt.str(), res, exp_ret, dtp); - u_int64_t dtok_rid = dtp->rid(); - if (dtp->done()) delete dtp; - return dtok_rid; - } - catch (exception& e) { delete dtp; throw; } -} - -u_int64_t -deq_txn_msg(jcntl& jc, const u_int64_t drid, const u_int64_t rid, const string& xid, - const iores exp_ret = RHM_IORES_SUCCESS) -{ - ostringstream ctxt; - ctxt << "deq_txn_msg(" << drid << ")"; - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_rid(rid); - dtp->set_dequeue_rid(drid); - dtp->set_external_rid(true); - dtp->set_wstate(data_tok::ENQ); - try - { - iores res = jc.dequeue_txn_data_record(dtp, xid); - check_iores(ctxt.str(), res, exp_ret, dtp); - u_int64_t dtok_rid = dtp->rid(); - if (dtp->done()) delete dtp; - return dtok_rid; - } - catch (exception& e) { delete dtp; throw; } -} - -u_int64_t -txn_abort(jcntl& jc, const u_int64_t rid, const string& xid, const iores exp_ret = RHM_IORES_SUCCESS) -{ - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_rid(rid); - dtp->set_external_rid(true); - try - { - iores res = jc.txn_abort(dtp, xid); - check_iores("txn_abort", res, exp_ret, dtp); - u_int64_t dtok_rid = dtp->rid(); - if (dtp->done()) delete dtp; - return dtok_rid; - } - catch (exception& e) { delete dtp; throw; } -} - -u_int64_t -txn_commit(jcntl& jc, const u_int64_t rid, const string& xid, const iores exp_ret = RHM_IORES_SUCCESS) -{ - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_rid(rid); - dtp->set_external_rid(true); - try - { - iores res = jc.txn_commit(dtp, xid); - check_iores("txn_commit", res, exp_ret, dtp); - u_int64_t dtok_rid = dtp->rid(); - if (dtp->done()) delete dtp; - return dtok_rid; - } - catch (exception& e) { delete dtp; throw; } -} - -void -read_msg(jcntl& jc, string& msg, string& xid, bool& transient, bool& external, const iores exp_ret = RHM_IORES_SUCCESS) -{ - void* mp = 0; - std::size_t msize = 0; - void* xp = 0; - std::size_t xsize = 0; - test_dtok* dtp = new test_dtok; - BOOST_CHECK_MESSAGE(dtp != 0, "Data token allocation failed (dtp == 0)."); - dtp->set_wstate(data_tok::ENQ); - - unsigned aio_sleep_cnt = 0; - try - { - iores res = jc.read_data_record(&mp, msize, &xp, xsize, transient, external, dtp); - while (handle_jcntl_response(res, jc, aio_sleep_cnt, "read_msg", exp_ret, dtp)) - res = jc.read_data_record(&mp, msize, &xp, xsize, transient, external, dtp); - } - catch (exception& e) { delete dtp; throw; } - - if (mp) - msg.assign((char*)mp, msize); - if (xp) - { - xid.assign((char*)xp, xsize); - std::free(xp); - xp = 0; - } - else if (mp) - { - std::free(mp); - mp = 0; - } - delete dtp; -} - -/* - * Returns the number of messages of size msg_rec_size_dblks that will fit into an empty journal with or without - * corresponding dequeues (controlled by include_deq) without a threshold - ie until the journal is full. Assumes - * that dequeue records fit into one dblk. - */ -u_int32_t -num_msgs_to_full(const u_int16_t num_files, const u_int32_t file_size_dblks, const u_int32_t msg_rec_size_dblks, - bool include_deq) -{ - u_int32_t rec_size_dblks = msg_rec_size_dblks; - if (include_deq) - rec_size_dblks++; - return u_int32_t(::floor(1.0 * num_files * file_size_dblks / rec_size_dblks)); -} - -/* - * Returns the number of messages of size msg_rec_size_dblks that will fit into an empty journal before the enqueue - * threshold of JRNL_ENQ_THRESHOLD (%). - */ -u_int32_t -num_msgs_to_threshold(const u_int16_t num_files, const u_int32_t file_size_dblks, const u_int32_t msg_rec_size_dblks) -{ - return u_int32_t(::floor(1.0 * num_files * file_size_dblks * JRNL_ENQ_THRESHOLD / msg_rec_size_dblks / 100)); -} - -/* - * Returns the amount of space reserved in dblks (== num dequeues assuming dequeue size of 1 dblk) for the enqueue - * threshold of JRNL_ENQ_THRESHOLD (%). - */ -u_int32_t -num_dequeues_rem(const u_int16_t num_files, const u_int32_t file_size_dblks) -{ - /* - * Fraction of journal remaining after threshold is used --------------+ - * Total no. dblks in journal ------+ | - * | | - * +------------+------------+ +-----------------+---------------------+ - */ - return u_int32_t(::ceil(num_files * file_size_dblks * (1.0 - (1.0 * JRNL_ENQ_THRESHOLD / 100)))); -} - -string& -create_msg(string& s, const int msg_num, const int len) -{ - ostringstream oss; - oss << "MSG_" << setfill('0') << setw(6) << msg_num << "_"; - for (int i=12; i<=len; i++) - oss << (char)('0' + i%10); - s.assign(oss.str()); - return s; -} - -string& -create_xid(string& s, const int msg_num, const int len) -{ - ostringstream oss; - oss << "XID_" << setfill('0') << setw(6) << msg_num << "_"; - for (int i=11; i -#include -#include "qpid/legacystore/jrnl/jcntl.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(journal_read) - -const string test_filename("_st_read"); - -#include "_st_helper_fns.h" - -// === Test suite === - -#ifndef LONG_TEST -/* - * ============================================== - * NORMAL TESTS - * This section contains normal "make check" tests - * for building/packaging. These are built when - * LONG_TEST is _not_ defined. - * ============================================== - */ - -QPID_AUTO_TEST_CASE(empty_read) -{ - string test_name = get_test_name(test_filename, "empty_read"); - try - { - string msg; - string rmsg; - string xid; - bool transientFlag; - bool externalFlag; - - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - jc.initialize(NUM_TEST_JFILES, false, 0, TEST_JFSIZE_SBLKS); - read_msg(jc, rmsg, xid, transientFlag, externalFlag, RHM_IORES_EMPTY); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(enqueue_read_dequeue_block) -{ - string test_name = get_test_name(test_filename, "enqueue_read_dequeue_block"); - try - { - string msg; - string rmsg; - string xid; - bool transientFlag; - bool externalFlag; - - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - jc.initialize(NUM_TEST_JFILES, false, 0, TEST_JFSIZE_SBLKS); - for (int m=0; m -#include -#include "qpid/legacystore/jrnl/jcntl.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(journal_read_txn) - -const string test_filename("_st_read_txn"); - -#include "_st_helper_fns.h" - -// === Test suite === - -QPID_AUTO_TEST_CASE(tx_enqueue_commit_block) -{ - string test_name = get_test_name(test_filename, "tx_enqueue_commit_block"); - try - { - string msg; - string xid; - string rmsg; - string rxid; - bool transientFlag; - bool externalFlag; - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - jc.initialize(NUM_TEST_JFILES, false, 0, TEST_JFSIZE_SBLKS); - create_xid(xid, 0, XID_SIZE); - for (int m=0; m -#include "qpid/legacystore/jrnl/enq_map.h" -#include "qpid/legacystore/jrnl/jerrno.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(enq_map_suite) - -const string test_filename("_ut_enq_map"); - -QPID_AUTO_TEST_CASE(constructor) -{ - cout << test_filename << ".constructor: " << flush; - enq_map e1; - BOOST_CHECK(e1.empty()); - BOOST_CHECK_EQUAL(e1.size(), u_int32_t(0)); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(insert_get) -{ - cout << test_filename << ".insert_get: " << flush; - u_int16_t pfid; - u_int64_t rid; - u_int16_t pfid_start = 0x2000U; - u_int64_t rid_begin = 0xffffffff00000000ULL; - u_int64_t rid_end = 0xffffffff00000200ULL; - - // insert with no dups - u_int64_t rid_incr_1 = 4ULL; - enq_map e2; - e2.set_num_jfiles(pfid_start + (rid_end - rid_begin)/rid_incr_1); - for (rid = rid_begin, pfid = pfid_start; rid < rid_end; rid += rid_incr_1, pfid++) - BOOST_CHECK_EQUAL(e2.insert_pfid(rid, pfid), enq_map::EMAP_OK); - BOOST_CHECK(!e2.empty()); - BOOST_CHECK_EQUAL(e2.size(), u_int32_t(128)); - - // get - u_int64_t rid_incr_2 = 6ULL; - for (u_int64_t rid = rid_begin; rid < rid_end; rid += rid_incr_2) - { - BOOST_CHECK_EQUAL(e2.is_enqueued(rid), (rid%rid_incr_1 ? false : true)); - u_int16_t exp_pfid = pfid_start + (u_int16_t)((rid - rid_begin)/rid_incr_1); - int16_t ret_fid = e2.get_pfid(rid); - if (ret_fid < enq_map::EMAP_OK) // fail - { - BOOST_CHECK_EQUAL(ret_fid, enq_map::EMAP_RID_NOT_FOUND); - BOOST_CHECK(rid%rid_incr_1); - } - else - { - BOOST_CHECK_EQUAL(ret_fid, exp_pfid); - BOOST_CHECK(rid%rid_incr_1 == 0); - } - if ((rid + rid_incr_2)%(8 * rid_incr_2) == 0) - pfid++; - } - - // insert with dups - for (rid = rid_begin, pfid = pfid_start; rid < rid_end; rid += rid_incr_2, pfid++) - { - int16_t res = e2.insert_pfid(rid, pfid); - if (res < enq_map::EMAP_OK) // fail - { - BOOST_CHECK_EQUAL(res, enq_map::EMAP_DUP_RID); - BOOST_CHECK(rid%rid_incr_1 == 0); - } - else - BOOST_CHECK(rid%rid_incr_1); - } - BOOST_CHECK_EQUAL(e2.size(), u_int32_t(171)); - e2.clear(); - BOOST_CHECK(e2.empty()); - BOOST_CHECK_EQUAL(e2.size(), u_int32_t(0)); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(get_remove) -{ - cout << test_filename << ".get_remove: " << flush; - u_int16_t pfid; - u_int64_t rid; - u_int16_t pfid_start = 0x3000U; - u_int64_t rid_begin = 0xeeeeeeee00000000ULL; - u_int64_t rid_end = 0xeeeeeeee00000200ULL; - - u_int64_t rid_incr_1 = 4ULL; - u_int64_t num_incr_1 = (rid_end - rid_begin)/rid_incr_1; - enq_map e3; - e3.set_num_jfiles(pfid_start + (rid_end - rid_begin)/rid_incr_1); - for (rid = rid_begin, pfid = pfid_start; rid < rid_end; rid += rid_incr_1, pfid++) - BOOST_CHECK_EQUAL(e3.insert_pfid(rid, pfid), enq_map::EMAP_OK); - BOOST_CHECK_EQUAL(e3.size(), num_incr_1); - - u_int64_t rid_incr_2 = 6ULL; - for (rid = rid_begin, pfid = pfid_start; rid < rid_end; rid += rid_incr_2, pfid++) - { - u_int16_t exp_pfid = pfid_start + (u_int16_t)((rid - rid_begin)/rid_incr_1); - int16_t ret_fid = e3.get_remove_pfid(rid); - if (ret_fid < enq_map::EMAP_OK) // fail - { - BOOST_CHECK_EQUAL(ret_fid, enq_map::EMAP_RID_NOT_FOUND); - BOOST_CHECK(rid%rid_incr_1); - } - else - { - BOOST_CHECK_EQUAL(ret_fid, exp_pfid); - BOOST_CHECK(rid%rid_incr_1 == 0); - } - } - BOOST_CHECK_EQUAL(e3.size(), u_int32_t(85)); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(lock) -{ - cout << test_filename << ".lock: " << flush; - u_int16_t pfid; - u_int64_t rid; - u_int16_t pfid_start = 0x4000U; - u_int64_t rid_begin = 0xdddddddd00000000ULL; - u_int64_t rid_end = 0xdddddddd00000200ULL; - - // insert, every second entry is locked - u_int64_t rid_incr_1 = 4ULL; - u_int64_t num_incr_1 = (rid_end - rid_begin)/rid_incr_1; - bool locked = false; - enq_map e4; - e4.set_num_jfiles(pfid_start + (rid_end - rid_begin)/rid_incr_1); - for (rid = rid_begin, pfid = pfid_start; rid < rid_end; rid += rid_incr_1, pfid++) - { - BOOST_CHECK_EQUAL(e4.insert_pfid(rid, pfid, locked), enq_map::EMAP_OK); - locked = !locked; - } - BOOST_CHECK_EQUAL(e4.size(), num_incr_1); - - // unlock and lock non-existent rids - int16_t res = e4.lock(1ULL); - if (res < enq_map::EMAP_OK) - BOOST_CHECK_EQUAL(res, enq_map::EMAP_RID_NOT_FOUND); - else - BOOST_ERROR("Failed to detect locking non-existent rid."); - res = e4.unlock(2ULL); - if (res < enq_map::EMAP_OK) - BOOST_CHECK_EQUAL(res, enq_map::EMAP_RID_NOT_FOUND); - else - BOOST_ERROR("Failed to detect unlocking non-existent rid."); - - // get / unlock - for (u_int64_t rid = rid_begin; rid < rid_end; rid += rid_incr_1) - { - int16_t fid = e4.get_pfid(rid); - if (fid < enq_map::EMAP_OK) // fail - { - BOOST_CHECK_EQUAL(fid, enq_map::EMAP_LOCKED); - BOOST_CHECK(rid%(2*rid_incr_1)); - // unlock, read, then relock - BOOST_CHECK_EQUAL(e4.unlock(rid), enq_map::EMAP_OK); - BOOST_CHECK(e4.get_pfid(rid) >= enq_map::EMAP_OK); - BOOST_CHECK_EQUAL(e4.lock(rid), enq_map::EMAP_OK); - fid = e4.get_pfid(rid); - if (fid < enq_map::EMAP_OK) // fail - BOOST_CHECK_EQUAL(fid, enq_map::EMAP_LOCKED); - else - BOOST_ERROR("Failed to prevent getting locked record"); - } - } - - // remove all; if locked, use with txn_flag true; should ignore all locked records - for (u_int64_t rid = rid_begin; rid < rid_end; rid += rid_incr_1) - BOOST_CHECK(e4.get_remove_pfid(rid, true) >= enq_map::EMAP_OK); - BOOST_CHECK(e4.empty()); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(lists) -{ - cout << test_filename << ".lists: " << flush; - u_int16_t pfid; - u_int64_t rid; - u_int16_t pfid_start = 0x5000UL; - u_int64_t rid_begin = 0xdddddddd00000000ULL; - u_int64_t rid_end = 0xdddddddd00000200ULL; - - // insert, every second entry is locked - u_int64_t rid_incr_1 = 4ULL; - u_int64_t num_incr_1 = (rid_end - rid_begin)/rid_incr_1; - vector rid_list; - vector pfid_list; - enq_map e5; - e5.set_num_jfiles(pfid_start + (rid_end - rid_begin)/rid_incr_1); - for (rid = rid_begin, pfid = pfid_start; rid < rid_end; rid += rid_incr_1, pfid++) - { - BOOST_CHECK_EQUAL(e5.insert_pfid(rid, pfid), enq_map::EMAP_OK); - rid_list.push_back(rid); - pfid_list.push_back(pfid); - } - BOOST_CHECK_EQUAL(e5.size(), num_incr_1); - BOOST_CHECK_EQUAL(rid_list.size(), num_incr_1); - BOOST_CHECK_EQUAL(pfid_list.size(), num_incr_1); - - vector ret_rid_list; - e5.rid_list(ret_rid_list); - BOOST_CHECK_EQUAL(ret_rid_list.size(), num_incr_1); - for (unsigned i=0; i ret_pfid_list; - e5.pfid_list(ret_pfid_list); - BOOST_CHECK_EQUAL(ret_pfid_list.size(), num_incr_1); - for (unsigned i=0; i= enq_map::EMAP_OK); - for (u_int16_t pfid=0; pfid<4; pfid++) - { - if (pfid == 1) - BOOST_CHECK_EQUAL(e6.get_enq_cnt(pfid), u_int32_t(90)); - else - BOOST_CHECK_EQUAL(e6.get_enq_cnt(pfid), u_int32_t(0)); - } - - // Now resize the file up and make sure the count in file 1 still exists - e6.set_num_jfiles(8); - for (u_int16_t pfid=0; pfid<8; pfid++) - { - if (pfid == 1) - BOOST_CHECK_EQUAL(e6.get_enq_cnt(pfid), u_int32_t(90)); - else - BOOST_CHECK_EQUAL(e6.get_enq_cnt(pfid), u_int32_t(0)); - } - - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(stress) -{ - cout << test_filename << ".stress: " << flush; - u_int64_t rid; - u_int64_t rid_cnt; - u_int64_t rid_begin = 0xffffffff00000000ULL; - u_int64_t num_rid = 10; - - enq_map e7; - e7.set_num_jfiles(rid_begin + num_rid); - - // insert even rids with no dups - for (rid = rid_begin, rid_cnt = u_int64_t(0); rid_cnt < num_rid; rid += 2ULL, rid_cnt++) - BOOST_CHECK_EQUAL(e7.insert_pfid(rid, u_int16_t(0)), enq_map::EMAP_OK); - BOOST_CHECK_EQUAL(e7.size(), num_rid); - - // insert odd rids with no dups - for (rid = rid_begin + 1, rid_cnt = u_int64_t(0); rid_cnt < num_rid; rid += 2ULL, rid_cnt++) - BOOST_CHECK_EQUAL(e7.insert_pfid(rid, u_int16_t(0)), enq_map::EMAP_OK); - BOOST_CHECK_EQUAL(e7.size(), num_rid * 2); - - // remove even rids - for (rid = rid_begin, rid_cnt = u_int64_t(0); rid_cnt < num_rid; rid += 2ULL, rid_cnt++) - BOOST_CHECK(e7.get_remove_pfid(rid) >= enq_map::EMAP_OK); - BOOST_CHECK_EQUAL(e7.size(), num_rid); - - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp deleted file mode 100644 index b55d5ff8ef..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_ut_jdir.cpp +++ /dev/null @@ -1,416 +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 "../unit_test.h" - -#include -#include -#include -#include -#include -#include -#include "qpid/legacystore/jrnl/file_hdr.h" -#include "qpid/legacystore/jrnl/jcfg.h" -#include "qpid/legacystore/jrnl/jdir.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" -#include - -#define NUM_JFILES 4 -#define JFSIZE_SBLKS 128 - -#define ERRORSTR(e) std::strerror(e) << " (" << e << ")" -#define NUM_CLEAR_OPS 20 - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(jdir_suite) - -const string test_filename("_ut_jdir"); -const char* tdp = getenv("TMP_DATA_DIR"); -const string test_dir(tdp && strlen(tdp) > 0 ? string(tdp) + "/_ut_jdir" : "/var/tmp/_ut_jdir"); - -// === Helper functions === - -void create_file(const char* filename, mode_t fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) -{ - ofstream of(filename, ofstream::out | ofstream::trunc); - if (!of.good()) - BOOST_FAIL("Unable to open file " << filename << " for writing."); - of.write(filename, std::strlen(filename)); - of.close(); - ::chmod(filename, fmode); -} - -void create_file(const string filename, mode_t fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) -{ - create_file(filename.c_str(), fmode); -} - -void create_jdat_file(const char* dirname, const char* base_filename, u_int32_t fid, - u_int64_t first_rid) -{ - stringstream fn; - fn << dirname << "/" << base_filename << "."; - fn << setfill('0') << hex << setw(4) << fid << ".jdat"; - file_hdr fh(RHM_JDAT_FILE_MAGIC, RHM_JDAT_VERSION, 0, first_rid, fid, 0x200, true); - ofstream of(fn.str().c_str(), ofstream::out | ofstream::trunc); - if (!of.good()) - BOOST_FAIL("Unable to open journal data file " << fn.str() << " for writing."); - of.write((const char*)&fh, sizeof(file_hdr)); - of.close(); -} - -void create_jinf_file(const char* dirname, const char* base_filename) -{ - timespec ts; - ::clock_gettime(CLOCK_REALTIME, &ts); - jinf ji("test journal id", dirname, base_filename, NUM_JFILES, false, 0, JFSIZE_SBLKS, - JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES, ts); - ji.write(); -} - -void create_jrnl_fileset(const char* dirname, const char* base_filename) -{ - create_jinf_file(dirname, base_filename); - for (u_int32_t fid = 0; fid < NUM_JFILES; fid++) - { - u_int64_t rid = 0x12340000 + (fid * 0x25); - create_jdat_file(dirname, base_filename, fid, rid); - } -} - -unsigned count_dir_contents(const char* dirname, bool incl_files, bool incl_dirs = true) -{ - struct dirent* entry; - struct stat s; - unsigned file_cnt = 0; - unsigned dir_cnt = 0; - unsigned other_cnt = 0; - DIR* dir = ::opendir(dirname); - if (!dir) - BOOST_FAIL("Unable to open directory " << dirname); - while ((entry = ::readdir(dir)) != NULL) - { - // Ignore . and .. - if (std::strcmp(entry->d_name, ".") != 0 && std::strcmp(entry->d_name, "..") != 0) - { - stringstream fn; - fn << dirname << "/" << entry->d_name; - if (::stat(fn.str().c_str(), &s)) - BOOST_FAIL("Unable to stat dir entry " << entry->d_name << "; err=" << - ERRORSTR(errno)); - if (S_ISREG(s.st_mode)) - file_cnt++; - else if (S_ISDIR(s.st_mode)) - dir_cnt++; - else - other_cnt++; - } - } - ::closedir(dir); - if (incl_files) - { - if (incl_dirs) - return file_cnt + dir_cnt; - return file_cnt; - } - else if (incl_dirs) - return dir_cnt; - return other_cnt; -} - -void check_dir_contents(const char* dirname, const char* base_filename, unsigned num_subdirs, - bool jrnl_present) -{ - if (jdir::is_dir(dirname)) - { - // Subdir count - BOOST_CHECK_EQUAL(count_dir_contents(dirname, false, true), num_subdirs); - - // Journal file count - unsigned num_jrnl_files = jrnl_present ? NUM_JFILES + 1 : 0; - BOOST_CHECK_EQUAL(count_dir_contents(dirname, true, false), num_jrnl_files); - - // Check journal files are present - if (jrnl_present) - try { jdir::verify_dir(dirname, base_filename); } - catch(const jexception& e) { BOOST_ERROR(e); } - for (unsigned subdir_num = 1; subdir_num <= num_subdirs; subdir_num++) - { - stringstream subdir_name; - subdir_name << dirname << "/_" << base_filename << ".bak."; - subdir_name << hex << setfill('0') << setw(4) << subdir_num; - try { jdir::verify_dir(subdir_name.str().c_str(), base_filename); } - catch(const jexception& e) { BOOST_ERROR(e); } - } - } - else - BOOST_ERROR(dirname << " is not a directory"); -} - -void check_dir_not_existing(const char* dirname) -{ - if (jdir::exists(dirname) && jdir::is_dir(dirname)) - jdir::delete_dir(dirname); - if (jdir::exists(dirname)) - BOOST_FAIL("Unable to remove directory " << dirname); -} - -void check_dir_not_existing(const string dirname) -{ - check_dir_not_existing(dirname.c_str()); -} - -// === Test suite === - -QPID_AUTO_TEST_CASE(constructor) -{ - cout << test_filename << ".constructor: " << flush; - string dir(test_dir + "/A/B/C/D/E/F"); - string bfn("test_base"); - jdir dir1(dir, bfn); - BOOST_CHECK(dir1.dirname().compare(dir) == 0); - BOOST_CHECK(dir1.base_filename().compare(bfn) == 0); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(create_delete_dir) -{ - cout << test_filename << ".create_delete_dir: " << flush; - // Use instance - string dir_A(test_dir + "/A"); - string dir_Ats(test_dir + "/A/"); // trailing '/' - check_dir_not_existing(test_dir + "/A"); - jdir dir1(dir_A, "test_base"); - dir1.create_dir(); - // check all combos of jdir::exists and jdir::is_dir() - BOOST_CHECK(jdir::exists(dir_A)); - BOOST_CHECK(jdir::exists(dir_Ats)); - BOOST_CHECK(jdir::exists(dir_A.c_str())); - BOOST_CHECK(jdir::exists(dir_Ats.c_str())); - BOOST_CHECK(jdir::is_dir(dir_A)); - BOOST_CHECK(jdir::is_dir(dir_Ats)); - BOOST_CHECK(jdir::is_dir(dir_Ats.c_str())); - BOOST_CHECK(jdir::is_dir(dir_Ats.c_str())); - // do it a second time when dir exists - dir1.create_dir(); - BOOST_CHECK(jdir::is_dir(dir_A)); - dir1.delete_dir(); - BOOST_CHECK(!jdir::exists(dir_A)); - - // Use static fn - check_dir_not_existing(test_dir + "/B"); - jdir::create_dir(test_dir + "/B"); - BOOST_CHECK(jdir::is_dir(test_dir + "/B")); - jdir::create_dir(test_dir + "/B"); - BOOST_CHECK(jdir::is_dir(test_dir + "/B")); - jdir::delete_dir(test_dir + "/B"); - BOOST_CHECK(!jdir::exists(test_dir + "/B")); - - // Non-empty dirs - check_dir_not_existing(test_dir + "/C"); - jdir::create_dir(test_dir + "/C"); - BOOST_CHECK(jdir::is_dir(test_dir + "/C")); - create_file(test_dir + "/C/test_file_1.txt"); // mode 644 (default) - create_file(test_dir + "/C/test_file_2.txt", S_IRWXU | S_IRWXG | S_IRWXO); // mode 777 - create_file(test_dir + "/C/test_file_3.txt", S_IRUSR | S_IRGRP | S_IROTH); // mode 444 (read-only) - create_file(test_dir + "/C/test_file_4.txt", 0); // mode 000 (no permissions) - BOOST_CHECK(jdir::is_dir(test_dir + "/C")); - jdir::create_dir(test_dir + "/C"); - BOOST_CHECK(jdir::is_dir(test_dir + "/C")); - jdir::delete_dir(test_dir + "/C"); - BOOST_CHECK(!jdir::exists(test_dir + "/C")); - - // Check non-existent dirs fail - check_dir_not_existing(test_dir + "/D"); - try - { - jdir::is_dir(test_dir + "/D"); - BOOST_ERROR("jdir::is_dir() failed to throw jexeption for non-existent directory."); - } - catch(const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_JDIR_STAT); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(create_delete_dir_recursive) -{ - cout << test_filename << ".create_delete_dir_recursive: " << flush; - // Use instances - check_dir_not_existing(test_dir + "/E"); - jdir dir1(test_dir + "/E/F/G/H", "test_base"); - dir1.create_dir(); - BOOST_CHECK(jdir::is_dir(test_dir + "/E/F/G/H")); - dir1.delete_dir(); - BOOST_CHECK(!jdir::exists(test_dir + "/E/F/G/H")); // only H deleted, E/F/G remain - BOOST_CHECK(jdir::exists(test_dir + "/E/F/G")); - jdir::delete_dir(test_dir + "/E"); // delete remaining dirs - BOOST_CHECK(!jdir::exists(test_dir + "/E")); - - check_dir_not_existing(test_dir + "/F"); - jdir dir2(test_dir + "/F/G/H/I/", "test_base"); // trailing '/' - dir2.create_dir(); - BOOST_CHECK(jdir::is_dir(test_dir + "/F/G/H/I/")); - dir2.delete_dir(); - BOOST_CHECK(!jdir::exists(test_dir + "/F/G/H/I/")); - BOOST_CHECK(jdir::exists(test_dir + "/F/G/H/")); - jdir::delete_dir(test_dir + "/F"); - BOOST_CHECK(!jdir::exists(test_dir + "/F")); - - check_dir_not_existing(test_dir + "/G"); - jdir dir3(test_dir + "/G/H//I//J", "test_base"); // extra '/' in path - dir3.create_dir(); - BOOST_CHECK(jdir::is_dir(test_dir + "/G/H//I//J")); - dir3.delete_dir(); - BOOST_CHECK(!jdir::exists(test_dir + "/G/H//I//J")); - BOOST_CHECK(jdir::exists(test_dir + "/G/H//I")); - jdir::delete_dir(test_dir + "/F"); - BOOST_CHECK(!jdir::exists(test_dir + "/F")); - - // Use static fn - check_dir_not_existing(test_dir + "/H"); - jdir::create_dir(test_dir + "/H/I/J/K"); - BOOST_CHECK(jdir::is_dir(test_dir + "/H/I/J/K")); - jdir::delete_dir(test_dir + "/H/I/J/K"); - BOOST_CHECK(!jdir::exists(test_dir + "/H/I/J/K")); // only J deleted, H/I/J remain - BOOST_CHECK(jdir::exists(test_dir + "/H/I/J")); - jdir::delete_dir(test_dir + "/H"); - BOOST_CHECK(!jdir::exists(test_dir + "/H")); - - check_dir_not_existing(test_dir + "/I"); - jdir::create_dir(test_dir + "/I/J/K/L/"); // trailing '/' - BOOST_CHECK(jdir::is_dir(test_dir + "/I/J/K/L/")); - jdir::delete_dir(test_dir + "/I/J/K/L/"); - BOOST_CHECK(!jdir::exists(test_dir + "/I/J/K/L/")); - BOOST_CHECK(jdir::exists(test_dir + "/I/J/K/")); - jdir::delete_dir(test_dir + "/I"); - BOOST_CHECK(!jdir::exists(test_dir + "/I")); - - check_dir_not_existing(test_dir + "//J"); - jdir::create_dir(test_dir + "//J//K//L//M"); // extra '/' in path - BOOST_CHECK(jdir::is_dir(test_dir + "//J//K//L//M")); - jdir::delete_dir(test_dir + "//J//K//L//M"); - BOOST_CHECK(!jdir::exists(test_dir + "//J//K//L//M")); - BOOST_CHECK(jdir::exists(test_dir + "//J//K//L")); - jdir::delete_dir(test_dir + "//J"); - BOOST_CHECK(!jdir::exists(test_dir + "//J")); - - // Non-empty dirs - check_dir_not_existing(test_dir + "/K"); - jdir::create_dir(test_dir + "/K/L/M1/N1"); - jdir::create_dir(test_dir + "/K/L/M1/N2"); - jdir::create_dir(test_dir + "/K/L/M1/N3"); - jdir::create_dir(test_dir + "/K/L/M1/N4"); - create_file(test_dir + "/K/L/M1/N4/test_file_1.txt"); // mode 644 (default) - create_file(test_dir + "/K/L/M1/N4/test_file_2.txt", S_IRWXU | S_IRWXG | S_IRWXO); // mode 777 - create_file(test_dir + "/K/L/M1/N4/test_file_3.txt", S_IRUSR | S_IRGRP | S_IROTH); // mode 444 - create_file(test_dir + "/K/L/M1/N4/test_file_4.txt", 0); // mode 000 (no permissions) - jdir::create_dir(test_dir + "/K/L/M2"); - jdir::create_dir(test_dir + "/K/L/M3/N5"); - jdir::create_dir(test_dir + "/K/L/M3/N6"); - BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M1/N1")); - BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M1/N2")); - BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M1/N3")); - BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M1/N4")); - BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M2")); - BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M3/N5")); - BOOST_CHECK(jdir::is_dir(test_dir + "/K/L/M3/N6")); - jdir::delete_dir(test_dir + "/K"); - BOOST_CHECK(!jdir::exists(test_dir + "/K")); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(clear_verify_dir) -{ - cout << test_filename << ".clear_verify_dir: " << flush; - // Use instances - const char* jrnl_dir = "/var/tmp/test_dir_1"; - const char* bfn = "test_base"; - check_dir_not_existing(jrnl_dir); - jdir test_dir_1(jrnl_dir, bfn); - test_dir_1.create_dir(); - BOOST_CHECK(jdir::is_dir(jrnl_dir)); - // add journal files, check they exist, then clear them - unsigned cnt = 0; - while (cnt < NUM_CLEAR_OPS) - { - create_jrnl_fileset(jrnl_dir, bfn); - check_dir_contents(jrnl_dir, bfn, cnt, true); - test_dir_1.clear_dir(); - check_dir_contents(jrnl_dir, bfn, ++cnt, false); - } - // clean up - test_dir_1.delete_dir(); - BOOST_CHECK(!jdir::exists(jrnl_dir)); - - // Non-existent dir with auto-create true - jrnl_dir = "/var/tmp/test_dir_2"; - check_dir_not_existing(jrnl_dir); - jdir test_dir_2(jrnl_dir, bfn); - // clear dir - test_dir_2.clear_dir(); // create flag is true by default - check_dir_contents(jrnl_dir, bfn, 0, false); - // clear empty dir, should not create subdir - test_dir_2.clear_dir(); // create flag is true by default - check_dir_contents(jrnl_dir, bfn, 0, false); - // clean up - test_dir_2.delete_dir(); - BOOST_CHECK(!jdir::exists(jrnl_dir)); - - // non-existent dir with auto-create false - jrnl_dir = "/var/tmp/test_dir_3"; - check_dir_not_existing(jrnl_dir); - jdir test_dir_3(jrnl_dir, bfn); - try - { - test_dir_3.clear_dir(false); - BOOST_ERROR("jdir::clear_dir(flase) failed to throw jexeption for non-existent directory."); - } - catch(const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_JDIR_OPENDIR); - } - - // Use static fn - jrnl_dir = "/var/tmp/test_dir_4"; - check_dir_not_existing(jrnl_dir); - jdir::clear_dir(jrnl_dir, bfn); // should create dir if it does not exist - // add journal files, check they exist, then clear them - cnt = 0; - while (cnt < NUM_CLEAR_OPS) - { - create_jrnl_fileset(jrnl_dir, bfn); - check_dir_contents(jrnl_dir, bfn, cnt, true); - jdir::clear_dir(jrnl_dir, bfn); - check_dir_contents(jrnl_dir, bfn, ++cnt, false); - } - // clean up - jdir::delete_dir(jrnl_dir); - BOOST_CHECK(!jdir::exists(jrnl_dir)); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp deleted file mode 100644 index 1ae1138355..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_ut_jerrno.cpp +++ /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. - * - */ - -#include "../unit_test.h" - -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(jerrno_suite) -using namespace mrg::journal; - -const string test_filename("_ut_jerrno"); - -QPID_AUTO_TEST_CASE(jerrno_val) -{ - cout << test_filename << ".jerrno_val: " << flush; - const char* m = "JERR__MALLOC"; - string malloc_msg = string(jerrno::err_msg(jerrno::JERR__MALLOC)); - BOOST_CHECK(malloc_msg.substr(0, std::strlen(m)).compare(m) == 0); - BOOST_CHECK(std::strcmp(jerrno::err_msg(0), "") == 0); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_ut_jexception.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_ut_jexception.cpp deleted file mode 100644 index 8b9e876aa6..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_ut_jexception.cpp +++ /dev/null @@ -1,346 +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 "../unit_test.h" - -#include -#include -#include "qpid/legacystore/jrnl/jerrno.h" -#include "qpid/legacystore/jrnl/jexception.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(jexception_suite) - -const string test_filename("_ut_jexception"); - -// === Helper functions === - -void throw_exception(const jexception& e, std::size_t what_len, std::size_t ai_len, - std::size_t tc_len, std::size_t tf_len) -{ - try { throw e; } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(std::strlen(e.what()), what_len); - BOOST_CHECK_EQUAL(e.additional_info().size(), ai_len); - BOOST_CHECK_EQUAL(e.throwing_class().size(), tc_len); - BOOST_CHECK_EQUAL(e.throwing_fn().size(), tf_len); - } -} - -void throw_exception(const jexception& e, std::size_t what_len, std::size_t ai_len) -{ - throw_exception(e, what_len, ai_len, 0, 0); -} - -void throw_exception(const jexception& e, std::size_t what_len, std::size_t tc_len, - std::size_t tf_len) -{ - throw_exception(e, what_len, 0, tc_len, tf_len); -} - -// === Test suite === - -QPID_AUTO_TEST_CASE(constructor_1) -{ - cout << test_filename << ".constructor_1: " << flush; - try - { - jexception e1; - BOOST_CHECK_EQUAL(e1.err_code(), (u_int32_t)0); - BOOST_CHECK(e1.additional_info().size() == 0); - BOOST_CHECK(e1.throwing_class().size() == 0); - BOOST_CHECK(e1.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e1.what()) > 0); - throw e1; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), (u_int32_t)0); - BOOST_CHECK(e.additional_info().size() == 0); - BOOST_CHECK(e.throwing_class().size() == 0); - BOOST_CHECK(e.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_2) -{ - cout << test_filename << ".constructor_2: " << flush; - const u_int32_t err_code = 2; - try - { - jexception e2(err_code); - BOOST_CHECK_EQUAL(e2.err_code(), err_code); - BOOST_CHECK(e2.additional_info().size() == 0); - BOOST_CHECK(e2.throwing_class().size() == 0); - BOOST_CHECK(e2.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e2.what()) > 0); - throw e2; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), err_code); - BOOST_CHECK(e.additional_info().size() == 0); - BOOST_CHECK(e.throwing_class().size() == 0); - BOOST_CHECK(e.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_3a) -{ - cout << test_filename << ".constructor_3a: " << flush; - const char* err_msg = "exception3"; - try - { - jexception e3(err_msg); - BOOST_CHECK_EQUAL(e3.err_code(), (u_int32_t)0); - BOOST_CHECK(e3.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e3.throwing_class().size() == 0); - BOOST_CHECK(e3.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e3.what()) > 0); - throw e3; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), (u_int32_t)0); - BOOST_CHECK(e.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e.throwing_class().size() == 0); - BOOST_CHECK(e.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_3b) -{ - cout << test_filename << ".constructor_3b: " << flush; - const string err_msg("exception3"); - try - { - jexception e3(err_msg); - BOOST_CHECK_EQUAL(e3.err_code(), (u_int32_t)0); - BOOST_CHECK(e3.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e3.throwing_class().size() == 0); - BOOST_CHECK(e3.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e3.what()) > 0); - throw e3; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), (u_int32_t)0); - BOOST_CHECK(e.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e.throwing_class().size() == 0); - BOOST_CHECK(e.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_4a) -{ - cout << test_filename << ".constructor_4a: " << flush; - const u_int32_t err_code = 4; - const char* err_msg = "exception4"; - try - { - jexception e4(err_code, err_msg); - BOOST_CHECK_EQUAL(e4.err_code(), err_code); - BOOST_CHECK(e4.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e4.throwing_class().size() == 0); - BOOST_CHECK(e4.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e4.what()) > 0); - throw e4; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), err_code); - BOOST_CHECK(e.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e.throwing_class().size() == 0); - BOOST_CHECK(e.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_4b) -{ - cout << test_filename << ".constructor_4b: " << flush; - const u_int32_t err_code = 4; - const string err_msg("exception4"); - try - { - jexception e4(err_code, err_msg); - BOOST_CHECK_EQUAL(e4.err_code(), err_code); - BOOST_CHECK(e4.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e4.throwing_class().size() == 0); - BOOST_CHECK(e4.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e4.what()) > 0); - throw e4; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), err_code); - BOOST_CHECK(e.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e.throwing_class().size() == 0); - BOOST_CHECK(e.throwing_fn().size() == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_5a) -{ - cout << test_filename << ".constructor_5a: " << flush; - const u_int32_t err_code = 5; - const char* err_class = "class5"; - const char* err_fn = "fn5"; - try - { - jexception e5(err_code, err_class, err_fn); - BOOST_CHECK_EQUAL(e5.err_code(), err_code); - BOOST_CHECK(e5.additional_info().size() == 0); - BOOST_CHECK(e5.throwing_class().compare(err_class) == 0); - BOOST_CHECK(e5.throwing_fn().compare(err_fn) == 0); - BOOST_CHECK(std::strlen(e5.what()) > 0); - throw e5; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), err_code); - BOOST_CHECK(e.additional_info().size() == 0); - BOOST_CHECK(e.throwing_class().compare(err_class) == 0); - BOOST_CHECK(e.throwing_fn().compare(err_fn) == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_5b) -{ - cout << test_filename << ".constructor_5b: " << flush; - const u_int32_t err_code = 5; - const string err_class("class5"); - const string err_fn("fn5"); - try - { - jexception e5(err_code, err_class, err_fn); - BOOST_CHECK_EQUAL(e5.err_code(), err_code); - BOOST_CHECK(e5.additional_info().size() == 0); - BOOST_CHECK(e5.throwing_class().compare(err_class) == 0); - BOOST_CHECK(e5.throwing_fn().compare(err_fn) == 0); - BOOST_CHECK(std::strlen(e5.what()) > 0); - throw e5; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), err_code); - BOOST_CHECK(e.additional_info().size() == 0); - BOOST_CHECK(e.throwing_class().compare(err_class) == 0); - BOOST_CHECK(e.throwing_fn().compare(err_fn) == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_6a) -{ - cout << test_filename << ".constructor_6a: " << flush; - const u_int32_t err_code = 6; - const char* err_msg = "exception6"; - const char* err_class = "class6"; - const char* err_fn = "fn6"; - try - { - jexception e6(err_code, err_msg, err_class, err_fn); - BOOST_CHECK_EQUAL(e6.err_code(), err_code); - BOOST_CHECK(e6.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e6.throwing_class().compare(err_class) == 0); - BOOST_CHECK(e6.throwing_fn().compare(err_fn) == 0); - BOOST_CHECK(std::strlen(e6.what()) > 0); - throw e6; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), err_code); - BOOST_CHECK(e.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e.throwing_class().compare(err_class) == 0); - BOOST_CHECK(e.throwing_fn().compare(err_fn) == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_6b) -{ - cout << test_filename << ".constructor_6b: " << flush; - const u_int32_t err_code = 6; - const string err_msg("exception6"); - const string err_class("class6"); - const string err_fn("fn6"); - try - { - jexception e6(err_code, err_msg, err_class, err_fn); - BOOST_CHECK_EQUAL(e6.err_code(), err_code); - BOOST_CHECK(e6.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e6.throwing_class().compare(err_class) == 0); - BOOST_CHECK(e6.throwing_fn().compare(err_fn) == 0); - BOOST_CHECK(std::strlen(e6.what()) > 0); - throw e6; - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), err_code); - BOOST_CHECK(e.additional_info().compare(err_msg) == 0); - BOOST_CHECK(e.throwing_class().compare(err_class) == 0); - BOOST_CHECK(e.throwing_fn().compare(err_fn) == 0); - BOOST_CHECK(std::strlen(e.what()) > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(msg_scope) -{ - cout << test_filename << ".msg_scope: " << flush; - try - { - // These will go out of scope as soon as jexception is thrown... - const string msg("Error message"); - const string cls("class"); - const string fn("function"); - throw jexception(100, msg, cls, fn); - } - catch (const jexception& e) - { - stringstream ss; - ss << e; - BOOST_CHECK(ss.str().size() > 0); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp deleted file mode 100644 index f239139306..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_ut_jinf.cpp +++ /dev/null @@ -1,402 +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 "../unit_test.h" - -#include -#include -#include "qpid/legacystore/jrnl/jcntl.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(jinf_suite) - -const string test_filename("_ut_jinf"); - -#include "_st_helper_fns.h" - -timespec ts; - -QPID_AUTO_TEST_CASE(write_constructor) -{ - string test_name = get_test_name(test_filename, "write_constructor"); - const string jid = test_name + "_jid"; - const string base_filename = test_name + "_bfn"; - jdir::create_dir(test_dir); // Check test dir exists; create it if not - ::clock_gettime(CLOCK_REALTIME, &ts); - jinf ji(jid, test_dir, base_filename, NUM_JFILES, false, 0, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES, ts); - BOOST_CHECK_EQUAL(ji.jver(), RHM_JDAT_VERSION); - BOOST_CHECK(ji.jid().compare(jid) == 0); - BOOST_CHECK(ji.jdir().compare(test_dir) == 0); - BOOST_CHECK(ji.base_filename().compare(base_filename) == 0); - const timespec this_ts = ji.ts(); - BOOST_CHECK_EQUAL(this_ts.tv_sec, ts.tv_sec); - BOOST_CHECK_EQUAL(this_ts.tv_nsec, ts.tv_nsec); - BOOST_CHECK_EQUAL(ji.num_jfiles(), u_int16_t(NUM_JFILES)); - BOOST_CHECK_EQUAL(ji.is_ae(), false); - BOOST_CHECK_EQUAL(ji.ae_max_jfiles(), u_int16_t(0)); - BOOST_CHECK_EQUAL(ji.jfsize_sblks(), u_int32_t(JFSIZE_SBLKS)); - BOOST_CHECK_EQUAL(ji.sblk_size_dblks(), u_int16_t(JRNL_SBLK_SIZE)); - BOOST_CHECK_EQUAL(ji.dblk_size(), u_int32_t(JRNL_DBLK_SIZE)); - BOOST_CHECK_EQUAL(ji.wcache_pgsize_sblks(), u_int32_t(JRNL_WMGR_DEF_PAGE_SIZE)); - BOOST_CHECK_EQUAL(ji.wcache_num_pages(), u_int16_t(JRNL_WMGR_DEF_PAGES)); - BOOST_CHECK_EQUAL(ji.rcache_pgsize_sblks(), u_int32_t(JRNL_RMGR_PAGE_SIZE)); - BOOST_CHECK_EQUAL(ji.rcache_num_pages(), u_int16_t(JRNL_RMGR_PAGES)); - ji.write(); - cout << "done" << endl; -} - -QPID_AUTO_TEST_CASE(read_constructor) -{ - string test_name = get_test_name(test_filename, "read_constructor"); - const string jid = test_name + "_jid"; - const string base_filename = test_name + "_bfn"; - lfid_pfid_map::create_new_jinf(jid, base_filename, false); - - stringstream fn; - fn << test_dir << "/" < sblk_buffer(expand_size, 0); - of.write(&sblk_buffer[0], expand_size); - of.close(); - - stringstream fn; - fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION; - jinf ji(fn.str(), false); - try - { - ji.analyze(); - BOOST_FAIL("Failed to detect irregular journal file size in file \"" << filename << "\""); - } - catch (const jexception& e) {} // ignore - expected - - m.destroy_journal(); - } - cout << "done" << endl; -} - -QPID_AUTO_TEST_CASE(analyze_owi_in_non_ae_journal) -{ - string test_name = get_test_name(test_filename, "analyze_owi_in_non_ae_journal"); - const string jid = test_name + "_jid"; - const string base_filename = test_name + "_bfn"; - lfid_pfid_map m(jid, base_filename); - for (u_int16_t oldest_file = 1; oldest_file < NUM_DEFAULT_JFILES-1; oldest_file++) - { - for (u_int16_t bad_owi_file = oldest_file + 1; bad_owi_file < NUM_DEFAULT_JFILES; bad_owi_file++) - { - m.journal_create(NUM_DEFAULT_JFILES, NUM_DEFAULT_JFILES, oldest_file, bad_owi_file); - m.write_journal(false, 0); - - stringstream fn; - fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION; - jinf ji(fn.str(), false); - try - { - ji.analyze(); - BOOST_FAIL("Failed to detect irregular OWI flag in non-ae journal file \"" << fn.str() << "\""); - } - catch (const jexception& e) {} // ignore - expected - - m.destroy_journal(); - } - } - cout << "done" << endl; -} - -QPID_AUTO_TEST_CASE(analyze_owi_in_ae_min_size_journal) -{ - string test_name = get_test_name(test_filename, "analyze_owi_in_ae_min_size_journal"); - const string jid = test_name + "_jid"; - const string base_filename = test_name + "_bfn"; - lfid_pfid_map m(jid, base_filename); - for (u_int16_t oldest_file = 1; oldest_file < NUM_JFILES-1; oldest_file++) - { - for (u_int16_t bad_owi_file = oldest_file + 1; bad_owi_file < NUM_JFILES; bad_owi_file++) - { - m.journal_create(NUM_JFILES, NUM_JFILES, oldest_file, bad_owi_file); - m.write_journal(true, 16); - - stringstream fn; - fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION; - jinf ji(fn.str(), false); - try - { - ji.analyze(); - BOOST_FAIL("Failed to detect irregular OWI flag in min-sized ae journal file \"" << fn.str() << "\""); - } - catch (const jexception& e) {} // ignore - expected - - m.destroy_journal(); - } - } - cout << "done" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp deleted file mode 100644 index 2dc20ffa7c..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_ut_lpmgr.cpp +++ /dev/null @@ -1,886 +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 "../unit_test.h" -#include -#include -#include "qpid/legacystore/jrnl/jcntl.h" -#include "qpid/legacystore/jrnl/lpmgr.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(arr_cnt_suite) - -const string test_filename("_ut_lpmgr"); - -#include "_st_helper_fns.h" - -// === Helper functions and definitions === - -typedef vector flist; -typedef flist::const_iterator flist_citr; - -class lpmgr_test_helper -{ - lpmgr_test_helper() {} - virtual ~lpmgr_test_helper() {} - -public: - static void check_pfids_lfids(const lpmgr& lm, const u_int16_t pfids[], const u_int16_t lfids[], - const size_t pfid_lfid_size) - { - vector res; - lm.get_pfid_list(res); - vectors_equal(lm, pfids, pfid_lfid_size, res, true); - lm.get_lfid_list(res); - vectors_equal(lm, lfids, pfid_lfid_size, res, false); - } - - static void check_pfids_lfids(const lpmgr& lm, const flist& pfids, const flist lfids) - { - vector res; - lm.get_pfid_list(res); - vectors_equal(lm, pfids, res, true); - lm.get_lfid_list(res); - vectors_equal(lm, lfids, res, false); - } - - static void check_linear_pfids_lfids(const lpmgr& lm, const size_t pfid_lfid_size) - { - vector res; - lm.get_pfid_list(res); - linear_vectors_equal(lm, pfid_lfid_size, res, true); - lm.get_lfid_list(res); - linear_vectors_equal(lm, pfid_lfid_size, res, false); - } - - static void rcvdat_init(rcvdat& rd, const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles, - const u_int16_t pfids[]) - { - rd.reset(num_jfiles, ae, ae_max_jfiles); - load_vector(pfids, num_jfiles, rd._fid_list); - rd._jempty = false; - rd._lfid = pfids[num_jfiles - 1]; - rd._eo = 100 * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE; - } - - static void rcvdat_init(rcvdat& rd, const flist& pfidl, const bool ae, const u_int16_t ae_max_jfiles) - { - const u_int16_t num_jfiles = pfidl.size(); - rd.reset(num_jfiles, ae, ae_max_jfiles); - load_vector(pfidl, rd._fid_list); - rd._jempty = false; - rd._lfid = pfidl[num_jfiles - 1]; - rd._eo = 100 * JRNL_DBLK_SIZE * JRNL_SBLK_SIZE; - } - - static void initialize(lpmgr& lm, test_jrnl& jc, const u_int16_t num_jfiles, const bool ae, - const u_int16_t ae_max_jfiles) - { - lm.initialize(num_jfiles, ae, ae_max_jfiles, &jc, &jc.new_fcntl); - BOOST_CHECK_EQUAL(lm.is_init(), true); - BOOST_CHECK_EQUAL(lm.is_ae(), ae); - BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); - BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles); - if (num_jfiles) - check_linear_pfids_lfids(lm, num_jfiles); - else - BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); - } - - // version which sets up the lfid_pfid_map for later manipulation by insert tests - static void initialize(lfid_pfid_map& lfm, lpmgr& lm, test_jrnl& jc, const u_int16_t num_jfiles, const bool ae, - const u_int16_t ae_max_jfiles) - { - lfm.journal_create(num_jfiles, num_jfiles); - initialize(lm, jc, num_jfiles, ae, ae_max_jfiles); - } - - static void prepare_recover(lfid_pfid_map& lfm, const u_int16_t size) - { - if (size < 4) BOOST_FAIL("prepare_recover(): size parameter (" << size << ") too small."); - lfm.journal_create(4, 4); // initial journal of size 4 - u_int16_t s = 4; // cumulative size - while (s < size) - { - const u_int16_t ins_posn = u_int16_t(s * ::drand48()); // this insert posn - if (3.0 * ::drand48() > 1.0 || size - s < 2) // 2:1 chance of single insert when >= 2 still to insert - { - lfm.journal_insert(ins_posn); // single insert - s++; - } - else - { - // multiple insert, either 2 - 5 - const u_int16_t max_ins_size = size - s >5 ? 5 : size - s; - const u_int16_t ins_size = 2 + u_int16_t((max_ins_size - 2) * ::drand48()); // this insert size - lfm.journal_insert(ins_posn, ins_size); - s += ins_size; - } - } - } - - static void recover(lfid_pfid_map& lfm, lpmgr& lm, test_jrnl& jc, const bool ae, const u_int16_t ae_max_jfiles) - { - flist pfidl; - flist lfidl; - rcvdat rd; - const u_int16_t num_jfiles = lfm.size(); - - lfm.get_pfid_list(pfidl); - lfm.get_lfid_list(lfidl); - lm.finalize(); // clear all file handles before erasing old journal files - lfm.write_journal(ae, ae_max_jfiles, JFSIZE_SBLKS); - - lpmgr_test_helper::rcvdat_init(rd, pfidl, ae, ae_max_jfiles); - lm.recover(rd, &jc, &jc.new_fcntl); - BOOST_CHECK_EQUAL(lm.is_init(), true); - BOOST_CHECK_EQUAL(lm.is_ae(), ae); - BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); - BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles); - if (num_jfiles) - check_pfids_lfids(lm, pfidl, lfidl); - else - BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); - } - - static void finalize(lpmgr& lm) - { - lm.finalize(); - BOOST_CHECK_EQUAL(lm.is_init(), false); - BOOST_CHECK_EQUAL(lm.is_ae(), false); - BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), u_int16_t(0)); - BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0)); - BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); - vector res; - lm.get_pfid_list(res); - BOOST_CHECK_EQUAL(res.size(), u_int16_t(0)); - lm.get_lfid_list(res); - BOOST_CHECK_EQUAL(res.size(), u_int16_t(0)); - } - - static void insert(lfid_pfid_map& lfm, lpmgr& lm, test_jrnl& jc, const u_int16_t after_lfid, const u_int16_t incr = 1) - { - flist pfidl; - flist lfidl; - const u_int16_t num_jfiles = lm.num_jfiles(); - lfm.journal_insert(after_lfid, incr); - lfm.get_pfid_list(pfidl); - lfm.get_lfid_list(lfidl); - lm.insert(after_lfid, &jc, &jc.new_fcntl, incr); - BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles + incr); - lpmgr_test_helper::check_pfids_lfids(lm, pfidl, lfidl); - } - - static void check_ae_max_jfiles(lpmgr& lm, const u_int16_t num_jfiles, const u_int16_t ae_max_jfiles) - { - bool legal = ae_max_jfiles > num_jfiles || ae_max_jfiles == 0; - - lm.set_ae(false); - BOOST_CHECK(!lm.is_ae()); - if (legal) - { - lm.set_ae_max_jfiles(ae_max_jfiles); - BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); - lm.set_ae(true); - BOOST_CHECK(lm.is_ae()); - BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), ae_max_jfiles - ? ae_max_jfiles - num_jfiles - : JRNL_MAX_NUM_FILES - num_jfiles); - } - else - { - lm.set_ae_max_jfiles(ae_max_jfiles); - BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); - try - { - lm.set_ae(true); // should raise exception - BOOST_ERROR("Auto-expand enabled with out-of-range ae_max_jfiles"); - } - catch (const jexception& e) { BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_BADAEFNUMLIM); } - BOOST_CHECK(!lm.is_ae()); - BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), 0); - } - BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), ae_max_jfiles); - } - - static void check_multiple_initialization_recover(lfid_pfid_map& lfm, test_jrnl& jc, - const u_int16_t num_jfiles_arr[][2], const bool init_flag_0, const bool finalize_flag, - const bool init_flag_1) - { - unsigned i_njf = 0; - while (num_jfiles_arr[i_njf][0] && num_jfiles_arr[i_njf][1]) // cycle through each entry in num_jfiles_arr - { - for (unsigned i1_njf = 0; i1_njf <= 1; i1_njf++) // cycle through the two numbers in each entry of num_jfiles_arr - { - const u_int16_t num_jfiles_0 = num_jfiles_arr[i_njf][i1_njf == 0]; // first number in pair - const u_int16_t num_jfiles_1 = num_jfiles_arr[i_njf][i1_njf != 0]; // second number in pair - - for (unsigned i_ae = 0; i_ae < 4; i_ae++) // cycle through combinations of enabling AE - { - const bool ae_0 = i_ae & 0x1; // first bit: enable AE on first init - const bool ae_1 = i_ae & 0x2; // second bit: enable AE on second init - for (unsigned i_aemjf = 0; i_aemjf < 4; i_aemjf++) // cycle through combinations of enabling/disabling ae limit - { - const u_int16_t ae_max_jfiles_0 = i_aemjf & 0x1 ? 3 * num_jfiles_0 : 0; // max ae files, 0 = disable max - const u_int16_t ae_max_jfiles_1 = i_aemjf & 0x2 ? 4 * num_jfiles_1 : 0; // max ae files, 0 = disable max - - lpmgr lm; // DUT - - if (init_flag_0) - initialize(lm, jc, num_jfiles_0, ae_0, ae_max_jfiles_0); - else - { - prepare_recover(lfm, num_jfiles_0); - recover(lfm, lm, jc, ae_1, ae_max_jfiles_0); - lfm.destroy_journal(); - } - - if (finalize_flag) finalize(lm); - - if (init_flag_1) - initialize(lm, jc, num_jfiles_1, ae_1, ae_max_jfiles_1); - else - { - prepare_recover(lfm, num_jfiles_1); - recover(lfm, lm, jc, ae_1, ae_max_jfiles_1); - lfm.destroy_journal(); - } - } - } - } - i_njf++; - } - } - - static void check_insert(lfid_pfid_map& lfm, lpmgr& lm, test_jrnl& jc, const u_int16_t after_lfid, - const u_int16_t incr = 1) - { - const u_int16_t num_jfiles = lm.num_jfiles(); - const u_int16_t ae_max_jfiles = lm.ae_max_jfiles(); - const u_int16_t effective_ae_max_jfiles = ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES; - BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles); - bool legal = lm.is_ae() && num_jfiles + incr <= effective_ae_max_jfiles; - if (legal) - { - insert(lfm, lm, jc, after_lfid, incr); - BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles + incr); - BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles - incr); - } - else - { - try - { - insert(lfm, lm, jc, after_lfid, incr); - if (lm.is_ae()) - BOOST_ERROR("lpmgr::insert() succeeded and exceeded limit"); - else - BOOST_ERROR("lpmgr::insert() succeeded with auto-expand disabled"); - } - catch (const jexception& e) - { - if (lm.is_ae()) - BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEFNUMLIMIT); - else - BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEDISABLED); - } - BOOST_CHECK_EQUAL(lm.num_jfiles(), num_jfiles); - BOOST_CHECK_EQUAL(lm.ae_jfiles_rem(), effective_ae_max_jfiles - num_jfiles); - } - } - - static void check_limit(lfid_pfid_map& lfm, test_jrnl& jc, const bool ae, const u_int16_t num_jfiles, - const u_int16_t ae_max_jfiles) - { - lpmgr lm; - - for (unsigned i = 0; i < 2; i++) - { - if (i) - initialize(lfm, lm, jc, num_jfiles, ae, ae_max_jfiles); - else - { - prepare_recover(lfm, num_jfiles); - recover(lfm, lm, jc, ae, ae_max_jfiles); - } - - // use up all available files - unsigned j = ae_max_jfiles ? ae_max_jfiles : JRNL_MAX_NUM_FILES; - while (ae && j > num_jfiles) - { - const u_int16_t posn = static_cast((lm.num_jfiles() - 1) * ::drand48()); - const u_int16_t incr = 1 + static_cast((lm.ae_jfiles_rem() > 4 - ? 3 : lm.ae_jfiles_rem() - 1) * ::drand48()); - check_insert(lfm, lm, jc, posn, incr); - j -= incr; - } - // these should be over the limit or illegal - check_insert(lfm, lm, jc, 0); - check_insert(lfm, lm, jc, 2, 2); - lfm.destroy_journal(); - } - } - -private: - static void load_vector(const u_int16_t a[], const size_t n, flist& v) - { - for (size_t i = 0; i < n; i++) - v.push_back(a[i]); - } - - static void load_vector(const flist& a, flist& b) - { - for (flist_citr i = a.begin(); i < a.end(); i++) - b.push_back(*i); - } - - static void vectors_equal(const lpmgr& lm, const u_int16_t a[], const size_t n, const flist& b, - const bool pfid_check) - { - BOOST_CHECK_EQUAL(n, b.size()); - for (size_t i = 0; i < n; i++) - { - BOOST_CHECK_EQUAL(a[i], b[i]); - fcntl* fp = lm.get_fcntlp(i); - BOOST_CHECK_MESSAGE(fp != (void*)0, "Unexpected void pointer returned by lpmgr::get_fcntlp()"); - if (fp) BOOST_CHECK_EQUAL(pfid_check ? fp->pfid() : fp->lfid(), pfid_check ? a[i] : i); - } - } - - static void vectors_equal(const lpmgr& lm, const flist& a, const flist& b, const bool pfid_check) - { - BOOST_CHECK_EQUAL(a.size(), b.size()); - for (size_t i = 0; i < a.size(); i++) - { - BOOST_CHECK_EQUAL(a[i], b[i]); - fcntl* fp = lm.get_fcntlp(i); - BOOST_CHECK_MESSAGE(fp != (void*)0, "Unexpected void pointer returned by lpmgr::get_fcntlp()"); - if (fp) BOOST_CHECK_EQUAL(pfid_check ? fp->pfid() : fp->lfid(), pfid_check ? a[i] : i); - } - } - - static void linear_vectors_equal(const lpmgr& lm, const size_t n, const flist& f, const bool pfid_check) - { - BOOST_CHECK_EQUAL(n, f.size()); - for (size_t i = 0; i < n; i++) - { - BOOST_CHECK_EQUAL(i, f[i]); - fcntl* fp = lm.get_fcntlp(i); - BOOST_CHECK_MESSAGE(fp != (void*)0, "Unexpected void pointer returned by lpmgr::get_fcntlp()"); - if (fp) BOOST_CHECK_EQUAL(pfid_check ? fp->pfid() : fp->lfid(), i); - } - } -}; - -// === Tests === - -#ifndef LONG_TEST -/* - * ============================================== - * NORMAL TESTS - * This section contains normal "make check" tests - * for building/packaging. These are built when - * LONG_TEST is _not_ defined. - * ============================================== - */ - -/* - * Check that after construction, the fcntl array _fcntl_arr is empty and the is_init() function returns false. - */ -QPID_AUTO_TEST_CASE(default_constructor) -{ - string test_name = get_test_name(test_filename, "default_constructor"); - try - { - lpmgr lm; - BOOST_CHECK_EQUAL(lm.is_init(), false); - BOOST_CHECK_EQUAL(lm.is_ae(), false); - BOOST_CHECK_EQUAL(lm.ae_max_jfiles(), u_int16_t(0)); - BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0)); - BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that initialize() correctly creates an ordered fcntl array _fcntl_arr. - */ -QPID_AUTO_TEST_CASE(initialize) -{ - string test_name = get_test_name(test_filename, "initialize"); - const u_int16_t num_jfiles = 8; - try - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - { - lpmgr lm; - lpmgr_test_helper::initialize(lm, jc, num_jfiles, false, 0); - } - { - lpmgr lm; - lpmgr_test_helper::initialize(lm, jc, num_jfiles, true, 0); - } - { - lpmgr lm; - lpmgr_test_helper::initialize(lm, jc, num_jfiles, true, 5 * num_jfiles); - } - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that recover() correctly sets up the specified pfid list order. - */ -QPID_AUTO_TEST_CASE(recover) -{ - string test_name = get_test_name(test_filename, "recover"); - ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() - try - { - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - - { - lpmgr lm; - lpmgr_test_helper::prepare_recover(lfm, 8); - lpmgr_test_helper::recover(lfm, lm, jc, false, 0); - lfm.destroy_journal(); - } - { - lpmgr lm; - lpmgr_test_helper::prepare_recover(lfm, 8); - lpmgr_test_helper::recover(lfm, lm, jc, true, 0); - lfm.destroy_journal(); - } - { - lpmgr lm; - lpmgr_test_helper::prepare_recover(lfm, 8); - lpmgr_test_helper::recover(lfm, lm, jc, true, 5 * lfm.size()); - lfm.destroy_journal(); - } - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that finalize() after an initialize() empties _fcntl_arr and that afterwards is_init() returns false. - */ -QPID_AUTO_TEST_CASE(initialize_finalize) -{ - string test_name = get_test_name(test_filename, "initialize_finalize"); - const u_int16_t num_jfiles = 8; - try - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - { - lpmgr lm; - lpmgr_test_helper::initialize(lm, jc, num_jfiles, false, 0); - lpmgr_test_helper::finalize(lm); - } - { - lpmgr lm; - lpmgr_test_helper::initialize(lm, jc, num_jfiles, true, 0); - lpmgr_test_helper::finalize(lm); - } - { - lpmgr lm; - lpmgr_test_helper::initialize(lm, jc, num_jfiles, true, 5 * num_jfiles); - lpmgr_test_helper::finalize(lm); - } - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that finalize() after a recover() empties _fcntl_arr and that afterwards is_init() returns false. - */ -QPID_AUTO_TEST_CASE(recover_finalize) -{ - string test_name = get_test_name(test_filename, "recover_finalize"); - const u_int16_t num_jfiles = 8; - ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() - try - { - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - - { - lpmgr lm; - lpmgr_test_helper::prepare_recover(lfm, num_jfiles); - lpmgr_test_helper::recover(lfm, lm, jc, false, 0); - lpmgr_test_helper::finalize(lm); - lfm.destroy_journal(); - } - { - lpmgr lm; - lpmgr_test_helper::prepare_recover(lfm, num_jfiles); - lpmgr_test_helper::recover(lfm, lm, jc, true, 0); - lpmgr_test_helper::finalize(lm); - lfm.destroy_journal(); - } - { - lpmgr lm; - lpmgr_test_helper::prepare_recover(lfm, num_jfiles); - lpmgr_test_helper::recover(lfm, lm, jc, true, 5 * lfm.size()); - lpmgr_test_helper::finalize(lm); - lfm.destroy_journal(); - } - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that 0 and/or null and other extreme/boundary parameters behave as expected. - */ -QPID_AUTO_TEST_CASE(zero_null_params) -{ - string test_name = get_test_name(test_filename, "zero_null_params"); - const u_int16_t num_jfiles = 8; - try - { - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - lpmgr lm; - lpmgr_test_helper::initialize(lfm, lm, jc, num_jfiles, true, 0); - - // Check that inserting 0 files works ok - lpmgr_test_helper::insert(lfm, lm, jc, 0, 0); - lpmgr_test_helper::insert(lfm, lm, jc, 2, 0); - lpmgr_test_helper::insert(lfm, lm, jc, num_jfiles - 1, 0); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that initialize()/recover() works correctly after a previous initialize()/recover() with/without an intervening - * finalize(). - */ -QPID_AUTO_TEST_CASE(multiple_initialization_recover) -{ - string test_name = get_test_name(test_filename, "multiple_initialization_recover"); - ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() - - // Set combinations of value pairs to be used for number of journal files in first and second init - u_int16_t num_jfiles_arr[][2] = {{8, 12}, {4, 7}, {0, 0}}; // end with zeros - try - { - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - for (unsigned p = 0; p < 8; p++) - { - const bool i_0 = p & 0x01; // first bit - const bool i_1 = p & 0x02; // second bit - const bool f = p & 0x04; // third bit - lpmgr_test_helper::check_multiple_initialization_recover(lfm, jc, num_jfiles_arr, i_0, f, i_1); - } - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that insert() works correctly after initialize() and shifts the pfid sequence beyond the insert point correctly: - * - * The following sequence is tested: - * initialize 4 pfids=[0,1,2,3] lfids=[0,1,2,3] - * insert 1 after lfid 0 pfids=[0,4,1,2,3] lfids=[0,2,3,4,1] - * insert 2 after lfid 2 pfids=[0,4,1,5,6,2,3] lfids=[0,2,5,6,1,3,4] - * insert 1 after lfid 6 pfids=[0,4,1,5,6,2,3,7] lfids=[0,2,5,6,1,3,4,7] - * issert 1 after lfid 3 pfids=[0,4,1,5,8,6,2,3,7] lfids=[0,2,6,7,1,3,5,8,4] - */ -QPID_AUTO_TEST_CASE(initialize_insert) -{ - string test_name = get_test_name(test_filename, "initialize_insert"); - const u_int16_t initial_num_jfiles = 8; - try - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - lpmgr lm; - lpmgr_test_helper::initialize(lfm, lm, jc, initial_num_jfiles, true, 0); - - lpmgr_test_helper::insert(lfm, lm, jc, 0); - lpmgr_test_helper::insert(lfm, lm, jc, 2, 2); - lpmgr_test_helper::insert(lfm, lm, jc, 6); - lpmgr_test_helper::insert(lfm, lm, jc, 3); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that insert() works correctly after recover() and shifts the pfid sequence beyond the insert point correctly: - * - * The following sequence is tested: - * recover 4 pfids=[0,2,3,1] lfids=[0,3,1,2] - * insert 1 after lfid 0 pfids=[0,4,2,3,1] lfids=[0,4,2,3,1] - * insert 2 after lfid 2 pfids=[0,4,2,5,6,3,1] lfids=[0,6,2,5,1,3,4] - * insert 1 after lfid 6 pfids=[0,4,2,5,6,3,1,7] lfids=[0,6,2,5,1,3,4,7] - * issert 1 after lfid 3 pfids=[0,4,2,5,8,6,3,1,7] lfids=[0,7,2,6,1,3,5,8,4] - */ -QPID_AUTO_TEST_CASE(recover_insert) -{ - string test_name = get_test_name(test_filename, "recover_insert"); - const u_int16_t initial_num_jfiles = 4; - ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() - try - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - lpmgr lm; - lpmgr_test_helper::prepare_recover(lfm, initial_num_jfiles); - lpmgr_test_helper::recover(lfm, lm, jc, true, 0); - - lpmgr_test_helper::insert(lfm, lm, jc, 0); - lpmgr_test_helper::insert(lfm, lm, jc, 2, 2); - lpmgr_test_helper::insert(lfm, lm, jc, 6); - lpmgr_test_helper::insert(lfm, lm, jc, 3); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that illegal ae parameter combinations are caught and result in an exception being thrown. - */ -QPID_AUTO_TEST_CASE(ae_parameters) -{ - string test_name = get_test_name(test_filename, "ae_parameters"); - ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() - try - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - const u_int16_t num_jfiles = 8; - lpmgr lm; - - for (unsigned i = 0; i < 2; i++) - { - if (i) - lpmgr_test_helper::initialize(lfm, lm, jc, num_jfiles, false, 0); - else - { - lpmgr_test_helper::prepare_recover(lfm, num_jfiles); - lpmgr_test_helper::recover(lfm, lm, jc, false, 0); - } - - lpmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, num_jfiles - 2); - lpmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, 0); - lpmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, 2 * num_jfiles); - lpmgr_test_helper::check_ae_max_jfiles(lm, num_jfiles, num_jfiles); - lfm.destroy_journal(); - } - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that initialized or recovered journals with auto-expand disabled will not allow either inserts or appends. - */ -QPID_AUTO_TEST_CASE(ae_disabled) -{ - string test_name = get_test_name(test_filename, "ae_disabled"); - ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() - try - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - lpmgr_test_helper::check_limit(lfm, jc, false, 8, 0); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that initialized or recovered journals with auto-expand enabled and a file limit set will enforce the correct - * limits on inserts and appends. - */ -QPID_AUTO_TEST_CASE(ae_enabled_limit) -{ - string test_name = get_test_name(test_filename, "ae_enabled_limit"); - ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() - try - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - lpmgr_test_helper::check_limit(lfm, jc, true, 8, 32); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -/* - * Check that initialized or recovered journals with auto-expand enabled and no file limit set (0) will allow inserts and - * appends up to the file limit JRNL_MAX_NUM_FILES. - */ -QPID_AUTO_TEST_CASE(ae_enabled_unlimited) -{ - string test_name = get_test_name(test_filename, "ae_enabled_unlimited"); - ::srand48(1); // init random gen for repeatable tests when using lpmgr_test_helper::prepare_recover() - try - { - jdir::create_dir(test_dir); // Check test dir exists; create it if not - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lfid_pfid_map lfm(test_name, test_name); - lpmgr_test_helper::check_limit(lfm, jc, true, 8, 0); - } - catch(const exception& e) { BOOST_FAIL(e.what()); } - cout << "done" << endl; -} - -#else -/* - * ============================================== - * LONG TESTS - * This section contains long tests and soak tests, - * and are run using target check-long (ie "make - * check-long"). These are built when LONG_TEST is - * defined. - * ============================================== - */ - -/* - * Tests randomized combinations of initialization/recovery, initial size, number, size and location of inserts. - * - * To reproduce a specific test, comment out the get_seed() statement and uncomment the literal below, adjusting the seed - * value to that required. - */ -QPID_AUTO_TEST_CASE(randomized_tests) -{ - string test_name = get_test_name(test_filename, "randomized_tests"); - const long seed = get_seed(); - // const long seed = 0x2d9b69d32; - cout << "seed=0x" << hex << seed << dec << " " << flush; - ::srand48(seed); - - lfid_pfid_map lfm(test_name, test_name); - flist pfidl; - flist lfidl; - rcvdat rd; - u_int16_t curr_ae_max_jfiles = 0; - jdir::create_dir(test_dir); // Check test dir exists; create it if not - - for (int test_num = 0; test_num < 250; test_num++) - { - test_jrnl_cb cb; - test_jrnl jc(test_name, test_dir, test_name, cb); - lpmgr lm; - // 50% chance of recovery except first run and if there is still ae space left - const bool recover_flag = test_num > 0 && - curr_ae_max_jfiles > lfm.size() && - 2.0 * ::drand48() < 1.0; - if (recover_flag) - { - // Recover from previous iteration - lfm.get_pfid_list(pfidl); - lfm.get_lfid_list(lfidl); - lfm.write_journal(true, curr_ae_max_jfiles, JFSIZE_SBLKS); - lpmgr_test_helper::rcvdat_init(rd, pfidl, true, curr_ae_max_jfiles); - lm.recover(rd, &jc, &jc.new_fcntl); - lpmgr_test_helper::check_pfids_lfids(lm, pfidl, lfidl); - } - else - { - // Initialize from scratch - const u_int16_t num_jfiles = 4 + u_int16_t(21.0 * ::drand48()); // size: 4 - 25 files - curr_ae_max_jfiles = u_int16_t(4 * num_jfiles * ::drand48()); // size: 0 - 100 files - if (curr_ae_max_jfiles > JRNL_MAX_NUM_FILES) curr_ae_max_jfiles = JRNL_MAX_NUM_FILES; - else if (curr_ae_max_jfiles <= num_jfiles) curr_ae_max_jfiles = 0; - lfm.destroy_journal(); - lfm.journal_create(num_jfiles, num_jfiles); - lfm.get_pfid_list(pfidl); - lfm.get_lfid_list(lfidl); - lm.initialize(num_jfiles, true, curr_ae_max_jfiles, &jc, &jc.new_fcntl); - lpmgr_test_helper::check_linear_pfids_lfids(lm, num_jfiles); - } - - // Loop to insert pfids - const int num_inserts = 1 + int(lfm.size() * ::drand48()); - for (int i = 0; i < num_inserts; i++) - { - const u_int16_t size = lm.num_jfiles(); - const u_int16_t after_lfid = u_int16_t(1.0 * size * ::drand48()); - const u_int16_t num_jfiles = 1 + u_int16_t(4.0 * ::drand48()); - const bool legal = lm.ae_max_jfiles() - ? size + num_jfiles <= lm.ae_max_jfiles() - : size + num_jfiles <= JRNL_MAX_NUM_FILES; - if (legal) - { - lfm.journal_insert(after_lfid, num_jfiles); - lfm.get_pfid_list(pfidl); - lfm.get_lfid_list(lfidl); - - lm.insert(after_lfid, &jc, &jc.new_fcntl, num_jfiles); - lpmgr_test_helper::check_pfids_lfids(lm, pfidl, lfidl); - } - else - { - try - { - lm.insert(after_lfid, &jc, &jc.new_fcntl, num_jfiles); - BOOST_FAIL("lpmgr::insert() succeeded and exceeded limit"); - } - catch (const jexception& e) - { - BOOST_CHECK_EQUAL(e.err_code(), jerrno::JERR_LFMGR_AEFNUMLIMIT); - break; // no more inserts... - } - } - } - lm.finalize(); - BOOST_CHECK_EQUAL(lm.is_init(), false); - BOOST_CHECK_EQUAL(lm.num_jfiles(), u_int16_t(0)); - BOOST_CHECK_EQUAL(lm.get_fcntlp(0), (void*)0); - } - cout << "done" << endl; -} - -#endif - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_ut_rec_hdr.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_ut_rec_hdr.cpp deleted file mode 100644 index 099e576bbd..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_ut_rec_hdr.cpp +++ /dev/null @@ -1,438 +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 "../unit_test.h" - -#include -#include -#include "qpid/legacystore/jrnl/deq_hdr.h" -#include "qpid/legacystore/jrnl/enq_hdr.h" -#include "qpid/legacystore/jrnl/file_hdr.h" -#include "qpid/legacystore/jrnl/jcfg.h" -#include "qpid/legacystore/jrnl/rec_tail.h" -#include "qpid/legacystore/jrnl/txn_hdr.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(rec_hdr_suite) - -const string test_filename("_ut_rec_hdr"); - -QPID_AUTO_TEST_CASE(hdr_class) -{ - cout << test_filename << ".hdr_class: " << flush; - rec_hdr h1; - BOOST_CHECK_EQUAL(h1._magic, 0UL); - BOOST_CHECK_EQUAL(h1._version, 0); - BOOST_CHECK_EQUAL(h1._eflag, 0); - BOOST_CHECK_EQUAL(h1._uflag, 0); - BOOST_CHECK_EQUAL(h1._rid, 0ULL); - BOOST_CHECK(!h1.get_owi()); - - const u_int32_t magic = 0x89abcdefUL; - const u_int16_t uflag = 0x5537; - const u_int8_t version = 0xef; - const u_int64_t rid = 0x123456789abcdef0ULL; - const bool owi = true; - - rec_hdr h2(magic, version, rid, owi); - BOOST_CHECK_EQUAL(h2._magic, magic); - BOOST_CHECK_EQUAL(h2._version, version); -#ifdef JRNL_LITTLE_ENDIAN - BOOST_CHECK_EQUAL(h2._eflag, RHM_LENDIAN_FLAG); -#else - BOOST_CHECK_EQUAL(h2._eflag, RHM_BENDIAN_FLAG); -#endif - BOOST_CHECK_EQUAL(h2._uflag, (const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK); - BOOST_CHECK_EQUAL(h2._rid, rid); - BOOST_CHECK_EQUAL(h2.get_owi(), owi); - h2._uflag = uflag; - BOOST_CHECK(h2.get_owi()); - h2.set_owi(true); - BOOST_CHECK(h2.get_owi()); - BOOST_CHECK_EQUAL(h2._uflag, uflag); - h2.set_owi(false); - BOOST_CHECK(!h2.get_owi()); - BOOST_CHECK_EQUAL(h2._uflag, (uflag & ~(const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK)); - h2.set_owi(true); - BOOST_CHECK(h2.get_owi()); - BOOST_CHECK_EQUAL(h2._uflag, uflag); - - h1.hdr_copy(h2); - BOOST_CHECK_EQUAL(h1._magic, magic); - BOOST_CHECK_EQUAL(h1._version, version); -#ifdef JRNL_LITTLE_ENDIAN - BOOST_CHECK_EQUAL(h1._eflag, RHM_LENDIAN_FLAG); -#else - BOOST_CHECK_EQUAL(h1._eflag, RHM_BENDIAN_FLAG); -#endif - BOOST_CHECK_EQUAL(h1._uflag, uflag); - BOOST_CHECK_EQUAL(h1._rid, rid); - BOOST_CHECK(h1.get_owi()); - BOOST_CHECK_EQUAL(h1._uflag, uflag); - - h1.reset(); - BOOST_CHECK_EQUAL(h1._magic, 0UL); - BOOST_CHECK_EQUAL(h1._version, 0); - BOOST_CHECK_EQUAL(h1._eflag, 0); - BOOST_CHECK_EQUAL(h1._uflag, 0); - BOOST_CHECK_EQUAL(h1._rid, 0ULL); - BOOST_CHECK(!h1.get_owi()); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(rec_tail_class) -{ - cout << test_filename << ".rec_tail_class: " << flush; - const u_int32_t magic = 0xfedcba98; - const u_int64_t rid = 0xfedcba9876543210ULL; - const u_int32_t xmagic = ~magic; - - { - rec_tail rt1; - BOOST_CHECK_EQUAL(rt1._xmagic, 0xffffffffUL); - BOOST_CHECK_EQUAL(rt1._rid, 0ULL); - } - - { - rec_tail rt2(magic, rid); - BOOST_CHECK_EQUAL(rt2._xmagic, magic); - BOOST_CHECK_EQUAL(rt2._rid, rid); - } - - { - rec_hdr h(magic, RHM_JDAT_VERSION, rid, true); - rec_tail rt3(h); - BOOST_CHECK_EQUAL(rt3._xmagic, xmagic); - BOOST_CHECK_EQUAL(rt3._rid, rid); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(file_hdr_class) -{ - cout << test_filename << ".file_hdr_class: " << flush; - const u_int32_t magic = 0xfedcba98UL; - const u_int8_t version = 0xa5; - const u_int16_t uflag = 0x5537; - const u_int64_t rid = 0xfedcba9876543210ULL; - const u_int16_t pfid = 0xfedcU; - const u_int16_t lfid = 0xf0e1U; -#ifdef JRNL_32_BIT - const std::size_t fro = 0xfedcba98UL; -#else - const std::size_t fro = 0xfedcba9876543210ULL; -#endif - timespec ts; - const bool owi = true; - - { - file_hdr fh1; - BOOST_CHECK_EQUAL(fh1._magic, 0UL); - BOOST_CHECK_EQUAL(fh1._version, 0); - BOOST_CHECK_EQUAL(fh1._eflag, 0); - BOOST_CHECK_EQUAL(fh1._uflag, 0); - BOOST_CHECK_EQUAL(fh1._rid, 0ULL); - BOOST_CHECK_EQUAL(fh1._pfid, 0UL); - BOOST_CHECK_EQUAL(fh1._lfid, 0U); - BOOST_CHECK_EQUAL(fh1._fro, std::size_t(0)); - BOOST_CHECK_EQUAL(fh1._ts_sec, std::time_t(0)); - BOOST_CHECK_EQUAL(fh1._ts_nsec, u_int32_t(0)); - BOOST_CHECK(!fh1.get_owi()); - } - - { - file_hdr fh2(magic, version, rid, pfid, lfid, fro, owi, false); - BOOST_CHECK_EQUAL(fh2._magic, magic); - BOOST_CHECK_EQUAL(fh2._version, version); -#ifdef JRNL_LITTLE_ENDIAN - BOOST_CHECK_EQUAL(fh2._eflag, RHM_LENDIAN_FLAG); -#else - BOOST_CHECK_EQUAL(fh2._eflag, RHM_BENDIAN_FLAG); -#endif - BOOST_CHECK_EQUAL(fh2._uflag, (const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK); - BOOST_CHECK_EQUAL(fh2._rid, rid); - BOOST_CHECK_EQUAL(fh2._pfid, pfid ); - BOOST_CHECK_EQUAL(fh2._lfid, lfid); - BOOST_CHECK_EQUAL(fh2._fro, fro); - BOOST_CHECK_EQUAL(fh2._ts_sec, std::time_t(0)); - BOOST_CHECK_EQUAL(fh2._ts_nsec, u_int32_t(0)); - ::clock_gettime(CLOCK_REALTIME, &ts); - fh2.set_time(ts); - BOOST_CHECK_EQUAL(fh2._ts_sec, ts.tv_sec); - BOOST_CHECK_EQUAL(fh2._ts_nsec, u_int32_t(ts.tv_nsec)); - BOOST_CHECK(fh2.get_owi()); - - fh2._uflag = uflag; - BOOST_CHECK(fh2.get_owi()); - - fh2.set_owi(false); - BOOST_CHECK(!fh2.get_owi()); - BOOST_CHECK_EQUAL(fh2._uflag, - (uflag & ~(const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK)); - - fh2.set_owi(true); - BOOST_CHECK(fh2.get_owi()); - BOOST_CHECK_EQUAL(fh2._uflag, uflag); - } - - { - file_hdr fh3(magic, version, rid, pfid, lfid, fro, owi, true); - BOOST_CHECK_EQUAL(fh3._magic, magic); - BOOST_CHECK_EQUAL(fh3._version, version); -#ifdef JRNL_LITTLE_ENDIAN - BOOST_CHECK_EQUAL(fh3._eflag, RHM_LENDIAN_FLAG); -#else - BOOST_CHECK_EQUAL(fh3._eflag, RHM_BENDIAN_FLAG); -#endif - BOOST_CHECK_EQUAL(fh3._uflag, (const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK); - BOOST_CHECK_EQUAL(fh3._rid, rid); - BOOST_CHECK_EQUAL(fh3._pfid, pfid); - BOOST_CHECK_EQUAL(fh3._lfid, lfid); - BOOST_CHECK_EQUAL(fh3._fro, fro); - BOOST_CHECK(fh3._ts_sec - ts.tv_sec <= 1); // No more than 1 sec difference - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(enq_hdr_class) -{ - cout << test_filename << ".enq_hdr_class: " << flush; - const u_int32_t magic = 0xfedcba98UL; - const u_int8_t version = 0xa5; - const u_int64_t rid = 0xfedcba9876543210ULL; - const u_int16_t uflag = 0x5537; -#ifdef JRNL_32_BIT - const std::size_t xidsize = 0xfedcba98UL; - const std::size_t dsize = 0x76543210UL; -#else - const std::size_t xidsize = 0xfedcba9876543210ULL; - const std::size_t dsize = 0x76543210fedcba98ULL; -#endif - const bool owi = true; - - { - enq_hdr eh1; - BOOST_CHECK_EQUAL(eh1._magic, 0UL); - BOOST_CHECK_EQUAL(eh1._version, 0); - BOOST_CHECK_EQUAL(eh1._eflag, 0); - BOOST_CHECK_EQUAL(eh1._uflag, 0); - BOOST_CHECK_EQUAL(eh1._rid, 0ULL); - BOOST_CHECK_EQUAL(eh1._xidsize, std::size_t(0)); - BOOST_CHECK_EQUAL(eh1._dsize, std::size_t(0)); - BOOST_CHECK(!eh1.get_owi()); - } - - { - enq_hdr eh2(magic, version, rid, xidsize, dsize, owi, false); - BOOST_CHECK_EQUAL(eh2._magic, magic); - BOOST_CHECK_EQUAL(eh2._version, version); -#ifdef JRNL_LITTLE_ENDIAN - BOOST_CHECK_EQUAL(eh2._eflag, RHM_LENDIAN_FLAG); -#else - BOOST_CHECK_EQUAL(eh2._eflag, RHM_BENDIAN_FLAG); -#endif - BOOST_CHECK_EQUAL(eh2._uflag, (const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK); - BOOST_CHECK_EQUAL(eh2._rid, rid); - BOOST_CHECK_EQUAL(eh2._xidsize, xidsize); - BOOST_CHECK_EQUAL(eh2._dsize, dsize); - BOOST_CHECK(eh2.get_owi()); - BOOST_CHECK(!eh2.is_transient()); - BOOST_CHECK(!eh2.is_external()); - - eh2._uflag = uflag; - BOOST_CHECK(eh2.get_owi()); - BOOST_CHECK(eh2.is_transient()); - BOOST_CHECK(eh2.is_external()); - - eh2.set_owi(false); - BOOST_CHECK(!eh2.get_owi()); - BOOST_CHECK(eh2.is_transient()); - BOOST_CHECK(eh2.is_external()); - BOOST_CHECK_EQUAL(eh2._uflag, - (uflag & ~(const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK)); - - eh2.set_owi(true); - BOOST_CHECK(eh2.get_owi()); - BOOST_CHECK(eh2.is_transient()); - BOOST_CHECK(eh2.is_external()); - BOOST_CHECK_EQUAL(eh2._uflag, uflag); - - eh2.set_transient(false); - BOOST_CHECK(eh2.get_owi()); - BOOST_CHECK(!eh2.is_transient()); - BOOST_CHECK(eh2.is_external()); - BOOST_CHECK_EQUAL(eh2._uflag, uflag & ~(const u_int16_t)enq_hdr::ENQ_HDR_TRANSIENT_MASK); - - eh2.set_transient(true); - BOOST_CHECK(eh2.get_owi()); - BOOST_CHECK(eh2.is_transient()); - BOOST_CHECK(eh2.is_external()); - BOOST_CHECK_EQUAL(eh2._uflag, uflag); - - eh2.set_external(false); - BOOST_CHECK(eh2.get_owi()); - BOOST_CHECK(eh2.is_transient()); - BOOST_CHECK(!eh2.is_external()); - BOOST_CHECK_EQUAL(eh2._uflag, uflag & ~(const u_int16_t)enq_hdr::ENQ_HDR_EXTERNAL_MASK); - - eh2.set_external(true); - BOOST_CHECK(eh2.get_owi()); - BOOST_CHECK(eh2.is_transient()); - BOOST_CHECK(eh2.is_external()); - BOOST_CHECK_EQUAL(eh2._uflag, uflag); - } - - { - enq_hdr eh3(magic, version, rid, xidsize, dsize, owi, true); - BOOST_CHECK_EQUAL(eh3._magic, magic); - BOOST_CHECK_EQUAL(eh3._version, version); -#ifdef JRNL_LITTLE_ENDIAN - BOOST_CHECK_EQUAL(eh3._eflag, RHM_LENDIAN_FLAG); -#else - BOOST_CHECK_EQUAL(eh3._eflag, RHM_BENDIAN_FLAG); -#endif - BOOST_CHECK_EQUAL(eh3._uflag, (const u_int16_t)enq_hdr::ENQ_HDR_TRANSIENT_MASK | - (const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK); - BOOST_CHECK_EQUAL(eh3._rid, rid); - BOOST_CHECK_EQUAL(eh3._xidsize, xidsize); - BOOST_CHECK_EQUAL(eh3._dsize, dsize); - BOOST_CHECK(eh3.get_owi()); - BOOST_CHECK(eh3.is_transient()); - BOOST_CHECK(!eh3.is_external()); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(deq_hdr_class) -{ - cout << test_filename << ".deq_hdr_class: " << flush; - const u_int32_t magic = 0xfedcba98UL; - const u_int8_t version = 0xa5; - const u_int16_t uflag = 0x5537; - const u_int64_t rid = 0xfedcba9876543210ULL; - const u_int64_t drid = 0x76543210fedcba98ULL; -#ifdef JRNL_32_BIT - const std::size_t xidsize = 0xfedcba98UL; -#else - const std::size_t xidsize = 0xfedcba9876543210ULL; -#endif - const bool owi = true; - - { - deq_hdr dh1; - BOOST_CHECK_EQUAL(dh1._magic, 0UL); - BOOST_CHECK_EQUAL(dh1._version, 0); - BOOST_CHECK_EQUAL(dh1._eflag, 0); - BOOST_CHECK_EQUAL(dh1._uflag, 0); - BOOST_CHECK_EQUAL(dh1._rid, 0ULL); - BOOST_CHECK_EQUAL(dh1._deq_rid, 0ULL); - BOOST_CHECK_EQUAL(dh1._xidsize, std::size_t(0)); - BOOST_CHECK(!dh1.get_owi()); - } - - { - deq_hdr dh2(magic, version, rid, drid, xidsize, owi); - BOOST_CHECK_EQUAL(dh2._magic, magic); - BOOST_CHECK_EQUAL(dh2._version, version); -#ifdef JRNL_LITTLE_ENDIAN - BOOST_CHECK_EQUAL(dh2._eflag, RHM_LENDIAN_FLAG); -#else - BOOST_CHECK_EQUAL(dh2._eflag, RHM_BENDIAN_FLAG); -#endif - BOOST_CHECK_EQUAL(dh2._uflag, (const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK); - BOOST_CHECK_EQUAL(dh2._rid, rid); - BOOST_CHECK_EQUAL(dh2._deq_rid, drid); - BOOST_CHECK_EQUAL(dh2._xidsize, xidsize); - BOOST_CHECK(dh2.get_owi()); - - dh2._uflag = uflag; - BOOST_CHECK(dh2.get_owi()); - - dh2.set_owi(false); - BOOST_CHECK(!dh2.get_owi()); - BOOST_CHECK_EQUAL(dh2._uflag, - (uflag & ~(const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK)); - - dh2.set_owi(true); - BOOST_CHECK(dh2.get_owi()); - BOOST_CHECK_EQUAL(dh2._uflag, uflag); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(txn_hdr_class) -{ - cout << test_filename << ".txn_hdr_class: " << flush; - const u_int32_t magic = 0xfedcba98UL; - const u_int8_t version = 0xa5; - const u_int16_t uflag = 0x5537; - const u_int64_t rid = 0xfedcba9876543210ULL; -#ifdef JRNL_32_BIT - const std::size_t xidsize = 0xfedcba98UL; -#else - const std::size_t xidsize = 0xfedcba9876543210ULL; -#endif - const bool owi = true; - - { - txn_hdr th1; - BOOST_CHECK_EQUAL(th1._magic, 0UL); - BOOST_CHECK_EQUAL(th1._version, 0); - BOOST_CHECK_EQUAL(th1._eflag, 0); - BOOST_CHECK_EQUAL(th1._uflag, 0); - BOOST_CHECK_EQUAL(th1._rid, 0ULL); - BOOST_CHECK_EQUAL(th1._xidsize, std::size_t(0)); - BOOST_CHECK(!th1.get_owi()); - } - - { - txn_hdr th2(magic, version, rid, xidsize, owi); - BOOST_CHECK_EQUAL(th2._magic, magic); - BOOST_CHECK_EQUAL(th2._version, version); -#ifdef JRNL_LITTLE_ENDIAN - BOOST_CHECK_EQUAL(th2._eflag, RHM_LENDIAN_FLAG); -#else - BOOST_CHECK_EQUAL(th2._eflag, RHM_BENDIAN_FLAG); -#endif - BOOST_CHECK_EQUAL(th2._uflag, (const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK); - BOOST_CHECK_EQUAL(th2._rid, rid); - BOOST_CHECK_EQUAL(th2._xidsize, xidsize); - BOOST_CHECK(th2.get_owi()); - - th2._uflag = uflag; - BOOST_CHECK(th2.get_owi()); - - th2.set_owi(false); - BOOST_CHECK(!th2.get_owi()); - BOOST_CHECK_EQUAL(th2._uflag, - (uflag & ~(const u_int16_t)rec_hdr::HDR_OVERWRITE_INDICATOR_MASK)); - - th2.set_owi(true); - BOOST_CHECK(th2.get_owi()); - BOOST_CHECK_EQUAL(th2._uflag, uflag); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_ut_time_ns.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_ut_time_ns.cpp deleted file mode 100644 index f1b53bb97b..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_ut_time_ns.cpp +++ /dev/null @@ -1,163 +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 "../unit_test.h" - -#include -#include -#include "qpid/legacystore/jrnl/time_ns.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(time_ns_suite) - -const string test_filename("_ut_time_ns"); - -QPID_AUTO_TEST_CASE(constructors) -{ - cout << test_filename << ".constructors: " << flush; - const std::time_t sec = 123; - const long nsec = 123456789; - - time_ns t1; - BOOST_CHECK_EQUAL(t1.tv_sec, 0); - BOOST_CHECK_EQUAL(t1.tv_nsec, 0); - BOOST_CHECK_EQUAL(t1.is_zero(), true); - time_ns t2(sec, nsec); - BOOST_CHECK_EQUAL(t2.tv_sec, sec); - BOOST_CHECK_EQUAL(t2.tv_nsec, nsec); - BOOST_CHECK_EQUAL(t2.is_zero(), false); - time_ns t3(t1); - BOOST_CHECK_EQUAL(t3.tv_sec, 0); - BOOST_CHECK_EQUAL(t3.tv_nsec, 0); - BOOST_CHECK_EQUAL(t3.is_zero(), true); - time_ns t4(t2); - BOOST_CHECK_EQUAL(t4.tv_sec, sec); - BOOST_CHECK_EQUAL(t4.tv_nsec, nsec); - BOOST_CHECK_EQUAL(t4.is_zero(), false); - t4.set_zero(); - BOOST_CHECK_EQUAL(t4.tv_sec, 0); - BOOST_CHECK_EQUAL(t4.tv_nsec, 0); - BOOST_CHECK_EQUAL(t4.is_zero(), true); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(operators) -{ - cout << test_filename << ".operators: " << flush; - const std::time_t sec1 = 123; - const long nsec1 = 123456789; - const std::time_t sec2 = 1; - const long nsec2 = 999999999; - const std::time_t sec_sum = sec1 + sec2 + 1; - const long nsec_sum = nsec1 + nsec2 - 1000000000; - const std::time_t sec_1_minus_2 = sec1 - sec2 - 1; - const long nsec_1_minus_2 = nsec1 - nsec2 + 1000000000; - const std::time_t sec_2_minus_1 = sec2 - sec1; - const long nsec_2_minus_1 = nsec2 - nsec1; - time_ns z; - time_ns t1(sec1, nsec1); - time_ns t2(sec2, nsec2); - - time_ns t3 = z; - BOOST_CHECK_EQUAL(t3.tv_sec, 0); - BOOST_CHECK_EQUAL(t3.tv_nsec, 0); - BOOST_CHECK_EQUAL(t3 == z, true); - BOOST_CHECK_EQUAL(t3 != z, false); - BOOST_CHECK_EQUAL(t3 > z, false); - BOOST_CHECK_EQUAL(t3 >= z, true); - BOOST_CHECK_EQUAL(t3 < z, false); - BOOST_CHECK_EQUAL(t3 <= z, true); - - t3 = t1; - BOOST_CHECK_EQUAL(t3.tv_sec, sec1); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec1); - BOOST_CHECK_EQUAL(t3 == t1, true); - BOOST_CHECK_EQUAL(t3 != t1, false); - BOOST_CHECK_EQUAL(t3 > t1, false); - BOOST_CHECK_EQUAL(t3 >= t1, true); - BOOST_CHECK_EQUAL(t3 < t1, false); - BOOST_CHECK_EQUAL(t3 <= t1, true); - - t3 += z; - BOOST_CHECK_EQUAL(t3.tv_sec, sec1); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec1); - - t3 = t2; - BOOST_CHECK_EQUAL(t3.tv_sec, sec2); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec2); - BOOST_CHECK_EQUAL(t3 == t2, true); - BOOST_CHECK_EQUAL(t3 != t2, false); - BOOST_CHECK_EQUAL(t3 > t2, false); - BOOST_CHECK_EQUAL(t3 >= t2, true); - BOOST_CHECK_EQUAL(t3 < t2, false); - BOOST_CHECK_EQUAL(t3 <= t2, true); - - t3 += z; - BOOST_CHECK_EQUAL(t3.tv_sec, sec2); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec2); - - t3 = t1; - t3 += t2; - BOOST_CHECK_EQUAL(t3.tv_sec, sec_sum); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec_sum); - - t3 = t1; - t3 -= t2; - BOOST_CHECK_EQUAL(t3.tv_sec, sec_1_minus_2); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec_1_minus_2); - - t3 = t2; - t3 -= t1; - BOOST_CHECK_EQUAL(t3.tv_sec, sec_2_minus_1); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec_2_minus_1); - - t3 = t1 + t2; - BOOST_CHECK_EQUAL(t3.tv_sec, sec_sum); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec_sum); - - t3 = t1 - t2; - BOOST_CHECK_EQUAL(t3.tv_sec, sec_1_minus_2); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec_1_minus_2); - - t3 = t2 - t1; - BOOST_CHECK_EQUAL(t3.tv_sec, sec_2_minus_1); - BOOST_CHECK_EQUAL(t3.tv_nsec, nsec_2_minus_1); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(str) -{ - cout << test_filename << ".str: " << flush; - time_ns t1(123, 123456789); - BOOST_CHECK_EQUAL(t1.str(), "123.123457"); - BOOST_CHECK_EQUAL(t1.str(9), "123.123456789"); - BOOST_CHECK_EQUAL(t1.str(0), "123"); - time_ns t2(1, 1); - BOOST_CHECK_EQUAL(t2.str(9), "1.000000001"); - time_ns t3(-12, 345); - BOOST_CHECK_EQUAL(t3.str(9), "-11.999999655"); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/_ut_txn_map.cpp b/qpid/cpp/src/tests/legacystore/jrnl/_ut_txn_map.cpp deleted file mode 100644 index 595ce0f6c6..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/_ut_txn_map.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 "../unit_test.h" - -#include -#include -#include "qpid/legacystore/jrnl/txn_map.h" -#include - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace std; - -QPID_AUTO_TEST_SUITE(txn_map_suite) - -const string test_filename("_ut_txn_map"); - -// === Helper functions === - -const string make_xid(u_int64_t rid) -{ - stringstream ss; - ss << "XID-" << setfill('0') << setw(16) << hex << rid; - ss << "-0123456789abcdef"; - return ss.str(); -} - -void check_td_equal(txn_data& td1, txn_data& td2) -{ - BOOST_CHECK_EQUAL(td1._rid, td2._rid); - BOOST_CHECK_EQUAL(td1._drid, td2._drid); - BOOST_CHECK_EQUAL(td1._pfid, td2._pfid); - BOOST_CHECK_EQUAL(td1._enq_flag, td2._enq_flag); - BOOST_CHECK_EQUAL(td1._aio_compl, td2._aio_compl); -} - -// === Test suite === - -QPID_AUTO_TEST_CASE(constructor) -{ - cout << test_filename << ".constructor: " << flush; - const u_int64_t rid = 0x123456789abcdef0ULL; - const u_int64_t drid = 0xfedcba9876543210ULL; - const u_int16_t pfid = 0xfedcU; - const bool enq_flag = true; - txn_data td(rid, drid, pfid, enq_flag); - BOOST_CHECK_EQUAL(td._rid, rid); - BOOST_CHECK_EQUAL(td._drid, drid); - BOOST_CHECK_EQUAL(td._pfid, pfid); - BOOST_CHECK_EQUAL(td._enq_flag, enq_flag); - BOOST_CHECK_EQUAL(td._aio_compl, false); - - txn_map t1; - BOOST_CHECK(t1.empty()); - BOOST_CHECK_EQUAL(t1.size(), u_int32_t(0)); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(insert_get) -{ - cout << test_filename << ".insert_get: " << flush; - u_int16_t fid; - u_int64_t rid; - u_int16_t pfid_start = 0x2000U; - u_int64_t rid_begin = 0xffffffff00000000ULL; - u_int64_t rid_end = 0xffffffff00000200ULL; - - // insert with no dups - u_int64_t rid_incr_1 = 4ULL; - txn_map t2; - t2.set_num_jfiles(pfid_start + (rid_end - rid_begin)/rid_incr_1); - for (rid = rid_begin, fid = pfid_start; rid < rid_end; rid += rid_incr_1, fid++) - t2.insert_txn_data(make_xid(rid), txn_data(rid, ~rid, fid, false)); - BOOST_CHECK(!t2.empty()); - BOOST_CHECK_EQUAL(t2.size(), u_int32_t(128)); - - // get - u_int64_t rid_incr_2 = 6ULL; - for (u_int64_t rid = rid_begin; rid < rid_end; rid += rid_incr_2) - { - string xid = make_xid(rid); - BOOST_CHECK_EQUAL(t2.in_map(xid), (rid%rid_incr_1 ? false : true)); - } - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/chk_jdata b/qpid/cpp/src/tests/legacystore/jrnl/chk_jdata deleted file mode 100755 index 2ac87d91b9..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/chk_jdata +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env 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. -# - - -JRNL_BLK_SIZE=512 # Block size in bytes -JRNL_PAGE_SIZE=256 # Journal page size in blocks -JRNL_FILE_SIZE=12 # Journal file size in pages -let END_OFFSET=${JRNL_BLK_SIZE}*${JRNL_PAGE_SIZE}*${JRNL_FILE_SIZE} -for f in jdata/test.*.jdat; do - echo $f - hexdump -C -n 1024 $f - hexdump -C -s ${END_OFFSET} $f - echo "============" -done diff --git a/qpid/cpp/src/tests/legacystore/jrnl/cp_rtest_jrnl b/qpid/cpp/src/tests/legacystore/jrnl/cp_rtest_jrnl deleted file mode 100755 index e21f991788..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/cp_rtest_jrnl +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env 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. -# - -JDATA_DIR=jdata -TAR_DIR=rd_test_jrnls - -function get_filename -{ - local prefix=$1 - local file_num=$2 - local suffix=$3 - - if (( file_num < 10 )); then - local num="000${file_num}" - elif (( file_num < 100 )); then - local num="00${file_num}" - elif (( file_num < 1000 )); then - local num="0${file_num}" - else - local num="${file_num}" - fi - FILENAME=${prefix}${num}${suffix} - return 0 -} - -if (( $# != 1 )); then - echo "Incorrect args, expected 1 arg (usage: \"prep \")" - exit -fi - -get_filename "t" $1 ".tar.gz" -if [[ -d ${JDATA_DIR} ]]; then - rm -rf ${JDATA_DIR}/* -else - mkdir -p ${JDATA_DIR} -fi -if [[ -f "${TAR_DIR}/${FILENAME}" ]]; then - tar -C ${JDATA_DIR} -xzf "${TAR_DIR}/${FILENAME}" -else - echo "Error: file \"${TAR_DIR}/${FILENAME}\" not found." -fi diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jhexdump b/qpid/cpp/src/tests/legacystore/jrnl/jhexdump deleted file mode 100755 index b013914441..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jhexdump +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env 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. -# - -if [ -z "$1" ]; then - echo "No directory specified." - exit -fi - -JDIR=$1 -echo "Target directory: ${JDIR}" - -rm -f j*.txt - -if [ -d "${JDIR}" ]; then - n=0 - for f in "${JDIR}"/*.jdat; do - echo "$f -> j$n.txt" - hexdump -C "$f" > j$n.txt - (( n += 1 )) - done -else - echo "This directory does not exist." -fi diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_data_src.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_data_src.cpp deleted file mode 100644 index e4656ef83f..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_data_src.cpp +++ /dev/null @@ -1,207 +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 "../../unit_test.h" -#include -#include "data_src.h" -#include -#include - -using namespace boost::unit_test; -using namespace mrg::jtt; -using namespace std; - -QPID_AUTO_TEST_SUITE(jtt_data_src) - -const string test_filename("_ut_data_src"); - -long -get_seed() -{ - timespec ts; - if (::clock_gettime(CLOCK_REALTIME, &ts)) - BOOST_FAIL("Unable to read clock to generate seed."); - long tenths = ts.tv_nsec / 100000000; - return long(10 * ts.tv_sec + tenths); // time in tenths of a second -} - -#ifndef LONG_TEST -/* - * ============================================== - * NORMAL TESTS - * This section contains normal "make check" tests - * for building/packaging. These are built when - * LONG_TEST is _not_ defined. - * ============================================== - */ - -QPID_AUTO_TEST_CASE(data) -{ - cout << test_filename << ".data: " << flush; - BOOST_CHECK(data_src::max_dsize > 0); - for (std::size_t i=0; i<1024; i++) - { - const char* dp = data_src::get_data(i); - BOOST_CHECK_EQUAL(*dp, static_cast('0' + ((i + 1) % 10))); - } - for (std::size_t i=data_src::max_dsize-1024; i('0' + ((i + 1) % 10))); - } - const char* dp1 = data_src::get_data(data_src::max_dsize); - BOOST_CHECK_EQUAL(dp1,(char*) 0); - const char* dp2 = data_src::get_data(data_src::max_dsize + 0x1000); - BOOST_CHECK_EQUAL(dp2, (char*)0); - cout << "ok" << endl; -} - -// There is a long version of this test in _ut_long_data_src.cpp -QPID_AUTO_TEST_CASE(xid_data_xid) -{ - const std::size_t num = 64; - cout << test_filename << ".xid_data_xid: " << flush; - BOOST_CHECK_EQUAL(data_src::get_xid(1), "0"); - BOOST_CHECK_EQUAL(data_src::get_xid(2), "01"); - BOOST_CHECK_EQUAL(data_src::get_xid(3), "002"); - BOOST_CHECK_EQUAL(data_src::get_xid(4), "0003"); - BOOST_CHECK_EQUAL(data_src::get_xid(5), "00004"); - BOOST_CHECK_EQUAL(data_src::get_xid(6), "000005"); - BOOST_CHECK_EQUAL(data_src::get_xid(7), "0000006"); - BOOST_CHECK_EQUAL(data_src::get_xid(8), "00000007"); - BOOST_CHECK_EQUAL(data_src::get_xid(9), "xid:00008"); - BOOST_CHECK_EQUAL(data_src::get_xid(10), "xid:000009"); - BOOST_CHECK_EQUAL(data_src::get_xid(11), "xid:0000010"); - BOOST_CHECK_EQUAL(data_src::get_xid(12), "xid:00000011"); - BOOST_CHECK_EQUAL(data_src::get_xid(13), "xid:00000012:"); - BOOST_CHECK_EQUAL(data_src::get_xid(14), "xid:00000013:n"); - BOOST_CHECK_EQUAL(data_src::get_xid(15), "xid:00000014:no"); - std::size_t i = 15; - for (; i - -using namespace boost::unit_test; -using namespace mrg::jtt; -using namespace std; - -QPID_AUTO_TEST_SUITE(jtt_jrnl_init_params) - -const string test_filename("_ut_jrnl_init_params"); - -QPID_AUTO_TEST_CASE(constructor) -{ - cout << test_filename << ".constructor: " << flush; - const string jid = "jid"; - const string jdir = "jdir"; - const string bfn = "base filename"; - const u_int16_t num_jfiles = 123; - const bool ae = false; - const u_int16_t ae_max_jfiles = 456; - const u_int32_t jfsize_sblks = 789; - jrnl_init_params jip(jid, jdir, bfn, num_jfiles, ae, ae_max_jfiles, jfsize_sblks); - BOOST_CHECK_EQUAL(jip.jid(), jid); - BOOST_CHECK_EQUAL(jip.jdir(), jdir); - BOOST_CHECK_EQUAL(jip.base_filename(), bfn); - BOOST_CHECK_EQUAL(jip.num_jfiles(), num_jfiles); - BOOST_CHECK_EQUAL(jip.is_ae(), ae); - BOOST_CHECK_EQUAL(jip.ae_max_jfiles(), ae_max_jfiles); - BOOST_CHECK_EQUAL(jip.jfsize_sblks(), jfsize_sblks); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(copy_constructor_1) -{ - cout << test_filename << ".copy_constructor_1: " << flush; - const string jid = "jid"; - const string jdir = "jdir"; - const string bfn = "base filename"; - const u_int16_t num_jfiles = 123; - const bool ae = false; - const u_int16_t ae_max_jfiles = 456; - const u_int32_t jfsize_sblks = 789; - jrnl_init_params jip1(jid, jdir, bfn, num_jfiles, ae, ae_max_jfiles, jfsize_sblks); - jrnl_init_params jip2(jip1); - BOOST_CHECK_EQUAL(jip2.jid(), jid); - BOOST_CHECK_EQUAL(jip2.jdir(), jdir); - BOOST_CHECK_EQUAL(jip2.base_filename(), bfn); - BOOST_CHECK_EQUAL(jip2.num_jfiles(), num_jfiles); - BOOST_CHECK_EQUAL(jip2.is_ae(), ae); - BOOST_CHECK_EQUAL(jip2.ae_max_jfiles(), ae_max_jfiles); - BOOST_CHECK_EQUAL(jip2.jfsize_sblks(), jfsize_sblks); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(copy_constructor_2) -{ - cout << test_filename << ".copy_constructor_2: " << flush; - const string jid = "jid"; - const string jdir = "jdir"; - const string bfn = "base filename"; - const u_int16_t num_jfiles = 123; - const bool ae = false; - const u_int16_t ae_max_jfiles = 456; - const u_int32_t jfsize_sblks = 789; - jrnl_init_params::shared_ptr p(new jrnl_init_params(jid, jdir, bfn, num_jfiles, ae, ae_max_jfiles, jfsize_sblks)); - jrnl_init_params jip2(p.get()); - BOOST_CHECK_EQUAL(jip2.jid(), jid); - BOOST_CHECK_EQUAL(jip2.jdir(), jdir); - BOOST_CHECK_EQUAL(jip2.base_filename(), bfn); - BOOST_CHECK_EQUAL(jip2.num_jfiles(), num_jfiles); - BOOST_CHECK_EQUAL(jip2.is_ae(), ae); - BOOST_CHECK_EQUAL(jip2.ae_max_jfiles(), ae_max_jfiles); - BOOST_CHECK_EQUAL(jip2.jfsize_sblks(), jfsize_sblks); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() - diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_jrnl_instance.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_jrnl_instance.cpp deleted file mode 100644 index 12f1c542d6..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_jrnl_instance.cpp +++ /dev/null @@ -1,178 +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 "../../unit_test.h" - -#include -#include "jrnl_init_params.h" -#include "jrnl_instance.h" -#include "qpid/legacystore/jrnl/jdir.h" -#include "qpid/legacystore/jrnl/jerrno.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace mrg::jtt; -using namespace std; - -QPID_AUTO_TEST_SUITE(jtt_jrnl_instance) - -const string test_filename("_ut_jrnl_instance"); -const char* tdp = getenv("TMP_DATA_DIR"); -const string test_dir(tdp && strlen(tdp) > 0 ? tdp : "/var/tmp/JttTest"); - -QPID_AUTO_TEST_CASE(constructor_1) -{ - cout << test_filename << ".constructor_1: " << flush; - const string jid = "jid1"; - const string jdir = test_dir + "/test1"; - const string bfn = "test"; - const u_int16_t num_jfiles = 20; - const bool ae = false; - const u_int16_t ae_max_jfiles = 45; - const u_int32_t jfsize_sblks = 128; - - args a("a1"); - using mrg::jtt::test_case; - test_case::shared_ptr p(new test_case(1, 0, 0, 0, false, 0, 0, test_case::JTT_PERSISTNET, test_case::JDL_INTERNAL, - "t1")); - jrnl_instance ji(jid, jdir, bfn, num_jfiles, ae, ae_max_jfiles, jfsize_sblks); - ji.init_tc(p, &a); - ji.run_tc(); - ji.tc_wait_compl(); - try { jdir::verify_dir(jdir, bfn); } - catch (const jexception& e) { BOOST_ERROR(e.what()); } - jdir::delete_dir(jdir); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_2) -{ - cout << test_filename << ".constructor_2: " << flush; - const string jid = "jid2"; - const string jdir = test_dir + "/test2"; - const string bfn = "test"; - const u_int16_t num_jfiles = 20; - const bool ae = false; - const u_int16_t ae_max_jfiles = 45; - const u_int32_t jfsize_sblks = 128; - - args a("a2"); - using mrg::jtt::test_case; - test_case::shared_ptr p(new test_case(2, 0, 0, 0, false, 0, 0, test_case::JTT_PERSISTNET, test_case::JDL_INTERNAL, - "t2")); - jrnl_init_params::shared_ptr jpp(new jrnl_init_params(jid, jdir, bfn, num_jfiles, ae, ae_max_jfiles, jfsize_sblks)); - jrnl_instance ji(jpp); - ji.init_tc(p, &a); - ji.run_tc(); - ji.tc_wait_compl(); - try { jdir::verify_dir(jdir, bfn); } - catch (const jexception& e) { BOOST_ERROR(e.what()); } - jdir::delete_dir(jdir); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_3) -{ - cout << test_filename << ".constructor_3: " << flush; - const string jid = "jid3"; - const string jdir = test_dir + "/test3"; - const string bfn = "test"; - const u_int16_t num_jfiles = 20; - const bool ae = false; - const u_int16_t ae_max_jfiles = 45; - const u_int32_t jfsize_sblks = 128; - - args a("a3"); - using mrg::jtt::test_case; - test_case::shared_ptr p(new test_case(3, 0, 0, 0, false, 0, 0, test_case::JTT_PERSISTNET, test_case::JDL_INTERNAL, - "t3")); - jrnl_init_params::shared_ptr jpp(new jrnl_init_params(jid, jdir, bfn, num_jfiles, ae, ae_max_jfiles, jfsize_sblks)); - jrnl_instance ji(jpp); - ji.init_tc(p, &a); - ji.run_tc(); - ji.tc_wait_compl(); - try { jdir::verify_dir(jdir, bfn); } - catch (const jexception& e) { BOOST_ERROR(e.what()); } - jdir::delete_dir(jdir); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(recover) -{ - cout << test_filename << ".recover: " << flush; - const string jid = "jid5"; - const string jdir = test_dir + "/test5"; - const string bfn = "test"; - const u_int16_t num_jfiles = 20; - const bool ae = false; - const u_int16_t ae_max_jfiles = 0; - const u_int32_t jfsize_sblks = 128; - - args a("a4"); - using mrg::jtt::test_case; - test_case::shared_ptr p(new test_case(5, 0, 0, 0, false, 0, 0, test_case::JTT_PERSISTNET, test_case::JDL_INTERNAL, - "t5")); - jrnl_init_params::shared_ptr jpp(new jrnl_init_params(jid, jdir, bfn, num_jfiles, ae, ae_max_jfiles, jfsize_sblks)); - jrnl_instance ji(jpp); - ji.init_tc(p, &a); - ji.run_tc(); - ji.tc_wait_compl(); - try { jdir::verify_dir(jdir, bfn); } - catch (const jexception& e) { BOOST_ERROR(e.what()); } - a.recover_mode = true; - ji.init_tc(p, &a); - ji.run_tc(); - ji.tc_wait_compl(); - try { jdir::verify_dir(jdir, bfn); } - catch (const jexception& e) { BOOST_ERROR(e.what()); } - jdir::delete_dir(jdir); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(recover_no_files) -{ - cout << test_filename << ".recover_no_files: " << flush; - const string jid = "jid6"; - const string jdir = test_dir + "/test6"; - const string bfn = "test"; - const u_int16_t num_jfiles = 20; - const bool ae = false; - const u_int16_t ae_max_jfiles = 0; - const u_int32_t jfsize_sblks = 128; - - args a("a5"); - a.recover_mode = true; - using mrg::jtt::test_case; - test_case::shared_ptr p(new test_case(6, 0, 0, 0, false, 0, 0, test_case::JTT_PERSISTNET, test_case::JDL_INTERNAL, - "t6")); - jrnl_init_params::shared_ptr jpp(new jrnl_init_params(jid, jdir, bfn, num_jfiles, ae, ae_max_jfiles, jfsize_sblks)); - jrnl_instance ji(jpp); - ji.init_tc(p, &a); - ji.run_tc(); - ji.tc_wait_compl(); - try { jdir::verify_dir(jdir, bfn); } - catch (const jexception& e) { BOOST_ERROR(e.what()); } - jdir::delete_dir(jdir); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() - diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_read_arg.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_read_arg.cpp deleted file mode 100644 index 0d2025270d..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_read_arg.cpp +++ /dev/null @@ -1,146 +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 "../../unit_test.h" -#include -#include "read_arg.h" -#include - -#include -namespace po = boost::program_options; -using namespace mrg::jtt; -using namespace boost::unit_test; -using namespace std; - -QPID_AUTO_TEST_SUITE(jtt_read_arg) - -const string test_filename("_ut_read_arg"); - -QPID_AUTO_TEST_CASE(constructor) -{ - cout << test_filename << ".constructor: " << flush; - read_arg ra1; - BOOST_CHECK_EQUAL(ra1.val(), read_arg::NONE); - BOOST_CHECK_EQUAL(ra1.str(), "NONE"); - read_arg ra2(read_arg::NONE); - BOOST_CHECK_EQUAL(ra2.val(), read_arg::NONE); - BOOST_CHECK_EQUAL(ra2.str(), "NONE"); - read_arg ra3(read_arg::ALL); - BOOST_CHECK_EQUAL(ra3.val(), read_arg::ALL); - BOOST_CHECK_EQUAL(ra3.str(), "ALL"); - read_arg ra4(read_arg::RANDOM); - BOOST_CHECK_EQUAL(ra4.val(), read_arg::RANDOM); - BOOST_CHECK_EQUAL(ra4.str(), "RANDOM"); - read_arg ra5(read_arg::LAZYLOAD); - BOOST_CHECK_EQUAL(ra5.val(), read_arg::LAZYLOAD); - BOOST_CHECK_EQUAL(ra5.str(), "LAZYLOAD"); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(set_val) -{ - cout << test_filename << ".set_val: " << flush; - read_arg ra; - BOOST_CHECK_EQUAL(ra.val(), read_arg::NONE); - BOOST_CHECK_EQUAL(ra.str(), "NONE"); - ra.set_val(read_arg::ALL); - BOOST_CHECK_EQUAL(ra.val(), read_arg::ALL); - BOOST_CHECK_EQUAL(ra.str(), "ALL"); - ra.set_val(read_arg::RANDOM); - BOOST_CHECK_EQUAL(ra.val(), read_arg::RANDOM); - BOOST_CHECK_EQUAL(ra.str(), "RANDOM"); - ra.set_val(read_arg::LAZYLOAD); - BOOST_CHECK_EQUAL(ra.val(), read_arg::LAZYLOAD); - BOOST_CHECK_EQUAL(ra.str(), "LAZYLOAD"); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(parse) -{ - cout << test_filename << ".parse: " << flush; - read_arg ra; - ra.parse("LAZYLOAD"); - BOOST_CHECK_EQUAL(ra.val(), read_arg::LAZYLOAD); - BOOST_CHECK_EQUAL(ra.str(), "LAZYLOAD"); - ra.parse("ALL"); - BOOST_CHECK_EQUAL(ra.val(), read_arg::ALL); - BOOST_CHECK_EQUAL(ra.str(), "ALL"); - BOOST_CHECK_THROW(ra.parse(""), po::invalid_option_value) - BOOST_CHECK_EQUAL(ra.val(), read_arg::ALL); - BOOST_CHECK_EQUAL(ra.str(), "ALL"); - BOOST_CHECK_THROW(ra.parse("abc123"), po::invalid_option_value) - BOOST_CHECK_EQUAL(ra.val(), read_arg::ALL); - BOOST_CHECK_EQUAL(ra.str(), "ALL"); - ra.parse("NONE"); - BOOST_CHECK_EQUAL(ra.val(), read_arg::NONE); - BOOST_CHECK_EQUAL(ra.str(), "NONE"); - ra.parse("RANDOM"); - BOOST_CHECK_EQUAL(ra.val(), read_arg::RANDOM); - BOOST_CHECK_EQUAL(ra.str(), "RANDOM"); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(istream_) -{ - cout << test_filename << ".istream_: " << flush; - read_arg ra; - istringstream ss1("LAZYLOAD", ios::in); - ss1 >> ra; - BOOST_CHECK_EQUAL(ra.val(), read_arg::LAZYLOAD); - BOOST_CHECK_EQUAL(ra.str(), "LAZYLOAD"); - istringstream ss2("ALL", ios::in); - ss2 >> ra; - BOOST_CHECK_EQUAL(ra.val(), read_arg::ALL); - BOOST_CHECK_EQUAL(ra.str(), "ALL"); - istringstream ss3("NONE", ios::in); - ss3 >> ra; - BOOST_CHECK_EQUAL(ra.val(), read_arg::NONE); - BOOST_CHECK_EQUAL(ra.str(), "NONE"); - istringstream ss4("RANDOM", ios::in); - ss4 >> ra; - BOOST_CHECK_EQUAL(ra.val(), read_arg::RANDOM); - BOOST_CHECK_EQUAL(ra.str(), "RANDOM"); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(ostream_) -{ - cout << test_filename << ".ostream_: " << flush; - ostringstream s1; - read_arg ra(read_arg::LAZYLOAD); - s1 << ra; - BOOST_CHECK_EQUAL(s1.str(), "LAZYLOAD"); - ra.set_val(read_arg::ALL); - ostringstream s2; - s2 << ra; - BOOST_CHECK_EQUAL(s2.str(), "ALL"); - ra.set_val(read_arg::NONE); - ostringstream s3; - s3 << ra; - BOOST_CHECK_EQUAL(s3.str(), "NONE"); - ra.set_val(read_arg::RANDOM); - ostringstream s4; - s4 << ra; - BOOST_CHECK_EQUAL(s4.str(), "RANDOM"); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case.cpp deleted file mode 100644 index 3a7d0f951c..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case.cpp +++ /dev/null @@ -1,113 +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 "../../unit_test.h" -#include -#include -#include -#include "test_case.h" -#include "test_case_result.h" - -using namespace boost::unit_test; -using namespace mrg::jtt; -using namespace std; - -QPID_AUTO_TEST_SUITE(jtt_test_case) - -const string test_filename("_ut_test_case"); - -QPID_AUTO_TEST_CASE(constructor) -{ - cout << test_filename << ".constructor: " << flush; - const unsigned test_case_num = 0x12345; - const u_int32_t num_msgs = 0x100; - const std::size_t min_data_size = 0x1000; - const std::size_t max_data_size = 0; - const bool auto_deq = true; - const std::size_t min_xid_size = 0x200; - const std::size_t max_xid_size = 0x200; - using mrg::jtt::test_case; - const test_case::transient_t transient = test_case::JTT_PERSISTNET; - const test_case::external_t external = test_case::JDL_INTERNAL; - const string comment = "This is a test"; - - test_case tc(test_case_num, num_msgs, min_data_size, max_data_size, auto_deq, - min_xid_size, max_xid_size, transient, external, comment); - BOOST_CHECK_EQUAL(tc.test_case_num(), test_case_num); - BOOST_CHECK_EQUAL(tc.num_msgs(), num_msgs); - BOOST_CHECK_EQUAL(tc.min_data_size(), min_data_size); - BOOST_CHECK_EQUAL(tc.max_data_size(), max_data_size); - BOOST_CHECK_EQUAL(tc.auto_deq(), auto_deq); - BOOST_CHECK_EQUAL(tc.min_xid_size(), min_xid_size); - BOOST_CHECK_EQUAL(tc.max_xid_size(), max_xid_size); - BOOST_CHECK_EQUAL(tc.transient(), transient); - BOOST_CHECK_EQUAL(tc.external(), external); - BOOST_CHECK_EQUAL(tc.comment(), comment); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(results) -{ - cout << test_filename << ".results: " << flush; - const unsigned test_case_num = 0x12345; - const u_int32_t num_msgs = 0x100; - const std::size_t min_data_size = 0x1000; - const std::size_t max_data_size = 0; - const bool auto_deq = true; - const std::size_t min_xid_size = 0x200; - const std::size_t max_xid_size = 0x200; - using mrg::jtt::test_case; - const test_case::transient_t transient = test_case::JTT_PERSISTNET; - const test_case::external_t external = test_case::JDL_INTERNAL; - const string comment = "This is a test"; - const unsigned num_results = 20; - - test_case tc(test_case_num, num_msgs, min_data_size, max_data_size, auto_deq, - min_xid_size, max_xid_size, transient, external, comment); - for (unsigned i=0; ijid(), oss.str()); - } - for (unsigned i=0; ijid(), oss.str()); - } - tc.clear(); - BOOST_CHECK_EQUAL(tc.num_results(), unsigned(0)); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_result.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_result.cpp deleted file mode 100644 index dd83dbee69..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_result.cpp +++ /dev/null @@ -1,206 +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 "../../unit_test.h" - -#include -#include "qpid/legacystore/jrnl/jexception.h" -#include "test_case_result.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace mrg::jtt; -using namespace std; - -QPID_AUTO_TEST_SUITE(jtt_test_case_result) - -const string test_filename("_ut_test_case_result"); - -QPID_AUTO_TEST_CASE(constructor) -{ - cout << test_filename << ".constructor: " << flush; - const string jid("journal id 1"); - test_case_result tcr(jid); - BOOST_CHECK_EQUAL(tcr.jid(), jid); - BOOST_CHECK_EQUAL(tcr.exception(), false); - BOOST_CHECK_EQUAL(tcr.exception_count(), 0U); - const time_ns& ts1 = tcr.start_time(); - BOOST_CHECK(ts1.is_zero()); - const time_ns& ts2 = tcr.stop_time(); - BOOST_CHECK(ts2.is_zero()); - const time_ns& ts3 = tcr.test_time(); - BOOST_CHECK(ts3.is_zero()); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(start_stop) -{ - cout << test_filename << ".start_stop: " << flush; - const string jid("journal id 2"); - test_case_result tcr(jid); - BOOST_CHECK_EQUAL(tcr.exception(), false); - BOOST_CHECK_EQUAL(tcr.exception_count(), 0U); - const time_ns& ts1 = tcr.start_time(); - BOOST_CHECK(ts1.is_zero()); - const time_ns& ts2 = tcr.stop_time(); - BOOST_CHECK(ts2.is_zero()); - const time_ns& ts3 = tcr.test_time(); - BOOST_CHECK(ts3.is_zero()); - - tcr.set_start_time(); - BOOST_CHECK_EQUAL(tcr.exception(), false); - BOOST_CHECK_EQUAL(tcr.exception_count(), 0U); - const time_ns& ts4 = tcr.start_time(); - BOOST_CHECK(!ts4.is_zero()); - const time_ns& ts5 = tcr.stop_time(); - BOOST_CHECK(ts5.is_zero()); - const time_ns& ts6 = tcr.test_time(); - BOOST_CHECK(ts6.is_zero()); - - ::usleep(1100000); // 1.1 sec in microseconds - tcr.set_stop_time(); - BOOST_CHECK_EQUAL(tcr.exception(), false); - BOOST_CHECK_EQUAL(tcr.exception_count(), 0U); - const time_ns& ts7 = tcr.stop_time(); - BOOST_CHECK(!ts7.is_zero()); - const time_ns& ts8 = tcr.test_time(); - BOOST_CHECK(ts8.tv_sec == 1); - BOOST_CHECK(ts8.tv_nsec > 100000000); // 0.1 sec in nanoseconds - BOOST_CHECK(ts8.tv_nsec < 200000000); // 0.2 sec in nanoseconds - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(start_exception_stop_1) -{ - cout << test_filename << ".start_exception_stop_1: " << flush; - const string jid("journal id 3"); - test_case_result tcr(jid); - const u_int32_t err_code = 0x321; - const string err_msg = "exception message"; - const jexception e(err_code, err_msg); - tcr.set_start_time(); - ::usleep(1100000); // 1.1 sec in microseconds - tcr.add_exception(e); - BOOST_CHECK_EQUAL(tcr.exception(), true); - BOOST_CHECK_EQUAL(tcr.exception_count(), 1U); - BOOST_CHECK_EQUAL(tcr[0], e.what()); - const time_ns& ts1 = tcr.stop_time(); - BOOST_CHECK(!ts1.is_zero()); - const time_ns& ts2 = tcr.test_time(); - BOOST_CHECK(ts2.tv_sec == 1); - BOOST_CHECK(ts2.tv_nsec > 100000000); // 0.1 sec in nanoseconds - BOOST_CHECK(ts2.tv_nsec < 200000000); // 0.2 sec in nanoseconds - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(start_exception_stop_2) -{ - cout << test_filename << ".start_exception_stop_2: " << flush; - const string jid("journal id 4"); - test_case_result tcr(jid); - const string err_msg = "exception message"; - tcr.set_start_time(); - ::usleep(1100000); // 1.1 sec in microseconds - tcr.add_exception(err_msg); - BOOST_CHECK_EQUAL(tcr.exception(), true); - BOOST_CHECK_EQUAL(tcr.exception_count(), 1U); - BOOST_CHECK_EQUAL(tcr[0], err_msg); - const time_ns& ts1 = tcr.stop_time(); - BOOST_CHECK(!ts1.is_zero()); - const time_ns& ts2 = tcr.test_time(); - BOOST_CHECK(ts2.tv_sec == 1); - BOOST_CHECK(ts2.tv_nsec > 100000000); // 0.1 sec in nanoseconds - BOOST_CHECK(ts2.tv_nsec < 200000000); // 0.2 sec in nanoseconds - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(start_exception_stop_3) -{ - cout << test_filename << ".start_exception_stop_3: " << flush; - const string jid("journal id 5"); - test_case_result tcr(jid); - const char* err_msg = "exception message"; - tcr.set_start_time(); - ::usleep(1100000); // 1.1 sec in microseconds - tcr.add_exception(err_msg); - BOOST_CHECK_EQUAL(tcr.exception(), true); - BOOST_CHECK_EQUAL(tcr.exception_count(), 1U); - BOOST_CHECK_EQUAL(tcr[0], err_msg); - const time_ns& ts1 = tcr.stop_time(); - BOOST_CHECK(!ts1.is_zero()); - const time_ns& ts2 = tcr.test_time(); - BOOST_CHECK(ts2.tv_sec == 1); - BOOST_CHECK(ts2.tv_nsec > 100000000); // 0.1 sec in nanoseconds - BOOST_CHECK(ts2.tv_nsec < 200000000); // 0.2 sec in nanoseconds - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(start_exception) -{ - cout << test_filename << ".start_exception: " << flush; - const string jid("journal id 6"); - test_case_result tcr(jid); - u_int32_t err_code = 0x654; - const string err_msg = "exception message"; - const jexception e(err_code, err_msg); - tcr.set_start_time(); - ::usleep(1100000); // 1.1 sec in microseconds - tcr.add_exception(e, false); - BOOST_CHECK_EQUAL(tcr.exception(), true); - BOOST_CHECK_EQUAL(tcr.exception_count(), 1U); - BOOST_CHECK_EQUAL(tcr[0], e.what()); - const time_ns& ts1 = tcr.stop_time(); - BOOST_CHECK(ts1.is_zero()); - const time_ns& ts2 = tcr.test_time(); - BOOST_CHECK(ts2.is_zero()); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(counters) -{ - cout << test_filename << ".counters: " << flush; - const u_int32_t num_enq = 125; - const u_int32_t num_deq = 64; - const u_int32_t num_read = 22; - const string jid("journal id 7"); - test_case_result tcr(jid); - BOOST_CHECK_EQUAL(tcr.num_enq(), u_int32_t(0)); - BOOST_CHECK_EQUAL(tcr.num_deq(), u_int32_t(0)); - BOOST_CHECK_EQUAL(tcr.num_read(), u_int32_t(0)); - for (unsigned i=0; i -#include -#include "test_case_result_agregation.h" - -using namespace boost::unit_test; -using namespace mrg::journal; -using namespace mrg::jtt; -using namespace std; - -QPID_AUTO_TEST_SUITE(jtt_test_case_result_agregation) - -const string test_filename("_ut_test_case_result_agregation"); - -// === Helper functions === - -void check_agregate(const test_case_result_agregation& tcra, const u_int32_t num_enq, - const u_int32_t num_deq, const u_int32_t num_reads, const u_int32_t num_results, - const u_int32_t num_exceptions, const std::time_t secs, const long nsec) -{ - BOOST_CHECK_EQUAL(tcra.num_enq(), num_enq); - BOOST_CHECK_EQUAL(tcra.num_deq(), num_deq); - BOOST_CHECK_EQUAL(tcra.num_read(), num_reads); - BOOST_CHECK_EQUAL(tcra.num_results(), num_results); - BOOST_CHECK_EQUAL(tcra.exception_count(), num_exceptions); - BOOST_CHECK_EQUAL(tcra.exception(), num_exceptions > 0); - const time_ns& ts1 = tcra.test_time(); - BOOST_CHECK_EQUAL(ts1.tv_sec, secs); - BOOST_CHECK_EQUAL(ts1.tv_nsec, nsec); -} - -test_case_result::shared_ptr make_result(const string& jid, const u_int32_t num_enq, - const u_int32_t num_deq, const u_int32_t num_reads, const std::time_t secs, const long nsec) -{ - test_case_result::shared_ptr tcrp(new test_case_result(jid)); - for (unsigned i=0; iincr_num_enq(); - for (unsigned i=0; iincr_num_deq(); - for (unsigned i=0; iincr_num_read(); - time_ns ts(secs, nsec); - tcrp->set_test_time(ts); - return tcrp; -} - -// === Test suite === - -QPID_AUTO_TEST_CASE(constructor_1) -{ - cout << test_filename << ".constructor_1: " << flush; - test_case_result_agregation tcra; - BOOST_CHECK_EQUAL(tcra.tc_average_mode(), true); - BOOST_CHECK_EQUAL(tcra.jid(), "Average"); - BOOST_CHECK_EQUAL(tcra.exception(), false); - BOOST_CHECK_EQUAL(tcra.exception_count(), 0U); - const time_ns& ts1 = tcra.start_time(); - BOOST_CHECK(ts1.is_zero()); - const time_ns& ts2 = tcra.stop_time(); - BOOST_CHECK(ts2.is_zero()); - const time_ns& ts3 = tcra.test_time(); - BOOST_CHECK(ts3.is_zero()); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(constructor_2) -{ - cout << test_filename << ".constructor_2: " << flush; - string jid("journal id"); - test_case_result_agregation tcra(jid); - BOOST_CHECK_EQUAL(tcra.tc_average_mode(), false); - BOOST_CHECK_EQUAL(tcra.jid(), jid); - BOOST_CHECK_EQUAL(tcra.exception(), false); - BOOST_CHECK_EQUAL(tcra.exception_count(), 0U); - const time_ns& ts1 = tcra.start_time(); - BOOST_CHECK(ts1.is_zero()); - const time_ns& ts2 = tcra.stop_time(); - BOOST_CHECK(ts2.is_zero()); - const time_ns& ts3 = tcra.test_time(); - BOOST_CHECK(ts3.is_zero()); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(add_test_case) -{ - cout << test_filename << ".add_test_case: " << flush; - string jid("jid1"); - test_case_result::shared_ptr tcrp1 = make_result("jid1", 10, 10, 0, 1, 101010101L); - test_case_result::shared_ptr tcrp2 = make_result("jid1", 25, 0, 35, 10, 20202020L); - test_case_result::shared_ptr tcrp3 = make_result("jid1", 0, 15, 5, 2, 555555555L); - test_case_result::shared_ptr tcrp4 = make_result("jid2", 100, 100, 100, 100, 323232324L); - test_case_result::shared_ptr tcrp5 = make_result("jid1", 5, 0, 0, 0, 100L); - tcrp5->add_exception(string("error 1"), false); - test_case_result::shared_ptr tcrp6 = make_result("jid3", 0, 5, 0, 0, 100L); - jexception e(0x123, "exception 2"); - tcrp6->add_exception(e, false); - test_case_result::shared_ptr tcrp7 = make_result("jid1", 0, 0, 0, 0, 0L); - test_case_result::shared_ptr tcrp8 = make_result("jid1", 200, 100, 300, 12, 323232224L); - - test_case_result_agregation tcra(jid); - check_agregate(tcra, 0, 0, 0, 0, 0, 0, 0L); - tcra.add_test_result(tcrp1); - check_agregate(tcra, 10, 10, 0, 1, 0, 1, 101010101L); - tcra.add_test_result(tcrp2); - check_agregate(tcra, 35, 10, 35, 2, 0, 11, 121212121L); - tcra.add_test_result(tcrp3); - check_agregate(tcra, 35, 25, 40, 3, 0, 13, 676767676L); - tcra.add_test_result(tcrp4); - check_agregate(tcra, 35, 25, 40, 3, 0, 13, 676767676L); - tcra.add_test_result(tcrp5); - check_agregate(tcra, 40, 25, 40, 4, 1, 13, 676767776L); - tcra.add_test_result(tcrp6); - check_agregate(tcra, 40, 25, 40, 4, 1, 13, 676767776L); - tcra.add_test_result(tcrp7); - check_agregate(tcra, 40, 25, 40, 5, 1, 13, 676767776L); - tcra.add_test_result(tcrp8); - check_agregate(tcra, 240, 125, 340, 6, 1, 26, 0L); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(add_test_case_average) -{ - cout << test_filename << ".add_test_case_average: " << flush; - test_case_result::shared_ptr tcrp1 = make_result("jid1", 10, 10, 0, 1, 101010101L); - test_case_result::shared_ptr tcrp2 = make_result("jid2", 25, 0, 35, 10, 20202020L); - test_case_result::shared_ptr tcrp3 = make_result("jid3", 0, 15, 5, 2, 555555555L); - test_case_result::shared_ptr tcrp4 = make_result("jid4", 100, 100, 100, 100, 323232324L); - test_case_result::shared_ptr tcrp5 = make_result("jid5", 5, 0, 0, 0, 100L); - tcrp5->add_exception(string("error 1"), false); - test_case_result::shared_ptr tcrp6 = make_result("jid6", 0, 5, 0, 0, 100L); - jexception e(0x123, "exception 2"); - tcrp6->add_exception(e, false); - test_case_result::shared_ptr tcrp7 = make_result("jid7", 0, 0, 0, 0, 0L); - test_case_result::shared_ptr tcrp8 = make_result("jid8", 200, 100, 300, 12, 222222022L); - - test_case_result_agregation tcra; - check_agregate(tcra, 0, 0, 0, 0, 0, 0, 0L); - tcra.add_test_result(tcrp1); - check_agregate(tcra, 10, 10, 0, 1, 0, 1, 101010101L); - tcra.add_test_result(tcrp2); - check_agregate(tcra, 35, 10, 35, 2, 0, 11, 121212121L); - tcra.add_test_result(tcrp3); - check_agregate(tcra, 35, 25, 40, 3, 0, 13, 676767676L); - tcra.add_test_result(tcrp4); - check_agregate(tcra, 135, 125, 140, 4, 0, 114, 0L); - tcra.add_test_result(tcrp5); - check_agregate(tcra, 140, 125, 140, 5, 1, 114, 100L); - tcra.add_test_result(tcrp6); - check_agregate(tcra, 140, 130, 140, 6, 2, 114, 200L); - tcra.add_test_result(tcrp7); - check_agregate(tcra, 140, 130, 140, 7, 2, 114, 200L); - tcra.add_test_result(tcrp8); - check_agregate(tcra, 340, 230, 440, 8, 2, 126, 222222222L); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_set.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_set.cpp deleted file mode 100644 index adbdf6884b..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_set.cpp +++ /dev/null @@ -1,147 +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 "../../unit_test.h" -#include -#include -#include -#include "test_case.h" -#include "test_case_set.h" - -using namespace boost::unit_test; -using namespace mrg::jtt; -using namespace std; - -QPID_AUTO_TEST_SUITE(jtt_test_case_set) - -const string csv_file("_ut_test_case_set.csv"); -const string test_filename("_ut_test_case_set"); - -// === Helper functions === - -bool check_csv_file(const char* filename) -{ - struct stat s; - if (::stat(filename, &s)) - return false; - if (S_ISREG(s.st_mode)) - return true; - return false; -} - -// === Test suite === - -QPID_AUTO_TEST_CASE(constructor) -{ - cout << test_filename << ".constructor: " << flush; - test_case_set tcs; - BOOST_CHECK(tcs.empty()); - BOOST_CHECK_EQUAL(tcs.size(), unsigned(0)); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(append_1) -{ - cout << test_filename << ".append_1: " << flush; - const unsigned test_case_num = 0x12345; - const u_int32_t num_msgs = 0x100; - const std::size_t min_data_size = 0x1000; - const std::size_t max_data_size = 0; - const bool auto_deq = true; - const std::size_t min_xid_size = 0x200; - const std::size_t max_xid_size = 0x200; - using mrg::jtt::test_case; - const test_case::transient_t transient = test_case::JTT_PERSISTNET; - const test_case::external_t external = test_case::JDL_INTERNAL; - const string comment = "This is a test"; - - test_case_set tcs; - tcs.append(test_case_num, num_msgs, min_data_size, max_data_size, auto_deq, min_xid_size, - max_xid_size, transient, external, comment); - BOOST_CHECK(!tcs.empty()); - BOOST_CHECK_EQUAL(tcs.size(), unsigned(1)); - test_case::shared_ptr tcp = tcs[0]; - BOOST_CHECK_EQUAL(tcp->test_case_num(), test_case_num); - BOOST_CHECK_EQUAL(tcp->num_msgs(), num_msgs); - BOOST_CHECK_EQUAL(tcp->min_data_size(), min_data_size); - BOOST_CHECK_EQUAL(tcp->max_data_size(), max_data_size); - BOOST_CHECK_EQUAL(tcp->min_xid_size(), min_xid_size); - BOOST_CHECK_EQUAL(tcp->max_xid_size(), max_xid_size); - BOOST_CHECK_EQUAL(tcp->transient(), transient); - BOOST_CHECK_EQUAL(tcp->external(), external); - BOOST_CHECK_EQUAL(tcp->comment(), comment); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(append_2) -{ - cout << test_filename << ".append_2: " << flush; - const unsigned test_case_num = 0x12345; - const u_int32_t num_msgs = 0x100; - const std::size_t min_data_size = 0x1000; - const std::size_t max_data_size = 0; - const bool auto_deq = true; - const std::size_t min_xid_size = 0x200; - const std::size_t max_xid_size = 0x200; - using mrg::jtt::test_case; - const test_case::transient_t transient = test_case::JTT_PERSISTNET; - const test_case::external_t external = test_case::JDL_INTERNAL; - const string comment = "This is a test"; - - test_case::shared_ptr tcp(new test_case(test_case_num, num_msgs, min_data_size, max_data_size, - auto_deq, min_xid_size, max_xid_size, transient, external, comment)); - test_case_set tcs; - tcs.append(tcp); - BOOST_CHECK(!tcs.empty()); - BOOST_CHECK_EQUAL(tcs.size(), unsigned(1)); - tcp = tcs[0]; - BOOST_CHECK_EQUAL(tcp->test_case_num(), test_case_num); - BOOST_CHECK_EQUAL(tcp->num_msgs(), num_msgs); - BOOST_CHECK_EQUAL(tcp->min_data_size(), min_data_size); - BOOST_CHECK_EQUAL(tcp->max_data_size(), max_data_size); - BOOST_CHECK_EQUAL(tcp->min_xid_size(), min_xid_size); - BOOST_CHECK_EQUAL(tcp->max_xid_size(), max_xid_size); - BOOST_CHECK_EQUAL(tcp->transient(), transient); - BOOST_CHECK_EQUAL(tcp->external(), external); - BOOST_CHECK_EQUAL(tcp->comment(), comment); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_CASE(append_from_csv) -{ - cout << test_filename << ".append_from_csv: " << flush; - test_case_set tcs; - BOOST_REQUIRE_MESSAGE(check_csv_file(csv_file.c_str()), "Test CSV file \"" << csv_file << - "\" is missing."); - tcs.append_from_csv(csv_file, false); - BOOST_CHECK(!tcs.empty()); - BOOST_CHECK_EQUAL(tcs.size(), unsigned(44)); - BOOST_CHECK_EQUAL(tcs.ignored(), unsigned(0)); - tcs.clear(); - BOOST_CHECK(tcs.empty()); - tcs.append_from_csv(csv_file, true); - BOOST_CHECK(!tcs.empty()); - BOOST_CHECK_EQUAL(tcs.size(), unsigned(18)); - BOOST_CHECK_EQUAL(tcs.ignored(), unsigned(26)); - cout << "ok" << endl; -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_set.csv b/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_set.csv deleted file mode 100644 index f886186275..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/_ut_test_case_set.csv +++ /dev/null @@ -1,74 +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. -# - -,,,,,,,"Msg size",,"Xid size",,,,,"enq-size",,"deq-size",,"txn-size",, -"Col. 0","1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20" -"Test #","tf","pf","amn","mn incr","#msgs","ms incr","Min","Max","Min","Max","auto-deq","transient","extern","bytes","dblks","bytes","dblks","bytes","dblks","comment" -,,,,,,,,,,,,,,,,,,,, -"Initialize only",,,,,,,,,,,,,,,,,,,, -0,"L",0,0,0,0,0,0,0,0,0,FALSE,FALSE,FALSE,44,1,0,0,0,0,"No messages - journal creation/initialization only" -,,,,,,,,,,,,,,,,,,,, -"Simple message combinations of persistent/deq transientueued/non-dequeued, transactional/non-transactional",,,,,,,,,,,,,,,,,,,, -1,"L",1,1,0,1,0,10,10,0,0,FALSE,FALSE,FALSE,54,1,0,0,0,0,"1 * 10-byte message" -2,"L",1,10,0,10,0,10,10,0,0,FALSE,FALSE,FALSE,54,1,0,0,0,0,"10 * 10-byte message" -3,"L",1,1,0,1,0,10,10,0,0,FALSE,TRUE,FALSE,54,1,0,0,0,0,"1 * 10-byte message [transient]" -4,"L",1,10,0,10,0,10,10,0,0,FALSE,TRUE,FALSE,54,1,0,0,0,0,"10 * 10-byte message [transient]" -5,"L",1,1,0,1,0,10,10,10,10,FALSE,FALSE,FALSE,64,1,0,0,0,0,"1 * 10-byte message [txn]" -6,"L",1,10,0,10,0,10,10,10,10,FALSE,FALSE,FALSE,64,1,0,0,0,0,"10 * 10-byte message [txn]" -7,"L",1,1,0,1,0,10,10,10,10,FALSE,TRUE,FALSE,64,1,0,0,0,0,"1 * 10-byte message [txn transient]" -8,"L",1,10,0,10,0,10,10,10,10,FALSE,TRUE,FALSE,64,1,0,0,0,0,"10 * 10-byte message [txn transient]" -9,"L",1,1,0,1,0,10,10,0,0,TRUE,FALSE,FALSE,54,1,32,1,0,0,"1 * 10-byte message [deq]" -10,"L",1,10,0,10,0,10,10,0,0,TRUE,FALSE,FALSE,54,1,32,1,0,0,"10 * 10-byte message [deq]" -11,"L",1,1,0,1,0,10,10,0,0,TRUE,TRUE,FALSE,54,1,32,1,0,0,"1 * 10-byte message [deq transient]" -12,"L",1,10,0,10,0,10,10,0,0,TRUE,TRUE,FALSE,54,1,32,1,0,0,"10 * 10-byte message [deq transient]" -13,"L",1,1,0,1,0,10,10,10,10,TRUE,FALSE,FALSE,64,1,54,1,46,1,"1 * 10-byte message [deq txn]" -14,"L",1,10,0,10,0,10,10,10,10,TRUE,FALSE,FALSE,64,1,54,1,46,1,"10 * 10-byte message [deq txn]" -15,"L",1,1,0,1,0,10,10,10,10,TRUE,TRUE,FALSE,64,1,54,1,46,1,"1 * 10-byte message [txn deq transient]" -16,"L",1,10,0,10,0,10,10,10,10,TRUE,TRUE,FALSE,64,1,54,1,46,1,"10 * 10-byte message [txn deq transient]" -17,"L",1,1,0,1,0,10,10,0,0,FALSE,FALSE,TRUE,54,1,0,0,0,0,"1 * 10-byte message [extern]" -18,"L",1,10,0,10,0,10,10,0,0,FALSE,FALSE,TRUE,54,1,0,0,0,0,"10 * 10-byte message [extern]" -19,"L",1,1,0,1,0,10,10,0,0,FALSE,TRUE,TRUE,54,1,0,0,0,0,"1 * 10-byte message [transient extern]" -20,"L",1,10,0,10,0,10,10,0,0,FALSE,TRUE,TRUE,54,1,0,0,0,0,"10 * 10-byte message [transient extern]" -21,"L",1,1,0,1,0,10,10,10,10,FALSE,FALSE,TRUE,64,1,0,0,0,0,"1 * 10-byte message [txn extern]" -22,"L",1,10,0,10,0,10,10,10,10,FALSE,FALSE,TRUE,64,1,0,0,0,0,"10 * 10-byte message [txn extern]" -23,"L",1,1,0,1,0,10,10,10,10,FALSE,TRUE,TRUE,64,1,0,0,0,0,"1 * 10-byte message [txn transient extern]" -24,"L",1,10,0,10,0,10,10,10,10,FALSE,TRUE,TRUE,64,1,0,0,0,0,"10 * 10-byte message [txn transient extern]" -25,"L",1,1,0,1,0,10,10,0,0,TRUE,FALSE,TRUE,54,1,32,1,0,0,"1 * 10-byte message [deq extern]" -26,"L",1,10,0,10,0,10,10,0,0,TRUE,FALSE,TRUE,54,1,32,1,0,0,"10 * 10-byte message [deq extern]" -27,"L",1,1,0,1,0,10,10,0,0,TRUE,TRUE,TRUE,54,1,32,1,0,0,"1 * 10-byte message [deq transient extern]" -28,"L",1,10,0,10,0,10,10,0,0,TRUE,TRUE,TRUE,54,1,32,1,0,0,"10 * 10-byte message [deq transient extern]" -29,"L",1,1,0,1,0,10,10,10,10,TRUE,FALSE,TRUE,64,1,54,1,46,1,"1 * 10-byte message [deq txn extern]" -30,"L",1,10,0,10,0,10,10,10,10,TRUE,FALSE,TRUE,64,1,54,1,46,1,"10 * 10-byte message [deq txn extern]" -31,"L",1,1,0,1,0,10,10,10,10,TRUE,TRUE,TRUE,64,1,54,1,46,1,"1 * 10-byte message [txn deq transient extern]" -32,"L",1,10,0,10,0,10,10,10,10,TRUE,TRUE,TRUE,64,1,54,1,46,1,"10 * 10-byte message [txn deq transient extern]" -,,,,,,,,,,,,,,,,,,,, -"High volume tests of random message lengths - RHM_WRONLY req'd for auto-dequeue == FALSE",,,,,,,,,,,,,,,,,,,, -33,"M",1,5000000,0,5000000,0,0,100,1,100,FALSE,RANDOM,RANDOM,244,2,0,0,0,0,"100 bytes xid max + 100 bytes data max [txn]" -34,"M",3,3000000,0,3000000,0,0,300,1,300,FALSE,RANDOM,RANDOM,644,6,0,0,0,0,"300 bytes xid max + 300 bytes data max [txn]" -35,"M",10,1600000,0,1600000,0,0,1000,1,1000,FALSE,RANDOM,RANDOM,2044,16,0,0,0,0,"1000 bytes xid max + 1000 bytes data max [txn]" -36,"M",30,600000,0,600000,0,0,3000,1,3000,FALSE,RANDOM,RANDOM,6044,48,0,0,0,0,"3000 bytes xid max + 3000 bytes data max [txn]" -37,"M",100,200000,0,200000,0,0,10000,1,10000,FALSE,RANDOM,RANDOM,20044,157,0,0,0,0,"10000 bytes xid max + 10000 bytes data max [txn]" -38,"M",300,60000,0,60000,0,0,30000,1,30000,FALSE,RANDOM,RANDOM,60044,470,0,0,0,0,"30000 bytes xid max + 30000 bytes data max [txn]" -39,"M",1000,20000,0,20000,0,0,100000,1,100000,FALSE,RANDOM,RANDOM,200044,1563,0,0,0,0,"100000 bytes xid max + 100000 bytes data max [txn]" -,,,,,,,,,,,,,,,,,,,, -"STANDARD PERFORMANCE BENCHMARK: 10,000,000 writes, data=212b (2 dblks)",,,,,,,,,,,,,,,,,,,, -40,"M",1,10000000,0,10000000,0,212,212,0,0,FALSE,FALSE,FALSE,256,2,0,0,0,0,"212 bytes data (2 dblks enq)" -41,"M",1,10000000,0,10000000,0,148,148,64,64,FALSE,FALSE,FALSE,256,2,0,0,0,0,"148 bytes data + 64 bytes xid (2 dblks enq)" -42,"M",1,10000000,0,10000000,0,212,212,0,0,TRUE,FALSE,FALSE,256,2,32,1,0,0,"212 bytes data (2 dblks enq + 1 dblk deq)" -43,"M",1,10000000,0,10000000,0,148,148,64,64,TRUE,FALSE,FALSE,256,2,108,1,100,1,"148 bytes data + 64 bytes xid (2 dblks enq + 1 dblks deq + 1 dblks txn)" diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/args.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/args.cpp deleted file mode 100644 index 0f041c380e..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/args.cpp +++ /dev/null @@ -1,226 +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 "args.h" - -#include -#include - -namespace po = boost::program_options; - -namespace mrg -{ -namespace jtt -{ - -args::args(std::string opt_title): - _options_descr(opt_title), - format_chk(false), - keep_jrnls(false), - lld_rd_num(10), - lld_skip_num(100), - num_jrnls(1), - pause_secs(0), - randomize(false), - read_mode(), - read_prob(50), - recover_mode(false), - repeat_flag(false), - reuse_instance(false), - seed(0) -{ - _options_descr.add_options() - ("csv-file,c", - po::value(&test_case_csv_file_name)->default_value("jtt.csv"), - "CSV file containing test cases.") - - ("format-chk", - po::value(&format_chk)->zero_tokens(), - "Check the format of each journal file.") - - ("help,h", "This help message.") - - ("jrnl-dir", - po::value(&journal_dir)->default_value("/var/tmp/jtt"), - "Directory in which journal files will be placed.") - - ("keep-jrnls", - po::value(&keep_jrnls)->zero_tokens(), - "Keep all test journals.") - - ("lld-rd-num", - po::value(&lld_rd_num)->default_value(10), - "Number of consecutive messages to read after only dequeueing lld-skip-num " - "messages during lazy-loading. Ignored if read-mode is not set to LAZYLOAD.") - - ("lld-skip-num", - po::value(&lld_skip_num)->default_value(100), - "Number of consecutive messages to dequeue only (without reading) prior to " - "reading lld-rd-num messages. Ignored if read-mode is not set to LAZYLOAD.") - - ("num-jrnls", - po::value(&num_jrnls)->default_value(1), - "Number of simultaneous journal instances to test.") - - ("pause", - po::value(&pause_secs)->default_value(0), - "Pause in seconds between test cases (allows disk to catch up).") - - ("randomize", - po::value(&randomize)->zero_tokens(), - "Randomize the order of the tests.") - - ("read-mode", - po::value(&read_mode)->default_value(read_arg::NONE), - read_arg::descr().c_str()) - - ("read-prob", - po::value(&read_prob)->default_value(50), - "Read probability (percent) for each message when read-mode is set to RANDOM.") - - ("recover-mode", - po::value(&recover_mode)->zero_tokens(), - "Recover journal from the previous test for each test case.") - - ("repeat", - po::value(&repeat_flag)->zero_tokens(), - "Repeat all test cases indefinitely.") - - ("reuse-instance", - po::value(&reuse_instance)->zero_tokens(), - "Reuse journal instance for all test cases.") - - ("seed", - po::value(&seed)->default_value(0), - "Seed for use in random number generator.") - - ("analyzer", - po::value(&jfile_analyzer)->default_value("./file_chk.py"), - "Journal file analyzer program to use when the --format-chk option is used, ignored otherwise.") - - ; -} - -bool -args::parse(int argc, char** argv) // return true if error, false if ok -{ - try - { - po::store(po::parse_command_line(argc, argv, _options_descr), _vmap); - po::notify(_vmap); - } - catch (const std::exception& e) - { - std::cout << "ERROR: " << e.what() << std::endl; - return usage(); - } - if (_vmap.count("help")) - return usage(); - if (num_jrnls == 0) - { - std::cout << "ERROR: num-jrnls must be 1 or more." << std::endl; - return usage(); - } - if (read_prob > 100) // read_prob is unsigned, so no need to check < 0 - { - std::cout << "ERROR: read-prob must be between 0 and 100 inclusive." << std::endl; - return usage(); - } - if (repeat_flag && keep_jrnls) - { - std::string resp; - std::cout << "WARNING: repeat and keep-jrnls: Monitor disk usage as test journals will" - " accumulate." << std::endl; - std::cout << "Continue? "; - std::cin >> resp; - if (resp.size() == 1) - { - if (resp[0] != 'y' && resp[0] != 'Y') - return true; - } - else if (resp.size() == 3) // any combo of lower- and upper-case - { - if (resp[0] != 'y' && resp[0] != 'Y') - return true; - if (resp[1] != 'e' && resp[1] != 'E') - return true; - if (resp[2] != 's' && resp[2] != 'S') - return true; - } - else - return true; - } - return false; -} - -bool -args::usage() const -{ - std::cout << _options_descr << std::endl; - return true; -} - -void -args::print_args() const -{ - std::cout << "Number of journals: " << num_jrnls << std::endl; - std::cout << "Read mode: " << read_mode << std::endl; - if (read_mode.val() == read_arg::RANDOM) - std::cout << "Read probability: " << read_prob << " %" << std::endl; - if (read_mode.val() == read_arg::LAZYLOAD) - { - std::cout << "Lazy-load skips: " << lld_skip_num << std::endl; - std::cout << "Lazy-load reads: " << lld_rd_num << std::endl; - } - if (pause_secs) - std::cout << "Pause between test cases: " << pause_secs << " sec." << std::endl; - if (seed) - std::cout << "Randomize seed: " << seed << std::endl; - print_flags(); -} - -void -args::print_flags() const -{ - if (format_chk || keep_jrnls || randomize || recover_mode || repeat_flag || - reuse_instance) - { - std::cout << "Flag options:"; - // TODO: Get flag args and their strings directly from _options_descr. - if (format_chk) - std::cout << " format-chk"; - if (keep_jrnls) - std::cout << " keep-jrnls"; - if (randomize) - std::cout << " randomize"; - if (recover_mode) - std::cout << " recover-mode"; - if (repeat_flag) - std::cout << " repeat-flag"; - if (reuse_instance) - std::cout << " reuse-instance"; - std::cout << std::endl; - } - std::cout << std::endl; -} - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/args.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/args.h deleted file mode 100644 index b6f7fb4a79..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/args.h +++ /dev/null @@ -1,66 +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. - * - */ - -#ifndef mrg_jtt_args_hpp -#define mrg_jtt_args_hpp - -#include -#include "read_arg.h" - -namespace mrg -{ -namespace jtt -{ - - struct args - { - boost::program_options::options_description _options_descr; - boost::program_options::variables_map _vmap; - - // Add args here - std::string jfile_analyzer; - std::string test_case_csv_file_name; - std::string journal_dir; - bool format_chk; - bool keep_jrnls; - unsigned lld_rd_num; - unsigned lld_skip_num; - unsigned num_jrnls; - unsigned pause_secs; - bool randomize; - read_arg read_mode; - unsigned read_prob; - bool recover_mode; - bool repeat_flag; - bool reuse_instance; - unsigned seed; - - args(std::string opt_title); - bool parse(int argc, char** argv); // return true if error, false if ok - bool usage() const; // return true - void print_args() const; - void print_flags() const; - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_args_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.cpp deleted file mode 100644 index 3530e0b223..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.cpp +++ /dev/null @@ -1,87 +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 "data_src.h" - -#include -#include -#include - -namespace mrg -{ -namespace jtt -{ - -char data_src::_data_src[data_src::max_dsize]; -char data_src::_xid_src[data_src::max_xsize]; -bool data_src::_initialized = data_src::__init(); -u_int64_t data_src::_xid_cnt = 0ULL; -mrg::journal::smutex data_src::_sm; - -data_src::data_src() -{} - -bool -data_src::__init() -{ - for (unsigned i=0; i= max_dsize) return 0; - return _data_src + offs; -} - -std::string -data_src::get_xid(const std::size_t xid_size) -{ - if (xid_size == 0) - return ""; - std::ostringstream oss; - oss << std::setfill('0'); - if (xid_size < 9) - oss << std::setw(xid_size) << get_xid_cnt(); - else if (xid_size < 13) - oss << "xid:" << std::setw(xid_size - 4) << get_xid_cnt(); - else - { - oss << "xid:" << std::setw(8) << get_xid_cnt() << ":"; - oss.write(get_xid_content(13), xid_size - 13); - } - return oss.str(); -} - -const char* -data_src::get_xid_content(const std::size_t offs) -{ - if (offs >= max_xsize) return 0; - return _xid_src + offs; -} - -} // namespace jtt -} // namespace mrg - diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.h deleted file mode 100644 index 66dc613787..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/data_src.h +++ /dev/null @@ -1,66 +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. - * - */ - -#ifndef mrg_jtt_data_src_hpp -#define mrg_jtt_data_src_hpp - -#include -#include "qpid/legacystore/jrnl/slock.h" -#include "qpid/legacystore/jrnl/smutex.h" -#include -#include -#include - -#define DATA_SIZE 1024 * 1024 -#define XID_SIZE 1024 * 1024 - -namespace mrg -{ -namespace jtt -{ - class data_src - { - public: - static const std::size_t max_dsize = DATA_SIZE; - static const std::size_t max_xsize = XID_SIZE; - - private: - static char _data_src[]; - static char _xid_src[]; - static u_int64_t _xid_cnt; - static bool _initialized; - static mrg::journal::smutex _sm; - - public: - static const char* get_data(const std::size_t offs); - static std::string get_xid(const std::size_t xid_size); - - private: - data_src(); - static u_int64_t get_xid_cnt() { mrg::journal::slock s(_sm); return _xid_cnt++; } - static const char* get_xid_content(const std::size_t offs); - static bool __init(); - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_data_src_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jfile_chk.py b/qpid/cpp/src/tests/legacystore/jrnl/jtt/jfile_chk.py deleted file mode 100755 index 36ef511f5c..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jfile_chk.py +++ /dev/null @@ -1,838 +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. -# - -import sys -import getopt -import string -import xml.parsers.expat -from struct import unpack, calcsize -from time import gmtime, strftime - -dblk_size = 128 -sblk_size = 4 * dblk_size -jfsize = None -hdr_ver = 1 - -TEST_NUM_COL = 0 -NUM_MSGS_COL = 5 -MIN_MSG_SIZE_COL = 7 -MAX_MSG_SIZE_COL = 8 -MIN_XID_SIZE_COL = 9 -MAX_XID_SIZE_COL = 10 -AUTO_DEQ_COL = 11 -TRANSIENT_COL = 12 -EXTERN_COL = 13 -COMMENT_COL = 20 - -owi_mask = 0x01 -transient_mask = 0x10 -extern_mask = 0x20 - -printchars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ ' - - - -#== global functions =========================================================== - -def load(f, klass): - args = load_args(f, klass) - subclass = klass.discriminate(args) - result = subclass(*args) - if subclass != klass: - result.init(f, *load_args(f, subclass)) - result.skip(f) - return result; - -def load_args(f, klass): - size = calcsize(klass.format) - foffs = f.tell(), - bin = f.read(size) - if len(bin) != size: - raise Exception("end of file") - return foffs + unpack(klass.format, bin) - -def size_blks(size, blk_size): - return (size + blk_size - 1)/blk_size - -def rem_in_blk(f, blk_size): - foffs = f.tell() - return (size_blks(f.tell(), blk_size) * blk_size) - foffs; - -def file_full(f): - return f.tell() >= jfsize - -def isprintable(s): - return s.strip(printchars) == '' - -def print_xid(xidsize, xid): - if xid == None: - if xidsize > 0: - raise Exception('Inconsistent XID size: xidsize=%d, xid=None' % xidsize) - return '' - if isprintable(xid): - xidstr = split_str(xid) - else: - xidstr = hex_split_str(xid) - if xidsize != len(xid): - raise Exception('Inconsistent XID size: xidsize=%d, xid(%d)=\"%s\"' % (xidsize, len(xid), xidstr)) - return 'xid(%d)=\"%s\" ' % (xidsize, xidstr) - -def print_data(dsize, data): - if data == None: - return '' - if isprintable(data): - datastr = split_str(data) - else: - datastr = hex_split_str(data) - if dsize != len(data): - raise Exception('Inconsistent data size: dsize=%d, data(%d)=\"%s\"' % (dsize, len(data), datastr)) - return 'data(%d)=\"%s\" ' % (dsize, datastr) - -def hex_split_str(s, split_size = 50): - if len(s) <= split_size: - return hex_str(s, 0, len(s)) - if len(s) > split_size + 25: - return hex_str(s, 0, 10) + ' ... ' + hex_str(s, 55, 65) + ' ... ' + hex_str(s, len(s)-10, len(s)) - return hex_str(s, 0, 10) + ' ... ' + hex_str(s, len(s)-10, len(s)) - -def hex_str(s, b, e): - o = '' - for i in range(b, e): - if isprintable(s[i]): - o += s[i] - else: - o += '\\%02x' % ord(s[i]) - return o - -def split_str(s, split_size = 50): - if len(s) < split_size: - return s - return s[:25] + ' ... ' + s[-25:] - -def inv_str(s): - si = '' - for i in range(0,len(s)): - si += chr(~ord(s[i]) & 0xff) - return si - -def load_file_data(f, size, data): - if size == 0: - return (data, True) - if data == None: - loaded = 0 - else: - loaded = len(data) - foverflow = f.tell() + size - loaded > jfsize - if foverflow: - rsize = jfsize - f.tell() - else: - rsize = size - loaded - bin = f.read(rsize) - if data == None: - data = unpack('%ds' % (rsize), bin)[0] - else: - data = data + unpack('%ds' % (rsize), bin)[0] - return (data, not foverflow) - -def exit(code, qflag): - if code != 0 or not qflag: - print out.getvalue() - out.close() - sys.exit(code) - -#== class Sizeable ============================================================= - -class Sizeable: - - def size(self): - classes = [self.__class__] - - size = 0 - while classes: - cls = classes.pop() - if hasattr(cls, "format"): - size += calcsize(cls.format) - classes.extend(cls.__bases__) - - return size - - -#== class Hdr ================================================================== - -class Hdr(Sizeable): - - format = '=4sBBHQ' - - def discriminate(args): - return CLASSES.get(args[1][-1], Hdr) - discriminate = staticmethod(discriminate) - - def __init__(self, foffs, magic, ver, end, flags, rid): - self.foffs = foffs - self.magic = magic - self.ver = ver - self.end = end - self.flags = flags - self.rid = rid - if self.magic[-1] not in ['0x00', 'a', 'c', 'd', 'e', 'f', 'x']: - error = 3 - - def __str__(self): - if self.empty(): - return '0x%08x: ' % (self.foffs) - if self.magic[-1] == 'x': - return '0x%08x: [\"%s\"]' % (self.foffs, self.magic) - if self.magic[-1] in ['a', 'c', 'd', 'e', 'f', 'x']: - return '0x%08x: [\"%s\" v=%d e=%d f=0x%04x rid=0x%x]' % (self.foffs, self.magic, self.ver, self.end, self.flags, self.rid) - return '0x%08x: ' % (self.foffs, self.magic) - - def empty(self): - return self.magic == '\x00'*4 - - def owi(self): - return self.flags & owi_mask != 0 - - def skip(self, f): - f.read(rem_in_blk(f, dblk_size)) - - def check(self): - if self.empty() or self.magic[:3] != 'RHM' or self.magic[3] not in ['a', 'c', 'd', 'e', 'f', 'x']: - return True - if self.ver != hdr_ver and self.magic[-1] != 'x': - raise Exception('%s: Invalid header version: found %d, expected %d.' % (self, self.ver, hdr_ver)) - return False - - -#== class FileHdr ============================================================== - -class FileHdr(Hdr): - - format = '=2H4x3Q' - - def init(self, f, foffs, fid, lid, fro, time_sec, time_ns): - self.fid = fid - self.lid = lid - self.fro = fro - self.time_sec = time_sec - self.time_ns = time_ns - - def __str__(self): - return '%s fid=%d lid=%d fro=0x%08x t=%s' % (Hdr.__str__(self), self.fid, self.lid, self.fro, self.timestamp_str()) - - def skip(self, f): - f.read(rem_in_blk(f, sblk_size)) - - def timestamp(self): - return (self.time_sec, self.time_ns) - - def timestamp_str(self): - ts = gmtime(self.time_sec) - fstr = '%%a %%b %%d %%H:%%M:%%S.%09d %%Y' % (self.time_ns) - return strftime(fstr, ts) - - -#== class DeqHdr =============================================================== - -class DeqHdr(Hdr): - - format = '=QQ' - - def init(self, f, foffs, deq_rid, xidsize): - self.deq_rid = deq_rid - self.xidsize = xidsize - self.xid = None - self.deq_tail = None - self.xid_complete = False - self.tail_complete = False - self.tail_bin = None - self.tail_offs = 0 - self.load(f) - - def load(self, f): - if self.xidsize == 0: - self.xid_complete = True - self.tail_complete = True - else: - if not self.xid_complete: - ret = load_file_data(f, self.xidsize, self.xid) - self.xid = ret[0] - self.xid_complete = ret[1] - if self.xid_complete and not self.tail_complete: - ret = load_file_data(f, calcsize(RecTail.format), self.tail_bin) - self.tail_bin = ret[0] - if ret[1]: - self.enq_tail = RecTail(self.tail_offs, *unpack(RecTail.format, self.tail_bin)) - if self.enq_tail.magic_inv != inv_str(self.magic) or self.enq_tail.rid != self.rid: - print " > %s" % self - raise Exception('Invalid dequeue record tail (magic=%s; rid=%d) at 0x%08x' % (self.enq_tail, self.enq_tail.rid, self.enq_tail.foffs)) - self.enq_tail.skip(f) - self.tail_complete = ret[1] - return self.complete() - - def complete(self): - return self.xid_complete and self.tail_complete - - def __str__(self): - return '%s %sdrid=0x%x' % (Hdr.__str__(self), print_xid(self.xidsize, self.xid), self.deq_rid) - - -#== class TxnHdr =============================================================== - -class TxnHdr(Hdr): - - format = '=Q' - - def init(self, f, foffs, xidsize): - self.xidsize = xidsize - self.xid = None - self.tx_tail = None - self.xid_complete = False - self.tail_complete = False - self.tail_bin = None - self.tail_offs = 0 - self.load(f) - - def load(self, f): - if not self.xid_complete: - ret = load_file_data(f, self.xidsize, self.xid) - self.xid = ret[0] - self.xid_complete = ret[1] - if self.xid_complete and not self.tail_complete: - ret = load_file_data(f, calcsize(RecTail.format), self.tail_bin) - self.tail_bin = ret[0] - if ret[1]: - self.enq_tail = RecTail(self.tail_offs, *unpack(RecTail.format, self.tail_bin)) - if self.enq_tail.magic_inv != inv_str(self.magic) or self.enq_tail.rid != self.rid: - print " > %s" % self - raise Exception('Invalid transaction record tail (magic=%s; rid=%d) at 0x%08x' % (self.enq_tail, self.enq_tail.rid, self.enq_tail.foffs)) - self.enq_tail.skip(f) - self.tail_complete = ret[1] - return self.complete() - - def complete(self): - return self.xid_complete and self.tail_complete - - def __str__(self): - return '%s %s' % (Hdr.__str__(self), print_xid(self.xidsize, self.xid)) - - -#== class RecTail ============================================================== - -class RecTail(Sizeable): - - format = '=4sQ' - - def __init__(self, foffs, magic_inv, rid): - self.foffs = foffs - self.magic_inv = magic_inv - self.rid = rid - - def __str__(self): - magic = inv_str(self.magic_inv) - return '[\"%s\" rid=0x%x]' % (magic, self.rid) - - def skip(self, f): - f.read(rem_in_blk(f, dblk_size)) - - -#== class EnqRec =============================================================== - -class EnqRec(Hdr): - - format = '=QQ' - - def init(self, f, foffs, xidsize, dsize): - self.xidsize = xidsize - self.dsize = dsize - self.transient = self.flags & transient_mask > 0 - self.extern = self.flags & extern_mask > 0 - self.xid = None - self.data = None - self.enq_tail = None - self.xid_complete = False - self.data_complete = False - self.tail_complete = False - self.tail_bin = None - self.tail_offs = 0 - self.load(f) - - def load(self, f): - if not self.xid_complete: - ret = load_file_data(f, self.xidsize, self.xid) - self.xid = ret[0] - self.xid_complete = ret[1] - if self.xid_complete and not self.data_complete: - if self.extern: - self.data_complete = True - else: - ret = load_file_data(f, self.dsize, self.data) - self.data = ret[0] - self.data_complete = ret[1] - if self.data_complete and not self.tail_complete: - ret = load_file_data(f, calcsize(RecTail.format), self.tail_bin) - self.tail_bin = ret[0] - if ret[1]: - self.enq_tail = RecTail(self.tail_offs, *unpack(RecTail.format, self.tail_bin)) - if self.enq_tail.magic_inv != inv_str(self.magic) or self.enq_tail.rid != self.rid: - print " > %s" % self - raise Exception('Invalid enqueue record tail (magic=%s; rid=%d) at 0x%08x' % (self.enq_tail, self.enq_tail.rid, self.enq_tail.foffs)) - self.enq_tail.skip(f) - self.tail_complete = ret[1] - return self.complete() - - def complete(self): - return self.xid_complete and self.data_complete and self.tail_complete - - def print_flags(self): - s = '' - if self.transient: - s = '*TRANSIENT' - if self.extern: - if len(s) > 0: - s += ',EXTERNAL' - else: - s = '*EXTERNAL' - if len(s) > 0: - s += '*' - return s - - def __str__(self): - return '%s %s%s %s %s' % (Hdr.__str__(self), print_xid(self.xidsize, self.xid), print_data(self.dsize, self.data), self.enq_tail, self.print_flags()) - - -#== class Main ================================================================= - -class Main: - def __init__(self, argv): - self.bfn = None - self.csvfn = None - self.jdir = None - self.aflag = False - self.hflag = False - self.qflag = False - self.tnum = None - self.num_jfiles = None - self.num_msgs = None - self.msg_len = None - self.auto_deq = None - self.xid_len = None - self.transient = None - self.extern = None - - self.file_start = 0 - self.file_num = 0 - self.fro = 0x200 - self.emap = {} - self.tmap = {} - self.rec_cnt = 0 - self.msg_cnt = 0 - self.txn_msg_cnt = 0 - self.fhdr = None - self.f = None - self.first_rec = False - self.last_file = False - self.last_rid = -1 - self.fhdr_owi_at_msg_start = None - - self.proc_args(argv) - self.proc_csv() - self.read_jinf() - - def run(self): - try: - start_info = self.analyze_files() - stop = self.advance_file(*start_info) - except Exception: - print 'WARNING: All journal files are empty.' - if self.num_msgs > 0: - raise Exception('All journal files are empty, but %d msgs expectd.' % self.num_msgs) - else: - stop = True - while not stop: - warn = '' - if file_full(self.f): - stop = self.advance_file() - if stop: - break - hdr = load(self.f, Hdr) - if hdr.empty(): - stop = True; - break - if hdr.check(): - stop = True; - else: - self.rec_cnt += 1 - self.fhdr_owi_at_msg_start = self.fhdr.owi() - if self.first_rec: - if self.fhdr.fro != hdr.foffs: - raise Exception('File header first record offset mismatch: fro=0x%08x; rec_offs=0x%08x' % (self.fhdr.fro, hdr.foffs)) - else: - if not self.qflag: print ' * fro ok: 0x%08x' % self.fhdr.fro - self.first_rec = False - if isinstance(hdr, EnqRec) and not stop: - while not hdr.complete(): - stop = self.advance_file() - if stop: - break - hdr.load(self.f) - if self.extern != None: - if hdr.extern: - if hdr.data != None: - raise Exception('Message data found on external record') - else: - if self.msg_len > 0 and len(hdr.data) != self.msg_len: - raise Exception('Message length (%d) incorrect; expected %d' % (len(hdr.data), self.msg_len)) - else: - if self.msg_len > 0 and len(hdr.data) != self.msg_len: - raise Exception('Message length (%d) incorrect; expected %d' % (len(hdr.data), self.msg_len)) - if self.xid_len > 0 and len(hdr.xid) != self.xid_len: - print ' ERROR: XID length (%d) incorrect; expected %d' % (len(hdr.xid), self.xid_len) - sys.exit(1) - #raise Exception('XID length (%d) incorrect; expected %d' % (len(hdr.xid), self.xid_len)) - if self.transient != None: - if self.transient: - if not hdr.transient: - raise Exception('Expected transient record, found persistent') - else: - if hdr.transient: - raise Exception('Expected persistent record, found transient') - stop = not self.check_owi(hdr) - if stop: - warn = ' (WARNING: OWI mismatch - could be overwrite boundary.)' - else: - self.msg_cnt += 1 - if self.aflag or self.auto_deq: - if hdr.xid == None: - self.emap[hdr.rid] = (self.fhdr.fid, hdr, False) - else: - self.txn_msg_cnt += 1 - if hdr.xid in self.tmap: - self.tmap[hdr.xid].append((self.fhdr.fid, hdr)) #Append tuple to existing list - else: - self.tmap[hdr.xid] = [(self.fhdr.fid, hdr)] # Create new list - elif isinstance(hdr, DeqHdr) and not stop: - while not hdr.complete(): - stop = self.advance_file() - if stop: - break - hdr.load(self.f) - stop = not self.check_owi(hdr) - if stop: - warn = ' (WARNING: OWI mismatch - could be overwrite boundary.)' - else: - if self.auto_deq != None: - if not self.auto_deq: - warn = ' WARNING: Dequeue record rid=%d found in non-dequeue test - ignoring.' % hdr.rid - if self.aflag or self.auto_deq: - if hdr.xid == None: - if hdr.deq_rid in self.emap: - if self.emap[hdr.deq_rid][2]: - warn = ' (WARNING: dequeue rid 0x%x dequeues locked enqueue record 0x%x)' % (hdr.rid, hdr.deq_rid) - del self.emap[hdr.deq_rid] - else: - warn = ' (WARNING: rid being dequeued 0x%x not found in enqueued records)' % hdr.deq_rid - else: - if hdr.deq_rid in self.emap: - t = self.emap[hdr.deq_rid] - self.emap[hdr.deq_rid] = (t[0], t[1], True) # Lock enq record - if hdr.xid in self.tmap: - self.tmap[hdr.xid].append((self.fhdr.fid, hdr)) #Append to existing list - else: - self.tmap[hdr.xid] = [(self.fhdr.fid, hdr)] # Create new list - elif isinstance(hdr, TxnHdr) and not stop: - while not hdr.complete(): - stop = self.advance_file() - if stop: - break - hdr.load(self.f) - stop = not self.check_owi(hdr) - if stop: - warn = ' (WARNING: OWI mismatch - could be overwrite boundary.)' - else: - if hdr.xid in self.tmap: - mismatched_rids = [] - if hdr.magic[-1] == 'c': # commit - for rec in self.tmap[hdr.xid]: - if isinstance(rec[1], EnqRec): - self.emap[rec[1].rid] = (rec[0], rec[1], False) # Transfer enq to emap - elif isinstance(rec[1], DeqHdr): - if rec[1].deq_rid in self.emap: - del self.emap[rec[1].deq_rid] # Delete from emap - else: - mismatched_rids.append('0x%x' % rec[1].deq_rid) - else: - raise Exception('Unknown header found in txn map: %s' % rec[1]) - elif hdr.magic[-1] == 'a': # abort - for rec in self.tmap[hdr.xid]: - if isinstance(rec[1], DeqHdr): - if rec[1].deq_rid in self.emap: - t = self.emap[rec[1].deq_rid] - self.emap[rec[1].deq_rid] = (t[0], t[1], False) # Unlock enq record - del self.tmap[hdr.xid] - if len(mismatched_rids) > 0: - warn = ' (WARNING: transactional dequeues not found in enqueue map; rids=%s)' % mismatched_rids - else: - warn = ' (WARNING: %s not found in transaction map)' % print_xid(len(hdr.xid), hdr.xid) - if not self.qflag: print ' > %s%s' % (hdr, warn) - if not stop: - stop = (self.last_file and hdr.check()) or hdr.empty() or self.fhdr.empty() - - def analyze_files(self): - fname = '' - fnum = -1 - rid = -1 - fro = -1 - tss = '' - if not self.qflag: print 'Analyzing journal files:' - owi_found = False - for i in range(0, self.num_jfiles): - jfn = self.jdir + '/' + self.bfn + '.%04d.jdat' % i - f = open(jfn) - fhdr = load(f, Hdr) - if fhdr.empty(): - if not self.qflag: - print ' %s: file empty' % jfn - break - if i == 0: - init_owi = fhdr.owi() - fname = jfn - fnum = i - rid = fhdr.rid - fro = fhdr.fro - tss = fhdr.timestamp_str() - elif fhdr.owi() != init_owi and not owi_found: - fname = jfn - fnum = i - rid = fhdr.rid - fro = fhdr.fro - tss = fhdr.timestamp_str() - owi_found = True - if not self.qflag: - print ' %s: owi=%s rid=0x%x, fro=0x%08x ts=%s' % (jfn, fhdr.owi(), fhdr.rid, fhdr.fro, fhdr.timestamp_str()) - if fnum < 0 or rid < 0 or fro < 0: - raise Exception('All journal files empty') - if not self.qflag: print ' Oldest complete file: %s: rid=%d, fro=0x%08x ts=%s' % (fname, rid, fro, tss) - return (fnum, rid, fro) - - def advance_file(self, *start_info): - seek_flag = False - if len(start_info) == 3: - self.file_start = self.file_num = start_info[0] - self.fro = start_info[2] - seek_flag = True - if self.f != None and file_full(self.f): - self.file_num = self.incr_fnum() - if self.file_num == self.file_start: - return True - if self.file_start == 0: - self.last_file = self.file_num == self.num_jfiles - 1 - else: - self.last_file = self.file_num == self.file_start - 1 - if self.file_num < 0 or self.file_num >= self.num_jfiles: - raise Exception('Bad file number %d' % self.file_num) - jfn = self.jdir + '/' + self.bfn + '.%04d.jdat' % self.file_num - self.f = open(jfn) - self.fhdr = load(self.f, Hdr) - if seek_flag and self.f.tell() != self.fro: - self.f.seek(self.fro) - self.first_rec = True - if not self.qflag: print jfn, ": ", self.fhdr - return False - - def incr_fnum(self): - self.file_num += 1 - if self.file_num >= self.num_jfiles: - self.file_num = 0; - return self.file_num - - def check_owi(self, hdr): - return self.fhdr_owi_at_msg_start == hdr.owi() - - def check_rid(self, hdr): - if self.last_rid != -1 and hdr.rid <= self.last_rid: - return False - self.last_rid = hdr.rid - return True - - def read_jinf(self): - filename = self.jdir + '/' + self.bfn + '.jinf' - try: - f = open(filename, 'r') - except IOError: - print 'ERROR: Unable to open jinf file %s' % filename - sys.exit(1) - p = xml.parsers.expat.ParserCreate() - p.StartElementHandler = self.handleStartElement - p.CharacterDataHandler = self.handleCharData - p.EndElementHandler = self.handleEndElement - p.ParseFile(f) - if self.num_jfiles == None: - print 'ERROR: number_jrnl_files not found in jinf file "%s"!' % filename - if jfsize == None: - print 'ERROR: jrnl_file_size_sblks not found in jinf file "%s"!' % filename - if self.num_jfiles == None or jfsize == None: - sys.exit(1) - - def handleStartElement(self, name, attrs): - global jfsize - if name == 'number_jrnl_files': - self.num_jfiles = int(attrs['value']) - if name == 'jrnl_file_size_sblks': - jfsize = (int(attrs['value']) + 1) * sblk_size - - def handleCharData(self, data): pass - - def handleEndElement(self, name): pass - - def proc_csv(self): - if self.csvfn != None and self.tnum != None: - tparams = self.get_test(self.csvfn, self.tnum) - if tparams == None: - print 'ERROR: Test %d not found in CSV file "%s"' % (self.tnum, self.csvfn) - sys.exit(1) - self.num_msgs = tparams['num_msgs'] - if tparams['min_size'] == tparams['max_size']: - self.msg_len = tparams['max_size'] - else: - self.msg_len = 0 - self.auto_deq = tparams['auto_deq'] - if tparams['xid_min_size'] == tparams['xid_max_size']: - self.xid_len = tparams['xid_max_size'] - else: - self.xid_len = 0 - self.transient = tparams['transient'] - self.extern = tparams['extern'] - - def get_test(self, filename, tnum): - try: - f=open(filename, 'r') - except IOError: - print 'ERROR: Unable to open CSV file "%s"' % filename - sys.exit(1) - for l in f: - sl = l.strip().split(',') - if len(sl[0]) > 0 and sl[0][0] != '"': - try: - if (int(sl[TEST_NUM_COL]) == tnum): - return { 'num_msgs':int(sl[NUM_MSGS_COL]), - 'min_size':int(sl[MIN_MSG_SIZE_COL]), - 'max_size':int(sl[MAX_MSG_SIZE_COL]), - 'auto_deq':not (sl[AUTO_DEQ_COL] == 'FALSE' or sl[AUTO_DEQ_COL] == '0'), - 'xid_min_size':int(sl[MIN_XID_SIZE_COL]), - 'xid_max_size':int(sl[MAX_XID_SIZE_COL]), - 'transient':not (sl[TRANSIENT_COL] == 'FALSE' or sl[TRANSIENT_COL] == '0'), - 'extern':not (sl[EXTERN_COL] == 'FALSE' or sl[EXTERN_COL] == '0'), - 'comment':sl[COMMENT_COL] } - except Exception: - pass - return None - - def proc_args(self, argv): - try: - opts, args = getopt.getopt(sys.argv[1:], "ab:c:d:hqt:", ["analyse", "base-filename=", "csv-filename=", "dir=", "help", "quiet", "test-num="]) - except getopt.GetoptError: - self.usage() - sys.exit(2) - for o, a in opts: - if o in ("-h", "--help"): - self.usage() - sys.exit() - if o in ("-a", "--analyze"): - self.aflag = True - if o in ("-b", "--base-filename"): - self.bfn = a - if o in ("-c", "--csv-filename"): - self.csvfn = a - if o in ("-d", "--dir"): - self.jdir = a - if o in ("-q", "--quiet"): - self.qflag = True - if o in ("-t", "--test-num"): - if not a.isdigit(): - print 'ERROR: Illegal test-num argument. Must be a non-negative number' - sys.exit(2) - self.tnum = int(a) - if self.bfn == None or self.jdir == None: - print 'ERROR: Missing requred args.' - self.usage() - sys.exit(2) - if self.tnum != None and self.csvfn == None: - print 'ERROR: Test number specified, but not CSV file' - self.usage() - sys.exit(2) - - def usage(self): - print 'Usage: %s opts' % sys.argv[0] - print ' where opts are in either short or long format (*=req\'d):' - print ' -a --analyze Analyze enqueue/dequeue records' - print ' -b --base-filename [string] * Base filename for journal files' - print ' -c --csv-filename [string] CSV filename containing test parameters' - print ' -d --dir [string] * Journal directory containing journal files' - print ' -h --help Print help' - print ' -q --quiet Quiet (reduced output)' - print ' -t --test-num [int] Test number from CSV file - only valid if CSV file named' - - def report(self): - if not self.qflag: - print - print ' === REPORT ====' - if self.num_msgs > 0 and self.msg_cnt != self.num_msgs: - print 'WARNING: Found %d messages; %d expected.' % (self.msg_cnt, self.num_msgs) - if len(self.emap) > 0: - print - print 'Remaining enqueued records (sorted by rid): ' - keys = sorted(self.emap.keys()) - for k in keys: - if self.emap[k][2] == True: # locked - locked = ' (locked)' - else: - locked = '' - print " fid=%d %s%s" % (self.emap[k][0], self.emap[k][1], locked) - print 'WARNING: Enqueue-Dequeue mismatch, %d enqueued records remain.' % len(self.emap) - if len(self.tmap) > 0: - txn_rec_cnt = 0 - print - print 'Remaining transactions: ' - for t in self.tmap: - print_xid(len(t), t) - for r in self.tmap[t]: - print " fid=%d %s" % (r[0], r[1]) - print " Total: %d records for xid %s" % (len(self.tmap[t]), t) - txn_rec_cnt += len(self.tmap[t]) - print 'WARNING: Incomplete transactions, %d xids remain containing %d records.' % (len(self.tmap), txn_rec_cnt) - print '%d enqueues, %d journal records processed.' % (self.msg_cnt, self.rec_cnt) - - -#=============================================================================== - -CLASSES = { - "a": TxnHdr, - "c": TxnHdr, - "d": DeqHdr, - "e": EnqRec, - "f": FileHdr -} - -m = Main(sys.argv) -m.run() -m.report() - -sys.exit(None) diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_init_params.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_init_params.cpp deleted file mode 100644 index 1bc04110af..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_init_params.cpp +++ /dev/null @@ -1,77 +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 "jrnl_init_params.h" - -namespace mrg -{ -namespace jtt -{ - -jrnl_init_params::jrnl_init_params(const std::string& jid, const std::string& jdir, const std::string& base_filename, - const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles, const u_int32_t jfsize_sblks, - const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks): - _jid(jid), - _jdir(jdir), - _base_filename(base_filename), - _num_jfiles(num_jfiles), - _ae(ae), - _ae_max_jfiles(ae_max_jfiles), - _jfsize_sblks(jfsize_sblks), - _wcache_num_pages(wcache_num_pages), - _wcache_pgsize_sblks(wcache_pgsize_sblks) -{} - -jrnl_init_params::jrnl_init_params(const jrnl_init_params& jp): - _jid(jp._jid), - _jdir(jp._jdir), - _base_filename(jp._base_filename), - _num_jfiles(jp._num_jfiles), - _ae(jp._ae), - _ae_max_jfiles(jp._ae_max_jfiles), - _jfsize_sblks(jp._jfsize_sblks), - _wcache_num_pages(jp._wcache_num_pages), - _wcache_pgsize_sblks(jp._wcache_pgsize_sblks) -{} - -jrnl_init_params::jrnl_init_params(const jrnl_init_params* const jp_ptr): - _jid(jp_ptr->_jid), - _jdir(jp_ptr->_jdir), - _base_filename(jp_ptr->_base_filename), - _num_jfiles(jp_ptr->_num_jfiles), - _ae(jp_ptr->_ae), - _ae_max_jfiles(jp_ptr->_ae_max_jfiles), - _jfsize_sblks(jp_ptr->_jfsize_sblks), - _wcache_num_pages(jp_ptr->_wcache_num_pages), - _wcache_pgsize_sblks(jp_ptr->_wcache_pgsize_sblks) -{} - -// static initializers - -const u_int16_t jrnl_init_params::def_num_jfiles = 8; -const bool jrnl_init_params::def_ae = false; -const u_int16_t jrnl_init_params::def_ae_max_jfiles = 0; -const u_int32_t jrnl_init_params::def_jfsize_sblks = 0xc00; -const u_int16_t jrnl_init_params::def_wcache_num_pages = 32; -const u_int32_t jrnl_init_params::def_wcache_pgsize_sblks = 64; - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_init_params.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_init_params.h deleted file mode 100644 index ece87f8e03..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_init_params.h +++ /dev/null @@ -1,80 +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. - * - */ - -#ifndef mrg_jtt_jrnl_init_params_hpp -#define mrg_jtt_jrnl_init_params_hpp - -#include -#include -#include - -namespace mrg -{ -namespace jtt -{ - - class jrnl_init_params - { - public: - static const u_int16_t def_num_jfiles; - static const bool def_ae; - static const u_int16_t def_ae_max_jfiles; - static const u_int32_t def_jfsize_sblks; - static const u_int16_t def_wcache_num_pages; - static const u_int32_t def_wcache_pgsize_sblks; - - typedef boost::shared_ptr shared_ptr; - - private: - std::string _jid; - std::string _jdir; - std::string _base_filename; - u_int16_t _num_jfiles; - bool _ae; - u_int16_t _ae_max_jfiles; - u_int32_t _jfsize_sblks; - u_int16_t _wcache_num_pages; - u_int32_t _wcache_pgsize_sblks; - - public: - jrnl_init_params(const std::string& jid, const std::string& jdir, const std::string& base_filename, - const u_int16_t num_jfiles = def_num_jfiles, const bool ae = def_ae, - const u_int16_t ae_max_jfiles = def_ae_max_jfiles, const u_int32_t jfsize_sblks = def_jfsize_sblks, - const u_int16_t wcache_num_pages = def_wcache_num_pages, - const u_int32_t wcache_pgsize_sblks = def_wcache_pgsize_sblks); - jrnl_init_params(const jrnl_init_params& jp); - jrnl_init_params(const jrnl_init_params* const jp_ptr); - - inline const std::string& jid() const { return _jid; } - inline const std::string& jdir() const { return _jdir; } - inline const std::string& base_filename() const { return _base_filename; } - inline u_int16_t num_jfiles() const { return _num_jfiles; } - inline bool is_ae() const { return _ae; } - inline u_int16_t ae_max_jfiles() const { return _ae_max_jfiles; } - inline u_int32_t jfsize_sblks() const { return _jfsize_sblks; } - inline u_int16_t wcache_num_pages() const { return _wcache_num_pages; } - inline u_int32_t wcache_pgsize_sblks() const { return _wcache_pgsize_sblks; } - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_jrnl_init_params_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_instance.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_instance.cpp deleted file mode 100644 index 339dc1b52c..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_instance.cpp +++ /dev/null @@ -1,439 +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 "jrnl_instance.h" - -#include -#include "data_src.h" -#include "qpid/legacystore/jrnl/data_tok.h" -#include "qpid/legacystore/jrnl/jerrno.h" -#include "test_case_result.h" - -#define MAX_WR_WAIT 10 // in ms -#define MAX_RD_WAIT 100 // in ms -#define MAX_ENQCAPTHRESH_CNT 1000 // 10s if MAX_WR_WAIT is 10 ms - -namespace mrg -{ -namespace jtt -{ - -jrnl_instance::jrnl_instance(const std::string& jid, const std::string& jdir, const std::string& base_filename, - const u_int16_t num_jfiles, const bool ae, const u_int16_t ae_max_jfiles, const u_int32_t jfsize_sblks, - const u_int16_t wcache_num_pages, const u_int32_t wcache_pgsize_sblks): - mrg::journal::jcntl(jid, jdir, base_filename), - _jpp(new jrnl_init_params(jid, jdir, base_filename, num_jfiles, ae, ae_max_jfiles, jfsize_sblks, - wcache_num_pages, wcache_pgsize_sblks)), - _args_ptr(0), - _dtok_master_enq_list(), - _dtok_master_txn_list(), - _dtok_rd_list(), - _dtok_deq_list(), - _rd_aio_cv(_rd_aio_mutex), - _wr_full_cv(_wr_full_mutex), - _rd_list_cv(_rd_list_mutex), - _deq_list_cv(_deq_list_mutex), - _tcp(), - _tcrp() -{} - -jrnl_instance::jrnl_instance(const jrnl_init_params::shared_ptr& p): - mrg::journal::jcntl(p->jid(), p->jdir(), p->base_filename()), - _jpp(p), - _args_ptr(0), - _dtok_master_enq_list(), - _dtok_master_txn_list(), - _dtok_rd_list(), - _dtok_deq_list(), - _rd_aio_cv(_rd_aio_mutex), - _wr_full_cv(_wr_full_mutex), - _rd_list_cv(_rd_list_mutex), - _deq_list_cv(_deq_list_mutex), - _tcp(), - _tcrp() -{} - -jrnl_instance::~jrnl_instance() {} - - -void -jrnl_instance::init_tc(test_case::shared_ptr& tcp, const args* const args_ptr) throw () -{ - test_case_result::shared_ptr p(new test_case_result(_jpp->jid())); - _tcrp = p; - _args_ptr = args_ptr; - try - { - _tcp = tcp; - _dtok_master_enq_list.clear(); - _dtok_master_txn_list.clear(); - _dtok_rd_list.clear(); - _dtok_deq_list.clear(); - - if (_args_ptr->recover_mode) - { - try - { - u_int64_t highest_rid; - recover(_jpp->num_jfiles(), _jpp->is_ae(), _jpp->ae_max_jfiles(), _jpp->jfsize_sblks(), - _jpp->wcache_num_pages(), _jpp->wcache_pgsize_sblks(), this, - 0, highest_rid); - recover_complete(); - } - catch (const mrg::journal::jexception& e) - { - if (e.err_code() == mrg::journal::jerrno::JERR_JDIR_STAT) - initialize(_jpp->num_jfiles(), _jpp->is_ae(), _jpp->ae_max_jfiles(), _jpp->jfsize_sblks(), - _jpp->wcache_num_pages(), _jpp->wcache_pgsize_sblks(), this); - else - throw; - } - } - else - initialize(_jpp->num_jfiles(), _jpp->is_ae(), _jpp->ae_max_jfiles(), _jpp->jfsize_sblks(), - _jpp->wcache_num_pages(), _jpp->wcache_pgsize_sblks(), this); - } - catch (const mrg::journal::jexception& e) { _tcrp->add_exception(e); } - catch (const std::exception& e) { _tcrp->add_exception(e.what()); } - catch (...) { _tcrp->add_exception("Unknown exception"); } -} - -void -jrnl_instance::run_tc() throw () -{ - _tcrp->set_start_time(); - ::pthread_create(&_enq_thread, 0, run_enq, this); - ::pthread_create(&_read_thread, 0, run_read, this); - ::pthread_create(&_deq_thread, 0, run_deq, this); -} - -void -jrnl_instance::tc_wait_compl() throw () -{ - try - { - ::pthread_join(_deq_thread, 0); - ::pthread_join(_read_thread, 0); - ::pthread_join(_enq_thread, 0); - stop(true); - } - catch (const mrg::journal::jexception& e) { _tcrp->add_exception(e); panic(); } - catch (const std::exception& e) { _tcrp->add_exception(e.what()); panic(); } - catch (...) { _tcrp->add_exception("Unknown exception"); panic(); } - _lpmgr.finalize(); - _tcrp->set_stop_time(); - _tcp->add_result(_tcrp); -} - -void -jrnl_instance::run_enq() throw () -{ - try - { - unsigned sleep_cnt = 0U; - while(_tcrp->num_enq() < _tcp->num_msgs() && !_tcrp->exception()) - { - dtok_ptr p(new mrg::journal::data_tok); - _dtok_master_enq_list.push_back(p); - const char* msgp = data_src::get_data(_tcrp->num_enq() % 10); - const std::size_t msg_size = _tcp->this_data_size(); - const std::size_t xid_size = _tcp->this_xid_size(); - const std::string xid(data_src::get_xid(xid_size)); - const bool external = _tcp->this_external(); - const bool transient = _tcp->this_transience(); - mrg::journal::iores res; - if (xid_size) - { - if (external) - res = enqueue_extern_txn_data_record(msg_size, p.get(), xid, transient); - else - res = enqueue_txn_data_record(msgp, msg_size, msg_size, p.get(), xid, - transient); - } - else - { - if (external) - res = enqueue_extern_data_record(msg_size, p.get(), transient); - else - res = enqueue_data_record(msgp, msg_size, msg_size, p.get(), transient); - } - switch (res) - { - case mrg::journal::RHM_IORES_SUCCESS: - sleep_cnt = 0U; - _tcrp->incr_num_enq(); - if (p->has_xid() && !_tcp->auto_deq()) - commit(p.get()); - break; - case mrg::journal::RHM_IORES_ENQCAPTHRESH: - if (++sleep_cnt > MAX_ENQCAPTHRESH_CNT) - { - _tcrp->add_exception("Timeout waiting for RHM_IORES_ENQCAPTHRESH to clear."); - panic(); - } - else if (get_wr_events(0) == 0) // *** GEV2 - { - mrg::journal::slock sl(_wr_full_mutex); - _wr_full_cv.waitintvl(MAX_WR_WAIT * 1000000); // MAX_WR_WAIT in ms - } - break; - default: - std::ostringstream oss; - oss << "ERROR: enqueue operation in journal \"" << _jid << "\" returned "; - oss << mrg::journal::iores_str(res) << "."; - _tcrp->add_exception(oss.str()); - } - } - flush(true); - } - catch (const mrg::journal::jexception& e) { _tcrp->add_exception(e); panic(); } - catch (const std::exception& e) { _tcrp->add_exception(e.what()); panic(); } - catch (...) { _tcrp->add_exception("Unknown exception"); panic(); } -} - -void -jrnl_instance::run_read() throw () -{ - try - { - read_arg::read_mode_t rd_mode = _args_ptr->read_mode.val(); - if (rd_mode != read_arg::NONE) - { - while (_tcrp->num_rproc() < _tcp->num_msgs() && !_tcrp->exception()) - { - journal::data_tok* dtokp = 0; - { - mrg::journal::slock sl(_rd_list_mutex); - if (_dtok_rd_list.empty()) - _rd_list_cv.wait(); - if (!_dtok_rd_list.empty()) - { - dtokp = _dtok_rd_list.front(); - _dtok_rd_list.pop_front(); - } - } - if (dtokp) - { - _tcrp->incr_num_rproc(); - - bool do_read = true; - if (rd_mode == read_arg::RANDOM) - do_read = 1.0 * std::rand() / RAND_MAX < _args_ptr->read_prob / 100.0; - else if (rd_mode == read_arg::LAZYLOAD) - do_read = _tcrp->num_rproc() >= _args_ptr->lld_skip_num && - _tcrp->num_read() < _args_ptr->lld_rd_num; - bool read_compl = false; - while (do_read && !read_compl && !_tcrp->exception()) - { - void* dptr = 0; - std::size_t dsize = 0; - void* xptr = 0; - std::size_t xsize = 0; - bool tr = false; - bool ext = false; - mrg::journal::iores res = read_data_record(&dptr, dsize, &xptr, xsize, tr, - ext, dtokp); - switch (res) - { - case mrg::journal::RHM_IORES_SUCCESS: - { - mrg::journal::slock sl(_deq_list_mutex); - _dtok_deq_list.push_back(dtokp); - _deq_list_cv.broadcast(); - } - read_compl = true; - _tcrp->incr_num_read(); - - // clean up - if (xsize) - std::free(xptr); - else if (dsize) - std::free(dptr); - dptr = 0; - xptr = 0; - break; - case mrg::journal::RHM_IORES_PAGE_AIOWAIT: - if (get_rd_events(0) == 0) - { - mrg::journal::slock sl(_rd_aio_mutex); - _rd_aio_cv.waitintvl(MAX_RD_WAIT * 1000000); // MAX_RD_WAIT in ms - } - break; - default: - std::ostringstream oss; - oss << "ERROR: read operation in journal \"" << _jid; - oss << "\" returned " << mrg::journal::iores_str(res) << "."; - _tcrp->add_exception(oss.str()); - { - mrg::journal::slock sl(_deq_list_mutex); - _deq_list_cv.broadcast(); // wake up deq thread - } - } - } - } - } - } - } - catch (const mrg::journal::jexception& e) { _tcrp->add_exception(e); panic(); } - catch (const std::exception& e) { _tcrp->add_exception(e.what()); panic(); } - catch (...) { _tcrp->add_exception("Unknown exception"); panic(); } -} - -void -jrnl_instance::run_deq() throw () -{ - try - { - if (_tcp->auto_deq()) - { - while(_tcrp->num_deq() < _tcp->num_msgs() && !_tcrp->exception()) - { - journal::data_tok* dtokp = 0; - { - mrg::journal::slock sl(_deq_list_mutex); - if (_dtok_deq_list.empty()) - _deq_list_cv.wait(); - if (!_dtok_deq_list.empty()) - { - dtokp = _dtok_deq_list.front(); - _dtok_deq_list.pop_front(); - } - } - if (dtokp) - { - mrg::journal::iores res; - if (dtokp->has_xid()) - res = dequeue_txn_data_record(dtokp, dtokp->xid()); - else - res = dequeue_data_record(dtokp); - if (res == mrg::journal::RHM_IORES_SUCCESS) - { - _tcrp->incr_num_deq(); - commit(dtokp); - } - else - { - std::ostringstream oss; - oss << "ERROR: dequeue operation in journal \"" << _jid; - oss << "\" returned " << mrg::journal::iores_str(res) << "."; - _tcrp->add_exception(oss.str()); - } - } - } - flush(true); - } - } - catch (const mrg::journal::jexception& e) { _tcrp->add_exception(e); panic(); } - catch (const std::exception& e) { _tcrp->add_exception(e.what()); panic(); } - catch (...) { _tcrp->add_exception("Unknown exception"); panic(); } -} - -void -jrnl_instance::abort(const mrg::journal::data_tok* dtokp) -{ - txn(dtokp, false); -} - -void -jrnl_instance::commit(const mrg::journal::data_tok* dtokp) -{ - txn(dtokp, true); -} - -void -jrnl_instance::txn(const mrg::journal::data_tok* dtokp, const bool commit) -{ - if (dtokp->has_xid()) - { - mrg::journal::data_tok* p = prep_txn_dtok(dtokp); - mrg::journal::iores res = commit ? txn_commit(p, p->xid()) : txn_abort(p, p->xid()); - if (res != mrg::journal::RHM_IORES_SUCCESS) - { - std::ostringstream oss; - oss << "ERROR: " << (commit ? "commit" : "abort") << " operation in journal \""; - oss << _jid << "\" returned " << mrg::journal::iores_str(res) << "."; - _tcrp->add_exception(oss.str()); - } - } -} - -mrg::journal::data_tok* -jrnl_instance::prep_txn_dtok(const mrg::journal::data_tok* dtokp) -{ - dtok_ptr p(new mrg::journal::data_tok); - _dtok_master_txn_list.push_back(p); - p->set_xid(dtokp->xid()); - return p.get(); -} - -void -jrnl_instance::panic() -{ - // In the event of a panic or exception condition, release all waiting CVs - _rd_aio_cv.broadcast(); - _wr_full_cv.broadcast(); - _rd_list_cv.broadcast(); - _deq_list_cv.broadcast(); -} - -// AIO callbacks - -void -jrnl_instance::wr_aio_cb(std::vector& dtokl) -{ - for (std::vector::const_iterator i=dtokl.begin(); i!=dtokl.end(); i++) - { - if ((*i)->wstate() == journal::data_tok::ENQ || (*i)->wstate() == journal::data_tok::DEQ) - { - journal::data_tok* dtokp = *i; - if (dtokp->wstate() == journal::data_tok::ENQ) - { - if (_args_ptr->read_mode.val() == read_arg::NONE) - { - mrg::journal::slock sl(_deq_list_mutex); - _dtok_deq_list.push_back(dtokp); - _deq_list_cv.broadcast(); - } - else - { - mrg::journal::slock sl(_rd_list_mutex); - _dtok_rd_list.push_back(dtokp); - _rd_list_cv.broadcast(); - } - } - else // DEQ - { - mrg::journal::slock sl(_wr_full_mutex); - _wr_full_cv.broadcast(); - } - } - } -} - -void -jrnl_instance::rd_aio_cb(std::vector& /*pil*/) -{ - mrg::journal::slock sl(_rd_aio_mutex); - _rd_aio_cv.broadcast(); -} - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_instance.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_instance.h deleted file mode 100644 index 5003f39b24..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jrnl_instance.h +++ /dev/null @@ -1,121 +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. - * - */ - -#ifndef mrg_jtt_jrnl_instance_hpp -#define mrg_jtt_jrnl_instance_hpp - -#include "args.h" -#include "jrnl_init_params.h" -#include "test_case.h" - -#include -#include "qpid/legacystore/jrnl/cvar.h" -#include "qpid/legacystore/jrnl/data_tok.h" -#include "qpid/legacystore/jrnl/jcntl.h" -#include "qpid/legacystore/jrnl/slock.h" -#include "qpid/legacystore/jrnl/smutex.h" -#include -#include - -namespace mrg -{ -namespace jtt -{ - - class jrnl_instance : public mrg::journal::jcntl, public virtual mrg::journal::aio_callback - { - public: - typedef boost::shared_ptr shared_ptr; - typedef boost::shared_ptr dtok_ptr; - - private: - jrnl_init_params::shared_ptr _jpp; - const args* _args_ptr; - std::vector _dtok_master_enq_list; - std::vector _dtok_master_txn_list; - std::list _dtok_rd_list; - std::list _dtok_deq_list; - mrg::journal::smutex _rd_aio_mutex; ///< Mutex for read aio wait conditions - mrg::journal::cvar _rd_aio_cv; ///< Condition var for read aio wait conditions - mrg::journal::smutex _wr_full_mutex; ///< Mutex for write full conditions - mrg::journal::cvar _wr_full_cv; ///< Condition var for write full conditions - mrg::journal::smutex _rd_list_mutex; ///< Mutex for _dtok_rd_list - mrg::journal::cvar _rd_list_cv; ///< Condition var for _dtok_rd_list - mrg::journal::smutex _deq_list_mutex; ///< Mutex for _dtok_deq_list - mrg::journal::cvar _deq_list_cv; ///< Condition var for _dtok_deq_list - pthread_t _enq_thread; - pthread_t _deq_thread; - pthread_t _read_thread; - test_case::shared_ptr _tcp; - test_case_result::shared_ptr _tcrp; - - public: - jrnl_instance(const std::string& jid, const std::string& jdir, - const std::string& base_filename, - const u_int16_t num_jfiles = jrnl_init_params::def_num_jfiles, - const bool ae = jrnl_init_params::def_ae, - const u_int16_t ae_max_jfiles = jrnl_init_params::def_ae_max_jfiles, - const u_int32_t jfsize_sblks = jrnl_init_params::def_jfsize_sblks, - const u_int16_t wcache_num_pages = jrnl_init_params::def_wcache_num_pages, - const u_int32_t wcache_pgsize_sblks = jrnl_init_params::def_wcache_pgsize_sblks); - jrnl_instance(const jrnl_init_params::shared_ptr& params); - virtual ~jrnl_instance(); - - inline const jrnl_init_params::shared_ptr& params() const { return _jpp; } - inline const std::string& jid() const { return _jpp->jid(); } - - void init_tc(test_case::shared_ptr& tcp, const args* const args_ptr) throw (); - void run_tc() throw (); - void tc_wait_compl() throw (); - - // AIO callbacks - virtual void wr_aio_cb(std::vector& dtokl); - virtual void rd_aio_cb(std::vector& pil); - - private: - void run_enq() throw (); - inline static void* run_enq(void* p) - { static_cast(p)->run_enq(); return 0; } - - void run_read() throw (); - inline static void* run_read(void* p) - { static_cast(p)->run_read(); return 0; } - - void run_deq() throw (); - inline static void* run_deq(void* p) - { static_cast(p)->run_deq(); return 0; } - - void abort(const mrg::journal::data_tok* dtokp); - void commit(const mrg::journal::data_tok* dtokp); - void txn(const mrg::journal::data_tok* dtokp, const bool commit); - mrg::journal::data_tok* prep_txn_dtok(const mrg::journal::data_tok* dtokp); - - void panic(); - -// // static callbacks -// static void aio_rd_callback(jcntl* journal, std::vector& pil); -// static void aio_wr_callback(jcntl* journal, std::vector& dtokl); - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_jrnl_instance_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jtt.csv b/qpid/cpp/src/tests/legacystore/jrnl/jtt/jtt.csv deleted file mode 100644 index df523e3f97..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/jtt.csv +++ /dev/null @@ -1,234 +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. -# - -,,,,,,,"Msg size",,"Xid size",,,,,"enq-size",,"deq-size",,"txn-size",, -"Test #","tf","pf","amn","mn incr","#msgs","ms incr","Min","Max","Min","Max","auto-deq","transient","extern","bytes","dblks","bytes","dblks","bytes","dblks","comment" -,,,,,,,,,,,,,,,,,,,, -"Initialize only",,,,,,,,,,,,,,,,,,,, -0,"L",0,0,0,0,0,0,0,0,0,FALSE,FALSE,FALSE,44,1,0,0,0,0,"No messages - journal creation/initialization only" -,,,,,,,,,,,,,,,,,,,, -"Simple message combinations of persistent/deq transientueued/non-dequeued, transactional/non-transactional",,,,,,,,,,,,,,,,,,,, -1,"L",1,1,0,1,0,10,10,0,0,FALSE,FALSE,FALSE,54,1,0,0,0,0,"1 * 10-byte message" -2,"L",1,10,0,10,0,10,10,0,0,FALSE,FALSE,FALSE,54,1,0,0,0,0,"10 * 10-byte message" -3,"L",1,1,0,1,0,10,10,0,0,FALSE,TRUE,FALSE,54,1,0,0,0,0,"1 * 10-byte message [transient]" -4,"L",1,10,0,10,0,10,10,0,0,FALSE,TRUE,FALSE,54,1,0,0,0,0,"10 * 10-byte message [transient]" -5,"L",1,1,0,1,0,10,10,10,10,FALSE,FALSE,FALSE,64,1,0,0,0,0,"1 * 10-byte message [txn]" -6,"L",1,10,0,10,0,10,10,10,10,FALSE,FALSE,FALSE,64,1,0,0,0,0,"10 * 10-byte message [txn]" -7,"L",1,1,0,1,0,10,10,10,10,FALSE,TRUE,FALSE,64,1,0,0,0,0,"1 * 10-byte message [txn transient]" -8,"L",1,10,0,10,0,10,10,10,10,FALSE,TRUE,FALSE,64,1,0,0,0,0,"10 * 10-byte message [txn transient]" -9,"L",1,1,0,1,0,10,10,0,0,TRUE,FALSE,FALSE,54,1,32,1,0,0,"1 * 10-byte message [deq]" -10,"L",1,10,0,10,0,10,10,0,0,TRUE,FALSE,FALSE,54,1,32,1,0,0,"10 * 10-byte message [deq]" -11,"L",1,1,0,1,0,10,10,0,0,TRUE,TRUE,FALSE,54,1,32,1,0,0,"1 * 10-byte message [deq transient]" -12,"L",1,10,0,10,0,10,10,0,0,TRUE,TRUE,FALSE,54,1,32,1,0,0,"10 * 10-byte message [deq transient]" -13,"L",1,1,0,1,0,10,10,10,10,TRUE,FALSE,FALSE,64,1,54,1,46,1,"1 * 10-byte message [deq txn]" -14,"L",1,10,0,10,0,10,10,10,10,TRUE,FALSE,FALSE,64,1,54,1,46,1,"10 * 10-byte message [deq txn]" -15,"L",1,1,0,1,0,10,10,10,10,TRUE,TRUE,FALSE,64,1,54,1,46,1,"1 * 10-byte message [txn deq transient]" -16,"L",1,10,0,10,0,10,10,10,10,TRUE,TRUE,FALSE,64,1,54,1,46,1,"10 * 10-byte message [txn deq transient]" -17,"L",1,1,0,1,0,10,10,0,0,FALSE,FALSE,TRUE,54,1,0,0,0,0,"1 * 10-byte message [extern]" -18,"L",1,10,0,10,0,10,10,0,0,FALSE,FALSE,TRUE,54,1,0,0,0,0,"10 * 10-byte message [extern]" -19,"L",1,1,0,1,0,10,10,0,0,FALSE,TRUE,TRUE,54,1,0,0,0,0,"1 * 10-byte message [transient extern]" -20,"L",1,10,0,10,0,10,10,0,0,FALSE,TRUE,TRUE,54,1,0,0,0,0,"10 * 10-byte message [transient extern]" -21,"L",1,1,0,1,0,10,10,10,10,FALSE,FALSE,TRUE,64,1,0,0,0,0,"1 * 10-byte message [txn extern]" -22,"L",1,10,0,10,0,10,10,10,10,FALSE,FALSE,TRUE,64,1,0,0,0,0,"10 * 10-byte message [txn extern]" -23,"L",1,1,0,1,0,10,10,10,10,FALSE,TRUE,TRUE,64,1,0,0,0,0,"1 * 10-byte message [txn transient extern]" -24,"L",1,10,0,10,0,10,10,10,10,FALSE,TRUE,TRUE,64,1,0,0,0,0,"10 * 10-byte message [txn transient extern]" -25,"L",1,1,0,1,0,10,10,0,0,TRUE,FALSE,TRUE,54,1,32,1,0,0,"1 * 10-byte message [deq extern]" -26,"L",1,10,0,10,0,10,10,0,0,TRUE,FALSE,TRUE,54,1,32,1,0,0,"10 * 10-byte message [deq extern]" -27,"L",1,1,0,1,0,10,10,0,0,TRUE,TRUE,TRUE,54,1,32,1,0,0,"1 * 10-byte message [deq transient extern]" -28,"L",1,10,0,10,0,10,10,0,0,TRUE,TRUE,TRUE,54,1,32,1,0,0,"10 * 10-byte message [deq transient extern]" -29,"L",1,1,0,1,0,10,10,10,10,TRUE,FALSE,TRUE,64,1,54,1,46,1,"1 * 10-byte message [deq txn extern]" -30,"L",1,10,0,10,0,10,10,10,10,TRUE,FALSE,TRUE,64,1,54,1,46,1,"10 * 10-byte message [deq txn extern]" -31,"L",1,1,0,1,0,10,10,10,10,TRUE,TRUE,TRUE,64,1,54,1,46,1,"1 * 10-byte message [txn deq transient extern]" -32,"L",1,10,0,10,0,10,10,10,10,TRUE,TRUE,TRUE,64,1,54,1,46,1,"10 * 10-byte message [txn deq transient extern]" -,,,,,,,,,,,,,,,,,,,, -"Transition from one d-block to two per message",,,,,,,,,,,,,,,,,,,, -33,"L",1,10,0,10,0,84,84,0,0,FALSE,FALSE,FALSE,128,1,0,0,0,0,"1 dblk exact fit" -34,"L",1,10,0,10,1,85,85,0,0,FALSE,FALSE,FALSE,129,2,0,0,0,0,"1 dblk + 1 byte" -35,"L",1,10,0,10,0,58,58,26,26,FALSE,FALSE,FALSE,128,1,0,0,0,0,"1 dblk exact fit [txn]" -36,"L",1,10,0,10,1,59,59,26,26,FALSE,FALSE,FALSE,129,2,0,0,0,0,"1 dblk + 1 byte [txn]" -,,,,,,,,,,,,,,,,,,,, -"Transition from one s-block to two per message",,,,,,,,,,,,,,,,,,,, -37,"L",1,10,0,10,0,468,468,0,0,FALSE,FALSE,FALSE,512,4,0,0,0,0,"1 sblk exact fit" -38,"L",1,10,0,10,1,469,469,0,0,FALSE,FALSE,FALSE,513,5,0,0,0,0,"1 sblk + 1 byte" -39,"L",1,10,0,10,0,442,442,26,26,FALSE,FALSE,FALSE,512,4,0,0,0,0,"1 sblk exact fit [txn]" -40,"L",1,10,0,10,1,443,443,26,26,FALSE,FALSE,FALSE,513,5,0,0,0,0,"1 sblk + 1 byte [txn]" -,,,,,,,,,,,,,,,,,,,, -"Transition from first page to second",,,,,,,,,,,,,,,,,,,, -41,"L",1,8,0,8,0,4052,4052,0,0,FALSE,FALSE,FALSE,4096,32,0,0,0,0,"1/8 page" -42,"L",1,8,1,9,0,4052,4052,0,0,FALSE,FALSE,FALSE,4096,32,0,0,0,0,"1/8 page" -43,"L",1,8,0,8,1,4053,4053,0,0,FALSE,FALSE,FALSE,4097,33,0,0,0,0,"1/8 page + 1 byte" -44,"L",1,8,0,8,0,3796,3796,256,256,FALSE,FALSE,FALSE,4096,32,0,0,0,0,"1/8 page [txn]" -45,"L",1,8,1,9,0,3796,3796,256,256,FALSE,FALSE,FALSE,4096,32,0,0,0,0,"1/8 page [txn]" -46,"L",1,8,0,8,1,3797,3797,256,256,FALSE,FALSE,FALSE,4097,33,0,0,0,0,"1/8 page + 1 byte [txn]" -47,"L",1,8,0,8,0,3924,3924,0,0,TRUE,FALSE,FALSE,3968,31,32,1,0,0,"1/8 page incl deq [deq]" -48,"L",1,8,1,9,0,3924,3924,0,0,TRUE,FALSE,FALSE,3968,31,32,1,0,0,"1/8 page incl deq [deq]" -49,"L",1,8,0,8,1,3925,3925,0,0,TRUE,FALSE,FALSE,3969,32,32,1,0,0,"1/8 page incl deq + 1 byte [deq]" -50,"L",1,8,0,8,0,3028,3028,256,256,TRUE,FALSE,FALSE,3328,26,300,3,292,3,"1/8 page incl deq & txn [deq txn]" -51,"L",1,8,1,9,0,3028,3028,256,256,TRUE,FALSE,FALSE,3328,26,300,3,292,3,"1/8 page incl deq & txn [deq txn]" -52,"L",1,8,0,8,1,3029,3029,256,256,TRUE,FALSE,FALSE,3329,27,300,3,292,3,"1/8 page incl deq & txn + 1 byte [deq txn]" -,,,,,,,,,,,,,,,,,,,, -"Page cache rollover (from page 32 back to page 0)",,,,,,,,,,,,,,,,,,,, -53,"L",1,32,0,32,0,32724,32724,0,0,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"1 page" -54,"L",1,32,1,33,0,32724,32724,0,0,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"1 page" -55,"L",1,32,0,32,1,32725,32725,0,0,FALSE,FALSE,FALSE,32769,257,0,0,0,0,"1 page + 1 byte" -56,"L",1.5,22,0,22,0,49108,49108,0,0,FALSE,FALSE,FALSE,49152,384,0,0,0,0,"1.5 pages" -57,"L",1,32,0,32,0,32468,32468,256,256,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"1 page [txn]" -58,"L",1,32,1,33,0,32468,32468,256,256,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"1 page [txn]" -59,"L",1,32,0,32,1,32469,32469,256,256,FALSE,FALSE,FALSE,32769,257,0,0,0,0,"1 page + 1 byte [txn]" -60,"L",1.5,22,0,22,0,48852,48852,256,256,FALSE,FALSE,FALSE,49152,384,0,0,0,0,"1.5 pages [txn]" -61,"L",1,32,0,32,0,32596,32596,0,0,TRUE,FALSE,FALSE,32640,255,32,1,0,0,"1 page incl deq [deq]" -62,"L",1,32,1,33,0,32596,32596,0,0,TRUE,FALSE,FALSE,32640,255,32,1,0,0,"1 page incl deq [deq]" -63,"L",1,32,0,32,1,32597,32597,0,0,TRUE,FALSE,FALSE,32641,256,32,1,0,0,"1 page incl deq + 1 byte [deq]" -64,"L",1.5,22,0,22,0,48980,48980,0,0,TRUE,FALSE,FALSE,49024,383,32,1,0,0,"1.5 pages incl deq [deq]" -65,"L",1,32,0,32,0,31700,31700,256,256,TRUE,FALSE,FALSE,32000,250,300,3,292,3,"1 page incl deq & txn [deq txn]" -66,"L",1,32,1,33,0,31700,31700,256,256,TRUE,FALSE,FALSE,32000,250,300,3,292,3,"1 page incl deq & txn [deq txn]" -67,"L",1,32,0,32,1,31701,31701,256,256,TRUE,FALSE,FALSE,32001,251,300,3,292,3,"1 page incl deq & txn + 1 byte [deq txn]" -68,"L",1.5,22,0,22,0,48084,48084,256,256,TRUE,FALSE,FALSE,48384,378,300,3,292,3,"1.5 pages incl deq & txn [deq txn]" -,,,,,,,,,,,,,,,,,,,, -"File transition (from file 0000 to 0001)",,,,,,,,,,,,,,,,,,,, -69,"L",1,48,0,48,0,32724,32724,0,0,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"1 page" -70,"L",1,48,1,49,0,32724,32724,0,0,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"1 page" -71,"L",1,48,0,48,1,32725,32725,0,0,FALSE,FALSE,FALSE,32769,257,0,0,0,0,"1 page + 1 byte" -72,"L",2.5,20,0,20,0,81876,81876,0,0,FALSE,FALSE,FALSE,81920,640,0,0,0,0,"2.5 pages" -73,"L",1,48,0,48,0,32468,32468,256,256,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"1 page [txn]" -74,"L",1,48,1,49,0,32468,32468,256,256,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"1 page [txn]" -75,"L",1,48,0,48,1,32469,32469,256,256,FALSE,FALSE,FALSE,32769,257,0,0,0,0,"1 page + 1 byte [txn]" -76,"L",2.5,20,0,20,0,81620,81620,256,256,FALSE,FALSE,FALSE,81920,640,0,0,0,0,"2.5 pages [txn]" -77,"L",1,48,0,48,0,32596,32596,0,0,TRUE,FALSE,FALSE,32640,255,32,1,0,0,"1 page incl deq [deq]" -78,"L",1,48,1,49,0,32596,32596,0,0,TRUE,FALSE,FALSE,32640,255,32,1,0,0,"1 page incl deq [deq]" -79,"L",1,48,0,48,1,32597,32597,0,0,TRUE,FALSE,FALSE,32641,256,32,1,0,0,"1 page incl deq + 1 byte [deq]" -80,"L",2.5,20,0,20,0,81748,81748,0,0,TRUE,FALSE,FALSE,81792,639,32,1,0,0,"2.5 pages incl deq [deq]" -81,"L",1,48,0,48,0,31700,31700,256,256,TRUE,FALSE,FALSE,32000,250,300,3,292,3,"1 page incl deq & txn [deq txn]" -82,"L",1,48,1,49,0,31700,31700,256,256,TRUE,FALSE,FALSE,32000,250,300,3,292,3,"1 page incl deq & txn [deq txn]" -83,"L",1,48,0,48,1,31701,31701,256,256,TRUE,FALSE,FALSE,32001,251,300,3,292,3,"1 page incl deq & txn + 1 byte [deq txn]" -84,"L",2.5,20,0,20,0,80852,80852,256,256,TRUE,FALSE,FALSE,81152,634,300,3,292,3,"2.5 pages incl deq & txn [deq txn]" -,,,,,,,,,,,,,,,,,,,, -"File rollover (from file 0007 to 0000) - RHM_WRONLY req'd for auto-dequeue == FALSE",,,,,,,,,,,,,,,,,,,, -85,"L",0.5,16,0,16,0,786260,786260,0,0,TRUE,FALSE,FALSE,786304,6143,32,1,0,0,"24 pages incl deq = ½ file [deq]" -86,"L",0.5,16,1,17,0,786260,786260,0,0,TRUE,FALSE,FALSE,786304,6143,32,1,0,0,"24 pages incl deq = ½ file [deq]" -87,"L",0.5,16,0,16,1,786261,786261,0,0,TRUE,FALSE,FALSE,786305,6144,32,1,0,0,"24 pages incl deq + 1 byte [deq]" -88,"L",0.5,16,0,16,0,785364,785364,256,256,TRUE,FALSE,FALSE,785664,6138,300,3,292,3,"24 pages incl deq & txn = ½ file [deq txn]" -89,"L",0.5,16,1,17,0,785364,785364,256,256,TRUE,FALSE,FALSE,785664,6138,300,3,292,3,"24 pages incl deq & txn = ½ file [deq txn]" -90,"L",0.5,16,0,16,1,785365,785365,256,256,TRUE,FALSE,FALSE,785665,6139,300,3,292,3,"24 pages incl deq & txn + 1 byte [deq txn]" -91,"L",0.25,32,0,32,0,786260,786260,0,0,TRUE,FALSE,FALSE,786304,6143,32,1,0,0,"24 pages incl deq = ½ file [deq]" -92,"L",0.25,32,1,33,0,786260,786260,0,0,TRUE,FALSE,FALSE,786304,6143,32,1,0,0,"24 pages incl deq = ½ file [deq]" -93,"L",0.25,32,0,32,1,786261,786261,0,0,TRUE,FALSE,FALSE,786305,6144,32,1,0,0,"24 pages incl deq + 1 byte [deq]" -94,"L",0.25,32,0,32,0,785364,785364,256,256,TRUE,FALSE,FALSE,785664,6138,300,3,292,3,"24 pages incl deq & txn = ½ file [deq txn]" -95,"L",0.25,32,1,33,0,785364,785364,256,256,TRUE,FALSE,FALSE,785664,6138,300,3,292,3,"24 pages incl deq & txn = ½ file [deq txn]" -96,"L",0.25,32,0,32,1,785365,785365,256,256,TRUE,FALSE,FALSE,785665,6139,300,3,292,3,"24 pages incl deq & txn + 1 byte [deq txn]" -,,,,,,,,,,,,,,,,,,,, -"Multi-page messages (large messages) - tests various paths in encoder.",,,,,,,,,,,,,,,,,,,, -97,"L",1,16,0,16,0,32724,32724,0,0,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"data 1 page" -98,"L",1,16,0,16,1,32725,32725,0,0,FALSE,FALSE,FALSE,32769,257,0,0,0,0,"data 1 page + 1 byte (tail split; 1 byte over page boundary)" -99,"L",1,16,0,16,11,32735,32735,0,0,FALSE,FALSE,FALSE,32779,257,0,0,0,0,"data 1 page + 11 bytes (tail split; 11 bytes over page boundary)" -100,"L",1,16,0,16,12,32736,32736,0,0,FALSE,FALSE,FALSE,32780,257,0,0,0,0,"data 1 page + 12 bytes (tail separated exactly onto next page)" -101,"L",1,16,0,16,13,32737,32737,0,0,FALSE,FALSE,FALSE,32781,257,0,0,0,0,"data 1 page + 13 bytes (data split; 1 byte over page boundary)" -102,"L",1,16,0,16,0,32468,32468,256,256,FALSE,FALSE,FALSE,32768,256,0,0,0,0,"data 1 page [txn]" -103,"L",1,16,0,16,1,32469,32469,256,256,FALSE,FALSE,FALSE,32769,257,0,0,0,0,"data 1 page + 1 byte (tail split; 1 byte over page boundary) [txn]" -104,"L",1,16,0,16,11,32479,32479,256,256,FALSE,FALSE,FALSE,32779,257,0,0,0,0,"data 1 page + 11 bytes (tail split; 11 bytes over page boundary) [txn]" -105,"L",1,16,0,16,12,32480,32480,256,256,FALSE,FALSE,FALSE,32780,257,0,0,0,0,"data 1 page + 12 bytes (tail separated exactly onto next page) [txn]" -106,"L",1,16,0,16,13,32481,32481,256,256,FALSE,FALSE,FALSE,32781,257,0,0,0,0,"data 1 page + 13 bytes (data split; 1 byte over page boundary) [txn]" -107,"L",2,16,0,16,0,65492,65492,0,0,FALSE,FALSE,FALSE,65536,512,0,0,0,0,"data 2 pages" -108,"L",2,16,0,16,1,65493,65493,0,0,FALSE,FALSE,FALSE,65537,513,0,0,0,0,"data 2 pages + 1 byte (tail split; 1 byte over page boundary)" -109,"L",2,16,0,16,11,65503,65503,0,0,FALSE,FALSE,FALSE,65547,513,0,0,0,0,"data 2 pages + 11 bytes (tail split; 11 bytes over page boundary)" -110,"L",2,16,0,16,12,65504,65504,0,0,FALSE,FALSE,FALSE,65548,513,0,0,0,0,"data 2 pages + 12 bytes (tail separated exactly onto next page)" -111,"L",2,16,0,16,13,65505,65505,0,0,FALSE,FALSE,FALSE,65549,513,0,0,0,0,"data 2 pages + 13 bytes (data split; 1 byte over page boundary)" -112,"L",2,16,0,16,0,65236,65236,256,256,FALSE,FALSE,FALSE,65536,512,0,0,0,0,"data 2 pages [txn]" -113,"L",2,16,0,16,1,65237,65237,256,256,FALSE,FALSE,FALSE,65537,513,0,0,0,0,"data 2 pages + 1 byte (tail split; 1 byte over page boundary) [txn]" -114,"L",2,16,0,16,11,65247,65247,256,256,FALSE,FALSE,FALSE,65547,513,0,0,0,0,"data 2 pages + 11 bytes (tail split; 11 bytes over page boundary) [txn]" -115,"L",2,16,0,16,12,65248,65248,256,256,FALSE,FALSE,FALSE,65548,513,0,0,0,0,"data 2 pages + 12 bytes (tail separated exactly onto next page) [txn]" -116,"L",2,16,0,16,13,65249,65249,256,256,FALSE,FALSE,FALSE,65549,513,0,0,0,0,"data 2 pages + 13 bytes (data split; 1 byte over page boundary) [txn]" -117,"L",4,16,0,16,0,131028,131028,0,0,FALSE,FALSE,FALSE,131072,1024,0,0,0,0,"data 4 pages" -118,"L",4,16,0,16,1,131029,131029,0,0,FALSE,FALSE,FALSE,131073,1025,0,0,0,0,"data 4 pages + 1 byte (tail split; 1 byte over page boundary)" -119,"L",4,16,0,16,11,131039,131039,0,0,FALSE,FALSE,FALSE,131083,1025,0,0,0,0,"data 4 pages + 11 bytes (tail split; 11 bytes over page boundary)" -120,"L",4,16,0,16,12,131040,131040,0,0,FALSE,FALSE,FALSE,131084,1025,0,0,0,0,"data 4 pages + 12 bytes (tail separated exactly onto next page)" -121,"L",4,16,0,16,13,131041,131041,0,0,FALSE,FALSE,FALSE,131085,1025,0,0,0,0,"data 4 pages + 13 bytes (data split; 1 byte over page boundary)" -122,"L",4,16,0,16,0,130772,130772,256,256,FALSE,FALSE,FALSE,131072,1024,0,0,0,0,"data 4 pages [txn]" -123,"L",4,16,0,16,1,130773,130773,256,256,FALSE,FALSE,FALSE,131073,1025,0,0,0,0,"data 4 pages + 1 byte (tail split; 1 byte over page boundary) [txn]" -124,"L",4,16,0,16,11,130783,130783,256,256,FALSE,FALSE,FALSE,131083,1025,0,0,0,0,"data 4 pages + 11 bytes (tail split; 11 bytes over page boundary) [txn]" -125,"L",4,16,0,16,12,130784,130784,256,256,FALSE,FALSE,FALSE,131084,1025,0,0,0,0,"data 4 pages + 12 bytes (tail separated exactly onto next page) [txn]" -126,"L",4,16,0,16,13,130785,130785,256,256,FALSE,FALSE,FALSE,131085,1025,0,0,0,0,"data 4 pages + 13 bytes (data split; 1 byte over page boundary) [txn]" -127,"L",3.5,16,0,16,0,114644,114644,0,0,FALSE,FALSE,FALSE,114688,896,0,0,0,0,"data 3.5 pages" -128,"L",3.5,16,0,16,1,114645,114645,0,0,FALSE,FALSE,FALSE,114689,897,0,0,0,0,"data 3.5 pages + 1 byte" -129,"L",3.5,16,0,16,0,114388,114388,256,256,FALSE,FALSE,FALSE,114688,896,0,0,0,0,"data 3.5 pages [txn]" -130,"L",3.5,16,0,16,1,114389,114389,256,256,FALSE,FALSE,FALSE,114689,897,0,0,0,0,"data 3.5 pages + 1 byte [txn]" -131,"L",1,16,0,16,-1,10,10,32735,32735,FALSE,FALSE,FALSE,32789,257,0,0,0,0,"xid 1 page – 1 byte; data 10 bytes (exact fit) [txn]" -132,"L",1,16,0,16,0,10,10,32736,32736,FALSE,FALSE,FALSE,32790,257,0,0,0,0,"xid 1 page; data 10 bytes (exact fit) [txn]" -133,"L",1,16,0,16,1,10,10,32737,32737,FALSE,FALSE,FALSE,32791,257,0,0,0,0,"xid 1 page + 1 byte; data 10 bytes (exact fit) [txn]" -134,"L",2,16,0,16,-1,10,10,65503,65503,FALSE,FALSE,FALSE,65557,513,0,0,0,0,"xid 2 pages – 1 byte; data 10 bytes (exact fit) [txn]" -135,"L",2,16,0,16,0,10,10,65504,65504,FALSE,FALSE,FALSE,65558,513,0,0,0,0,"xid 2 pages; data 10 bytes (exact fit) [txn]" -136,"L",2,16,0,16,1,10,10,65505,65505,FALSE,FALSE,FALSE,65559,513,0,0,0,0,"xid 2 pages + 1 byte; data 10 bytes (exact fit) [txn]" -137,"L",4,16,0,16,-1,10,10,131039,131039,FALSE,FALSE,FALSE,131093,1025,0,0,0,0,"xid 4 pages – 1 byte; data 10 bytes (exact fit) [txn]" -138,"L",4,16,0,16,0,10,10,131040,131040,FALSE,FALSE,FALSE,131094,1025,0,0,0,0,"xid 4 pages; data 10 bytes (exact fit) [txn]" -139,"L",4,16,0,16,1,10,10,131041,131041,FALSE,FALSE,FALSE,131095,1025,0,0,0,0,"xid 4 pages + 1 byte; data 10 bytes (exact fit) [txn]" -140,"L",3.5,16,0,16,0,10,10,114656,114656,FALSE,FALSE,FALSE,114710,897,0,0,0,0,"xid 3.5 pages; data 10 bytes (exact fit) [txn]" -141,"L",3.5,16,0,16,1,10,10,114657,114657,FALSE,FALSE,FALSE,114711,897,0,0,0,0,"xid 3.5 pages + 1 byte; data 10 bytes (exact fit) [txn]" -142,"L",1,16,0,16,-1,10,10,32735,32735,TRUE,FALSE,FALSE,32789,257,32779,257,32771,257,"xid 1 page – 1 byte for enq rec; data 10 bytes (exact fit) [deq, txn]" -143,"L",1,16,0,16,0,10,10,32736,32736,TRUE,FALSE,FALSE,32790,257,32780,257,32772,257,"xid 1 page for enq rec; data 10 bytes (exact fit) [deq, txn]" -144,"L",1,16,0,16,1,10,10,32737,32737,TRUE,FALSE,FALSE,32791,257,32781,257,32773,257,"xid 1 page + 1 byte for enq rec; data 10 bytes (exact fit) [deq, txn]" -145,"L",2,16,0,16,-1,10,10,65503,65503,TRUE,FALSE,FALSE,65557,513,65547,513,65539,513,"xid 2 pages – 1 byte for enq rec; data 10 bytes (exact fit) [deq, txn]" -146,"L",2,16,0,16,0,10,10,65504,65504,TRUE,FALSE,FALSE,65558,513,65548,513,65540,513,"xid 2 pages for enq rec; data 10 bytes (exact fit) [deq, txn]" -147,"L",2,16,0,16,1,10,10,65505,65505,TRUE,FALSE,FALSE,65559,513,65549,513,65541,513,"xid 2 pages + 1 byte for enq rec; data 10 bytes (exact fit) [deq, txn]" -148,"L",4,16,0,16,-1,10,10,131039,131039,TRUE,FALSE,FALSE,131093,1025,131083,1025,131075,1025,"xid 4 pages – 1 byte for enq rec; data 10 bytes (exact fit) [deq, txn]" -149,"L",4,16,0,16,0,10,10,131040,131040,TRUE,FALSE,FALSE,131094,1025,131084,1025,131076,1025,"xid 4 pages for enq rec; data 10 bytes (exact fit) [deq, txn]" -150,"L",4,16,0,16,1,10,10,131041,131041,TRUE,FALSE,FALSE,131095,1025,131085,1025,131077,1025,"xid 4 pages + 1 byte for enq rec; data 10 bytes (exact fit) [deq, txn]" -151,"L",3.5,16,0,16,0,10,10,114656,114656,TRUE,FALSE,FALSE,114710,897,114700,897,114692,897,"xid 3.5 pages for enq rec; data 10 bytes (exact fit) [deq, txn]" -152,"L",3.5,16,0,16,1,10,10,114657,114657,TRUE,FALSE,FALSE,114711,897,114701,897,114693,897,"xid 3.5 pages + 1 byte for enq rec; data 10 bytes (exact fit) [deq, txn]" -153,"L",1,16,0,16,-1,10,10,32735,32735,TRUE,FALSE,FALSE,32789,257,32779,257,32771,257,"xid 1 page – 1 byte for deq rec; data 10 bytes (exact fit) [deq, txn]" -154,"L",1,16,0,16,0,10,10,32736,32736,TRUE,FALSE,FALSE,32790,257,32780,257,32772,257,"xid 1 page for deq rec; data 10 bytes (exact fit) [deq, txn]" -155,"L",1,16,0,16,1,10,10,32737,32737,TRUE,FALSE,FALSE,32791,257,32781,257,32773,257,"xid 1 page + 1 byte for deq rec; data 10 bytes (exact fit) [deq, txn]" -156,"L",2,16,0,16,-1,10,10,65503,65503,TRUE,FALSE,FALSE,65557,513,65547,513,65539,513,"xid 2 pages – 1 byte for deq rec; data 10 bytes (exact fit) [deq, txn]" -157,"L",2,16,0,16,0,10,10,65504,65504,TRUE,FALSE,FALSE,65558,513,65548,513,65540,513,"xid 2 pages for deq rec; data 10 bytes (exact fit) [deq, txn]" -158,"L",2,16,0,16,1,10,10,65505,65505,TRUE,FALSE,FALSE,65559,513,65549,513,65541,513,"xid 2 pages + 1 byte for deq rec; data 10 bytes (exact fit) [deq, txn]" -159,"L",4,16,0,16,-1,10,10,131039,131039,TRUE,FALSE,FALSE,131093,1025,131083,1025,131075,1025,"xid 4 pages – 1 byte for deq rec; data 10 bytes (exact fit) [deq, txn]" -160,"L",4,16,0,16,0,10,10,131040,131040,TRUE,FALSE,FALSE,131094,1025,131084,1025,131076,1025,"xid 4 pages for deq rec; data 10 bytes (exact fit) [deq, txn]" -161,"L",4,16,0,16,1,10,10,131041,131041,TRUE,FALSE,FALSE,131095,1025,131085,1025,131077,1025,"xid 4 pages + 1 byte for deq rec; data 10 bytes (exact fit) [deq, txn]" -162,"L",3.5,16,0,16,0,10,10,114656,114656,TRUE,FALSE,FALSE,114710,897,114700,897,114692,897,"xid 3.5 pages for deq rec; data 10 bytes (exact fit) [deq, txn]" -163,"L",3.5,16,0,16,1,10,10,114657,114657,TRUE,FALSE,FALSE,114711,897,114701,897,114693,897,"xid 3.5 pages + 1 byte for deq rec; data 10 bytes (exact fit) [deq, txn]" -164,"L",1,16,0,16,-1,10,10,32743,32743,TRUE,FALSE,FALSE,32797,257,32787,257,32779,257,"xid 1 page – 1 byte for txn rec; data 10 bytes (exact fit) [deq, txn]" -165,"L",1,16,0,16,0,10,10,32744,32744,TRUE,FALSE,FALSE,32798,257,32788,257,32780,257,"xid 1 page for txn rec; data 10 bytes (exact fit) [deq, txn]" -166,"L",1,16,0,16,1,10,10,32745,32745,TRUE,FALSE,FALSE,32799,257,32789,257,32781,257,"xid 1 page + 1 byte for txn rec; data 10 bytes (exact fit) [deq, txn]" -167,"L",2,16,0,16,-1,10,10,65511,65511,TRUE,FALSE,FALSE,65565,513,65555,513,65547,513,"xid 2 pages – 1 byte for txn rec; data 10 bytes (exact fit) [deq, txn]" -168,"L",2,16,0,16,0,10,10,65512,65512,TRUE,FALSE,FALSE,65566,513,65556,513,65548,513,"xid 2 pages for txn rec; data 10 bytes (exact fit) [deq, txn]" -169,"L",2,16,0,16,1,10,10,65513,65513,TRUE,FALSE,FALSE,65567,513,65557,513,65549,513,"xid 2 pages + 1 byte for txn rec; data 10 bytes (exact fit) [deq, txn]" -170,"L",4,16,0,16,-1,10,10,131047,131047,TRUE,FALSE,FALSE,131101,1025,131091,1025,131083,1025,"xid 4 pages – 1 byte for txn rec; data 10 bytes (exact fit) [deq, txn]" -171,"L",4,16,0,16,0,10,10,131048,131048,TRUE,FALSE,FALSE,131102,1025,131092,1025,131084,1025,"xid 4 pages for txn rec; data 10 bytes (exact fit) [deq, txn]" -172,"L",4,16,0,16,1,10,10,131049,131049,TRUE,FALSE,FALSE,131103,1025,131093,1025,131085,1025,"xid 4 pages + 1 byte for txn rec; data 10 bytes (exact fit) [deq, txn]" -173,"L",3.5,16,0,16,0,10,10,114664,114664,TRUE,FALSE,FALSE,114718,897,114708,897,114700,897,"xid 3.5 pages for txn rec; data 10 bytes (exact fit) [deq, txn]" -174,"L",3.5,16,0,16,1,10,10,114665,114665,TRUE,FALSE,FALSE,114719,897,114709,897,114701,897,"xid 3.5 pages + 1 byte for txn rec; data 10 bytes (exact fit) [deq, txn]" -,,,,,,,,,,,,,,,,,,,, -"High volume tests of random message lengths - RHM_WRONLY req'd for auto-dequeue == FALSE",,,,,,,,,,,,,,,,,,,, -#175,"M",1,5000000,0,5000000,0,0,84,0,0,TRUE,FALSE,FALSE,128,1,32,1,0,0,"1 dblk max [deq]" -#176,"M",3,3000000,0,3000000,0,0,340,0,0,TRUE,FALSE,FALSE,384,3,32,1,0,0,"3 dblks max [deq]" -#177,"M",10,1600000,0,1600000,0,0,1236,0,0,TRUE,FALSE,FALSE,1280,10,32,1,0,0,"10 dblks max [deq]" -#178,"M",30,600000,0,600000,0,0,3796,0,0,TRUE,FALSE,FALSE,3840,30,32,1,0,0,"30 dblks max [deq]" -#179,"M",100,200000,0,200000,0,0,12756,0,0,TRUE,FALSE,FALSE,12800,100,32,1,0,0,"100 dblks max [deq]" -#180,"M",300,60000,0,60000,0,0,38356,0,0,TRUE,FALSE,FALSE,38400,300,32,1,0,0,"300 dblks max [deq]" -#181,"M",1000,20000,0,20000,0,0,127956,0,0,TRUE,FALSE,FALSE,128000,1000,32,1,0,0,"1000 dblks max [deq]" -#182,"M",1,5000000,0,5000000,0,0,100,1,100,TRUE,FALSE,FALSE,244,2,144,2,136,2,"100 bytes xid max + 100 bytes data max [deq txn]" -#183,"M",3,3000000,0,3000000,0,0,300,1,300,TRUE,FALSE,FALSE,644,6,344,3,336,3,"300 bytes xid max + 300 bytes data max [deq txn]" -#184,"M",10,1600000,0,1600000,0,0,1000,1,1000,TRUE,FALSE,FALSE,2044,16,1044,9,1036,9,"1000 bytes xid max + 1000 bytes data max [deq txn]" -#185,"M",30,600000,0,600000,0,0,3000,1,3000,TRUE,FALSE,FALSE,6044,48,3044,24,3036,24,"3000 bytes xid max + 3000 bytes data max [deq txn]" -#186,"M",100,200000,0,200000,0,0,10000,1,10000,TRUE,FALSE,FALSE,20044,157,10044,79,10036,79,"10000 bytes xid max + 10000 bytes data max [deq txn]" -#187,"M",300,60000,0,60000,0,0,30000,1,30000,TRUE,FALSE,FALSE,60044,470,30044,235,30036,235,"30000 bytes xid max + 30000 bytes data max [deq txn]" -#188,"M",1000,20000,0,20000,0,0,100000,1,100000,TRUE,FALSE,FALSE,200044,1563,100044,782,100036,782,"100000 bytes xid max + 100000 bytes data max [deq txn]" -,,,,,,,,,,,,,,,,,,,, -"STANDARD PERFORMANCE BENCHMARK: 10,000,000 writes, data=212b (2 dblks)",,,,,,,,,,,,,,,,,,,, -#189,"M",1,10000000,0,10000000,0,212,212,0,0,TRUE,FALSE,FALSE,256,2,32,1,0,0,"212 bytes data (2 dblks enq + 1 dblk deq)" -#190,"M",1,10000000,0,10000000,0,148,148,64,64,TRUE,FALSE,FALSE,256,2,108,1,100,1,"148 bytes data + 64 bytes xid (2 dblks enq + 1 dblks deq + 1 dblks txn)" diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/main.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/main.cpp deleted file mode 100644 index c8a4642b1c..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/main.cpp +++ /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. - * - */ - -#include "test_mgr.h" - -#include "args.h" -#include -#include - -#define PACKAGE_NAME "Journal Test Tool" -#define VERSION "0.1" - -namespace po = boost::program_options; - -int main(int argc, char** argv) -{ - std::signal(SIGINT, mrg::jtt::test_mgr::signal_handler); - std::signal(SIGTERM, mrg::jtt::test_mgr::signal_handler); - - std::cout << PACKAGE_NAME << " v." << VERSION << std::endl; - - std::ostringstream oss; - oss << PACKAGE_NAME << " options"; - mrg::jtt::args args(oss.str()); - if (args.parse(argc, argv)) return 1; - - try - { - mrg::jtt::test_mgr tm(args); - tm.run(); - if (tm.error()) return 2; // One or more tests threw exceptions - } - catch (const std::exception& e) - { - std::cerr << e.what() << std::endl; - return 3; - } - return 0; -} diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.cpp deleted file mode 100644 index 94a07c7005..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.cpp +++ /dev/null @@ -1,93 +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 "read_arg.h" - -#include -#include -namespace po = boost::program_options; - -namespace mrg -{ -namespace jtt -{ -std::map read_arg::_map; -std::string read_arg::_description; -const bool read_arg::init = __init(); - -// static init fn -bool -read_arg::__init() -{ - // Set string versions of each enum option here - _map["NONE"] = NONE; - _map["ALL"] = ALL; - _map["RANDOM"] = RANDOM; - _map["LAZYLOAD"] = LAZYLOAD; - _description = "Determines if and when messages will be read prior to dequeueing. " - "Values: (NONE | ALL | RANDOM | LAZYLOAD)"; - return true; -} - -void -read_arg::parse(const std::string& str) -{ - std::map::const_iterator i = _map.find(str); - if (i == _map.end()) - throw po::invalid_option_value(str); - _rm = i->second; -} - -// static fn -const std::string& -read_arg::str(const read_mode_t rm) -{ - std::map::const_iterator i = _map.begin(); - while (i->second != rm && i != _map.end()) i++; - assert(i != _map.end()); - return i->first; -} - -// static fn -const std::string& -read_arg::descr() -{ - return _description; -} - -std::ostream& -operator<<(std::ostream& os, const read_arg& ra) -{ - os << ra.str(); - return os; -} - -std::istream& -operator>>(std::istream& is, read_arg& ra) -{ - std::string s; - is >> s; - ra.parse(s); - return is; -} - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.h deleted file mode 100644 index a8fd6f198e..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/read_arg.h +++ /dev/null @@ -1,62 +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. - * - */ - -#ifndef mrg_jtt_read_arg_hpp -#define mrg_jtt_read_arg_hpp - -#include -#include - -namespace mrg -{ -namespace jtt -{ - -class read_arg -{ - public: - enum read_mode_t { NONE, ALL, RANDOM, LAZYLOAD}; - private: - static std::map _map; - static std::string _description; - static const bool init; - static bool __init(); - read_mode_t _rm; - public: - inline read_arg() : _rm(NONE) {} - inline read_arg(read_mode_t rm) : _rm(rm) {} - - inline read_mode_t val() const { return _rm; } - inline void set_val(const read_mode_t rm) { _rm = rm; } - void parse(const std::string& str); - - inline const std::string& str() const { return str(_rm); } - static const std::string& str(const read_mode_t rm); - static const std::string& descr(); - - friend std::ostream& operator<<(std::ostream& os, const read_arg& ra); - friend std::istream& operator>>(std::istream& is, read_arg& ra); -}; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_read_arg_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case.cpp deleted file mode 100644 index e06e053504..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "test_case.h" - -#include -#include -#include - -namespace mrg -{ -namespace jtt -{ - -test_case::test_case(const unsigned test_case_num, const u_int32_t num_msgs, - const std::size_t min_data_size, const std::size_t max_data_size, const bool auto_deq, - const std::size_t min_xid_size, const std::size_t max_xid_size, const transient_t transient, - const external_t external, const std::string& comment): - _test_case_num(test_case_num), - _num_msgs(num_msgs), - _min_data_size(min_data_size), - _max_data_size(max_data_size), - _auto_dequeue(auto_deq), - _min_xid_size(min_xid_size), - _max_xid_size(max_xid_size), - _transient(transient), - _external(external), - _comment(comment), - _result_average(), - _result_jmap() -{} - -test_case::~test_case() -{} - -std::size_t -test_case::this_data_size() const -{ - if (_min_data_size == _max_data_size) - return _max_data_size; - std::size_t size_diff = _max_data_size - _min_data_size; - return _min_data_size + std::size_t(1.0 * std::rand() * size_diff/(RAND_MAX + 1.0)); -} - -std::size_t -test_case::this_xid_size() const -{ - // TODO: rework when probabilities are introduced. Assume 50% if _min_xid_size = 0 - if (_max_xid_size == 0) - return std::size_t(0); - if (_min_xid_size == 0) - { - if (1.0 * std::rand() / RAND_MAX < 0.5) - return std::size_t(0); - } - std::size_t size_diff = _max_xid_size - _min_xid_size; - return _min_xid_size + std::size_t(1.0 * std::rand() * size_diff/(RAND_MAX + 1.0)); -} - -bool -test_case::this_transience() const -{ - // TODO: rework when probabilities are introduced. Assume 50% if JTT_RANDOM - if (_transient == JTT_TRANSIENT) - return false; - if (_transient == JTT_PERSISTNET) - return true; - return 1.0 * std::rand() / RAND_MAX < 0.5; -} - -bool -test_case::this_external() const -{ - // TODO: rework when probabilities are introduced. Assume 50% if JDL_RANDOM - if (_external == JDL_INTERNAL) - return false; - if (_external == JDL_EXTERNAL) - return true; - return 1.0 * std::rand() / RAND_MAX < 0.5; -} - -void -test_case::add_result(test_case_result::shared_ptr& tcrp) -{ - _result_average.add_test_result(tcrp); - res_map_citr ari = _result_jmap.find(tcrp->jid()); - if (ari == _result_jmap.end()) - { - test_case_result_agregation::shared_ptr p(new test_case_result_agregation(tcrp->jid())); - p->add_test_result(tcrp); - _result_jmap.insert(res_map_pair(tcrp->jid(), p)); - } - else - ari->second->add_test_result(tcrp); -} - -void -test_case::set_fmt_chk_res(const bool res, const std::string& jid) -{ - _result_average.set_fmt_chk_res(res); - res_map_citr ari = _result_jmap.find(jid); - if (ari != _result_jmap.end()) - ari->second->set_fmt_chk_res(res); -} - -const test_case_result::shared_ptr -test_case::jmap_last(std::string& jid) const -{ - res_map_citr i = _result_jmap.find(jid); - if (i == _result_jmap.end()) - return test_case_result::shared_ptr(); - u_int32_t num_res = (*i).second->num_results(); - if (num_res) - return (*(*i).second)[num_res - 1]; - return test_case_result::shared_ptr(); -} - -void -test_case::clear() -{ - _result_average.clear(); - _result_jmap.clear(); -} - -const std::string -test_case::str() const -{ - std::ostringstream oss; - oss << "Test Parameters: Test case no. " << _test_case_num << ":" << std::endl; - oss << " Comment: " << _comment << std::endl; - oss << " Number of messages: " << _num_msgs << std::endl; - oss << " Data size: " << _min_data_size; - if (_min_data_size == _max_data_size) - oss << " bytes (fixed)" << std::endl; - else - oss << " - " << _max_data_size << " bytes" << std::endl; - oss << " XID size: " << _min_xid_size; - if (_min_xid_size == _max_xid_size) - oss << " bytes (fixed)" << std::endl; - else - oss << " - " << _max_xid_size << " bytes" << std::endl; - oss << " Auto-dequeue: " << (_auto_dequeue ? "true" : "false") << std::endl; - oss << " Persistence: "; - switch (_transient) - { - case JTT_TRANSIENT: oss << "TRANSIENT" << std::endl; break; - case JTT_PERSISTNET: oss << "PERSISTNET" << std::endl; break; - case JTT_RANDOM: oss << "RANDOM" << std::endl; break; - } - oss << " Message Data: "; - switch (_external) - { - case JDL_INTERNAL: oss << "INTERNAL"; break; - case JDL_EXTERNAL: oss << "EXTERNAL"; break; - case JDL_RANDOM: oss << "RANDOM"; break; - } - return oss.str(); -} - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case.h deleted file mode 100644 index f72dd05f0c..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case.h +++ /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. - * - */ - -#ifndef mrg_jtt_test_case_hpp -#define mrg_jtt_test_case_hpp - -#include -#include -#include -#include "test_case_result.h" -#include "test_case_result_agregation.h" -#include - -namespace mrg -{ -namespace jtt -{ - - class test_case - { - public: - enum transient_type { JTT_TRANSIENT = 0, JTT_PERSISTNET, JTT_RANDOM }; - typedef transient_type transient_t; - - enum data_location { JDL_INTERNAL = 0, JDL_EXTERNAL, JDL_RANDOM }; - typedef data_location external_t; - - typedef boost::shared_ptr shared_ptr; - - typedef std::map res_map; - typedef std::pair res_map_pair; - typedef res_map::const_iterator res_map_citr; - - private: - unsigned _test_case_num; - u_int32_t _num_msgs; - std::size_t _min_data_size; - std::size_t _max_data_size; - bool _auto_dequeue; - // TODO: add probability of transaction to these params - std::size_t _min_xid_size; - std::size_t _max_xid_size; - // TODO: change these enums (transient_t & external_t) to probabilities - transient_t _transient; - external_t _external; - std::string _comment; - - test_case_result_agregation _result_average; // overall average result - res_map _result_jmap; // map of per-journal averages - - public: - test_case(const unsigned test_case_num, const u_int32_t num_msgs, - const std::size_t min_data_size, const std::size_t max_data_size, - const bool auto_deq, const std::size_t min_xid_size, - const std::size_t max_xid_size, const transient_t transient, - const external_t external, const std::string& comment); - virtual ~test_case(); - - inline unsigned test_case_num() const { return _test_case_num; } - inline u_int32_t num_msgs() const { return _num_msgs; } - inline std::size_t min_data_size() const { return _min_data_size; } - inline std::size_t max_data_size() const { return _max_data_size; } - std::size_t this_data_size() const; - inline bool auto_deq() const { return _auto_dequeue; } - inline std::size_t min_xid_size() const { return _min_xid_size; } - inline std::size_t max_xid_size() const { return _max_xid_size; } - std::size_t this_xid_size() const; - inline transient_t transient() const { return _transient; } - bool this_transience() const; - inline external_t external() const { return _external; } - bool this_external() const; - inline const std::string& comment() const { return _comment; } - - void add_result(test_case_result::shared_ptr& p); - void set_fmt_chk_res(const bool res, const std::string& jid); - - inline const test_case_result_agregation& average() const { return _result_average; } - inline u_int32_t num_results() const { return _result_average.num_results(); } - inline unsigned num_jrnls() const { return _result_jmap.size(); } - inline res_map_citr jrnl_average(std::string& jid) const { return _result_jmap.find(jid); } - inline res_map_citr jmap_begin() const { return _result_jmap.begin(); } - inline res_map_citr jmap_end() const { return _result_jmap.end(); } - const test_case_result::shared_ptr jmap_last(std::string& jid) const; - - void clear(); - const std::string str() const; - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_test_case_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result.cpp deleted file mode 100644 index 2f88f265a5..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result.cpp +++ /dev/null @@ -1,201 +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 "test_case_result.h" - -#include -#include - -namespace mrg -{ -namespace jtt -{ - -test_case_result::test_case_result(const std::string& jid): - _jid(jid), - _num_enq(0), - _num_deq(0), - _num_read(0), - _num_rproc(0), - _start_time(), - _stop_time(), - _stopped(false), - _test_time(), - _exception_list() -{} - -test_case_result::~test_case_result() -{} - -const std::string -test_case_result::test_time_str() const -{ - return _test_time.str(9); -} - -void -test_case_result::add_exception(const journal::jexception& e, const bool set_stop_time_flag) -{ - if (!_stopped && set_stop_time_flag) - { - set_stop_time(); - _stopped = true; - } - _exception_list.push_back(e.what()); -} - -void -test_case_result::add_exception(const std::string& err_str, const bool set_stop_time_flag) -{ - if (!_stopped && set_stop_time_flag) - { - set_stop_time(); - _stopped = true; - } - _exception_list.push_back(err_str); -} - -void -test_case_result::add_exception(const char* err_str, const bool set_stop_time_flag) -{ - if (!_stopped && set_stop_time_flag) - { - set_stop_time(); - _stopped = true; - } - _exception_list.push_back(err_str); -} - -void -test_case_result::clear() -{ - _num_enq = 0; - _num_deq = 0; - _num_read = 0; - _start_time.set_zero(); - _stop_time.set_zero(); - _test_time.set_zero(); - _exception_list.clear(); -} - -const std::string -test_case_result::str(const bool summary) const -{ - std::ostringstream oss; - if (summary) - { - oss << _jid << ":"; - oss << str_summary(); - if (_exception_list.size()) - oss << "; fail: " << _exception_list[0] << std::endl; - else - oss << "; ok" << std::endl; - } - else - { - oss << "--- Journal instance: jid=\"" << _jid << "\" ---" << std::endl; - oss << str_full(); - if (_exception_list.size()) - oss << " exception/error:" << _exception_list[0] << std::endl; - } - return oss.str(); -} - -const std::string -test_case_result::str_full() const -{ - const double t = _test_time.tv_sec + (_test_time.tv_nsec/1e9); - const bool no_exception = _exception_list.empty(); - std::ostringstream oss; - oss.setf(std::ios::fixed, std::ios::floatfield); - oss.precision(2); - if (no_exception) - { - oss.precision(6); - oss << " total test time: " << t << "s" << std::endl; - } - oss.precision(3); - oss << " total number enqueues: " << _num_enq; - if (no_exception) - oss << " (" << (_num_enq / t) << " enq/sec)"; - oss << std::endl; - oss << " total number dequeues: " << _num_deq; - if (no_exception) - oss << " (" << (_num_deq / t) << " deq/sec)"; - oss << std::endl; - oss << "total write operations: " << (_num_enq + _num_deq); - if (no_exception) - oss << " (" << ((_num_enq + _num_deq) / t) << " wrops/sec)"; - oss << std::endl; - oss << " total number reads: " << _num_read; - if (no_exception) - oss << " (" << (_num_read / t) << " rd/sec)"; - oss << std::endl; - oss << " total operations: " << (_num_enq + _num_deq + _num_read); - if (no_exception) - oss << " (" << ((_num_enq + _num_deq + _num_read) / t) << " ops/sec)"; - oss << std::endl; - oss << " overall result: " << (no_exception ? "PASS" : "*** FAIL ***") << std::endl; - return oss.str(); -} - -const std::string -test_case_result::str_summary() const -{ - const double t = _test_time.tv_sec + (_test_time.tv_nsec/1e9); - const bool no_exception = _exception_list.empty(); - std::ostringstream oss; - oss.setf(std::ios::fixed, std::ios::floatfield); - if (no_exception) - { - oss.precision(6); - oss << " t=" << t << "s;"; - } - else - oss << " exception"; - oss.precision(3); - oss << " enq=" << _num_enq; - if (no_exception) - oss << " (" << (_num_enq / t) << ")"; - oss << "; deq=" << _num_deq; - if (no_exception) - oss << " (" << (_num_deq / t) << ")"; - oss << "; wr=" << (_num_enq + _num_deq); - if (no_exception) - oss << " (" << ((_num_enq + _num_deq) / t) << ")"; - oss << "; rd=" << _num_read; - if (no_exception) - oss << " (" << (_num_read / t) << ")"; - oss << "; tot=" << (_num_enq + _num_deq + _num_read); - if (no_exception) - oss << " (" << ((_num_enq + _num_deq + _num_read) / t) << ")"; - return oss.str(); -} - -void -test_case_result::calc_test_time() -{ - if (!_start_time.is_zero() && _stop_time >= _start_time) - _test_time = _stop_time - _start_time; -} - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result.h deleted file mode 100644 index d15f9d021d..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result.h +++ /dev/null @@ -1,100 +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. - * - */ - -#ifndef mrg_jtt_test_case_result_hpp -#define mrg_jtt_test_case_result_hpp - -#include -#include -#include "qpid/legacystore/jrnl/jexception.h" -#include "qpid/legacystore/jrnl/time_ns.h" -#include - -namespace mrg -{ -namespace jtt -{ - - class test_case_result - { - public: - typedef boost::shared_ptr shared_ptr; - - typedef std::deque elist; - typedef elist::const_iterator elist_citr; - - protected: - std::string _jid; - u_int32_t _num_enq; - u_int32_t _num_deq; - u_int32_t _num_read; // Messages actually read - u_int32_t _num_rproc; // Messages handled by read thread (not all are read) - journal::time_ns _start_time; - journal::time_ns _stop_time; - bool _stopped; - journal::time_ns _test_time; - elist _exception_list; - - public: - test_case_result(const std::string& jid); - virtual ~test_case_result(); - - inline const std::string& jid() const { return _jid; } - inline u_int32_t num_enq() const { return _num_enq; } - inline u_int32_t incr_num_enq() { return ++_num_enq; } - inline u_int32_t num_deq() const { return _num_deq; } - inline u_int32_t incr_num_deq() { return ++_num_deq; } - inline u_int32_t num_read() const { return _num_read; } - inline u_int32_t incr_num_read() { return ++_num_read; } - inline u_int32_t num_rproc() const { return _num_rproc; } - inline u_int32_t incr_num_rproc() { return ++_num_rproc; } - - inline const journal::time_ns& start_time() const { return _start_time; } - inline void set_start_time() { ::clock_gettime(CLOCK_REALTIME, &_start_time); } - inline const journal::time_ns& stop_time() const { return _stop_time; } - inline void set_stop_time() - { ::clock_gettime(CLOCK_REALTIME, &_stop_time); calc_test_time(); } - inline void set_test_time(const journal::time_ns& ts) { _test_time = ts; } - inline const journal::time_ns& test_time() const { return _test_time; } - const std::string test_time_str() const; - - void add_exception(const journal::jexception& e, const bool set_stop_time_flag = true); - void add_exception(const std::string& err_str, const bool set_stop_time_flag = true); - void add_exception(const char* err_str, const bool set_stop_time_flag = true); - inline bool exception() const { return _exception_list.size() > 0; } - inline unsigned exception_count() const { return _exception_list.size(); } - inline elist_citr begin() { return _exception_list.begin(); } - inline elist_citr end() { return _exception_list.end(); } - inline const std::string& operator[](unsigned i) { return _exception_list[i]; } - - void clear(); - const std::string str(const bool summary) const; - - protected: - const std::string str_full() const; - const std::string str_summary() const; - void calc_test_time(); - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_test_case_result_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result_agregation.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result_agregation.cpp deleted file mode 100644 index da439e71e8..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result_agregation.cpp +++ /dev/null @@ -1,185 +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 "test_case_result_agregation.h" - -#include -#include - -namespace mrg -{ -namespace jtt -{ - -test_case_result_agregation::test_case_result_agregation(): - test_case_result("Average"), - _tc_average(true), - _fmt_chk_done(false), - _fmt_chk_err(false), - _res_list() -{ -} - -test_case_result_agregation::test_case_result_agregation(const std::string& jid): - test_case_result(jid), - _tc_average(false), - _fmt_chk_done(false), - _fmt_chk_err(false), - _res_list() -{} - -test_case_result_agregation::~test_case_result_agregation() -{} - -void -test_case_result_agregation::add_test_result(const test_case_result::shared_ptr& tcrp) -{ - if (_tc_average || _jid.compare(tcrp->jid()) == 0) - { - _num_enq += tcrp->num_enq(); - _num_deq += tcrp->num_deq(); - _num_read += tcrp->num_read(); - add_test_time(tcrp->test_time()); - _exception_list.insert(_exception_list.end(), tcrp->begin(), tcrp->end()); - _res_list.push_back(tcrp); - } -} - -bool -test_case_result_agregation::exception() const -{ - for (tcrp_list_citr i = _res_list.begin(); i < _res_list.end(); i++) - if ((*i)->exception()) - return true; - return false; -} - -unsigned -test_case_result_agregation::exception_count() const -{ - unsigned cnt = 0; - for (tcrp_list_citr i = _res_list.begin(); i < _res_list.end(); i++) - cnt += (*i)->exception_count(); - return cnt; -} - -void -test_case_result_agregation::clear() -{ - test_case_result::clear(); - _res_list.clear(); -} - -const std::string -test_case_result_agregation::str(const bool last_only, const bool summary) const -{ - std::ostringstream oss; - if (last_only) - oss << " " << _res_list.at(_res_list.size()-1)->str(summary); - else - { - for (tcrp_list_citr i=_res_list.begin(); i!=_res_list.end(); i++) - oss << " " << (*i)->str(summary); - } - if (_res_list.size() > 1) - oss << " " << (summary ? str_summary(last_only) : str_full(last_only)); - return oss.str(); -} - -const std::string -test_case_result_agregation::str_full(const bool /*last_only*/) const -{ - std::ostringstream oss; - oss.precision(2); - if (_tc_average) - oss << "Average across all journal instances:" << std::endl; - else - oss << "Average for jid=\"" << _jid << "\":" << std::endl; - oss << " total number results: " << _res_list.size() << std::endl; - oss << " number exceptions: " << _exception_list.size() << " (" << - (100.0 * _res_list.size() / _exception_list.size()) << "%)" << std::endl; - - oss << test_case_result::str_full(); - - if (_exception_list.size()) - { - unsigned n = 0; - oss << "List of exceptions/errors:" << std::endl; - for (elist_citr i = _exception_list.begin(); i != _exception_list.end(); i++, n++) - oss << " " << n << ". " << (*i) << std::endl; - } - - if (!_tc_average && _res_list.size() > 1) - { - oss << "Individual results:" << std::endl; - for (tcrp_list_citr i=_res_list.begin(); i!=_res_list.end(); i++) - oss << " " << (*i)->str(false) << std::endl; - oss << std::endl; - } - - return oss.str(); -} - -const std::string -test_case_result_agregation::str_summary(const bool /*last_only*/) const -{ - std::ostringstream oss; - if (_tc_average) - oss << "overall average [" << _res_list.size() << "]:"; - else - oss << "average (" << _res_list.size() << "):"; - - oss << test_case_result::str_summary(); - if (_fmt_chk_done) - oss << " fmt-chk=" << (_fmt_chk_err ? "fail" : "ok"); - - if (_exception_list.size()) - { - if (_tc_average) - oss << " fail: " << _exception_list.size() << " exception" - << (_exception_list.size()>1?"s":"") << std::endl; - else - { - if (_exception_list.size() == 1) - oss << " fail: " << *_exception_list.begin() << std::endl; - else - { - oss << std::endl; - unsigned n = 0; - for (elist_citr i = _exception_list.begin(); i != _exception_list.end(); i++, n++) - oss << " " << n << ". " << (*i) << std::endl; - } - } - } - else - oss << " ok" << std::endl; - return oss.str(); -} - -const journal::time_ns& -test_case_result_agregation::add_test_time(const journal::time_ns& t) -{ - _test_time += t; - return _test_time; -} - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result_agregation.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result_agregation.h deleted file mode 100644 index 0b3998176c..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_result_agregation.h +++ /dev/null @@ -1,81 +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. - * - */ - -#ifndef mrg_jtt_test_case_result_agregation_hpp -#define mrg_jtt_test_case_result_agregation_hpp - -#include "test_case_result.h" - -#include -#include - -namespace mrg -{ -namespace jtt -{ - - class test_case_result_agregation : public test_case_result - { - public: - typedef boost::shared_ptr shared_ptr; - - typedef std::vector tcrp_list; - typedef tcrp_list::const_iterator tcrp_list_citr; - - private: - bool _tc_average; - bool _fmt_chk_done; - bool _fmt_chk_err; - tcrp_list _res_list; - - public: - test_case_result_agregation(); // used for average across jrnl instances - test_case_result_agregation(const std::string& jid); - virtual ~test_case_result_agregation(); - - void add_test_result(const test_case_result::shared_ptr& tcrp); - - inline bool tc_average_mode() const { return _tc_average; } - inline bool fmt_chk_done() const { return _fmt_chk_done; } - inline bool fmt_chk_res() const { return _fmt_chk_err; } - inline void set_fmt_chk_res(const bool err) - { _fmt_chk_done = true; _fmt_chk_err |= err; if (err) add_exception("Journal format error"); } - inline u_int32_t num_results() const { return _res_list.size(); } - inline tcrp_list_citr rlist_begin() const { return _res_list.begin(); } - inline tcrp_list_citr rlist_end() const { return _res_list.end(); } - inline const test_case_result::shared_ptr& operator[](unsigned i) const - { return _res_list[i]; } - bool exception() const; - unsigned exception_count() const; - - void clear(); - const std::string str(const bool last_only, const bool summary) const; - - private: - const std::string str_full(const bool last_only) const; - const std::string str_summary(const bool last_only) const; - const journal::time_ns& add_test_time(const journal::time_ns& t); - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_test_case_result_agregation_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_set.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_set.cpp deleted file mode 100644 index b818d6c7ae..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_set.cpp +++ /dev/null @@ -1,169 +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 "test_case_set.h" - -#include -#include -#include - -namespace mrg -{ -namespace jtt -{ - -test_case_set::test_case_set(): - _tc_list(), - _csv_ignored(0) -{} - -test_case_set::test_case_set(const std::string& csv_filename, const bool recover_mode, - const csv_map& cols): - _tc_list(), - _csv_ignored(0) -{ - append_from_csv(csv_filename, recover_mode, cols); -} - -test_case_set::~test_case_set() -{} - -void -test_case_set::append(const unsigned test_case_num, const u_int32_t num_msgs, - const std::size_t min_data_size, const std::size_t max_data_size, const bool auto_deq, - const std::size_t min_xid_size, const std::size_t max_xid_size, - const test_case::transient_t transient, const test_case::external_t external, - const std::string& comment) -{ - test_case::shared_ptr tcp(new test_case(test_case_num, num_msgs, min_data_size, - max_data_size, auto_deq, min_xid_size, max_xid_size, transient, external, comment)); - append(tcp); -} - - -#define CSV_BUFF_SIZE 2048 -void -test_case_set::append_from_csv(const std::string& csv_filename, const bool recover_mode, - const csv_map& cols) -{ - char buff[CSV_BUFF_SIZE]; - std::ifstream ifs(csv_filename.c_str()); - while (ifs.good()) - { - ifs.getline(buff, (std::streamsize)CSV_BUFF_SIZE); - if (ifs.gcount()) - { - test_case::shared_ptr tcp = get_tc_from_csv(buff, cols); - if (tcp.get()) - { - if (!recover_mode || tcp->auto_deq()) - append(tcp); - else - _csv_ignored++; - } - } - } -} - -test_case::shared_ptr -test_case_set::get_tc_from_csv(const std::string& csv_line, const csv_map& cols) -{ - unsigned test_case_num = 0; - u_int32_t num_msgs = 0; - std::size_t min_data_size = 0; - std::size_t max_data_size = 0; - bool auto_deq = false; - std::size_t min_xid_size = 0; - std::size_t max_xid_size = 0; - test_case::transient_t transient = test_case::JTT_TRANSIENT; - test_case::external_t external = test_case::JDL_INTERNAL; - std::string comment; - - csv_tok t(csv_line); - unsigned col_num = 0; - for (csv_tok_citr t_itr = t.begin(); t_itr != t.end(); ++t_itr, ++col_num) - { - const std::string& tok = *t_itr; - csv_map_citr m_citr = cols.find(col_num); - if (m_citr != cols.end()) - { - switch (m_citr->second) - { - case CSV_TC_NUM: - if (!tok.size() || tok[0] < '0' || tok[0] > '9') - return test_case::shared_ptr(); - test_case_num = unsigned(std::atol(tok.c_str())); - break; - case CSV_TC_NUM_MSGS: num_msgs = u_int32_t(std::atol(tok.c_str())); break; - case CSV_TC_MIN_DATA_SIZE: min_data_size = std::size_t(std::atol(tok.c_str())); break; - case CSV_TC_MAX_DATA_SIZE: max_data_size = std::size_t(std::atol(tok.c_str())); break; - case CSV_TC_AUTO_DEQ: - if (tok == "TRUE" || tok == "1") - auto_deq = true; - break; - case CSV_TC_MIN_XID_SIZE: min_xid_size = std::size_t(std::atol(tok.c_str())); break; - case CSV_TC_MAX_XID_SIZE: max_xid_size = std::size_t(std::atol(tok.c_str())); break; - case CSV_TC_TRANSIENT: - if (tok == "TRUE" || tok == "1") - transient = test_case::JTT_PERSISTNET; - else if (tok == "RANDOM" || tok == "-1") - transient = test_case::JTT_RANDOM; - break; - case CSV_TC_EXTERNAL: - if (tok == "TRUE" || tok == "1") - external = test_case::JDL_EXTERNAL; - else if (tok == "RANDOM" || tok == "-1") - external = test_case::JDL_RANDOM; - break; - case CSV_TC_COMMENT: comment = *t_itr; break; - } - } - } - if (col_num) - return test_case::shared_ptr(new test_case(test_case_num, num_msgs, min_data_size, - max_data_size, auto_deq, min_xid_size, max_xid_size, transient, external, comment)); - else - return test_case::shared_ptr(); -} - -// Static member initializations -// This csv_map is for use on the standard spreadsheet-derived test case csv files. -test_case_set::csv_map test_case_set::std_csv_map; -const bool test_case_set::_map_init = __init(); - -bool -test_case_set::__init() -{ - std_csv_map.insert(test_case_set::csv_pair(0, test_case_set::CSV_TC_NUM)); - std_csv_map.insert(test_case_set::csv_pair(5, test_case_set::CSV_TC_NUM_MSGS)); - std_csv_map.insert(test_case_set::csv_pair(7, test_case_set::CSV_TC_MIN_DATA_SIZE)); - std_csv_map.insert(test_case_set::csv_pair(8, test_case_set::CSV_TC_MAX_DATA_SIZE)); - std_csv_map.insert(test_case_set::csv_pair(11, test_case_set::CSV_TC_AUTO_DEQ)); - std_csv_map.insert(test_case_set::csv_pair(9, test_case_set::CSV_TC_MIN_XID_SIZE)); - std_csv_map.insert(test_case_set::csv_pair(10, test_case_set::CSV_TC_MAX_XID_SIZE)); - std_csv_map.insert(test_case_set::csv_pair(12, test_case_set::CSV_TC_TRANSIENT)); - std_csv_map.insert(test_case_set::csv_pair(13, test_case_set::CSV_TC_EXTERNAL)); - std_csv_map.insert(test_case_set::csv_pair(20, test_case_set::CSV_TC_COMMENT)); - return true; -} - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_set.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_set.h deleted file mode 100644 index 94a1ee3172..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_case_set.h +++ /dev/null @@ -1,99 +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. - * - */ - -#ifndef mrg_jtt_test_case_set_hpp -#define mrg_jtt_test_case_set_hpp - -#include "test_case.h" - -#include -#include -#include -#include - -namespace mrg -{ -namespace jtt -{ - - class test_case_set - { - public: - enum csv_col_enum { - CSV_TC_NUM = 0, - CSV_TC_NUM_MSGS, - CSV_TC_MIN_DATA_SIZE, - CSV_TC_MAX_DATA_SIZE, - CSV_TC_AUTO_DEQ, - CSV_TC_MIN_XID_SIZE, - CSV_TC_MAX_XID_SIZE, - CSV_TC_TRANSIENT, - CSV_TC_EXTERNAL, - CSV_TC_COMMENT }; - typedef std::pair csv_pair; - typedef std::map csv_map; - typedef csv_map::const_iterator csv_map_citr; - static csv_map std_csv_map; - - typedef std::vector tcl; - typedef tcl::iterator tcl_itr; - typedef tcl::const_iterator tcl_citr; - - typedef boost::tokenizer > csv_tok; - typedef csv_tok::const_iterator csv_tok_citr; - - private: - tcl _tc_list; - static const bool _map_init; - unsigned _csv_ignored; - - public: - test_case_set(); - test_case_set(const std::string& csv_filename, const bool recover_mode, - const csv_map& cols = std_csv_map); - virtual ~test_case_set(); - - inline unsigned size() const { return _tc_list.size(); } - inline unsigned ignored() const { return _csv_ignored; } - inline bool empty() const { return _tc_list.empty(); } - - inline void append(const test_case::shared_ptr& tc) { _tc_list.push_back(tc); } - void append(const unsigned test_case_num, const u_int32_t num_msgs, - const std::size_t min_data_size, const std::size_t max_data_size, - const bool auto_deq, const std::size_t min_xid_size, - const std::size_t max_xid_size, const test_case::transient_t transient, - const test_case::external_t external, const std::string& comment); - void append_from_csv(const std::string& csv_filename, const bool recover_mode, - const csv_map& cols = std_csv_map); - inline tcl_itr begin() { return _tc_list.begin(); } - inline tcl_itr end() { return _tc_list.end(); } - inline const test_case::shared_ptr& operator[](unsigned i) { return _tc_list[i]; } - inline void clear() { _tc_list.clear(); } - - private: - test_case::shared_ptr get_tc_from_csv(const std::string& csv_line, const csv_map& cols); - static bool __init(); - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_test_case_set_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.cpp b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.cpp deleted file mode 100644 index de0b5dbfb9..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.cpp +++ /dev/null @@ -1,218 +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 "test_mgr.h" - -#include -#include -#include -#include "test_case_set.h" - -namespace mrg -{ -namespace jtt -{ - -test_mgr::test_mgr(args& args): - _ji_list(), - _args(args), - _err_flag(false), - _random_fn_ptr(random_fn) -{ - if (_args.seed) - std::srand(_args.seed); -} - -test_mgr::~test_mgr() -{} - -void -test_mgr::run() -{ - // TODO: complete tidy-up of non-summary (verbose) results, then pull through - // a command-line summary to control this. - // Idea: --summary: prints short results afterwards - // --verbose: prints long version as test progresses - // defualt: none of these, similar to current summary = true version. - const bool summary = true; - - std::cout << "CSV file: \"" << _args.test_case_csv_file_name << "\""; - test_case_set tcs(_args.test_case_csv_file_name, _args.recover_mode); - - if (tcs.size()) - { - std::cout << " (found " << tcs.size() << " test case" << (tcs.size() != 1 ? "s" : "") << - ")" << std::endl; - if (tcs.ignored()) - std::cout << "WARNING: " << tcs.ignored() << " test cases were ignored. (All test " - "cases without auto-dequeue are ignored when recover-mode is selected.)" << - std::endl; - _args.print_args(); - } - else if(tcs.ignored()) - { - std::cout << " WARNING: All " << tcs.ignored() << " test case(s) were ignored. (All test " - "cases without auto-dequeue are ignored when recover-mode is selected.)" << - std::endl; - } - else - std::cout << " (WARNING: This CSV file is empty or does not exist.)" << std::endl; - - do - { - unsigned u = 0; - if (_args.randomize) - random_shuffle(tcs.begin(), tcs.end(), _random_fn_ptr); - for (test_case_set::tcl_itr tci = tcs.begin(); tci != tcs.end(); tci++, u++) - { - if (summary) - std::cout << "Test case " << (*tci)->test_case_num() << ": \"" << - (*tci)->comment() << "\"" << std::endl; - else - std::cout << (*tci)->str() << std::endl; - if (!_args.reuse_instance || _ji_list.empty()) - initialize_jrnls(); - for (ji_list_citr jii=_ji_list.begin(); jii!=_ji_list.end(); jii++) - (*jii)->init_tc(*tci, &_args); - for (ji_list_citr jii=_ji_list.begin(); jii!=_ji_list.end(); jii++) - (*jii)->run_tc(); - for (ji_list_citr jii=_ji_list.begin(); jii!=_ji_list.end(); jii++) - (*jii)->tc_wait_compl(); - - if (_args.format_chk) - { - for (ji_list_citr jii=_ji_list.begin(); jii!=_ji_list.end(); jii++) - { - jrnl_init_params::shared_ptr jpp = (*jii)->params(); - std::string ja = _args.jfile_analyzer; - if (ja.empty()) ja = "./jfile_chk.py"; - if (!exists(ja)) - { - std::ostringstream oss; - oss << "ERROR: Validation program \"" << ja << "\" does not exist" << std::endl; - throw std::runtime_error(oss.str()); - } - std::ostringstream oss; - oss << ja << " -b " << jpp->base_filename(); - // TODO: When jfile_check.py can handle previously recovered journals for - // specific tests, then remove this exclusion. - if (!_args.recover_mode) - { - oss << " -c " << _args.test_case_csv_file_name; - oss << " -t " << (*tci)->test_case_num(); - } - oss << " -q " << jpp->jdir(); - bool res = system(oss.str().c_str()) != 0; - (*tci)->set_fmt_chk_res(res, jpp->jid()); - if (res) _err_flag = true; - } - } - - if (!_args.recover_mode && !_args.keep_jrnls) - for (ji_list_citr jii=_ji_list.begin(); jii!=_ji_list.end(); jii++) - try { mrg::journal::jdir::delete_dir((*jii)->jrnl_dir()); } - catch (...) {} // TODO - work out exception strategy for failure here... - - print_results(*tci, summary); - if ((*tci)->average().exception()) - _err_flag = true; - if (_abort || (!_args.repeat_flag && _signal)) - break; - if (_args.pause_secs && tci != tcs.end()) - ::usleep(_args.pause_secs * 1000000); - } - } - while (_args.repeat_flag && !_signal); -} - -// static fn: -void -test_mgr::signal_handler(int sig) -{ - if (_signal) - _abort = true; - _signal = sig; - std::cout << std::endl; - std::cout << "********************************" << std::endl; - std::cout << "Caught signal " << sig << std::endl; - if (_abort) - std::cout << "Aborting..." << std::endl; - else - std::cout << "Completing current test cycle..." << std::endl; - std::cout << "********************************" << std::endl << std::endl; -} - -bool -test_mgr::exists(std::string fname) -{ - struct stat s; - if (::stat(fname.c_str(), &s)) - { - if (errno == ENOENT) // No such dir or file - return false; - // Throw for any other condition - std::ostringstream oss; - oss << "ERROR: test_mgr::exists(): file=\"" << fname << "\": " << FORMAT_SYSERR(errno); - throw std::runtime_error(oss.str()); - } - return true; -} - -void -test_mgr::initialize_jrnls() -{ - _ji_list.clear(); - for (unsigned i=0; i<_args.num_jrnls; i++) - { - std::ostringstream jid; - jid << std::hex << std::setfill('0'); - jid << "test_" << std::setw(4) << std::hex << i; - std::ostringstream jdir; - jdir << _args.journal_dir << "/" << jid.str(); - jrnl_init_params::shared_ptr jpp(new jrnl_init_params(jid.str(), jdir.str(), jid.str())); - jrnl_instance::shared_ptr jip(new jrnl_instance(jpp)); - _ji_list.push_back(jip); - } -} - -void -test_mgr::print_results(test_case::shared_ptr tcp, const bool summary) -{ - if (!summary) - std::cout << " === Results ===" << std::endl; - -// TODO - the reporting is broken when --repeat is used. The following commented-out -// section was an attempt to fix it, but there are too many side-effects. -// for (test_case::res_map_citr i=tcp->jmap_begin(); i!=tcp->jmap_end(); i++) -// std::cout << (*i).second->str(summary, summary); -// if (tcp->num_jrnls() > 1) - std::cout << tcp->average().str(false, summary); - - if (!summary) - std::cout << std::endl; -} - -// static instances -volatile sig_atomic_t test_mgr::_signal = 0; -volatile bool test_mgr::_abort = false; - -} // namespace jtt -} // namespace mrg diff --git a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.h b/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.h deleted file mode 100644 index e608ac6280..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/jtt/test_mgr.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef mrg_jtt_test_mgr_hpp -#define mrg_jtt_test_mgr_hpp - -#include "args.h" -#include -#include -#include "jrnl_instance.h" - -namespace mrg -{ -namespace jtt -{ - class test_mgr - { - public: - typedef std::vector ji_list; - typedef ji_list::iterator ji_list_itr; - typedef ji_list::const_iterator ji_list_citr; - - private: - ji_list _ji_list; - args& _args; - bool _err_flag; - ptrdiff_t (*_random_fn_ptr)(const ptrdiff_t i); - static volatile std::sig_atomic_t _signal; - static volatile bool _abort; - - public: - test_mgr(args& args); - virtual ~test_mgr(); - void run(); - inline bool error() const { return _err_flag; } - - static void signal_handler(int signal); - - private: - static bool exists(std::string file_name); - void initialize_jrnls(); - void print_results(test_case::shared_ptr tcp, const bool summary); - inline static ptrdiff_t random_fn(const ptrdiff_t i) - { return static_cast(1.0 * i * std::rand() / RAND_MAX); } - }; - -} // namespace jtt -} // namespace mrg - -#endif // ifndef mrg_jtt_test_mgr_hpp diff --git a/qpid/cpp/src/tests/legacystore/jrnl/prof b/qpid/cpp/src/tests/legacystore/jrnl/prof deleted file mode 100755 index 2abe7baa4a..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/prof +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env 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. -# - -mkdir -p profile -opcontrol --setup --no-vmlinux --separate=library -opcontrol --start -# -- Do stuff here -- -./jtest wtests.csv 264 -# -- End of stuff -- -opcontrol --stop -opcontrol --dump -opcontrol --shutdown -opreport -l ./jtest -opannotate --source --output-dir=profile ./jtest diff --git a/qpid/cpp/src/tests/legacystore/jrnl/run-journal-tests b/qpid/cpp/src/tests/legacystore/jrnl/run-journal-tests deleted file mode 100755 index e169e39c60..0000000000 --- a/qpid/cpp/src/tests/legacystore/jrnl/run-journal-tests +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env 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. -# - -if test x${TMP_DATA_DIR} == x; then - export TMP_DATA_DIR=/tmp -fi -fail=0 -num_jrnls=3 - -# Run jtt using default test set -echo -echo "===== Mode 1: New journal instance, no recover =====" -jtt/jtt --analyzer ../../tools/store_chk --jrnl-dir ${TMP_DATA_DIR} --csv jtt/jtt.csv --format-chk --num-jrnls ${num_jrnls} || fail=1 -rm -rf ${TMP_DATA_DIR}/test_0* -echo -echo "===== Mode 2: Re-use journal instance, no recover =====" -jtt/jtt --analyzer ../../tools/store_chk --jrnl-dir ${TMP_DATA_DIR} --csv jtt/jtt.csv --reuse-instance --format-chk --num-jrnls ${num_jrnls} || fail=1 -rm -rf ${TMP_DATA_DIR}/test_0* -echo -echo "===== Mode 3: New journal instance, recover previous test journal =====" -jtt/jtt --analyzer ../../tools/store_chk --jrnl-dir ${TMP_DATA_DIR} --csv jtt/jtt.csv --recover-mode --format-chk --num-jrnls ${num_jrnls} || fail=1 -rm -rf ${TMP_DATA_DIR}/test_0* -echo -echo "===== Mode 4: Re-use journal instance, recover previous test journal =====" -jtt/jtt --analyzer ../../tools/store_chk --jrnl-dir ${TMP_DATA_DIR} --csv jtt/jtt.csv --reuse-instance --recover-mode --format-chk --num-jrnls ${num_jrnls} || fail=1 -rm -rf ${TMP_DATA_DIR}/test_0* -echo - -exit $fail diff --git a/qpid/cpp/src/tests/legacystore/jrnl/tests.ods b/qpid/cpp/src/tests/legacystore/jrnl/tests.ods deleted file mode 100644 index d900374321..0000000000 Binary files a/qpid/cpp/src/tests/legacystore/jrnl/tests.ods and /dev/null differ diff --git a/qpid/cpp/src/tests/legacystore/persistence.py b/qpid/cpp/src/tests/legacystore/persistence.py deleted file mode 100644 index c4ab712f14..0000000000 --- a/qpid/cpp/src/tests/legacystore/persistence.py +++ /dev/null @@ -1,574 +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. -# - -import sys, re, traceback, socket -from getopt import getopt, GetoptError - -from qpid.connection import Connection -from qpid.util import connect -from qpid.datatypes import Message, RangedSet -from qpid.queue import Empty -from qpid.session import SessionException -from qpid.testlib import TestBase010 -from time import sleep - -class PersistenceTest(TestBase010): - - XA_RBROLLBACK = 1 - XA_RBTIMEOUT = 2 - XA_OK = 0 - - def createMessage(self, **kwargs): - session = self.session - dp = {} - dp['delivery_mode'] = 2 - mp = {} - for k, v in kwargs.iteritems(): - if k in ['routing_key', 'delivery_mode']: dp[k] = v - if k in ['message_id', 'correlation_id', 'application_headers']: mp[k] = v - args = [] - args.append(session.delivery_properties(**dp)) - if len(mp): - args.append(session.message_properties(**mp)) - if kwargs.has_key('body'): args.append(kwargs['body']) - return Message(*args) - - def phase1(self): - session = self.session - - session.queue_declare(queue="queue-a", durable=True) - session.queue_declare(queue="queue-b", durable=True) - session.exchange_bind(queue="queue-a", exchange="amq.direct", binding_key="a") - session.exchange_bind(queue="queue-b", exchange="amq.direct", binding_key="b") - - session.message_transfer(destination="amq.direct", - message=self.createMessage(routing_key="a", correlation_id="Msg0001", body="A_Message1")) - session.message_transfer(destination="amq.direct", - message=self.createMessage(routing_key="b", correlation_id="Msg0002", body="B_Message1")) - -# session.queue_declare(queue="lvq-test", durable=True, arguments={"qpid.last_value_queue":True}) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"B"}, body="B1")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"A"}, body="A1")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"A"}, body="A2")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"B"}, body="B2")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"B"}, body="B3")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"C"}, body="C1")) - - - - def phase2(self): - session = self.session - - #check queues exists - session.queue_declare(queue="queue-a", durable=True, passive=True) - session.queue_declare(queue="queue-b", durable=True, passive=True) - - #check they are still bound to amq.direct correctly - responses = [] - responses.append(session.exchange_bound(queue="queue-a", exchange="amq.direct", binding_key="a")) - responses.append(session.exchange_bound(queue="queue-b", exchange="amq.direct", binding_key="b")) - for r in responses: - self.assert_(not r.exchange_not_found) - self.assert_(not r.queue_not_found) - self.assert_(not r.key_not_matched) - - - #check expected messages are there - self.assertMessageOnQueue("queue-a", "Msg0001", "A_Message1") - self.assertMessageOnQueue("queue-b", "Msg0002", "B_Message1") - - self.assertEmptyQueue("queue-a") - self.assertEmptyQueue("queue-b") - - session.queue_declare(queue="queue-c", durable=True) - - #send a message to a topic such that it reaches all queues - session.exchange_bind(queue="queue-a", exchange="amq.topic", binding_key="abc") - session.exchange_bind(queue="queue-b", exchange="amq.topic", binding_key="abc") - session.exchange_bind(queue="queue-c", exchange="amq.topic", binding_key="abc") - - session.message_transfer(destination="amq.topic", - message=self.createMessage(routing_key="abc", correlation_id="Msg0003", body="AB_Message2")) - -# #check LVQ exists and has exepected messages: -# session.queue_declare(queue="lvq-test", durable=True, passive=True) -# session.message_subscribe(destination="lvq", queue="lvq-test") -# lvq = session.incoming("lvq") -# lvq.start() -# accepted = RangedSet() -# for m in ["A2", "B3", "C1"]: -# msg = lvq.get(timeout=1) -# self.assertEquals(m, msg.body) -# accepted.add(msg.id) -# try: -# extra = lvq.get(timeout=1) -# self.fail("lvq-test not empty, contains: " + extra.body) -# except Empty: None -# #publish some more messages while subscriber is active (no replacement): -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"C"}, body="C2")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"C"}, body="C3")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"A"}, body="A3")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"A"}, body="A4")) -# session.message_transfer(message=self.createMessage(routing_key="lvq-test", application_headers={"qpid.LVQ_key":"C"}, body="C4")) -# #check that accepting replaced messages is safe -# session.message_accept(accepted) - - - def phase3(self): - session = self.session - -# #lvq recovery validation -# session.queue_declare(queue="lvq-test", durable=True, passive=True) -# session.message_subscribe(destination="lvq", queue="lvq-test") -# lvq = session.incoming("lvq") -# lvq.start() -# accepted = RangedSet() -# lvq.start() -# for m in ["C4", "A4"]: -# msg = lvq.get(timeout=1) -# self.assertEquals(m, msg.body) -# accepted.add(msg.id) -# session.message_accept(accepted) -# try: -# extra = lvq.get(timeout=1) -# self.fail("lvq-test not empty, contains: " + extra.body) -# except Empty: None -# session.message_cancel(destination="lvq") -# session.queue_delete(queue="lvq-test") - - - #check queues exists - session.queue_declare(queue="queue-a", durable=True, passive=True) - session.queue_declare(queue="queue-b", durable=True, passive=True) - session.queue_declare(queue="queue-c", durable=True, passive=True) - - session.tx_select() - #check expected messages are there - self.assertMessageOnQueue("queue-a", "Msg0003", "AB_Message2") - self.assertMessageOnQueue("queue-b", "Msg0003", "AB_Message2") - self.assertMessageOnQueue("queue-c", "Msg0003", "AB_Message2") - - self.assertEmptyQueue("queue-a") - self.assertEmptyQueue("queue-b") - self.assertEmptyQueue("queue-c") - - #note: default bindings must be restored for this to work - session.message_transfer(message=self.createMessage( - routing_key="queue-a", correlation_id="Msg0004", body="A_Message3")) - session.message_transfer(message=self.createMessage( - routing_key="queue-a", correlation_id="Msg0005", body="A_Message4")) - session.message_transfer(message=self.createMessage( - routing_key="queue-a", correlation_id="Msg0006", body="A_Message5")) - - session.tx_commit() - - - #delete a queue - session.queue_delete(queue="queue-c") - - session.message_subscribe(destination="ctag", queue="queue-a", accept_mode=0) - session.message_flow(destination="ctag", unit=0, value=0xFFFFFFFF) - session.message_flow(destination="ctag", unit=1, value=0xFFFFFFFF) - included = session.incoming("ctag") - msg1 = included.get(timeout=1) - self.assertExpectedContent(msg1, "Msg0004", "A_Message3") - msg2 = included.get(timeout=1) - self.assertExpectedContent(msg2, "Msg0005", "A_Message4") - msg3 = included.get(timeout=1) - self.assertExpectedContent(msg3, "Msg0006", "A_Message5") - self.ack(msg1, msg2, msg3) - - session.message_transfer(destination="amq.direct", message=self.createMessage( - routing_key="queue-b", correlation_id="Msg0007", body="B_Message3")) - - session.tx_rollback() - - - def phase4(self): - session = self.session - - #check queues exists - session.queue_declare(queue="queue-a", durable=True, passive=True) - session.queue_declare(queue="queue-b", durable=True, passive=True) - - self.assertMessageOnQueue("queue-a", "Msg0004", "A_Message3") - self.assertMessageOnQueue("queue-a", "Msg0005", "A_Message4") - self.assertMessageOnQueue("queue-a", "Msg0006", "A_Message5") - - self.assertEmptyQueue("queue-a") - self.assertEmptyQueue("queue-b") - - #check this queue doesn't exist - try: - session.queue_declare(queue="queue-c", durable=True, passive=True) - raise Exception("Expected queue-c to have been deleted") - except SessionException, e: - self.assertEquals(404, e.args[0].error_code) - - def phase5(self): - - session = self.session - queues = ["queue-a1", "queue-a2", "queue-b1", "queue-b2", "queue-c1", "queue-c2", "queue-d1", "queue-d2"] - - for q in queues: - session.queue_declare(queue=q, durable=True) - session.queue_purge(queue=q) - - session.message_transfer(message=self.createMessage( - routing_key="queue-a1", correlation_id="MsgA", body="MessageA")) - session.message_transfer(message=self.createMessage( - routing_key="queue-b1", correlation_id="MsgB", body="MessageB")) - session.message_transfer(message=self.createMessage( - routing_key="queue-c1", correlation_id="MsgC", body="MessageC")) - session.message_transfer(message=self.createMessage( - routing_key="queue-d1", correlation_id="MsgD", body="MessageD")) - - session.dtx_select() - txa = self.xid('a') - txb = self.xid('b') - txc = self.xid('c') - txd = self.xid('d') - - self.txswap("queue-a1", "queue-a2", txa) - self.txswap("queue-b1", "queue-b2", txb) - self.txswap("queue-c1", "queue-c2", txc) - self.txswap("queue-d1", "queue-d2", txd) - - #no queue should have any messages accessible - for q in queues: - self.assertEqual(0, session.queue_query(queue=q).message_count, "Bad count for %s" % (q)) - - self.assertEqual(self.XA_OK, session.dtx_commit(xid=txa, one_phase=True).status) - self.assertEqual(self.XA_OK, session.dtx_rollback(xid=txb).status) - self.assertEqual(self.XA_OK, session.dtx_prepare(xid=txc).status) - self.assertEqual(self.XA_OK, session.dtx_prepare(xid=txd).status) - - #further checks - not_empty = ["queue-a2", "queue-b1"] - for q in queues: - if q in not_empty: - self.assertEqual(1, session.queue_query(queue=q).message_count, "Bad count for %s" % (q)) - else: - self.assertEqual(0, session.queue_query(queue=q).message_count, "Bad count for %s" % (q)) - - - def phase6(self): - session = self.session - - #check prepared transaction are reported correctly by recover - txc = self.xid('c') - txd = self.xid('d') - - xids = session.dtx_recover().in_doubt - ids = [x.global_id for x in xids] #TODO: come up with nicer way to test these - - if txc.global_id not in ids: - self.fail("Recovered xids not as expected. missing: %s" % (txc)) - if txd.global_id not in ids: - self.fail("Recovered xids not as expected. missing: %s" % (txd)) - self.assertEqual(2, len(xids)) - - - queues = ["queue-a1", "queue-a2", "queue-b1", "queue-b2", "queue-c1", "queue-c2", "queue-d1", "queue-d2"] - not_empty = ["queue-a2", "queue-b1"] - - #re-check - not_empty = ["queue-a2", "queue-b1"] - for q in queues: - if q in not_empty: - self.assertEqual(1, session.queue_query(queue=q).message_count, "Bad count for %s" % (q)) - else: - self.assertEqual(0, session.queue_query(queue=q).message_count, "Bad count for %s" % (q)) - - #complete the prepared transactions - self.assertEqual(self.XA_OK, session.dtx_commit(xid=txc).status) - self.assertEqual(self.XA_OK, session.dtx_rollback(xid=txd).status) - not_empty.append("queue-c2") - not_empty.append("queue-d1") - - for q in queues: - if q in not_empty: - self.assertEqual(1, session.queue_query(queue=q).message_count) - else: - self.assertEqual(0, session.queue_query(queue=q).message_count) - - def phase7(self): - session = self.session - session.synchronous = False - - # check xids from phase 6 are gone - txc = self.xid('c') - txd = self.xid('d') - - xids = session.dtx_recover().in_doubt - ids = [x.global_id for x in xids] #TODO: come up with nicer way to test these - - if txc.global_id in ids: - self.fail("Xid still present : %s" % (txc)) - if txd.global_id in ids: - self.fail("Xid still present : %s" % (txc)) - self.assertEqual(0, len(xids)) - - #test deletion of queue after publish - #create queue - session.queue_declare(queue = "q", auto_delete=True, durable=True) - - #send message - for i in range(1, 10): - session.message_transfer(message=self.createMessage(routing_key = "q", body = "my-message")) - - session.synchronous = True - #explicitly delete queue - session.queue_delete(queue = "q") - - #test acking of message from auto-deleted queue - #create queue - session.queue_declare(queue = "q", auto_delete=True, durable=True) - - #send message - session.message_transfer(message=self.createMessage(routing_key = "q", body = "my-message")) - - #create consumer - session.message_subscribe(queue = "q", destination = "a", accept_mode=0, acquire_mode=0) - session.message_flow(unit = 1, value = 0xFFFFFFFF, destination = "a") - session.message_flow(unit = 0, value = 10, destination = "a") - queue = session.incoming("a") - - #consume the message, cancel subscription (triggering auto-delete), then ack it - msg = queue.get(timeout = 5) - session.message_cancel(destination = "a") - self.ack(msg) - - #test implicit deletion of bindings when queue is deleted - session.queue_declare(queue = "durable-subscriber-queue", exclusive=True, durable=True) - session.exchange_bind(exchange="amq.topic", queue="durable-subscriber-queue", binding_key="xyz") - session.message_transfer(destination= "amq.topic", message=self.createMessage(routing_key = "xyz", body = "my-message")) - session.queue_delete(queue = "durable-subscriber-queue") - - #test unbind: - #create a series of bindings to a queue - session.queue_declare(queue = "binding-test-queue", durable=True) - session.exchange_bind(exchange="amq.direct", queue="binding-test-queue", binding_key="abc") - session.exchange_bind(exchange="amq.direct", queue="binding-test-queue", binding_key="pqr") - session.exchange_bind(exchange="amq.direct", queue="binding-test-queue", binding_key="xyz") - session.exchange_bind(exchange="amq.match", queue="binding-test-queue", binding_key="a", arguments={"x-match":"all", "p":"a"}) - session.exchange_bind(exchange="amq.match", queue="binding-test-queue", binding_key="b", arguments={"x-match":"all", "p":"b"}) - session.exchange_bind(exchange="amq.match", queue="binding-test-queue", binding_key="c", arguments={"x-match":"all", "p":"c"}) - #then restart broker... - - - def phase8(self): - session = self.session - - #continue testing unbind: - #send messages to the queue via each of the bindings - for k in ["abc", "pqr", "xyz"]: - data = "first %s" % (k) - session.message_transfer(destination= "amq.direct", message=self.createMessage(routing_key=k, body=data)) - for a in [{"p":"a"}, {"p":"b"}, {"p":"c"}]: - data = "first %s" % (a["p"]) - session.message_transfer(destination="amq.match", message=self.createMessage(application_headers=a, body=data)) - #unbind some bindings (using final 0-10 semantics) - session.exchange_unbind(exchange="amq.direct", queue="binding-test-queue", binding_key="pqr") - session.exchange_unbind(exchange="amq.match", queue="binding-test-queue", binding_key="b") - #send messages again - for k in ["abc", "pqr", "xyz"]: - data = "second %s" % (k) - session.message_transfer(destination= "amq.direct", message=self.createMessage(routing_key=k, body=data)) - for a in [{"p":"a"}, {"p":"b"}, {"p":"c"}]: - data = "second %s" % (a["p"]) - session.message_transfer(destination="amq.match", message=self.createMessage(application_headers=a, body=data)) - - #check that only the correct messages are received - expected = [] - for k in ["abc", "pqr", "xyz"]: - expected.append("first %s" % (k)) - for a in [{"p":"a"}, {"p":"b"}, {"p":"c"}]: - expected.append("first %s" % (a["p"])) - for k in ["abc", "xyz"]: - expected.append("second %s" % (k)) - for a in [{"p":"a"}, {"p":"c"}]: - expected.append("second %s" % (a["p"])) - - session.message_subscribe(queue = "binding-test-queue", destination = "binding-test") - session.message_flow(unit = 1, value = 0xFFFFFFFF, destination = "binding-test") - session.message_flow(unit = 0, value = 10, destination = "binding-test") - queue = session.incoming("binding-test") - - while len(expected): - msg = queue.get(timeout=1) - if msg.body not in expected: - self.fail("Missing message: %s" % msg.body) - expected.remove(msg.body) - try: - msg = queue.get(timeout=1) - self.fail("Got extra message: %s" % msg.body) - except Empty: pass - - - - session.queue_declare(queue = "durable-subscriber-queue", exclusive=True, durable=True) - session.exchange_bind(exchange="amq.topic", queue="durable-subscriber-queue", binding_key="xyz") - session.message_transfer(destination= "amq.topic", message=self.createMessage(routing_key = "xyz", body = "my-message")) - session.queue_delete(queue = "durable-subscriber-queue") - - - def xid(self, txid, branchqual = ''): - return self.session.xid(format=0, global_id=txid, branch_id=branchqual) - - def txswap(self, src, dest, tx): - self.assertEqual(self.XA_OK, self.session.dtx_start(xid=tx).status) - self.session.message_subscribe(destination="temp-swap", queue=src, accept_mode=0) - self.session.message_flow(destination="temp-swap", unit=0, value=1) - self.session.message_flow(destination="temp-swap", unit=1, value=0xFFFFFFFF) - msg = self.session.incoming("temp-swap").get(timeout=1) - self.session.message_cancel(destination="temp-swap") - self.session.message_transfer(message=self.createMessage(routing_key=dest, correlation_id=self.getProperty(msg, 'correlation_id'), - body=msg.body)) - self.ack(msg) - self.assertEqual(self.XA_OK, self.session.dtx_end(xid=tx).status) - - def assertEmptyQueue(self, name): - self.assertEqual(0, self.session.queue_query(queue=name).message_count) - - def assertConnectionException(self, expectedCode, message): - self.assertEqual("connection", message.method.klass.name) - self.assertEqual("close", message.method.name) - self.assertEqual(expectedCode, message.reply_code) - - def assertExpectedMethod(self, reply, klass, method): - self.assertEqual(klass, reply.method.klass.name) - self.assertEqual(method, reply.method.name) - - def assertExpectedContent(self, msg, id, body): - self.assertEqual(id, self.getProperty(msg, 'correlation_id')) - self.assertEqual(body, msg.body) - return msg - - def getProperty(self, msg, name): - for h in msg.headers: - if hasattr(h, name): return getattr(h, name) - return None - - def ack(self, *msgs): - session = self.session - set = RangedSet() - for m in msgs: - set.add(m.id) - #TODO: tidy up completion - session.receiver._completed.add(m.id) - session.message_accept(set) - session.channel.session_completed(session.receiver._completed) - - def assertExpectedGetResult(self, id, body): - return self.assertExpectedContent(session.incoming("incoming-gets").get(timeout=1), id, body) - - def assertEqual(self, expected, actual, msg=''): - if expected != actual: raise Exception("%s expected: %s actual: %s" % (msg, expected, actual)) - - def assertMessageOnQueue(self, queue, id, body): - self.session.message_subscribe(destination="incoming-gets", queue=queue, accept_mode=0) - self.session.message_flow(destination="incoming-gets", unit=0, value=1) - self.session.message_flow(destination="incoming-gets", unit=1, value=0xFFFFFFFF) - msg = self.session.incoming("incoming-gets").get(timeout=1) - self.assertExpectedContent(msg, id, body) - self.ack(msg) - self.session.message_cancel(destination="incoming-gets") - - - def __init__(self): - TestBase010.__init__(self, "run") - self.setBroker("localhost") - self.errata = [] - - def connect(self): - """ Connects to the broker """ - self.conn = Connection(connect(self.host, self.port)) - self.conn.start(timeout=10) - self.session = self.conn.session("test-session", timeout=10) - - def run(self, args=sys.argv[1:]): - try: - opts, extra = getopt(args, "r:s:e:b:p:h", ["retry=", "spec=", "errata=", "broker=", "phase=", "help"]) - except GetoptError, e: - self._die(str(e)) - phase = 0 - retry = 0; - for opt, value in opts: - if opt in ("-h", "--help"): self._die() - if opt in ("-s", "--spec"): self.spec = value - if opt in ("-e", "--errata"): self.errata.append(value) - if opt in ("-b", "--broker"): self.setBroker(value) - if opt in ("-p", "--phase"): phase = int(value) - if opt in ("-r", "--retry"): retry = int(value) - - if not phase: self._die("please specify the phase to run") - phase = "phase%d" % phase - self.connect() - - try: - getattr(self, phase)() - print phase, "succeeded" - res = True; - except Exception, e: - print phase, "failed: ", e - traceback.print_exc() - res = False - - - if not self.session.error(): self.session.close(timeout=10) - self.conn.close(timeout=10) - - # Crude fix to wait for thread in client to exit after return from session_close() - # Reduces occurrences of "Unhandled exception in thread" messages after each test - import time - time.sleep(1) - - return res - - - def setBroker(self, broker): - rex = re.compile(r""" - # [ [ / ] @] [ : ] - ^ (?: ([^/]*) (?: / ([^@]*) )? @)? ([^:]+) (?: :([0-9]+))?$""", re.X) - match = rex.match(broker) - if not match: self._die("'%s' is not a valid broker" % (broker)) - self.user, self.password, self.host, self.port = match.groups() - self.port = int(default(self.port, 5672)) - self.user = default(self.user, "guest") - self.password = default(self.password, "guest") - - def _die(self, message = None): - if message: print message - print """ -Options: - -h/--help : this message - -s/--spec : file containing amqp XML spec - -p/--phase : test phase to run - -b/--broker [[/]@][:] : broker to connect to - """ - sys.exit(1) - -def default(value, default): - if (value == None): return default - else: return value - -if __name__ == "__main__": - test = PersistenceTest() - if not test.run(): sys.exit(1) diff --git a/qpid/cpp/src/tests/legacystore/python_tests/__init__.py b/qpid/cpp/src/tests/legacystore/python_tests/__init__.py deleted file mode 100644 index ebb9da8670..0000000000 --- a/qpid/cpp/src/tests/legacystore/python_tests/__init__.py +++ /dev/null @@ -1,24 +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. -# - -# Do not delete - marks this directory as a python package. - -from client_persistence import * -from resize import * - diff --git a/qpid/cpp/src/tests/legacystore/python_tests/client_persistence.py b/qpid/cpp/src/tests/legacystore/python_tests/client_persistence.py deleted file mode 100644 index 37c12601be..0000000000 --- a/qpid/cpp/src/tests/legacystore/python_tests/client_persistence.py +++ /dev/null @@ -1,239 +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. -# - -import os - -from brokertest import EXPECT_EXIT_OK -from store_test import StoreTest, Qmf, store_args -from qpid.messaging import * - -import qpid.messaging, brokertest -brokertest.qm = qpid.messaging # FIXME aconway 2014-04-04: Tests fail with SWIG client. - -class ExchangeQueueTests(StoreTest): - """ - Simple tests of the broker exchange and queue types - """ - - def test_direct_exchange(self): - """Test Direct exchange.""" - broker = self.broker(store_args(), name="test_direct_exchange", expect=EXPECT_EXIT_OK) - msg1 = Message("A_Message1", durable=True, correlation_id="Msg0001") - msg2 = Message("B_Message1", durable=True, correlation_id="Msg0002") - broker.send_message("a", msg1) - broker.send_message("b", msg2) - broker.terminate() - - broker = self.broker(store_args(), name="test_direct_exchange") - self.check_message(broker, "a", msg1, True) - self.check_message(broker, "b", msg2, True) - - def test_topic_exchange(self): - """Test Topic exchange.""" - broker = self.broker(store_args(), name="test_topic_exchange", expect=EXPECT_EXIT_OK) - ssn = broker.connect().session() - snd1 = ssn.sender("abc/key1; {create:always, node:{type:topic, durable:True}}") - snd2 = ssn.sender("abc/key2; {create:always, node:{type:topic, durable:True}}") - ssn.receiver("a; {create:always, link:{x-bindings:[{exchange:abc, key:key1}]}, node:{durable:True}}") - ssn.receiver("b; {create:always, link:{x-bindings:[{exchange:abc, key:key1}]}, node:{durable:True}}") - ssn.receiver("c; {create:always, link:{x-bindings:[{exchange:abc, key:key1}, " - "{exchange:abc, key: key2}]}, node:{durable:True}}") - ssn.receiver("d; {create:always, link:{x-bindings:[{exchange:abc, key:key2}]}, node:{durable:True}}") - ssn.receiver("e; {create:always, link:{x-bindings:[{exchange:abc, key:key2}]}, node:{durable:True}}") - msg1 = Message("Message1", durable=True, correlation_id="Msg0003") - snd1.send(msg1) - msg2 = Message("Message2", durable=True, correlation_id="Msg0004") - snd2.send(msg2) - broker.terminate() - - broker = self.broker(store_args(), name="test_topic_exchange") - self.check_message(broker, "a", msg1, True) - self.check_message(broker, "b", msg1, True) - self.check_messages(broker, "c", [msg1, msg2], True) - self.check_message(broker, "d", msg2, True) - self.check_message(broker, "e", msg2, True) - - - def test_legacy_lvq(self): - """Test legacy LVQ.""" - broker = self.broker(store_args(), name="test_lvq", expect=EXPECT_EXIT_OK) - ma1 = Message("A1", durable=True, correlation_id="Msg0005", properties={"qpid.LVQ_key":"A"}) - ma2 = Message("A2", durable=True, correlation_id="Msg0006", properties={"qpid.LVQ_key":"A"}) - mb1 = Message("B1", durable=True, correlation_id="Msg0007", properties={"qpid.LVQ_key":"B"}) - mb2 = Message("B2", durable=True, correlation_id="Msg0008", properties={"qpid.LVQ_key":"B"}) - mb3 = Message("B3", durable=True, correlation_id="Msg0009", properties={"qpid.LVQ_key":"B"}) - mc1 = Message("C1", durable=True, correlation_id="Msg0010", properties={"qpid.LVQ_key":"C"}) - broker.send_messages("lvq-test", [mb1, ma1, ma2, mb2, mb3, mc1], - xprops="arguments:{\"qpid.last_value_queue\":True}") - broker.terminate() - - broker = self.broker(store_args(), name="test_lvq", expect=EXPECT_EXIT_OK) - ssn = self.check_messages(broker, "lvq-test", [ma2, mb3, mc1], empty=True, ack=False) - # Add more messages while subscriber is active (no replacement): - ma3 = Message("A3", durable=True, correlation_id="Msg0011", properties={"qpid.LVQ_key":"A"}) - ma4 = Message("A4", durable=True, correlation_id="Msg0012", properties={"qpid.LVQ_key":"A"}) - mc2 = Message("C2", durable=True, correlation_id="Msg0013", properties={"qpid.LVQ_key":"C"}) - mc3 = Message("C3", durable=True, correlation_id="Msg0014", properties={"qpid.LVQ_key":"C"}) - mc4 = Message("C4", durable=True, correlation_id="Msg0015", properties={"qpid.LVQ_key":"C"}) - broker.send_messages("lvq-test", [mc2, mc3, ma3, ma4, mc4], session=ssn) - ssn.acknowledge() - broker.terminate() - - broker = self.broker(store_args(), name="test_lvq") - self.check_messages(broker, "lvq-test", [ma4, mc4], True) - - - def test_fanout_exchange(self): - """Test Fanout Exchange""" - broker = self.broker(store_args(), name="test_fanout_exchange", expect=EXPECT_EXIT_OK) - ssn = broker.connect().session() - snd = ssn.sender("TestFanoutExchange; {create: always, node: {type: topic, x-declare: {type: fanout}}}") - ssn.receiver("TestFanoutExchange; {link: {name: \"q1\", durable: True, reliability:at-least-once}}") - ssn.receiver("TestFanoutExchange; {link: {name: \"q2\", durable: True, reliability:at-least-once}}") - ssn.receiver("TestFanoutExchange; {link: {name: \"q3\", durable: True, reliability:at-least-once}}") - msg1 = Message("Msg1", durable=True, correlation_id="Msg0001") - snd.send(msg1) - msg2 = Message("Msg2", durable=True, correlation_id="Msg0002") - snd.send(msg2) - broker.terminate() - - broker = self.broker(store_args(), name="test_fanout_exchange") - self.check_messages(broker, "q1", [msg1, msg2], True) - self.check_messages(broker, "q2", [msg1, msg2], True) - self.check_messages(broker, "q3", [msg1, msg2], True) - - - def test_message_reject(self): - broker = self.broker(store_args(), name="test_message_reject", expect=EXPECT_EXIT_OK) - ssn = broker.connect().session() - snd = ssn.sender("tmr; {create:always, node:{type:queue, durable:True}}") - rcv = ssn.receiver("tmr; {create:always, node:{type:queue, durable:True}}") - m1 = Message("test_message_reject", durable=True, correlation_id="Msg0001") - snd.send(m1) - m2 = rcv.fetch() - ssn.acknowledge(message=m2, disposition=Disposition(REJECTED)) - broker.terminate() - - broker = self.broker(store_args(), name="test_message_reject") - qmf = Qmf(broker) - assert qmf.queue_message_count("tmr") == 0 - - - def test_route(self): - """ Test the recovery of a route (link and bridge objects.""" - broker = self.broker(store_args(), name="test_route", expect=EXPECT_EXIT_OK) - qmf = Qmf(broker) - qmf_broker_obj = qmf.get_objects("broker")[0] - - # create a "link" - link_args = {"host":"a.fake.host.com", "port":9999, "durable":True, - "authMechanism":"PLAIN", "username":"guest", "password":"guest", - "transport":"tcp"} - result = qmf_broker_obj.create("link", "test-link", link_args, False) - self.assertEqual(result.status, 0, result) - link = qmf.get_objects("link")[0] - - # create bridge - bridge_args = {"link":"test-link", "src":"amq.direct", "dest":"amq.fanout", - "key":"my-key", "durable":True} - result = qmf_broker_obj.create("bridge", "test-bridge", bridge_args, False); - self.assertEqual(result.status, 0, result) - bridge = qmf.get_objects("bridge")[0] - - broker.terminate() - - # recover the link and bridge - broker = self.broker(store_args(), name="test_route") - qmf = Qmf(broker) - qmf_broker_obj = qmf.get_objects("broker")[0] - self.assertEqual(len(qmf.get_objects("link")), 1) - self.assertEqual(len(qmf.get_objects("bridge")), 1) - - - -class AlternateExchangePropertyTests(StoreTest): - """ - Test the persistence of the Alternate Exchange property for exchanges and queues. - """ - - def test_exchange(self): - """Exchange alternate exchange property persistence test""" - broker = self.broker(store_args(), name="test_exchange", expect=EXPECT_EXIT_OK) - qmf = Qmf(broker) - qmf.add_exchange("altExch", "direct", durable=True) # Serves as alternate exchange instance - qmf.add_exchange("testExch", "direct", durable=True, alt_exchange_name="altExch") - qmf.close() - broker.terminate() - - broker = self.broker(store_args(), name="test_exchange") - qmf = Qmf(broker) - try: - qmf.add_exchange("altExch", "direct", passive=True) - except Exception, error: - self.fail("Alternate exchange (\"altExch\") instance not recovered: %s" % error) - try: - qmf.add_exchange("testExch", "direct", passive=True) - except Exception, error: - self.fail("Test exchange (\"testExch\") instance not recovered: %s" % error) - self.assertTrue(qmf.query_exchange("testExch", alt_exchange_name = "altExch"), - "Alternate exchange property not found or is incorrect on exchange \"testExch\".") - qmf.close() - - def test_queue(self): - """Queue alternate exchange property persistexchangeNamece test""" - broker = self.broker(store_args(), name="test_queue", expect=EXPECT_EXIT_OK) - qmf = Qmf(broker) - qmf.add_exchange("altExch", "direct", durable=True) # Serves as alternate exchange instance - qmf.add_queue("testQueue", durable=True, alt_exchange_name="altExch") - qmf.close() - broker.terminate() - - broker = self.broker(store_args(), name="test_queue") - qmf = Qmf(broker) - try: - qmf.add_exchange("altExch", "direct", passive=True) - except Exception, error: - self.fail("Alternate exchange (\"altExch\") instance not recovered: %s" % error) - try: - qmf.add_queue("testQueue", passive=True) - except Exception, error: - self.fail("Test queue (\"testQueue\") instance not recovered: %s" % error) - self.assertTrue(qmf.query_queue("testQueue", alt_exchange_name = "altExch"), - "Alternate exchange property not found or is incorrect on queue \"testQueue\".") - qmf.close() - - -class RedeliveredTests(StoreTest): - """ - Test the behavior of the redelivered flag in the context of persistence - """ - - def test_broker_recovery(self): - """Test that the redelivered flag is set on messages after recovery of broker""" - broker = self.broker(store_args(), name="test_broker_recovery", expect=EXPECT_EXIT_OK) - msg_content = "xyz"*100 - msg = Message(msg_content, durable=True) - broker.send_message("testQueue", msg) - broker.terminate() - - broker = self.broker(store_args(), name="test_broker_recovery") - rcv_msg = broker.get_message("testQueue") - self.assertEqual(msg_content, rcv_msg.content) - self.assertTrue(rcv_msg.redelivered) - diff --git a/qpid/cpp/src/tests/legacystore/python_tests/resize.py b/qpid/cpp/src/tests/legacystore/python_tests/resize.py deleted file mode 100644 index e719b755da..0000000000 --- a/qpid/cpp/src/tests/legacystore/python_tests/resize.py +++ /dev/null @@ -1,170 +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. -# - -import glob -import os -import subprocess - -from brokertest import EXPECT_EXIT_OK -from qpid.datatypes import uuid4 -from store_test import StoreTest, store_args -from qpid.messaging import Message - -import qpid.messaging, brokertest -brokertest.qm = qpid.messaging # TODO aconway 2014-04-04: Tests fail with SWIG client. - -class ResizeTest(StoreTest): - - resize_tool = os.getenv("QPID_STORE_RESIZE_TOOL", "qpid-store-resize") - print resize_tool - def _resize_store(self, store_dir, queue_name, resize_num_files, resize_file_size, exp_fail): - for f in glob.glob(os.path.join(store_dir, "*")): - final_store_dir = os.path.join(f, queue_name) - p = subprocess.Popen([self.resize_tool, final_store_dir, "--num-jfiles", str(resize_num_files), - "--jfile-size-pgs", str(resize_file_size), "--quiet"], stdout = subprocess.PIPE, - stderr = subprocess.STDOUT) - res = p.wait() - err_found = False - try: - for l in p.stdout: - if exp_fail: - err_found = True - print "[Expected error]:", - print l, - finally: - p.stdout.close() - return res - - def _resize_test(self, queue_name, num_msgs, msg_size, resize_num_files, resize_file_size, init_num_files = 8, - init_file_size = 24, exp_fail = False, wait_time = None): - # Using a sender will force the creation of an empty persistent queue which is needed for some tests - broker = self.broker(store_args(), name="broker", expect=EXPECT_EXIT_OK, wait=wait_time) - ssn = broker.connect().session() - snd = ssn.sender("%s; {create:always, node:{durable:True}}" % queue_name) - - msgs = [] - for index in range(0, num_msgs): - msg = Message(self.make_message(index, msg_size), durable=True, id=uuid4(), correlation_id="msg-%04d"%index) - msgs.append(msg) - snd.send(msg) - broker.terminate() - - res = self._resize_store(os.path.join(self.dir, "broker", "rhm", "jrnl"), queue_name, resize_num_files, - resize_file_size, exp_fail) - if res != 0: - if exp_fail: - return - self.fail("ERROR: Resize operation failed with return code %d" % res) - elif exp_fail: - self.fail("ERROR: Resize operation succeeded, but a failure was expected") - - broker = self.broker(store_args(), name="broker") - self.check_messages(broker, queue_name, msgs, True) - - # TODO: Check the physical files to check number and size are as expected. - - -class SimpleTest(ResizeTest): - """ - Simple tests of the resize utility for resizing a journal to larger and smaller sizes. - """ - - def test_empty_store_same(self): - self._resize_test(queue_name = "empty_store_same", - num_msgs = 0, msg_size = 0, - init_num_files = 8, init_file_size = 24, - resize_num_files = 8, resize_file_size = 24) - - def test_empty_store_up(self): - self._resize_test(queue_name = "empty_store_up", - num_msgs = 0, msg_size = 0, - init_num_files = 8, init_file_size = 24, - resize_num_files = 16, resize_file_size = 48) - - def test_empty_store_down(self): - self._resize_test(queue_name = "empty_store_down", - num_msgs = 0, msg_size = 0, - init_num_files = 8, init_file_size = 24, - resize_num_files = 6, resize_file_size = 12) - -# TODO: Put into long tests, make sure there is > 128GB free disk space -# def test_empty_store_max(self): -# self._resize_test(queue_name = "empty_store_max", -# num_msgs = 0, msg_size = 0, -# init_num_files = 8, init_file_size = 24, -# resize_num_files = 64, resize_file_size = 32768, -# wait_time = 120) - - def test_empty_store_min(self): - self._resize_test(queue_name = "empty_store_min", - num_msgs = 0, msg_size = 0, - init_num_files = 8, init_file_size = 24, - resize_num_files = 4, resize_file_size = 1) - - def test_basic_up(self): - self._resize_test(queue_name = "basic_up", - num_msgs = 100, msg_size = 10000, - init_num_files = 8, init_file_size = 24, - resize_num_files = 16, resize_file_size = 48) - - def test_basic_down(self): - self._resize_test(queue_name = "basic_down", - num_msgs = 100, msg_size = 10000, - init_num_files = 8, init_file_size = 24, - resize_num_files = 4, resize_file_size = 15) - - def test_basic_low(self): - self._resize_test(queue_name = "basic_low", - num_msgs = 100, msg_size = 10000, - init_num_files = 8, init_file_size = 24, - resize_num_files = 4, resize_file_size = 4, - exp_fail = True) - - def test_basic_under(self): - self._resize_test(queue_name = "basic_under", - num_msgs = 100, msg_size = 10000, - init_num_files = 8, init_file_size = 24, - resize_num_files = 4, resize_file_size = 3, - exp_fail = True) - - def test_very_large_msg_up(self): - self._resize_test(queue_name = "very_large_msg_up", - num_msgs = 4, msg_size = 2000000, - init_num_files = 8, init_file_size = 24, - resize_num_files = 16, resize_file_size = 48) - - def test_very_large_msg_down(self): - self._resize_test(queue_name = "very_large_msg_down", - num_msgs = 4, msg_size = 2000000, - init_num_files = 16, init_file_size = 64, - resize_num_files = 16, resize_file_size = 48) - - def test_very_large_msg_low(self): - self._resize_test(queue_name = "very_large_msg_low", - num_msgs = 4, msg_size = 2000000, - init_num_files = 8, init_file_size = 24, - resize_num_files = 7, resize_file_size = 20, - exp_fail = True) - - def test_very_large_msg_under(self): - self._resize_test(queue_name = "very_large_msg_under", - num_msgs = 4, msg_size = 2000000, - init_num_files = 8, init_file_size = 24, - resize_num_files = 6, resize_file_size = 8, - exp_fail = True) diff --git a/qpid/cpp/src/tests/legacystore/python_tests/store_test.py b/qpid/cpp/src/tests/legacystore/python_tests/store_test.py deleted file mode 100644 index cc846aefd4..0000000000 --- a/qpid/cpp/src/tests/legacystore/python_tests/store_test.py +++ /dev/null @@ -1,417 +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. -# - -import re -from brokertest import BrokerTest -from qpid.messaging import Empty -from qmf.console import Session - -import qpid.messaging, brokertest -brokertest.qm = qpid.messaging # TODO aconway 2014-04-04: Tests fail with SWIG client. - - -def store_args(store_dir = None): - """Return the broker args necessary to load the async store""" - assert BrokerTest.store_lib - if store_dir == None: - return [] - return ["--store-dir", store_dir] - -class Qmf: - """ - QMF functions not yet available in the new QMF API. Remove this and replace with new API when it becomes available. - """ - def __init__(self, broker): - self.__session = Session() - self.__broker = self.__session.addBroker("amqp://localhost:%d"%broker.port()) - - def add_exchange(self, exchange_name, exchange_type, alt_exchange_name=None, passive=False, durable=False, - arguments = None): - """Add a new exchange""" - amqp_session = self.__broker.getAmqpSession() - if arguments == None: - arguments = {} - if alt_exchange_name: - amqp_session.exchange_declare(exchange=exchange_name, type=exchange_type, - alternate_exchange=alt_exchange_name, passive=passive, durable=durable, - arguments=arguments) - else: - amqp_session.exchange_declare(exchange=exchange_name, type=exchange_type, passive=passive, durable=durable, - arguments=arguments) - - def add_queue(self, queue_name, alt_exchange_name=None, passive=False, durable=False, arguments = None): - """Add a new queue""" - amqp_session = self.__broker.getAmqpSession() - if arguments == None: - arguments = {} - if alt_exchange_name: - amqp_session.queue_declare(queue_name, alternate_exchange=alt_exchange_name, passive=passive, - durable=durable, arguments=arguments) - else: - amqp_session.queue_declare(queue_name, passive=passive, durable=durable, arguments=arguments) - - def delete_queue(self, queue_name): - """Delete an existing queue""" - amqp_session = self.__broker.getAmqpSession() - amqp_session.queue_delete(queue_name) - - def _query(self, name, _class, package, alt_exchange_name=None): - """Qmf query function which can optionally look for the presence of an alternate exchange name""" - try: - obj_list = self.__session.getObjects(_class=_class, _package=package) - found = False - for obj in obj_list: - if obj.name == name: - found = True - if alt_exchange_name != None: - alt_exch_list = self.__session.getObjects(_objectId=obj.altExchange) - if len(alt_exch_list) == 0 or alt_exch_list[0].name != alt_exchange_name: - return False - break - return found - except Exception: - return False - - - def query_exchange(self, exchange_name, alt_exchange_name=None): - """Test for the presence of an exchange, and optionally whether it has an alternate exchange set to a known - value.""" - return self._query(exchange_name, "exchange", "org.apache.qpid.broker", alt_exchange_name) - - def query_queue(self, queue_name, alt_exchange_name=None): - """Test for the presence of an exchange, and optionally whether it has an alternate exchange set to a known - value.""" - return self._query(queue_name, "queue", "org.apache.qpid.broker", alt_exchange_name) - - def queue_message_count(self, queue_name): - """Query the number of messages on a queue""" - queue_list = self.__session.getObjects(_class="queue", _name=queue_name) - if len(queue_list): - return queue_list[0].msgDepth - - def queue_empty(self, queue_name): - """Check if a queue is empty (has no messages waiting)""" - return self.queue_message_count(queue_name) == 0 - - def get_objects(self, target_class, target_package="org.apache.qpid.broker"): - return self.__session.getObjects(_class=target_class, _package=target_package) - - - def close(self): - self.__session.delBroker(self.__broker) - self.__session = None - - -class StoreTest(BrokerTest): - """ - This subclass of BrokerTest adds some convenience test/check functions - """ - - def _chk_empty(self, queue, receiver): - """Check if a queue is empty (has no more messages)""" - try: - msg = receiver.fetch(timeout=0) - self.assert_(False, "Queue \"%s\" not empty: found message: %s" % (queue, msg)) - except Empty: - pass - - @staticmethod - def make_message(msg_count, msg_size): - """Make message content. Format: 'abcdef....' followed by 'msg-NNNN', where NNNN is the message count""" - msg = "msg-%04d" % msg_count - msg_len = len(msg) - buff = "" - if msg_size != None and msg_size > msg_len: - for index in range(0, msg_size - msg_len): - if index == msg_size - msg_len - 1: - buff += "-" - else: - buff += chr(ord('a') + (index % 26)) - return buff + msg - - # Functions for formatting address strings - - @staticmethod - def _fmt_csv(string_list, list_braces = None): - """Format a list using comma-separation. Braces are optionally added.""" - if len(string_list) == 0: - return "" - first = True - str_ = "" - if list_braces != None: - str_ += list_braces[0] - for string in string_list: - if string != None: - if first: - first = False - else: - str_ += ", " - str_ += string - if list_braces != None: - str_ += list_braces[1] - return str_ - - def _fmt_map(self, string_list): - """Format a map {l1, l2, l3, ...} from a string list. Each item in the list must be a formatted map - element('key:val').""" - return self._fmt_csv(string_list, list_braces="{}") - - def _fmt_list(self, string_list): - """Format a list [l1, l2, l3, ...] from a string list.""" - return self._fmt_csv(string_list, list_braces="[]") - - def addr_fmt(self, node_name, **kwargs): - """Generic AMQP to new address formatter. Takes common (but not all) AMQP options and formats an address - string.""" - # Get keyword args - node_subject = kwargs.get("node_subject") - create_policy = kwargs.get("create_policy") - delete_policy = kwargs.get("delete_policy") - assert_policy = kwargs.get("assert_policy") - mode = kwargs.get("mode") - link = kwargs.get("link", False) - link_name = kwargs.get("link_name") - node_type = kwargs.get("node_type") - durable = kwargs.get("durable", False) - link_reliability = kwargs.get("link_reliability") - x_declare_list = kwargs.get("x_declare_list", []) - x_bindings_list = kwargs.get("x_bindings_list", []) - x_subscribe_list = kwargs.get("x_subscribe_list", []) - - node_flag = not link and (node_type != None or durable or len(x_declare_list) > 0 or len(x_bindings_list) > 0) - link_flag = link and (link_name != None or durable or link_reliability != None or len(x_declare_list) > 0 or - len(x_bindings_list) > 0 or len(x_subscribe_list) > 0) - assert not (node_flag and link_flag) - - opt_str_list = [] - if create_policy != None: - opt_str_list.append("create: %s" % create_policy) - if delete_policy != None: - opt_str_list.append("delete: %s" % delete_policy) - if assert_policy != None: - opt_str_list.append("assert: %s" % assert_policy) - if mode != None: - opt_str_list.append("mode: %s" % mode) - if node_flag or link_flag: - node_str_list = [] - if link_name != None: - node_str_list.append("name: \"%s\"" % link_name) - if node_type != None: - node_str_list.append("type: %s" % node_type) - if durable: - node_str_list.append("durable: True") - if link_reliability != None: - node_str_list.append("reliability: %s" % link_reliability) - if len(x_declare_list) > 0: - node_str_list.append("x-declare: %s" % self._fmt_map(x_declare_list)) - if len(x_bindings_list) > 0: - node_str_list.append("x-bindings: %s" % self._fmt_list(x_bindings_list)) - if len(x_subscribe_list) > 0: - node_str_list.append("x-subscribe: %s" % self._fmt_map(x_subscribe_list)) - if node_flag: - opt_str_list.append("node: %s" % self._fmt_map(node_str_list)) - else: - opt_str_list.append("link: %s" % self._fmt_map(node_str_list)) - addr_str = node_name - if node_subject != None: - addr_str += "/%s" % node_subject - if len(opt_str_list) > 0: - addr_str += "; %s" % self._fmt_map(opt_str_list) - return addr_str - - def snd_addr(self, node_name, **kwargs): - """ Create a send (node) address""" - # Get keyword args - topic = kwargs.get("topic") - topic_flag = kwargs.get("topic_flag", False) - auto_create = kwargs.get("auto_create", True) - auto_delete = kwargs.get("auto_delete", False) - durable = kwargs.get("durable", False) - exclusive = kwargs.get("exclusive", False) - ftd_count = kwargs.get("ftd_count") - ftd_size = kwargs.get("ftd_size") - policy = kwargs.get("policy", "flow-to-disk") - exchage_type = kwargs.get("exchage_type") - - create_policy = None - if auto_create: - create_policy = "always" - delete_policy = None - if auto_delete: - delete_policy = "always" - node_type = None - if topic != None or topic_flag: - node_type = "topic" - x_declare_list = ["\"exclusive\": %s" % exclusive] - if ftd_count != None or ftd_size != None: - queue_policy = ["\'qpid.policy_type\': %s" % policy] - if ftd_count: - queue_policy.append("\'qpid.max_count\': %d" % ftd_count) - if ftd_size: - queue_policy.append("\'qpid.max_size\': %d" % ftd_size) - x_declare_list.append("arguments: %s" % self._fmt_map(queue_policy)) - if exchage_type != None: - x_declare_list.append("type: %s" % exchage_type) - - return self.addr_fmt(node_name, topic=topic, create_policy=create_policy, delete_policy=delete_policy, - node_type=node_type, durable=durable, x_declare_list=x_declare_list) - - def rcv_addr(self, node_name, **kwargs): - """ Create a receive (link) address""" - # Get keyword args - auto_create = kwargs.get("auto_create", True) - auto_delete = kwargs.get("auto_delete", False) - link_name = kwargs.get("link_name") - durable = kwargs.get("durable", False) - browse = kwargs.get("browse", False) - exclusive = kwargs.get("exclusive", False) - binding_list = kwargs.get("binding_list", []) - ftd_count = kwargs.get("ftd_count") - ftd_size = kwargs.get("ftd_size") - policy = kwargs.get("policy", "flow-to-disk") - - create_policy = None - if auto_create: - create_policy = "always" - delete_policy = None - if auto_delete: - delete_policy = "always" - mode = None - if browse: - mode = "browse" - x_declare_list = ["\"exclusive\": %s" % exclusive] - if ftd_count != None or ftd_size != None: - queue_policy = ["\'qpid.policy_type\': %s" % policy] - if ftd_count: - queue_policy.append("\'qpid.max_count\': %d" % ftd_count) - if ftd_size: - queue_policy.append("\'qpid.max_size\': %d" % ftd_size) - x_declare_list.append("arguments: %s" % self._fmt_map(queue_policy)) - x_bindings_list = [] - for binding in binding_list: - x_bindings_list.append("{exchange: %s, key: %s}" % binding) - if durable: reliability = 'at-least-once' - else: reliability = None - return self.addr_fmt(node_name, create_policy=create_policy, delete_policy=delete_policy, mode=mode, link=True, - link_name=link_name, durable=durable, x_declare_list=x_declare_list, - x_bindings_list=x_bindings_list, link_reliability=reliability) - - def check_message(self, broker, queue, exp_msg, transactional=False, empty=False, ack=True, browse=False): - """Check that a message is on a queue by dequeuing it and comparing it to the expected message""" - return self.check_messages(broker, queue, [exp_msg], transactional, empty, ack, browse) - - def check_messages(self, broker, queue, exp_msg_list, transactional=False, empty=False, ack=True, browse=False, - emtpy_flag=False): - """Check that messages is on a queue by dequeuing them and comparing them to the expected messages""" - if emtpy_flag: - num_msgs = 0 - else: - num_msgs = len(exp_msg_list) - ssn = broker.connect().session(transactional=transactional) - rcvr = ssn.receiver(self.rcv_addr(queue, browse=browse), capacity=num_msgs) - if num_msgs > 0: - try: - recieved_msg_list = [rcvr.fetch(timeout=0) for i in range(num_msgs)] - except Empty: - self.assert_(False, "Queue \"%s\" is empty, unable to retrieve expected message %d." % (queue, i)) - for i in range(0, len(recieved_msg_list)): - self.assertEqual(recieved_msg_list[i].content, exp_msg_list[i].content) - self.assertEqual(recieved_msg_list[i].correlation_id, exp_msg_list[i].correlation_id) - if empty: - self._chk_empty(queue, rcvr) - if ack: - ssn.acknowledge() - if transactional: - ssn.commit() - ssn.connection.close() - else: - if transactional: - ssn.commit() - return ssn - - - # Functions for finding strings in the broker log file (or other files) - - @staticmethod - def _read_file(file_name): - """Returns the content of file named file_name as a string""" - file_handle = file(file_name) - try: - return file_handle.read() - finally: - file_handle.close() - - def _get_hits(self, broker, search): - """Find all occurrences of the search in the broker log (eliminating possible duplicates from msgs on multiple - queues)""" - # TODO: Use sets when RHEL-4 is no longer supported - hits = [] - for hit in search.findall(self._read_file(broker.log)): - if hit not in hits: - hits.append(hit) - return hits - - def _reconsile_hits(self, broker, ftd_msgs, release_hits): - """Remove entries from list release_hits if they match the message id in ftd_msgs. Check for remaining - release_hits.""" - for msg in ftd_msgs: - found = False - for hit in release_hits: - if str(msg.id) in hit: - release_hits.remove(hit) - #print "Found %s in %s" % (msg.id, broker.log) - found = True - break - if not found: - self.assert_(False, "Unable to locate released message %s in log %s" % (msg.id, broker.log)) - if len(release_hits) > 0: - err = "Messages were unexpectedly released in log %s:\n" % broker.log - for hit in release_hits: - err += " %s\n" % hit - self.assert_(False, err) - - def check_msg_release(self, broker, ftd_msgs): - """ Check for 'Content released' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content released$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) - - def check_msg_release_on_commit(self, broker, ftd_msgs): - """ Check for 'Content released on commit' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content released on commit$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) - - def check_msg_release_on_recover(self, broker, ftd_msgs): - """ Check for 'Content released after recovery' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content released after recovery$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) - - def check_msg_block(self, broker, ftd_msgs): - """Check for 'Content release blocked' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content release blocked$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) - - def check_msg_block_on_commit(self, broker, ftd_msgs): - """Check for 'Content release blocked' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content release blocked on commit$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) diff --git a/qpid/cpp/src/tests/legacystore/run_long_python_tests b/qpid/cpp/src/tests/legacystore/run_long_python_tests deleted file mode 100644 index be6380302c..0000000000 --- a/qpid/cpp/src/tests/legacystore/run_long_python_tests +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env 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_python_tests LONG_TEST diff --git a/qpid/cpp/src/tests/legacystore/run_python_tests b/qpid/cpp/src/tests/legacystore/run_python_tests deleted file mode 100755 index 4d8baec121..0000000000 --- a/qpid/cpp/src/tests/legacystore/run_python_tests +++ /dev/null @@ -1,47 +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. -# - -import os -import sys - -# Put the python test library on the path so we can get our -# environment - -file_path = os.path.abspath(__file__) -store_tests_dir = os.path.split(file_path)[0] -tests_dir = os.path.split(store_tests_dir)[0] - -sys.path.insert(0, tests_dir) - -from common import * - -# Add our directory to the python path - -ENV["PYTHONPATH"] = "{0}:{1}".format(store_tests_dir, ENV["PYTHONPATH"]) - -# To debug a test, add the following options to the end of the following line: -# -v DEBUG -c qpid.messaging.io.ops [*.testName] - -port = start_broker("broker", "--load-module {0}".format(STORE_LIB)) - -run_broker_tests(port, "-m python_tests", "-DOUTDIR={0}".format(WORK_DIR)) - -check_results() diff --git a/qpid/cpp/src/tests/legacystore/run_short_python_tests b/qpid/cpp/src/tests/legacystore/run_short_python_tests deleted file mode 100644 index 9b9e7c59be..0000000000 --- a/qpid/cpp/src/tests/legacystore/run_short_python_tests +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env 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_python_tests SHORT_TEST diff --git a/qpid/cpp/src/tests/legacystore/system_test.sh b/qpid/cpp/src/tests/legacystore/system_test.sh deleted file mode 100644 index 52cecbce8a..0000000000 --- a/qpid/cpp/src/tests/legacystore/system_test.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env 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. -# - -error() { echo $*; exit 1; } - -# Make sure $QPID_DIR contains what we need. -if ! test -d "$QPID_DIR" ; then - echo "WARNING: QPID_DIR is not set skipping system tests." - exit -fi -STORE_LIB=../lib/.libs/msgstore.so - -xml_spec=$QPID_DIR/specs/amqp.0-10-qpid-errata.stripped.xml -test -f $xml_spec || error "$xml_spec not found: invalid \$QPID_DIR ?" -export PYTHONPATH=$QPID_DIR/python:$QPID_DIR/extras/qmf/src/py:$QPID_DIR/tools/src/py - -echo "Using directory $TMP_DATA_DIR" - -fail=0 - -# Run the tests with a given set of flags -BROKER_OPTS="--no-module-dir --load-module=$STORE_LIB --data-dir=$TMP_DATA_DIR --auth=no --wcache-page-size 16" -run_tests() { - for p in `seq 1 8`; do - $abs_srcdir/start_broker "$@" ${BROKER_OPTS} || { echo "FAIL broker start"; return 1; } - python "$abs_srcdir/persistence.py" -s "$xml_spec" -b localhost:`cat qpidd.port` -p $p -r 3 || fail=1; - $abs_srcdir/stop_broker - done -} - -run_tests || fail=1 - -exit $fail diff --git a/qpid/cpp/src/tests/legacystore/unit_test.cpp b/qpid/cpp/src/tests/legacystore/unit_test.cpp deleted file mode 100644 index add80a6f91..0000000000 --- a/qpid/cpp/src/tests/legacystore/unit_test.cpp +++ /dev/null @@ -1,28 +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. - * - */ - - -// Defines test_main function to link with actual unit test code. -#define BOOST_AUTO_TEST_MAIN // Boost 1.33 -#define BOOST_TEST_MAIN - -#include "unit_test.h" - diff --git a/qpid/cpp/src/tests/legacystore/unit_test.h b/qpid/cpp/src/tests/legacystore/unit_test.h deleted file mode 100644 index 16b6ae2ffb..0000000000 --- a/qpid/cpp/src/tests/legacystore/unit_test.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef QPIPD_TEST_UNIT_TEST_H_ -#define QPIPD_TEST_UNIT_TEST_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. - * - */ - - -// Workaround so we can build against boost 1.32, 1.33 and boost 1.34. -// Remove when we no longer need to support 1.32 or 1.33. - -#include - -#if (BOOST_VERSION < 103400) // v.1.33 and earlier -# include -#else // v.1.34 and later -# include -#endif - -// Keep the test function for compilation but do not not register it. -// TODO aconway 2008-04-23: better workaround for expected failures. -// The following causes the test testUpdateTxState not to run at all. -# define QPID_AUTO_TEST_CASE_EXPECTED_FAILURES(test_name,n) \ - namespace { struct test_name { void test_method(); }; } \ - void test_name::test_method() -// The following runs the test testUpdateTxState, but it fails. -/*#define QPID_AUTO_TEST_CASE_EXPECTED_FAILURES(test_name,n) \ - namespace { struct test_name { void test_method(); }; } \ - BOOST_AUTO_TEST_CASE(name)*/ - -#if (BOOST_VERSION < 103300) // v.1.32 and earlier - -# define QPID_AUTO_TEST_SUITE(name) -# define QPID_AUTO_TEST_CASE(name) BOOST_AUTO_UNIT_TEST(name) -# define QPID_AUTO_TEST_SUITE_END() - -#elif (BOOST_VERSION < 103400) // v.1.33 - -// Note the trailing ';' -# define QPID_AUTO_TEST_SUITE(name) BOOST_AUTO_TEST_SUITE(name); -# define QPID_AUTO_TEST_CASE(name) BOOST_AUTO_TEST_CASE(name) -# define QPID_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END(); - -#else // v.1.34 and later - -# define QPID_AUTO_TEST_SUITE(name) BOOST_AUTO_TEST_SUITE(name) -# define QPID_AUTO_TEST_CASE(name) BOOST_AUTO_TEST_CASE(name) -# define QPID_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END() - -#endif - -#endif /*!QPIPD_TEST_UNIT_TEST_H_*/ diff --git a/qpid/cpp/src/tests/linearstore/CMakeLists.txt b/qpid/cpp/src/tests/linearstore/CMakeLists.txt deleted file mode 100644 index 760c54f3b1..0000000000 --- a/qpid/cpp/src/tests/linearstore/CMakeLists.txt +++ /dev/null @@ -1,26 +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. -# - -if (BUILD_LINEARSTORE AND BUILD_TESTING) - -message(STATUS "Building linearstore tests") - -add_test(linearstore_python_tests ${PYTHON_EXECUTABLE} run_python_tests) - -endif (BUILD_LINEARSTORE AND BUILD_TESTING) diff --git a/qpid/cpp/src/tests/linearstore/linearstoredirsetup.sh b/qpid/cpp/src/tests/linearstore/linearstoredirsetup.sh deleted file mode 100755 index ef39767e9b..0000000000 --- a/qpid/cpp/src/tests/linearstore/linearstoredirsetup.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env 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. -# - -# This script sets up a test directory which contains both -# recoverable and non-recoverable files and directories for -# the empty file pool (EFP). - -# NOTE: The following is based on typical development tree paths, not installed paths - -BASE_DIR=${HOME}/RedHat -STORE_DIR=${BASE_DIR} -PYTHON_TOOLS_DIR=${BASE_DIR}/qpid/tools/src/linearstore -export PYTHONPATH=${BASE_DIR}/qpid/python:${BASE_DIR}/qpid/extras/qmf/src/py:${BASE_DIR}/qpid/tools/src/py - -# Remove old dirs (if present) -rm -rf ${STORE_DIR}/qls -rm -rf ${STORE_DIR}/p002 -rm ${STORE_DIR}/p004 - -# Create new dir tree and links -mkdir ${STORE_DIR}/p002_ext -touch ${STORE_DIR}/p004_ext -mkdir ${STORE_DIR}/qls -mkdir ${STORE_DIR}/qls/p001 -touch ${STORE_DIR}/qls/p003 -ln -s ${STORE_DIR}/p002_ext ${STORE_DIR}/qls/p002 -ln -s ${STORE_DIR}/p004_ext ${STORE_DIR}/qls/p004 - -# Populate efp dirs with empty files -${PYTHON_TOOLS_DIR}/efptool.py $STORE_DIR/qls/ -a -p 1 -s 2048 -n 25 -${PYTHON_TOOLS_DIR}/efptool.py $STORE_DIR/qls/ -a -p 1 -s 512 -n 25 -${PYTHON_TOOLS_DIR}/efptool.py $STORE_DIR/qls/ -a -p 2 -s 2048 -n 25 - -# Show the result for information -${LINEARSTOREDIR}/tools/src/py/linearstore/efptool.py $STORE_DIR/qls/ -l -tree -la $STORE_DIR/qls - diff --git a/qpid/cpp/src/tests/linearstore/python_tests/__init__.py b/qpid/cpp/src/tests/linearstore/python_tests/__init__.py deleted file mode 100644 index 1e59d403e4..0000000000 --- a/qpid/cpp/src/tests/linearstore/python_tests/__init__.py +++ /dev/null @@ -1,23 +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. -# - -# Do not delete - marks this directory as a python package. - -from client_persistence import * - diff --git a/qpid/cpp/src/tests/linearstore/python_tests/client_persistence.py b/qpid/cpp/src/tests/linearstore/python_tests/client_persistence.py deleted file mode 100644 index 9ff9480c4c..0000000000 --- a/qpid/cpp/src/tests/linearstore/python_tests/client_persistence.py +++ /dev/null @@ -1,239 +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. -# - -import os - -from brokertest import EXPECT_EXIT_OK -from store_test import StoreTest, Qmf, store_args -from qpid.messaging import * - -import qpid.messaging, brokertest -brokertest.qm = qpid.messaging # FIXME aconway 2014-04-04: Tests fail with SWIG client. - -class ExchangeQueueTests(StoreTest): - """ - Simple tests of the broker exchange and queue types - """ - - def test_direct_exchange(self): - """Test Direct exchange.""" - broker = self.broker(store_args(), name="test_direct_exchange", expect=EXPECT_EXIT_OK) - msg1 = Message("A_Message1", durable=True, correlation_id="Msg0001") - msg2 = Message("B_Message1", durable=True, correlation_id="Msg0002") - broker.send_message("a", msg1) - broker.send_message("b", msg2) - broker.terminate() - - broker = self.broker(store_args(), name="test_direct_exchange") - self.check_message(broker, "a", msg1, True) - self.check_message(broker, "b", msg2, True) - - def test_topic_exchange(self): - """Test Topic exchange.""" - broker = self.broker(store_args(), name="test_topic_exchange", expect=EXPECT_EXIT_OK) - ssn = broker.connect().session() - snd1 = ssn.sender("abc/key1; {create:always, node:{type:topic, durable:True}}") - snd2 = ssn.sender("abc/key2; {create:always, node:{type:topic, durable:True}}") - ssn.receiver("a; {create:always, link:{x-bindings:[{exchange:abc, key:key1}]}, node:{durable:True}}") - ssn.receiver("b; {create:always, link:{x-bindings:[{exchange:abc, key:key1}]}, node:{durable:True}}") - ssn.receiver("c; {create:always, link:{x-bindings:[{exchange:abc, key:key1}, " - "{exchange:abc, key: key2}]}, node:{durable:True}}") - ssn.receiver("d; {create:always, link:{x-bindings:[{exchange:abc, key:key2}]}, node:{durable:True}}") - ssn.receiver("e; {create:always, link:{x-bindings:[{exchange:abc, key:key2}]}, node:{durable:True}}") - msg1 = Message("Message1", durable=True, correlation_id="Msg0003") - snd1.send(msg1) - msg2 = Message("Message2", durable=True, correlation_id="Msg0004") - snd2.send(msg2) - broker.terminate() - - broker = self.broker(store_args(), name="test_topic_exchange") - self.check_message(broker, "a", msg1, True) - self.check_message(broker, "b", msg1, True) - self.check_messages(broker, "c", [msg1, msg2], True) - self.check_message(broker, "d", msg2, True) - self.check_message(broker, "e", msg2, True) - - - def test_legacy_lvq(self): - """Test legacy LVQ.""" - broker = self.broker(store_args(), name="test_lvq", expect=EXPECT_EXIT_OK) - ma1 = Message("A1", durable=True, correlation_id="Msg0005", properties={"qpid.LVQ_key":"A"}) - ma2 = Message("A2", durable=True, correlation_id="Msg0006", properties={"qpid.LVQ_key":"A"}) - mb1 = Message("B1", durable=True, correlation_id="Msg0007", properties={"qpid.LVQ_key":"B"}) - mb2 = Message("B2", durable=True, correlation_id="Msg0008", properties={"qpid.LVQ_key":"B"}) - mb3 = Message("B3", durable=True, correlation_id="Msg0009", properties={"qpid.LVQ_key":"B"}) - mc1 = Message("C1", durable=True, correlation_id="Msg0010", properties={"qpid.LVQ_key":"C"}) - broker.send_messages("lvq-test", [mb1, ma1, ma2, mb2, mb3, mc1], - xprops="arguments:{\"qpid.last_value_queue\":True}") - broker.terminate() - - broker = self.broker(store_args(), name="test_lvq", expect=EXPECT_EXIT_OK) - ssn = self.check_messages(broker, "lvq-test", [ma2, mb3, mc1], empty=True, ack=False) - # Add more messages while subscriber is active (no replacement): - ma3 = Message("A3", durable=True, correlation_id="Msg0011", properties={"qpid.LVQ_key":"A"}) - ma4 = Message("A4", durable=True, correlation_id="Msg0012", properties={"qpid.LVQ_key":"A"}) - mc2 = Message("C2", durable=True, correlation_id="Msg0013", properties={"qpid.LVQ_key":"C"}) - mc3 = Message("C3", durable=True, correlation_id="Msg0014", properties={"qpid.LVQ_key":"C"}) - mc4 = Message("C4", durable=True, correlation_id="Msg0015", properties={"qpid.LVQ_key":"C"}) - broker.send_messages("lvq-test", [mc2, mc3, ma3, ma4, mc4], session=ssn) - ssn.acknowledge() - broker.terminate() - - broker = self.broker(store_args(), name="test_lvq") - self.check_messages(broker, "lvq-test", [ma4, mc4], True) - - - def test_fanout_exchange(self): - """Test Fanout Exchange""" - broker = self.broker(store_args(), name="test_fanout_exchange", expect=EXPECT_EXIT_OK) - ssn = broker.connect().session() - snd = ssn.sender("TestFanoutExchange; {create: always, node: {type: topic, x-declare: {type: fanout}}}") - ssn.receiver("TestFanoutExchange; {link: {name: \"q1\", durable: True, reliability:at-least-once}}") - ssn.receiver("TestFanoutExchange; {link: {name: \"q2\", durable: True, reliability:at-least-once}}") - ssn.receiver("TestFanoutExchange; {link: {name: \"q3\", durable: True, reliability:at-least-once}}") - msg1 = Message("Msg1", durable=True, correlation_id="Msg0001") - snd.send(msg1) - msg2 = Message("Msg2", durable=True, correlation_id="Msg0002") - snd.send(msg2) - broker.terminate() - - broker = self.broker(store_args(), name="test_fanout_exchange") - self.check_messages(broker, "q1", [msg1, msg2], True) - self.check_messages(broker, "q2", [msg1, msg2], True) - self.check_messages(broker, "q3", [msg1, msg2], True) - - - def test_message_reject(self): - broker = self.broker(store_args(), name="test_message_reject", expect=EXPECT_EXIT_OK) - ssn = broker.connect().session() - snd = ssn.sender("tmr; {create:always, node:{type:queue, durable:True}}") - rcv = ssn.receiver("tmr; {create:always, node:{type:queue, durable:True}}") - m1 = Message("test_message_reject", durable=True, correlation_id="Msg0001") - snd.send(m1) - m2 = rcv.fetch() - ssn.acknowledge(message=m2, disposition=Disposition(REJECTED)) - broker.terminate() - - broker = self.broker(store_args(), name="test_message_reject") - qmf = Qmf(broker) - assert qmf.queue_message_count("tmr") == 0 - - - def test_route(self): - """ Test the recovery of a route (link and bridge objects.""" - broker = self.broker(store_args(), name="test_route", expect=EXPECT_EXIT_OK) - qmf = Qmf(broker) - qmf_broker_obj = qmf.get_objects("broker")[0] - - # create a "link" - link_args = {"host":"a.fake.host.com", "port":9999, "durable":True, - "authMechanism":"PLAIN", "username":"guest", "password":"guest", - "transport":"tcp"} - result = qmf_broker_obj.create("link", "test-link", link_args, False) - self.assertEqual(result.status, 0, result) - link = qmf.get_objects("link")[0] - - # create bridge - bridge_args = {"link":"test-link", "src":"amq.direct", "dest":"amq.fanout", - "key":"my-key", "durable":True} - result = qmf_broker_obj.create("bridge", "test-bridge", bridge_args, False); - self.assertEqual(result.status, 0, result) - bridge = qmf.get_objects("bridge")[0] - - broker.terminate() - - # recover the link and bridge - broker = self.broker(store_args(), name="test_route") - qmf = Qmf(broker) - qmf_broker_obj = qmf.get_objects("broker")[0] - self.assertEqual(len(qmf.get_objects("link")), 1) - self.assertEqual(len(qmf.get_objects("bridge")), 1) - - - -class AlternateExchangePropertyTests(StoreTest): - """ - Test the persistence of the Alternate Exchange property for exchanges and queues. - """ - - def test_exchange(self): - """Exchange alternate exchange property persistence test""" - broker = self.broker(store_args(), name="test_exchange", expect=EXPECT_EXIT_OK) - qmf = Qmf(broker) - qmf.add_exchange("altExch", "direct", durable=True) # Serves as alternate exchange instance - qmf.add_exchange("testExch", "direct", durable=True, alt_exchange_name="altExch") - qmf.close() - broker.terminate() - - broker = self.broker(store_args(), name="test_exchange") - qmf = Qmf(broker) - try: - qmf.add_exchange("altExch", "direct", passive=True) - except Exception, error: - self.fail("Alternate exchange (\"altExch\") instance not recovered: %s" % error) - try: - qmf.add_exchange("testExch", "direct", passive=True) - except Exception, error: - self.fail("Test exchange (\"testExch\") instance not recovered: %s" % error) - self.assertTrue(qmf.query_exchange("testExch", alt_exchange_name = "altExch"), - "Alternate exchange property not found or is incorrect on exchange \"testExch\".") - qmf.close() - - def test_queue(self): - """Queue alternate exchange property persistexchangeNamece test""" - broker = self.broker(store_args(), name="test_queue", expect=EXPECT_EXIT_OK) - qmf = Qmf(broker) - qmf.add_exchange("altExch", "direct", durable=True) # Serves as alternate exchange instance - qmf.add_queue("testQueue", durable=True, alt_exchange_name="altExch") - qmf.close() - broker.terminate() - - broker = self.broker(store_args(), name="test_queue") - qmf = Qmf(broker) - try: - qmf.add_exchange("altExch", "direct", passive=True) - except Exception, error: - self.fail("Alternate exchange (\"altExch\") instance not recovered: %s" % error) - try: - qmf.add_queue("testQueue", passive=True) - except Exception, error: - self.fail("Test queue (\"testQueue\") instance not recovered: %s" % error) - self.assertTrue(qmf.query_queue("testQueue", alt_exchange_name = "altExch"), - "Alternate exchange property not found or is incorrect on queue \"testQueue\".") - qmf.close() - - -class RedeliveredTests(StoreTest): - """ - Test the behavior of the redelivered flag in the context of persistence - """ - - def test_broker_recovery(self): - """Test that the redelivered flag is set on messages after recovery of broker""" - broker = self.broker(store_args(), name="test_broker_recovery", expect=EXPECT_EXIT_OK) - msg_content = "xyz"*100 - msg = Message(msg_content, durable=True) - broker.send_message("testQueue", msg) - broker.terminate() - - broker = self.broker(store_args(), name="test_broker_recovery") - rcv_msg = broker.get_message("testQueue") - self.assertEqual(msg_content, rcv_msg.content) - self.assertTrue(rcv_msg.redelivered) - diff --git a/qpid/cpp/src/tests/linearstore/python_tests/store_test.py b/qpid/cpp/src/tests/linearstore/python_tests/store_test.py deleted file mode 100644 index cc846aefd4..0000000000 --- a/qpid/cpp/src/tests/linearstore/python_tests/store_test.py +++ /dev/null @@ -1,417 +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. -# - -import re -from brokertest import BrokerTest -from qpid.messaging import Empty -from qmf.console import Session - -import qpid.messaging, brokertest -brokertest.qm = qpid.messaging # TODO aconway 2014-04-04: Tests fail with SWIG client. - - -def store_args(store_dir = None): - """Return the broker args necessary to load the async store""" - assert BrokerTest.store_lib - if store_dir == None: - return [] - return ["--store-dir", store_dir] - -class Qmf: - """ - QMF functions not yet available in the new QMF API. Remove this and replace with new API when it becomes available. - """ - def __init__(self, broker): - self.__session = Session() - self.__broker = self.__session.addBroker("amqp://localhost:%d"%broker.port()) - - def add_exchange(self, exchange_name, exchange_type, alt_exchange_name=None, passive=False, durable=False, - arguments = None): - """Add a new exchange""" - amqp_session = self.__broker.getAmqpSession() - if arguments == None: - arguments = {} - if alt_exchange_name: - amqp_session.exchange_declare(exchange=exchange_name, type=exchange_type, - alternate_exchange=alt_exchange_name, passive=passive, durable=durable, - arguments=arguments) - else: - amqp_session.exchange_declare(exchange=exchange_name, type=exchange_type, passive=passive, durable=durable, - arguments=arguments) - - def add_queue(self, queue_name, alt_exchange_name=None, passive=False, durable=False, arguments = None): - """Add a new queue""" - amqp_session = self.__broker.getAmqpSession() - if arguments == None: - arguments = {} - if alt_exchange_name: - amqp_session.queue_declare(queue_name, alternate_exchange=alt_exchange_name, passive=passive, - durable=durable, arguments=arguments) - else: - amqp_session.queue_declare(queue_name, passive=passive, durable=durable, arguments=arguments) - - def delete_queue(self, queue_name): - """Delete an existing queue""" - amqp_session = self.__broker.getAmqpSession() - amqp_session.queue_delete(queue_name) - - def _query(self, name, _class, package, alt_exchange_name=None): - """Qmf query function which can optionally look for the presence of an alternate exchange name""" - try: - obj_list = self.__session.getObjects(_class=_class, _package=package) - found = False - for obj in obj_list: - if obj.name == name: - found = True - if alt_exchange_name != None: - alt_exch_list = self.__session.getObjects(_objectId=obj.altExchange) - if len(alt_exch_list) == 0 or alt_exch_list[0].name != alt_exchange_name: - return False - break - return found - except Exception: - return False - - - def query_exchange(self, exchange_name, alt_exchange_name=None): - """Test for the presence of an exchange, and optionally whether it has an alternate exchange set to a known - value.""" - return self._query(exchange_name, "exchange", "org.apache.qpid.broker", alt_exchange_name) - - def query_queue(self, queue_name, alt_exchange_name=None): - """Test for the presence of an exchange, and optionally whether it has an alternate exchange set to a known - value.""" - return self._query(queue_name, "queue", "org.apache.qpid.broker", alt_exchange_name) - - def queue_message_count(self, queue_name): - """Query the number of messages on a queue""" - queue_list = self.__session.getObjects(_class="queue", _name=queue_name) - if len(queue_list): - return queue_list[0].msgDepth - - def queue_empty(self, queue_name): - """Check if a queue is empty (has no messages waiting)""" - return self.queue_message_count(queue_name) == 0 - - def get_objects(self, target_class, target_package="org.apache.qpid.broker"): - return self.__session.getObjects(_class=target_class, _package=target_package) - - - def close(self): - self.__session.delBroker(self.__broker) - self.__session = None - - -class StoreTest(BrokerTest): - """ - This subclass of BrokerTest adds some convenience test/check functions - """ - - def _chk_empty(self, queue, receiver): - """Check if a queue is empty (has no more messages)""" - try: - msg = receiver.fetch(timeout=0) - self.assert_(False, "Queue \"%s\" not empty: found message: %s" % (queue, msg)) - except Empty: - pass - - @staticmethod - def make_message(msg_count, msg_size): - """Make message content. Format: 'abcdef....' followed by 'msg-NNNN', where NNNN is the message count""" - msg = "msg-%04d" % msg_count - msg_len = len(msg) - buff = "" - if msg_size != None and msg_size > msg_len: - for index in range(0, msg_size - msg_len): - if index == msg_size - msg_len - 1: - buff += "-" - else: - buff += chr(ord('a') + (index % 26)) - return buff + msg - - # Functions for formatting address strings - - @staticmethod - def _fmt_csv(string_list, list_braces = None): - """Format a list using comma-separation. Braces are optionally added.""" - if len(string_list) == 0: - return "" - first = True - str_ = "" - if list_braces != None: - str_ += list_braces[0] - for string in string_list: - if string != None: - if first: - first = False - else: - str_ += ", " - str_ += string - if list_braces != None: - str_ += list_braces[1] - return str_ - - def _fmt_map(self, string_list): - """Format a map {l1, l2, l3, ...} from a string list. Each item in the list must be a formatted map - element('key:val').""" - return self._fmt_csv(string_list, list_braces="{}") - - def _fmt_list(self, string_list): - """Format a list [l1, l2, l3, ...] from a string list.""" - return self._fmt_csv(string_list, list_braces="[]") - - def addr_fmt(self, node_name, **kwargs): - """Generic AMQP to new address formatter. Takes common (but not all) AMQP options and formats an address - string.""" - # Get keyword args - node_subject = kwargs.get("node_subject") - create_policy = kwargs.get("create_policy") - delete_policy = kwargs.get("delete_policy") - assert_policy = kwargs.get("assert_policy") - mode = kwargs.get("mode") - link = kwargs.get("link", False) - link_name = kwargs.get("link_name") - node_type = kwargs.get("node_type") - durable = kwargs.get("durable", False) - link_reliability = kwargs.get("link_reliability") - x_declare_list = kwargs.get("x_declare_list", []) - x_bindings_list = kwargs.get("x_bindings_list", []) - x_subscribe_list = kwargs.get("x_subscribe_list", []) - - node_flag = not link and (node_type != None or durable or len(x_declare_list) > 0 or len(x_bindings_list) > 0) - link_flag = link and (link_name != None or durable or link_reliability != None or len(x_declare_list) > 0 or - len(x_bindings_list) > 0 or len(x_subscribe_list) > 0) - assert not (node_flag and link_flag) - - opt_str_list = [] - if create_policy != None: - opt_str_list.append("create: %s" % create_policy) - if delete_policy != None: - opt_str_list.append("delete: %s" % delete_policy) - if assert_policy != None: - opt_str_list.append("assert: %s" % assert_policy) - if mode != None: - opt_str_list.append("mode: %s" % mode) - if node_flag or link_flag: - node_str_list = [] - if link_name != None: - node_str_list.append("name: \"%s\"" % link_name) - if node_type != None: - node_str_list.append("type: %s" % node_type) - if durable: - node_str_list.append("durable: True") - if link_reliability != None: - node_str_list.append("reliability: %s" % link_reliability) - if len(x_declare_list) > 0: - node_str_list.append("x-declare: %s" % self._fmt_map(x_declare_list)) - if len(x_bindings_list) > 0: - node_str_list.append("x-bindings: %s" % self._fmt_list(x_bindings_list)) - if len(x_subscribe_list) > 0: - node_str_list.append("x-subscribe: %s" % self._fmt_map(x_subscribe_list)) - if node_flag: - opt_str_list.append("node: %s" % self._fmt_map(node_str_list)) - else: - opt_str_list.append("link: %s" % self._fmt_map(node_str_list)) - addr_str = node_name - if node_subject != None: - addr_str += "/%s" % node_subject - if len(opt_str_list) > 0: - addr_str += "; %s" % self._fmt_map(opt_str_list) - return addr_str - - def snd_addr(self, node_name, **kwargs): - """ Create a send (node) address""" - # Get keyword args - topic = kwargs.get("topic") - topic_flag = kwargs.get("topic_flag", False) - auto_create = kwargs.get("auto_create", True) - auto_delete = kwargs.get("auto_delete", False) - durable = kwargs.get("durable", False) - exclusive = kwargs.get("exclusive", False) - ftd_count = kwargs.get("ftd_count") - ftd_size = kwargs.get("ftd_size") - policy = kwargs.get("policy", "flow-to-disk") - exchage_type = kwargs.get("exchage_type") - - create_policy = None - if auto_create: - create_policy = "always" - delete_policy = None - if auto_delete: - delete_policy = "always" - node_type = None - if topic != None or topic_flag: - node_type = "topic" - x_declare_list = ["\"exclusive\": %s" % exclusive] - if ftd_count != None or ftd_size != None: - queue_policy = ["\'qpid.policy_type\': %s" % policy] - if ftd_count: - queue_policy.append("\'qpid.max_count\': %d" % ftd_count) - if ftd_size: - queue_policy.append("\'qpid.max_size\': %d" % ftd_size) - x_declare_list.append("arguments: %s" % self._fmt_map(queue_policy)) - if exchage_type != None: - x_declare_list.append("type: %s" % exchage_type) - - return self.addr_fmt(node_name, topic=topic, create_policy=create_policy, delete_policy=delete_policy, - node_type=node_type, durable=durable, x_declare_list=x_declare_list) - - def rcv_addr(self, node_name, **kwargs): - """ Create a receive (link) address""" - # Get keyword args - auto_create = kwargs.get("auto_create", True) - auto_delete = kwargs.get("auto_delete", False) - link_name = kwargs.get("link_name") - durable = kwargs.get("durable", False) - browse = kwargs.get("browse", False) - exclusive = kwargs.get("exclusive", False) - binding_list = kwargs.get("binding_list", []) - ftd_count = kwargs.get("ftd_count") - ftd_size = kwargs.get("ftd_size") - policy = kwargs.get("policy", "flow-to-disk") - - create_policy = None - if auto_create: - create_policy = "always" - delete_policy = None - if auto_delete: - delete_policy = "always" - mode = None - if browse: - mode = "browse" - x_declare_list = ["\"exclusive\": %s" % exclusive] - if ftd_count != None or ftd_size != None: - queue_policy = ["\'qpid.policy_type\': %s" % policy] - if ftd_count: - queue_policy.append("\'qpid.max_count\': %d" % ftd_count) - if ftd_size: - queue_policy.append("\'qpid.max_size\': %d" % ftd_size) - x_declare_list.append("arguments: %s" % self._fmt_map(queue_policy)) - x_bindings_list = [] - for binding in binding_list: - x_bindings_list.append("{exchange: %s, key: %s}" % binding) - if durable: reliability = 'at-least-once' - else: reliability = None - return self.addr_fmt(node_name, create_policy=create_policy, delete_policy=delete_policy, mode=mode, link=True, - link_name=link_name, durable=durable, x_declare_list=x_declare_list, - x_bindings_list=x_bindings_list, link_reliability=reliability) - - def check_message(self, broker, queue, exp_msg, transactional=False, empty=False, ack=True, browse=False): - """Check that a message is on a queue by dequeuing it and comparing it to the expected message""" - return self.check_messages(broker, queue, [exp_msg], transactional, empty, ack, browse) - - def check_messages(self, broker, queue, exp_msg_list, transactional=False, empty=False, ack=True, browse=False, - emtpy_flag=False): - """Check that messages is on a queue by dequeuing them and comparing them to the expected messages""" - if emtpy_flag: - num_msgs = 0 - else: - num_msgs = len(exp_msg_list) - ssn = broker.connect().session(transactional=transactional) - rcvr = ssn.receiver(self.rcv_addr(queue, browse=browse), capacity=num_msgs) - if num_msgs > 0: - try: - recieved_msg_list = [rcvr.fetch(timeout=0) for i in range(num_msgs)] - except Empty: - self.assert_(False, "Queue \"%s\" is empty, unable to retrieve expected message %d." % (queue, i)) - for i in range(0, len(recieved_msg_list)): - self.assertEqual(recieved_msg_list[i].content, exp_msg_list[i].content) - self.assertEqual(recieved_msg_list[i].correlation_id, exp_msg_list[i].correlation_id) - if empty: - self._chk_empty(queue, rcvr) - if ack: - ssn.acknowledge() - if transactional: - ssn.commit() - ssn.connection.close() - else: - if transactional: - ssn.commit() - return ssn - - - # Functions for finding strings in the broker log file (or other files) - - @staticmethod - def _read_file(file_name): - """Returns the content of file named file_name as a string""" - file_handle = file(file_name) - try: - return file_handle.read() - finally: - file_handle.close() - - def _get_hits(self, broker, search): - """Find all occurrences of the search in the broker log (eliminating possible duplicates from msgs on multiple - queues)""" - # TODO: Use sets when RHEL-4 is no longer supported - hits = [] - for hit in search.findall(self._read_file(broker.log)): - if hit not in hits: - hits.append(hit) - return hits - - def _reconsile_hits(self, broker, ftd_msgs, release_hits): - """Remove entries from list release_hits if they match the message id in ftd_msgs. Check for remaining - release_hits.""" - for msg in ftd_msgs: - found = False - for hit in release_hits: - if str(msg.id) in hit: - release_hits.remove(hit) - #print "Found %s in %s" % (msg.id, broker.log) - found = True - break - if not found: - self.assert_(False, "Unable to locate released message %s in log %s" % (msg.id, broker.log)) - if len(release_hits) > 0: - err = "Messages were unexpectedly released in log %s:\n" % broker.log - for hit in release_hits: - err += " %s\n" % hit - self.assert_(False, err) - - def check_msg_release(self, broker, ftd_msgs): - """ Check for 'Content released' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content released$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) - - def check_msg_release_on_commit(self, broker, ftd_msgs): - """ Check for 'Content released on commit' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content released on commit$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) - - def check_msg_release_on_recover(self, broker, ftd_msgs): - """ Check for 'Content released after recovery' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content released after recovery$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) - - def check_msg_block(self, broker, ftd_msgs): - """Check for 'Content release blocked' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content release blocked$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) - - def check_msg_block_on_commit(self, broker, ftd_msgs): - """Check for 'Content release blocked' messages in broker log for messages in ftd_msgs""" - hits = self._get_hits(broker, re.compile("debug Message id=\"[0-9a-f-]{36}\"; pid=0x[0-9a-f]+: " - "Content release blocked on commit$", re.MULTILINE)) - self._reconsile_hits(broker, ftd_msgs, hits) diff --git a/qpid/cpp/src/tests/linearstore/run_long_python_tests b/qpid/cpp/src/tests/linearstore/run_long_python_tests deleted file mode 100644 index be6380302c..0000000000 --- a/qpid/cpp/src/tests/linearstore/run_long_python_tests +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env 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_python_tests LONG_TEST diff --git a/qpid/cpp/src/tests/linearstore/run_python_tests b/qpid/cpp/src/tests/linearstore/run_python_tests deleted file mode 100755 index 4d8baec121..0000000000 --- a/qpid/cpp/src/tests/linearstore/run_python_tests +++ /dev/null @@ -1,47 +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. -# - -import os -import sys - -# Put the python test library on the path so we can get our -# environment - -file_path = os.path.abspath(__file__) -store_tests_dir = os.path.split(file_path)[0] -tests_dir = os.path.split(store_tests_dir)[0] - -sys.path.insert(0, tests_dir) - -from common import * - -# Add our directory to the python path - -ENV["PYTHONPATH"] = "{0}:{1}".format(store_tests_dir, ENV["PYTHONPATH"]) - -# To debug a test, add the following options to the end of the following line: -# -v DEBUG -c qpid.messaging.io.ops [*.testName] - -port = start_broker("broker", "--load-module {0}".format(STORE_LIB)) - -run_broker_tests(port, "-m python_tests", "-DOUTDIR={0}".format(WORK_DIR)) - -check_results() diff --git a/qpid/cpp/src/tests/linearstore/run_short_python_tests b/qpid/cpp/src/tests/linearstore/run_short_python_tests deleted file mode 100644 index 9b9e7c59be..0000000000 --- a/qpid/cpp/src/tests/linearstore/run_short_python_tests +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env 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_python_tests SHORT_TEST diff --git a/qpid/cpp/src/tests/linearstore/tx-test-soak.sh b/qpid/cpp/src/tests/linearstore/tx-test-soak.sh deleted file mode 100755 index 7d5581961f..0000000000 --- a/qpid/cpp/src/tests/linearstore/tx-test-soak.sh +++ /dev/null @@ -1,275 +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. -# - -# tx-test-soak -# -# Basic test methodology: -# 1. Start broker -# 2. Run qpid-txtest against broker using randomly generated parameters -# 3. After some time, kill the broker using SIGKILL -# 4. Restart broker, recover messages -# 5. Run qpid-txtest against broker in check mode, which checks that all expected messages are present. -# 6. Wash, rinse, repeat... The number of runs is determined by ${NUM_RUNS} - -# NOTE: The following is based on typical development tree paths, not installed paths - -NUM_RUNS=1000 -BASE_DIR=${HOME}/RedHat -CMAKE_BUILD_DIR=${BASE_DIR}/q.cm - -# Infrequently adjusted -RESULT_BASE_DIR_PREFIX=${BASE_DIR}/results.tx-test-soak -RECOVER_TIME_PER_QUEUE=1 -STORE_MODULE="linearstore.so" -BROKER_LOG_LEVEL="info+" -BROKER_MANAGEMENT="no" # "no" or "yes" -TRUNCATE_INTERVAL=10 -MAX_DISK_PERC_USED=90 - -# Constants (don't adjust these) -export BASE_DIR -RELATIVE_BASE_DIR=`python -c "import os,os.path; print os.path.relpath(os.environ['BASE_DIR'], os.environ['PWD'])"` -export PYTHONPATH=${BASE_DIR}/qpid/python:${BASE_DIR}/qpid/extras/qmf/src/py:${BASE_DIR}/qpid/tools/src/py -LOG_FILE_NAME=log.txt -QPIDD_FN=qpidd -QPIDD=${CMAKE_BUILD_DIR}/src/${QPIDD_FN} -TXTEST_FN=qpid-txtest -TXTEST=${CMAKE_BUILD_DIR}/src/tests/${TXTEST_FN} -ANALYZE_FN=qpid_qls_analyze.py -ANALYZE=${BASE_DIR}/qpid/tools/src/py/${ANALYZE_FN} -ANALYZE_ARGS="--efp --show-recs --stats" -QPIDD_BASE_ARGS="--load-module ${STORE_MODULE} -m ${BROKER_MANAGEMENT} --auth no --default-flow-stop-threshold 0 --default-flow-resume-threshold 0 --default-queue-limit 0 --store-dir ${BASE_DIR} --log-enable ${BROKER_LOG_LEVEL} --log-to-stderr no --log-to-stdout no" -TXTEST_INIT_STR="--init yes --transfer no --check no" -TXTEST_RUN_STR="--init no --transfer yes --check no" -TXTEST_CHK_STR="--init no --transfer no --check yes" -SUCCESS_MSG="All expected messages were retrieved." -TIMESTAMP_FORMAT="+%Y-%m-%d_%H:%M:%S" -ANSI_RED="\e[1;31m" -ANSI_NONE="\e[0m" -DEFAULT_EFP_DIR=2048k -DEFAULT_EFP_SIZE=2101248 -SIG_KILL=-9 -SIG_TERM=-15 - -# Creates a random number into the variable named in string $1 in the range [$2..$3] (both inclusive). -# $1: variable name as string to which random value is assigned -# $2: minimum inclusive range of random number -# $3: maximum inclusive range of random number -get_random() { - eval $1=`python -S -c "import random; print random.randint($2,$3)"` -} - -# Uses anon-uniform distribution to set a random message size. -# Most messages must be small (0 - 1k), but we need a few medium (10k) and large (100k) ones also. -# Sets message size into var ${MSG_SIZE} -set_message_size() { - local key=0 - get_random "key" 1 10 - if (( "${key}" == "10" )); then # 1 out of 10 - very large - get_random "MSG_SIZE" 100000 1000000 - FILE_SIZE_MULTIPLIER=3 - elif (( "${key}" >= "8" )); then # 2 out of 10 - large - get_random "MSG_SIZE" 10000 100000 - FILE_SIZE_MULTIPLIER=2 - elif (( "${key}" >= "6" )); then # 2 out of 10 - medium - get_random "MSG_SIZE" 1000 10000 - FILE_SIZE_MULTIPLIER=1 - else # 5 out of 10 - small - get_random "MSG_SIZE" 10 1000 - FILE_SIZE_MULTIPLIER=1 - fi -} - -# Start or restart broker -# $1: Log suffix: either "A" or "B". If "A", broker is started with truncation, otherwise broker is restarted with recovery. -# $2: Truncate flag - only used if Log suffix is "A": if true, then truncate store -# The PID of the broker is returned in ${QPIDD_PID} -start_broker() { - local truncate_val - local truncate_str - if [[ "$1" == "A" ]]; then - if [[ $2 == true ]]; then - truncate_val="yes" - truncate_str="(Store truncated)" - if [[ -e ${BASE_DIR}/qls/p001/efp/${DEFAULT_EFP_DIR} ]]; then - for f in ${BASE_DIR}/qls/p001/efp/${DEFAULT_EFP_DIR}/*; do - local filesize=`stat -c%s "${f}"` - if (( ${filesize} != ${DEFAULT_EFP_SIZE} )); then - rm ${f} - fi - done - fi - else - truncate_val="no" - fi - else - truncate_val="no" - fi - echo "${QPIDD} ${QPIDD_BASE_ARGS} --truncate ${truncate_val} --log-to-file ${RESULT_DIR}/qpidd.$1.log &" > ${RESULT_DIR}/qpidd.$1.cmd - ${QPIDD} ${QPIDD_BASE_ARGS} --truncate ${truncate_val} --log-to-file ${RESULT_DIR}/qpidd.$1.log & - QPIDD_PID=$! - echo "Broker PID=${QPIDD_PID} ${truncate_str}" | tee -a ${LOG_FILE} -} - -# Start or evaluate results of transaction test client -# $1: Log suffix flag: either "A" or "B". If "A", client is started in test mode, otherwise client evaluates recovery. -start_tx_test() { - local tx_test_params="--messages-per-tx ${MSGS_PER_TX} --tx-count 1000000 --total-messages ${TOT_MSGS} --size ${MSG_SIZE} --queues ${NUM_QUEUES}" - if [[ "$1" == "A" ]]; then - # Run in background - echo "${TXTEST##*/} parameters: ${tx_test_params}" | tee -a ${LOG_FILE} - echo "${TXTEST} ${tx_test_params} ${TXTEST_INIT_STR} &> ${RESULT_DIR}/txtest.$1.log" > ${RESULT_DIR}/txtest.$1.cmd - ${TXTEST} ${tx_test_params} ${TXTEST_INIT_STR} &> ${RESULT_DIR}/txtest.$1.log - echo "${TXTEST} ${tx_test_params} ${TXTEST_RUN_STR} &> ${RESULT_DIR}/txtest.$1.log &" >> ${RESULT_DIR}/txtest.$1.cmd - ${TXTEST} ${tx_test_params} ${TXTEST_RUN_STR} &> ${RESULT_DIR}/txtest.$1.log & - else - # Run in foreground - #echo "${TXTEST##*/} ${tx_test_params} ${TXTEST_CHK_STR}" | tee -a ${LOG_FILE} - echo "${TXTEST} ${tx_test_params} ${TXTEST_CHK_STR} &> ${RESULT_DIR}/txtest.$1.log" > ${RESULT_DIR}/txtest.$1.cmd - ${TXTEST} ${tx_test_params} ${TXTEST_CHK_STR} &> ${RESULT_DIR}/txtest.$1.log - fi -} - -# Search for the presence of core.* files, move them into the current result directory and run gdb against them. -# No params -process_core_files() { - ls core.* &> /dev/null - if (( "$?" == "0" )); then - for cf in core.*; do - gdb --batch --quiet -ex "thread apply all bt" -ex "quit" ${QPIDD} ${cf} &> ${RESULT_DIR}/${cf##*/}.gdb.txt - gdb --batch --quiet -ex "thread apply all bt full" -ex "quit" ${QPIDD} ${cf} &> ${RESULT_DIR}/${cf##*/}.gdb-full.txt - cat ${RESULT_DIR}/${cf##*/}.gdb.txt - mv ${cf} ${RESULT_DIR}/ - echo "Core file ${cf##*/} found and recovered" - done - fi -} - -# Kill a process quietly -# $1: Signal -# $2: PID -kill_process() { - kill ${1} ${2} &>> ${LOG_FILE} - wait ${2} &>> ${LOG_FILE} -} - -# Check that test can run: No other copy of qpidd running, enough disk space -check_ready_to_run() { - # Check no copy of qpidd is running - PID=`pgrep ${QPIDD_FN}` - if [[ "$?" == "0" ]]; then - echo "ERROR: qpidd running as pid ${PID}" - exit 1 - fi - # Check disk is < 90% full - local perc_full=`df -h ${HOME} | tail -1 | awk '{print substr($5,0, length($5)-1)}'` - if (( ${perc_full} >= ${MAX_DISK_PERC_USED} )); then - echo "ERROR: Disk is too close to full (${perc_full}%)" - exit 2 - fi -} - -# Analyze store files -# $1: Log suffix flag: either "A" or "B". If "A", client is started in test mode, otherwise client evaluates recovery. -analyze_store() { - ${ANALYZE} ${ANALYZE_ARGS} ${BASE_DIR}/qls &> ${RESULT_DIR}/qls_analysis.$1.log - echo >> ${RESULT_DIR}/qls_analysis.$1.log - echo "----------------------------------------------------------" >> ${RESULT_DIR}/qls_analysis.$1.log - echo "With transactional reconsiliation:" >> ${RESULT_DIR}/qls_analysis.$1.log - echo >> ${RESULT_DIR}/qls_analysis.$1.log - ${ANALYZE} ${ANALYZE_ARGS} --txn ${BASE_DIR}/qls &>> ${RESULT_DIR}/qls_analysis.$1.log -} - -ulimit -c unlimited # Allow core files to be created - -RESULT_BASE_DIR_SUFFIX=`date "${TIMESTAMP_FORMAT}"` -RESULT_BASE_DIR="${RESULT_BASE_DIR_PREFIX}.${RESULT_BASE_DIR_SUFFIX}" -LOG_FILE=${RESULT_BASE_DIR}/${LOG_FILE_NAME} -if [[ -n "${RESULT_BASE_DIR}" ]]; then - rm -rf ${RESULT_BASE_DIR} -fi - -mkdir -p ${RESULT_BASE_DIR} -for rn in `seq ${NUM_RUNS}`; do - # === Prepare result dir, check ready to run test, set run vars === - RESULT_DIR=${RESULT_BASE_DIR}/run_${rn} - mkdir -p ${RESULT_DIR} - check_ready_to_run - if (( (${rn} - 1) % ${TRUNCATE_INTERVAL} == 0 )) || [[ -n ${ERROR_FLAG} ]]; then - TRUNCATE_FLAG=true - else - TRUNCATE_FLAG=false - fi - set_message_size - get_random "MSGS_PER_TX" 1 20 - get_random "TOT_MSGS" 100 1000 - get_random "NUM_QUEUES" 2 15 - MIN_RUNTIME=$(( 20 * ${FILE_SIZE_MULTIPLIER} )) - MAX_RUNTIME=$(( 120 * ${FILE_SIZE_MULTIPLIER} )) - get_random "RUN_TIME" ${MIN_RUNTIME} ${MAX_RUNTIME} - RECOVER_TIME=$(( ${NUM_QUEUES} * ${RECOVER_TIME_PER_QUEUE} * ${FILE_SIZE_MULTIPLIER} )) - echo "Run ${rn} of ${NUM_RUNS} ==============" | tee -a ${LOG_FILE} - - # === PART A: Initial run of qpid-txtest === - start_broker "A" ${TRUNCATE_FLAG} - sleep ${RECOVER_TIME} # Need a way to test if broker has started here - start_tx_test "A" - echo "Running for ${RUN_TIME} secs..." | tee -a ${LOG_FILE} - sleep ${RUN_TIME} - kill_process ${SIG_KILL} ${QPIDD_PID} - sleep 2 - analyze_store "A" - tar -czf ${RESULT_DIR}/qls_A.tar.gz ${RELATIVE_BASE_DIR}/qls - - # === PART B: Recovery and check === - start_broker "B" - echo "Recover time=${RECOVER_TIME} secs..." | tee -a ${LOG_FILE} - sleep ${RECOVER_TIME} # Need a way to test if broker has started here - start_tx_test "B" - sleep 1 - kill_process ${SIG_TERM} ${QPIDD_PID} - sleep 2 - PID=`pgrep ${QPIDD_FN}` - if [[ "$?" == "0" ]]; then - kill_process ${SIG_KILL} ${PID} - sleep 2 - fi - analyze_store "B" - tar -czf ${RESULT_DIR}/qls_B.tar.gz ${RELATIVE_BASE_DIR}/qls - - # === Check for errors, cores and exceptions in logs === - grep -Hn "jexception" ${RESULT_DIR}/qpidd.A.log | tee -a ${LOG_FILE} - grep -Hn "jexception" ${RESULT_DIR}/qpidd.B.log | tee -a ${LOG_FILE} - grep -Hn "Traceback (most recent call last):" ${RESULT_DIR}/qls_analysis.A.log | tee -a ${LOG_FILE} - grep -Hn "Traceback (most recent call last):" ${RESULT_DIR}/qls_analysis.B.log | tee -a ${LOG_FILE} - grep "${SUCCESS_MSG}" ${RESULT_DIR}/txtest.B.log &> /dev/null - if [[ "$?" != "0" ]]; then - echo "ERROR in run ${rn}" >> ${LOG_FILE} - echo -e "${ANSI_RED}ERROR${ANSI_NONE} in run ${rn}" - ERROR_FLAG=true - else - unset ERROR_FLAG - fi - sleep 2 - process_core_files - echo | tee -a ${LOG_FILE} -done - diff --git a/qpid/cpp/src/tests/logging.cpp b/qpid/cpp/src/tests/logging.cpp deleted file mode 100644 index 32cd09d73d..0000000000 --- a/qpid/cpp/src/tests/logging.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * - * 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 "test_tools.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/OstreamOutput.h" -#include "qpid/memory.h" -#include "qpid/Options.h" -#if defined (_WIN32) -# include "qpid/log/windows/SinkOptions.h" -#else -# include "qpid/log/posix/SinkOptions.h" -#endif - -#include -#include -#include -#include "unit_test.h" - -#include -#include -#include - - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(loggingTestSuite) - -using namespace std; -using namespace qpid::log; -using boost::ends_with; -using boost::contains; -using boost::format; - -QPID_AUTO_TEST_CASE(testStatementInit) { - Statement s=QPID_LOG_STATEMENT_INIT(debug); int line=__LINE__; - BOOST_CHECK(!s.enabled); - BOOST_CHECK_EQUAL(string(__FILE__), s.file); - BOOST_CHECK_EQUAL(line, s.line); - BOOST_CHECK_EQUAL(debug, s.level); -} - - -QPID_AUTO_TEST_CASE(testSelector_enable) { - Selector s; - // Simple enable - s.enable(debug,"foo"); - BOOST_CHECK(s.isEnabled(debug,"foo")); - BOOST_CHECK(!s.isEnabled(error,"foo")); - BOOST_CHECK(!s.isEnabled(error,"bar")); - - // Substring match - BOOST_CHECK(s.isEnabled(debug, "bazfoobar")); - BOOST_CHECK(!s.isEnabled(debug, "bazbar")); - - // Different levels for different substrings. - s.enable(info, "bar"); - BOOST_CHECK(s.isEnabled(debug, "foobar")); - BOOST_CHECK(s.isEnabled(info, "foobar")); - BOOST_CHECK(!s.isEnabled(debug, "bar")); - BOOST_CHECK(!s.isEnabled(info, "foo")); - - // Enable-strings - s.enable("notice:blob"); - BOOST_CHECK(s.isEnabled(notice, "blob")); - s.enable("error+:oops"); - BOOST_CHECK(s.isEnabled(error, "oops")); - BOOST_CHECK(s.isEnabled(critical, "oops")); -} - -QPID_AUTO_TEST_CASE(testSelector_disable) { - Selector s; - // Simple enable/disable - s.enable(trace,"foo"); - BOOST_CHECK(s.isEnabled(trace,"foo")); - BOOST_CHECK(!s.isDisabled(trace,"foo")); - s.disable(trace,"foo"); - BOOST_CHECK(s.isEnabled(trace,"foo")); - BOOST_CHECK(s.isDisabled(trace,"foo")); -} - -QPID_AUTO_TEST_CASE(testStatementEnabled) { - // Verify that the singleton enables and disables static - // log statements. - Logger& l = Logger::instance(); - ScopedSuppressLogging ls(l); - l.select(Selector(debug)); - static Statement s=QPID_LOG_STATEMENT_INIT(debug); - BOOST_CHECK(!s.enabled); - static Statement::Initializer init(s); - BOOST_CHECK(s.enabled); - - static Statement s2=QPID_LOG_STATEMENT_INIT(warning); - static Statement::Initializer init2(s2); - BOOST_CHECK(!s2.enabled); - - l.select(Selector(warning)); - BOOST_CHECK(!s.enabled); - BOOST_CHECK(s2.enabled); -} - -struct TestOutput : public Logger::Output { - vector msg; - vector stmt; - - TestOutput(Logger& l) { - l.output(std::auto_ptr(this)); - } - - void log(const Statement& s, const string& m) { - msg.push_back(m); - stmt.push_back(s); - } - string last() { return msg.back(); } -}; - -using boost::assign::list_of; - -QPID_AUTO_TEST_CASE(testLoggerOutput) { - Logger l; - l.clear(); - l.select(Selector(debug)); - Statement s=QPID_LOG_STATEMENT_INIT(debug); - - TestOutput* out=new TestOutput(l); - - // Verify message is output. - l.log(s, "foo"); - vector expect=list_of("foo\n"); - BOOST_CHECK_EQUAL(expect, out->msg); - - // Verify multiple outputs - TestOutput* out2=new TestOutput(l); - l.log(Statement(), "baz"); - expect.push_back("baz\n"); - BOOST_CHECK_EQUAL(expect, out->msg); - expect.erase(expect.begin()); - BOOST_CHECK_EQUAL(expect, out2->msg); -} - -QPID_AUTO_TEST_CASE(testMacro) { - Logger& l=Logger::instance(); - ScopedSuppressLogging ls(l); - l.select(Selector(info)); - TestOutput* out=new TestOutput(l); - QPID_LOG(info, "foo"); - vector expect=list_of("foo\n"); - BOOST_CHECK_EQUAL(expect, out->msg); - BOOST_CHECK_EQUAL(__FILE__, out->stmt.front().file); - - // Not enabled: - QPID_LOG(debug, "bar"); - BOOST_CHECK_EQUAL(expect, out->msg); - - QPID_LOG(info, 42 << " bingo"); - expect.push_back("42 bingo\n"); - BOOST_CHECK_EQUAL(expect, out->msg); -} - -QPID_AUTO_TEST_CASE(testLoggerFormat) { - Logger& l = Logger::instance(); - ScopedSuppressLogging ls(l); - l.select(Selector(critical)); - TestOutput* out=new TestOutput(l); - - l.format(Logger::FILE); - QPID_LOG(critical, "foo"); - BOOST_CHECK_EQUAL(out->last(), string(__FILE__)+": foo\n"); - - l.format(Logger::FILE|Logger::LINE); - QPID_LOG(critical, "foo"); - BOOST_CHECK_EQUAL(out->last().find(__FILE__), 0u); - - l.format(Logger::FUNCTION); - QPID_LOG(critical, "foo"); - BOOST_CHECK( ends_with( out->last(), ": foo\n")); - string name = out->last().substr(0, out->last().length() - 6); - BOOST_CHECK( contains( string(BOOST_CURRENT_FUNCTION), name)); - - l.format(Logger::LEVEL); - QPID_LOG(critical, "foo"); - BOOST_CHECK_EQUAL("critical foo\n", out->last()); -} - -QPID_AUTO_TEST_CASE(testOstreamOutput) { - Logger& l=Logger::instance(); - ScopedSuppressLogging ls(l); - l.select(Selector(error)); - ostringstream os; - l.output(qpid::make_auto_ptr(new OstreamOutput(os))); - QPID_LOG(error, "foo"); - QPID_LOG(error, "bar"); - QPID_LOG(error, "baz"); - BOOST_CHECK_EQUAL("foo\nbar\nbaz\n", os.str()); -} - -#if 0 // This test requires manual intervention. Normally disabled. -QPID_AUTO_TEST_CASE(testSyslogOutput) { - Logger& l=Logger::instance(); - Logger::StateSaver ls(l); - l.clear(); - l.select(Selector(info)); - l.syslog("qpid_test"); - QPID_LOG(info, "Testing QPID"); - BOOST_ERROR("Manually verify that /var/log/messages contains a recent line 'Testing QPID'"); -} -#endif // 0 - -int count() { - static int n = 0; - return n++; -} - -int loggedCount() { - static int n = 0; - QPID_LOG(debug, "counting: " << n); - return n++; -} - - -using namespace qpid::sys; - -// Measure CPU time. -clock_t timeLoop(int times, int (*fp)()) { - clock_t start=clock(); - while (times-- > 0) - (*fp)(); - return clock() - start; -} - -// Overhead test disabled because it consumes a ton of CPU and takes -// forever under valgrind. Not friendly for regular test runs. -// -#if 0 -QPID_AUTO_TEST_CASE(testOverhead) { - // Ensure that the ratio of CPU time for an incrementing loop - // with and without disabled log statements is in acceptable limits. - // - int times=100000000; - clock_t noLog=timeLoop(times, count); - clock_t withLog=timeLoop(times, loggedCount); - double ratio=double(withLog)/double(noLog); - - // NB: in initial tests the ratio was consistently below 1.5, - // 2.5 is reasonable and should avoid spurios failures - // due to machine load. - // - BOOST_CHECK_SMALL(ratio, 2.5); -} -#endif // 0 - -Statement statement( - Level level, const char* file="", int line=0, const char* fn=0) -{ - Statement s={0, file, line, fn, level, ::qpid::log::unspecified}; - return s; -} - - -#define ARGC(argv) (sizeof(argv)/sizeof(char*)) - -QPID_AUTO_TEST_CASE(testOptionsParse) { - const char* argv[]={ - 0, - "--log-enable", "error+:foo", - "--log-enable", "debug:bar", - "--log-enable", "info", - "--log-disable", "error+:foo", - "--log-disable", "debug:bar", - "--log-disable", "info", - "--log-to-stderr", "no", - "--log-to-file", "logout", - "--log-level", "yes", - "--log-source", "1", - "--log-thread", "true", - "--log-function", "YES" - }; - qpid::log::Options opts(""); -#ifdef _WIN32 - qpid::log::windows::SinkOptions sinks("test"); -#else - qpid::log::posix::SinkOptions sinks("test"); -#endif - opts.parse(ARGC(argv), const_cast(argv)); - sinks = *opts.sinkOptions; - vector expect=list_of("error+:foo")("debug:bar")("info"); - BOOST_CHECK_EQUAL(expect, opts.selectors); - BOOST_CHECK_EQUAL(expect, opts.deselectors); - BOOST_CHECK(!sinks.logToStderr); - BOOST_CHECK(!sinks.logToStdout); - BOOST_CHECK(sinks.logFile == "logout"); - BOOST_CHECK(opts.level); - BOOST_CHECK(opts.source); - BOOST_CHECK(opts.function); - BOOST_CHECK(opts.thread); -} - -QPID_AUTO_TEST_CASE(testOptionsDefault) { - qpid::log::Options opts(""); -#ifdef _WIN32 - qpid::log::windows::SinkOptions sinks("test"); -#else - qpid::log::posix::SinkOptions sinks("test"); -#endif - sinks = *opts.sinkOptions; - BOOST_CHECK(sinks.logToStderr); - BOOST_CHECK(!sinks.logToStdout); - BOOST_CHECK(sinks.logFile.length() == 0); - vector expect=list_of("notice+"); - BOOST_CHECK_EQUAL(expect, opts.selectors); - BOOST_CHECK(opts.time && opts.level); - BOOST_CHECK(!(opts.source || opts.function || opts.thread)); -} - -QPID_AUTO_TEST_CASE(testSelectorFromOptions) { - const char* argv[]={ - 0, - "--log-enable", "error+:foo", - "--log-enable", "debug:bar", - "--log-enable", "info" - }; - qpid::log::Options opts(""); - opts.parse(ARGC(argv), const_cast(argv)); - vector expect=list_of("error+:foo")("debug:bar")("info"); - BOOST_CHECK_EQUAL(expect, opts.selectors); - Selector s(opts); - BOOST_CHECK(!s.isEnabled(warning, "x")); - BOOST_CHECK(!s.isEnabled(debug, "x")); - BOOST_CHECK(s.isEnabled(debug, "bar")); - BOOST_CHECK(s.isEnabled(error, "foo")); - BOOST_CHECK(s.isEnabled(critical, "foo")); -} - -QPID_AUTO_TEST_CASE(testDeselectorFromOptions) { - const char* argv[]={ - 0, - "--log-disable", "error-:foo", - "--log-disable", "debug:bar", - "--log-disable", "info" - }; - qpid::log::Options opts(""); - opts.parse(ARGC(argv), const_cast(argv)); - vector expect=list_of("error-:foo")("debug:bar")("info"); - BOOST_CHECK_EQUAL(expect, opts.deselectors); - Selector s(opts); - BOOST_CHECK(!s.isDisabled(warning, "x")); - BOOST_CHECK(!s.isDisabled(debug, "x")); - BOOST_CHECK(s.isDisabled(debug, "bar")); - BOOST_CHECK(s.isDisabled(trace, "foo")); - BOOST_CHECK(s.isDisabled(debug, "foo")); - BOOST_CHECK(s.isDisabled(info, "foo")); - BOOST_CHECK(s.isDisabled(notice, "foo")); - BOOST_CHECK(s.isDisabled(warning, "foo")); - BOOST_CHECK(s.isDisabled(error, "foo")); - BOOST_CHECK(!s.isDisabled(critical, "foo")); -} - -QPID_AUTO_TEST_CASE(testMultiConflictingSelectorFromOptions) { - const char* argv[]={ - 0, - "--log-enable", "trace+:foo", - "--log-disable", "error-:foo", - "--log-enable", "debug:bar", - "--log-disable", "debug:bar", - "--log-enable", "info", - "--log-disable", "info", - "--log-enable", "debug+:Model", - "--log-disable", "info-:Model" - }; - qpid::log::Options opts(""); - opts.parse(ARGC(argv), const_cast(argv)); - Selector s(opts); - BOOST_CHECK(!s.isEnabled(warning, "x", log::broker)); - BOOST_CHECK(!s.isEnabled(debug, "x", log::broker)); - BOOST_CHECK(!s.isEnabled(trace, "foo", log::broker)); - BOOST_CHECK(!s.isEnabled(debug, "foo", log::broker)); - BOOST_CHECK(!s.isEnabled(info, "foo", log::broker)); - BOOST_CHECK(!s.isEnabled(notice, "foo", log::broker)); - BOOST_CHECK(!s.isEnabled(warning, "foo", log::broker)); - BOOST_CHECK(!s.isEnabled(error, "foo", log::broker)); - BOOST_CHECK(s.isEnabled(critical, "foo", log::broker)); - BOOST_CHECK(!s.isEnabled(debug, "bar", log::model)); - BOOST_CHECK(!s.isEnabled(trace, "zaz", log::model)); - BOOST_CHECK(!s.isEnabled(debug, "zaz", log::model)); - BOOST_CHECK(!s.isEnabled(info, "zaz", log::model)); - BOOST_CHECK(s.isEnabled(notice, "zaz", log::model)); - BOOST_CHECK(s.isEnabled(warning, "zaz", log::model)); - BOOST_CHECK(s.isEnabled(error, "zaz", log::model)); - BOOST_CHECK(s.isEnabled(critical, "zaz", log::model)); -} - -QPID_AUTO_TEST_CASE(testLoggerStateure) { - Logger& l=Logger::instance(); - ScopedSuppressLogging ls(l); - qpid::log::Options opts("test"); - const char* argv[]={ - 0, - "--log-time", "no", - "--log-source", "yes", - "--log-to-stderr", "no", - "--log-to-file", "logging.tmp", - "--log-enable", "critical" - }; - opts.parse(ARGC(argv), const_cast(argv)); - l.configure(opts); - QPID_LOG_CAT(critical, test, "foo"); int srcline=__LINE__; - ifstream log("logging.tmp"); - string line; - getline(log, line); - string expect=(format("[Test] critical %s:%d: foo")%__FILE__%srcline).str(); - BOOST_CHECK_EQUAL(expect, line); - log.close(); - unlink("logging.tmp"); -} - -QPID_AUTO_TEST_CASE(testQuoteNonPrintable) { - Logger& l=Logger::instance(); - ScopedSuppressLogging ls(l); - qpid::log::Options opts("test"); - opts.time=false; -#ifdef _WIN32 - qpid::log::windows::SinkOptions *sinks = - dynamic_cast(opts.sinkOptions.get()); -#else - qpid::log::posix::SinkOptions *sinks = - dynamic_cast(opts.sinkOptions.get()); -#endif - sinks->logToStderr = false; - sinks->logFile = "logging.tmp"; - l.configure(opts); - - char s[] = "null\0tab\tspace newline\nret\r\x80\x99\xff"; - string str(s, sizeof(s)); - QPID_LOG_CAT(critical, test, str); - ifstream log("logging.tmp"); - string line; - getline(log, line, '\0'); - string expect="[Test] critical null\\x00tab\tspace newline\nret\r\\x80\\x99\\xFF\\x00\n"; - BOOST_CHECK_EQUAL(expect, line); - log.close(); - unlink("logging.tmp"); -} - -QPID_AUTO_TEST_CASE(testSelectorElements) { - SelectorElement s("debug"); - BOOST_CHECK_EQUAL(s.levelStr, "debug"); - BOOST_CHECK_EQUAL(s.patternStr, ""); - BOOST_CHECK_EQUAL(s.level, debug); - BOOST_CHECK(!s.isDisable); - BOOST_CHECK(!s.isCategory); - BOOST_CHECK(!s.isLevelAndAbove); - BOOST_CHECK(!s.isLevelAndBelow); - - SelectorElement t("debug:Broker"); - BOOST_CHECK_EQUAL(t.levelStr, "debug"); - BOOST_CHECK_EQUAL(t.patternStr, "Broker"); - BOOST_CHECK_EQUAL(t.level, debug); - BOOST_CHECK_EQUAL(t.category, broker); - BOOST_CHECK(!t.isDisable); - BOOST_CHECK(t.isCategory); - BOOST_CHECK(!t.isLevelAndAbove); - BOOST_CHECK(!t.isLevelAndBelow); - - SelectorElement u("info+:qmf::"); - BOOST_CHECK_EQUAL(u.levelStr, "info"); - BOOST_CHECK_EQUAL(u.patternStr, "qmf::"); - BOOST_CHECK_EQUAL(u.level, info); - BOOST_CHECK(!u.isDisable); - BOOST_CHECK(!u.isCategory); - BOOST_CHECK(u.isLevelAndAbove); - BOOST_CHECK(!u.isLevelAndBelow); - - SelectorElement v("critical-"); - BOOST_CHECK_EQUAL(v.levelStr, "critical"); - BOOST_CHECK_EQUAL(v.patternStr, ""); - BOOST_CHECK_EQUAL(v.level, critical); - BOOST_CHECK(!v.isDisable); - BOOST_CHECK(!v.isCategory); - BOOST_CHECK(!v.isLevelAndAbove); - BOOST_CHECK(v.isLevelAndBelow); - - SelectorElement w("!warning-:Management"); - BOOST_CHECK_EQUAL(w.levelStr, "warning"); - BOOST_CHECK_EQUAL(w.patternStr, "Management"); - BOOST_CHECK_EQUAL(w.level, warning); - BOOST_CHECK_EQUAL(w.category, management); - BOOST_CHECK(w.isDisable); - BOOST_CHECK(w.isCategory); - BOOST_CHECK(!w.isLevelAndAbove); - BOOST_CHECK(w.isLevelAndBelow); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/mgmt_1.py b/qpid/cpp/src/tests/mgmt_1.py deleted file mode 100644 index 39812c2995..0000000000 --- a/qpid/cpp/src/tests/mgmt_1.py +++ /dev/null @@ -1,99 +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. -# - -from qpid.tests.messaging.implementation import * - -class Mgmt: - """ - Simple QMF management utility (qpidtoollibs uses - qpid.messaging.Message rather than swigged version) - """ - def __init__(self, conn): - self.conn = conn - self.sess = self.conn.session() - self.reply_to = "qmf.default.topic/direct.%s;{node:{type:topic}, link:{x-declare:{auto-delete:True,exclusive:True}}}" % \ - str(uuid4()) - self.reply_rx = self.sess.receiver(self.reply_to) - self.reply_rx.capacity = 10 - self.tx = self.sess.sender("qmf.default.direct/broker") - self.next_correlator = 1 - - def close(self): - self.conn.close() - - def list(self, class_name): - props = {'method' : 'request', - 'qmf.opcode' : '_query_request', - 'x-amqp-0-10.app-id' : 'qmf2'} - correlator = str(self.next_correlator) - self.next_correlator += 1 - - content = {'_what' : 'OBJECT', - '_schema_id' : {'_class_name' : class_name.lower()}} - - message = Message(content, reply_to=self.reply_to, correlation_id=correlator, - properties=props, subject="broker") - self.tx.send(message) - - - response = self.reply_rx.fetch(10) - if response.properties['qmf.opcode'] != '_query_response': - raise Exception("bad response") - items = [] - done = False - while not done: - for item in response.content: - items.append(item['_values']) - if 'partial' in response.properties: - response = self.reply_rx.fetch(10) - else: - done = True - self.sess.acknowledge() - return items - - def do_qmf_method(self, method, arguments, addr="org.apache.qpid.broker:broker:amqp-broker", timeout=10): - props = {'method' : 'request', - 'qmf.opcode' : '_method_request', - 'x-amqp-0-10.app-id' : 'qmf2'} - correlator = str(self.next_correlator) - self.next_correlator += 1 - - content = {'_object_id' : {'_object_name' : addr}, - '_method_name' : method, - '_arguments' : arguments} - - message = Message(content, reply_to=self.reply_to, correlation_id=correlator, - properties=props, subject="broker") - self.tx.send(message) - response = self.reply_rx.fetch(timeout) - self.sess.acknowledge() - if response.properties['qmf.opcode'] == '_exception': - raise Exception("Exception from Agent: %r" % response.content['_values']) - if response.properties['qmf.opcode'] != '_method_response': - raise Exception("bad response: %r" % response.properties) - return response.content['_arguments'] - - def create(self, _type, name, properties={}): - return self.do_qmf_method('create', {'type': _type, 'name': name, 'properties': properties}) - - def delete(self, _type, name): - return self.do_qmf_method('delete', {'type': _type, 'name': name}) - - def reload_acl_file(self): - self.do_qmf_method('reloadACLFile', {}, "org.apache.qpid.acl:acl:org.apache.qpid.broker:broker:amqp-broker") diff --git a/qpid/cpp/src/tests/misc.py b/qpid/cpp/src/tests/misc.py deleted file mode 100644 index 257fb9e754..0000000000 --- a/qpid/cpp/src/tests/misc.py +++ /dev/null @@ -1,119 +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. -# - -from qpid.tests.messaging.implementation import * -from qpid.tests.messaging import VersionTest - -class MiscellaneousTests (VersionTest): - """ - Tests for various aspects of qpidd behaviour - """ - def test_exclusive(self): - con = self.create_connection("amqp1.0", True) - rcv = con.session().receiver("q; {create:always, node:{properties:{exclusive:True,auto-delete:True}}}") - - other = self.create_connection("amqp1.0", True) - try: - #can send to the queue - snd = other.session().sender("q") - - #can browse the queue - browser = other.session().receiver("q; {mode:browse}") - - #can't consume from the queue - try: - consumer = other.session().receiver("q") - assert False, ("Should not be able to consume from exclusively owned queue") - except LinkError, e: None - try: - exclusive = other.session().receiver("q; {create: always, node:{properties:{exclusive:True}}}") - assert False, ("Should not be able to consume exclusively from exclusively owned queue") - except LinkError, e: None - finally: - rcv.close() - con.close() - other.close() - -class AutoDeleteExchangeTests(VersionTest): - def init_test(self, exchange_type="topic"): - rcv = self.ssn.receiver("my-topic; {create:always, node:{type:topic, properties:{'exchange-type':%s, 'auto-delete':True}}}" % exchange_type) - snd = self.ssn.sender("my-topic") - #send some messages - msgs = [Message(content=c) for c in ['a','b','c','d']] - for m in msgs: snd.send(m) - - #verify receipt - for expected in msgs: - msg = rcv.fetch(0) - assert msg.content == expected.content - self.ssn.acknowledge(msg) - return (rcv, snd) - - def on_rcv_detach_test(self, exchange_type="topic"): - rcv, snd = self.init_test(exchange_type) - rcv.close() - #verify exchange is still there - snd.send(Message(content="will be dropped")) - snd.close() - #now verify it is no longer there - try: - self.ssn.sender("my-topic") - assert False, "Attempt to send to deleted exchange should fail" - except MessagingError: None - - def on_snd_detach_test(self, exchange_type="topic"): - rcv, snd = self.init_test(exchange_type) - snd.close() - #verify exchange is still there - snd = self.ssn.sender("my-topic") - snd.send(Message(content="will be dropped")) - snd.close() - rcv.close() - #now verify it is no longer there - try: - self.ssn.sender("my-topic") - assert False, "Attempt to send to deleted exchange should fail" - except MessagingError: None - - def test_autodelete_fanout_exchange_on_rcv_detach(self): - self.on_rcv_detach_test("fanout") - - def test_autodelete_fanout_exchange_on_snd_detach(self): - self.on_snd_detach_test("fanout") - - def test_autodelete_direct_exchange_on_rcv_detach(self): - self.on_rcv_detach_test("direct") - - def test_autodelete_direct_exchange_on_snd_detach(self): - self.on_snd_detach_test("direct") - - def test_autodelete_topic_exchange_on_rcv_detach(self): - self.on_rcv_detach_test("topic") - - def test_autodelete_topic_exchange_on_snd_detach(self): - self.on_snd_detach_test("topic") - - def test_autodelete_headers_exchange_on_rcv_detach(self): - self.on_rcv_detach_test("headers") - - def test_autodelete_headers_exchange_on_snd_detach(self): - self.on_snd_detach_test("headers") - - - diff --git a/qpid/cpp/src/tests/msg_group_test.cpp b/qpid/cpp/src/tests/msg_group_test.cpp deleted file mode 100644 index ca87197ff3..0000000000 --- a/qpid/cpp/src/tests/msg_group_test.cpp +++ /dev/null @@ -1,641 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/SystemInfo.h" - -#include -#include -#include - -using namespace qpid::messaging; -using namespace qpid::types; -using namespace std; - -namespace qpid { -namespace tests { - -struct Options : public qpid::Options -{ - bool help; - std::string url; - std::string address; - std::string connectionOptions; - uint messages; - uint capacity; - uint ackFrequency; - bool failoverUpdates; - qpid::log::Options log; - uint senders; - uint receivers; - uint groupSize; - bool printReport; - std::string groupKey; - bool durable; - bool allowDuplicates; - bool randomizeSize; - bool stickyConsumer; - uint timeout; - uint interleave; - std::string prefix; - uint sendRate; - - Options(const std::string& argv0=std::string()) - : qpid::Options("Options"), - help(false), - url("amqp:tcp:127.0.0.1"), - messages(10000), - capacity(1000), - ackFrequency(100), - failoverUpdates(false), - log(argv0), - senders(2), - receivers(2), - groupSize(10), - printReport(false), - groupKey("qpid.no_group"), - durable(false), - allowDuplicates(false), - randomizeSize(false), - stickyConsumer(false), - timeout(10), - interleave(1), - sendRate(0) - { - addOptions() - ("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)") - ("address,a", qpid::optValue(address, "ADDRESS"), "address to send and receive from") - ("allow-duplicates", qpid::optValue(allowDuplicates), "Ignore the delivery of duplicated messages") - ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to") - ("capacity", qpid::optValue(capacity, "N"), "Pre-fetch window (0 implies no pre-fetch)") - ("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection") - ("durable", qpid::optValue(durable, "yes|no"), "Mark messages as durable.") - ("failover-updates", qpid::optValue(failoverUpdates), "Listen for membership updates distributed via amq.failover") - ("group-key", qpid::optValue(groupKey, "KEY"), "Key of the message header containing the group identifier.") - ("group-prefix", qpid::optValue(prefix, "STRING"), "Add 'prefix' to the start of all generated group identifiers.") - ("group-size", qpid::optValue(groupSize, "N"), "Number of messages per a group.") - ("interleave", qpid::optValue(interleave, "N"), "Simultaineously interleave messages from N different groups.") - ("messages,m", qpid::optValue(messages, "N"), "Number of messages to send per each sender.") - ("receivers,r", qpid::optValue(receivers, "N"), "Number of message consumers.") - ("randomize-group-size", qpid::optValue(randomizeSize), "Randomize the number of messages per group to [1...group-size].") - ("send-rate", qpid::optValue(sendRate,"N"), "Send at rate of N messages/second. 0 means send as fast as possible.") - ("senders,s", qpid::optValue(senders, "N"), "Number of message producers.") - ("sticky-consumers", qpid::optValue(stickyConsumer), "If set, verify that all messages in a group are consumed by the same client [TBD].") - ("timeout", qpid::optValue(timeout, "N"), "Fail with a stall error should all consumers remain idle for timeout seconds.") - ("print-report", qpid::optValue(printReport), "Dump message group statistics to stdout.") - ("help", qpid::optValue(help), "print this usage statement"); - add(log); - //("check-redelivered", qpid::optValue(checkRedelivered), "Fails with exception if a duplicate is not marked as redelivered (only relevant when ignore-duplicates is selected)") - //("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)") - //("rollback-frequency", qpid::optValue(rollbackFrequency, "N"), "rollback frequency (0 implies no transaction will be rolledback)") - } - - bool parse(int argc, char** argv) - { - try { - qpid::Options::parse(argc, argv); - if (address.empty()) throw qpid::Exception("Address must be specified!"); - if (senders == 0 && receivers == 0) throw qpid::Exception("No senders and No receivers?"); - if (messages == 0) throw qpid::Exception("The message count cannot be zero."); - qpid::log::Logger::instance().configure(log); - if (help) { - std::cout << *this << std::endl << std::endl - << "Verifies the behavior of grouped messages." << std::endl; - return false; - } else { - return true; - } - } catch (const std::exception& e) { - std::cerr << *this << std::endl << std::endl << e.what() << std::endl; - return false; - } - } -}; - -const string EOS("eos"); -const string SN("sn"); - - -// class that monitors group state across all publishers and consumers. tracks the next -// expected sequence for each group, and total messages consumed. -class GroupChecker -{ - qpid::sys::Mutex lock; - - uint consumerCt; - uint producerCt; - uint totalMsgs; - uint totalMsgsConsumed; - uint totalMsgsPublished; - bool allowDuplicates; - uint duplicateMsgs; - - typedef std::map SequenceMap; - SequenceMap sequenceMap; - - // Statistics - for each group, store the names of all clients that consumed messages - // from that group, and the number of messages consumed per client. - typedef std::map ClientCounter; - typedef std::map GroupStatistics; - GroupStatistics statistics; - -public: - - GroupChecker( uint messages, uint consumers, uint producers, bool d) : - consumerCt(consumers), producerCt(producers), - totalMsgs(0), totalMsgsConsumed(0), totalMsgsPublished(0), allowDuplicates(d), - duplicateMsgs(0) - { - // if consumering only - we a draining a queue of 'messages' queued messages. - if (producerCt != 0) { - totalMsgs = producers * messages; - } else { - totalMsgs = messages; - } - } - - bool checkSequence( const std::string& groupId, - uint sequence, const std::string& client ) - { - qpid::sys::Mutex::ScopedLock l(lock); - - QPID_LOG(debug, "Client " << client << " has received " << groupId << ":" << sequence); - - GroupStatistics::iterator gs = statistics.find(groupId); - if (gs == statistics.end()) { - statistics[groupId][client] = 1; - } else { - gs->second[client]++; - } - // now verify - SequenceMap::iterator s = sequenceMap.find(groupId); - if (s == sequenceMap.end()) { - QPID_LOG(debug, "Client " << client << " thinks this is the first message from group " << groupId << ":" << sequence); - // if duplication allowed, it is possible that the last msg(s) of an old sequence are redelivered on reconnect. - // in this case, set the sequence from the first msg. - sequenceMap[groupId] = (allowDuplicates) ? sequence : 0; - s = sequenceMap.find(groupId); - } else if (sequence < s->second) { - duplicateMsgs++; - QPID_LOG(debug, "Client " << client << " thinks this message is a duplicate! " << groupId << ":" << sequence); - return allowDuplicates; - } - totalMsgsConsumed++; - return sequence == s->second++; - } - - void sendingSequence( const std::string& groupId, - uint sequence, bool eos, - const std::string& client ) - { - qpid::sys::Mutex::ScopedLock l(lock); - ++totalMsgsPublished; - - QPID_LOG(debug, "Client " << client << " sending " << groupId << ":" << sequence << - ((eos) ? " (last)" : "")); - } - - bool eraseGroup( const std::string& groupId, const std::string& name ) - { - qpid::sys::Mutex::ScopedLock l(lock); - QPID_LOG(debug, "Deleting group " << groupId << " (by client " << name << ")"); - return sequenceMap.erase( groupId ) == 1; - } - - uint getNextExpectedSequence( const std::string& groupId ) - { - qpid::sys::Mutex::ScopedLock l(lock); - return sequenceMap[groupId]; - } - - bool allMsgsPublished() // true when done publishing msgs - { - qpid::sys::Mutex::ScopedLock l(lock); - return (producerCt == 0 || totalMsgsPublished >= totalMsgs); - } - - bool allMsgsConsumed() // true when done consuming msgs - { - qpid::sys::Mutex::ScopedLock l(lock); - return (consumerCt == 0 || - (totalMsgsConsumed >= totalMsgs && sequenceMap.size() == 0)); - } - - uint getTotalMessages() - { - return totalMsgs; - } - - uint getConsumedTotal() - { - qpid::sys::Mutex::ScopedLock l(lock); - return totalMsgsConsumed; - } - - uint getPublishedTotal() - { - qpid::sys::Mutex::ScopedLock l(lock); - return totalMsgsPublished; - } - - ostream& print(ostream& out) - { - qpid::sys::Mutex::ScopedLock l(lock); - out << "Total Published: " << totalMsgsPublished << ", Total Consumed: " << totalMsgsConsumed << - ", Duplicates detected: " << duplicateMsgs << std::endl; - out << "Total Groups: " << statistics.size() << std::endl; - unsigned long consumers = 0; - for (GroupStatistics::iterator gs = statistics.begin(); gs != statistics.end(); ++gs) { - out << " GroupId: " << gs->first; - consumers += gs->second.size(); // # of consumers that processed this group - if (gs->second.size() == 1) - out << " completely consumed by a single client." << std::endl; - else - out << " consumed by " << gs->second.size() << " different clients." << std::endl; - - for (ClientCounter::iterator cc = gs->second.begin(); cc != gs->second.end(); ++cc) { - out << " Client: " << cc->first << " consumed " << cc->second << " messages from the group." << std::endl; - } - } - out << "Average # of consumers per group: " << ((statistics.size() != 0) ? (double(consumers)/statistics.size()) : 0) << std::endl; - return out; - } -}; - - -namespace { - // rand() is not thread safe. Create a singleton obj to hold a lock while calling - // rand() so it can be called safely by multiple concurrent clients. - class Randomizer { - qpid::sys::Mutex lock; - public: - uint operator()(uint max) { - qpid::sys::Mutex::ScopedLock l(lock); - return (rand() % max) + 1; - } - }; - - static Randomizer randomizer; -} - - -// tag each generated message with a group identifer -// -class GroupGenerator { - - const std::string groupPrefix; - const uint groupSize; - const bool randomizeSize; - const uint interleave; - - uint groupSuffix; - uint total; - - struct GroupState { - std::string id; - const uint size; - uint count; - GroupState( const std::string& i, const uint s ) - : id(i), size(s), count(0) {} - }; - typedef std::list GroupList; - GroupList groups; - GroupList::iterator current; - - // add a new group identifier to the list - void newGroup() { - std::ostringstream groupId(groupPrefix, ios_base::out|ios_base::ate); - groupId << std::string(":") << groupSuffix++; - uint size = (randomizeSize) ? randomizer(groupSize) : groupSize; - QPID_LOG(trace, "New group: GROUPID=[" << groupId.str() << "] size=" << size << " this=" << this); - GroupState group( groupId.str(), size ); - groups.push_back( group ); - } - -public: - GroupGenerator( const std::string& prefix, - const uint t, - const uint size, - const bool randomize, - const uint i) - : groupPrefix(prefix), groupSize(size), - randomizeSize(randomize), interleave(i), groupSuffix(0), total(t) - { - QPID_LOG(trace, "New group generator: PREFIX=[" << prefix << "] total=" << total << " size=" << size << " rand=" << randomize << " interleave=" << interleave << " this=" << this); - for (uint i = 0; i < 1 || i < interleave; ++i) { - newGroup(); - } - current = groups.begin(); - } - - bool genGroup(std::string& groupId, uint& seq, bool& eos) - { - if (!total) return false; - --total; - if (current == groups.end()) - current = groups.begin(); - groupId = current->id; - seq = current->count++; - if (current->count == current->size) { - QPID_LOG(trace, "Last msg for " << current->id << ", " << current->count << " this=" << this); - eos = true; - if (total >= interleave) { // need a new group to replace this one - newGroup(); - groups.erase(current++); - } else ++current; - } else { - ++current; - eos = total < interleave; // mark eos on the last message of each group - } - QPID_LOG(trace, "SENDING GROUPID=[" << groupId << "] seq=" << seq << " eos=" << eos << " this=" << this); - return true; - } -}; - - - -class Client : public qpid::sys::Runnable -{ -public: - typedef boost::shared_ptr shared_ptr; - enum State {ACTIVE, DONE, FAILURE}; - Client( const std::string& n, const Options& o ) : name(n), opts(o), state(ACTIVE), stopped(false) {} - virtual ~Client() {} - State getState() { return state; } - void testFailed( const std::string& reason ) { state = FAILURE; error << "Client '" << name << "' failed: " << reason; } - void clientDone() { if (state == ACTIVE) state = DONE; } - qpid::sys::Thread& getThread() { return thread; } - const std::string getErrorMsg() { return error.str(); } - void stop() {stopped = true;} - const std::string& getName() { return name; } - -protected: - const std::string name; - const Options& opts; - qpid::sys::Thread thread; - ostringstream error; - State state; - bool stopped; -}; - - -class Consumer : public Client -{ - GroupChecker& checker; - -public: - Consumer(const std::string& n, const Options& o, GroupChecker& c ) : Client(n, o), checker(c) {}; - virtual ~Consumer() {}; - - void run() - { - Connection connection; - try { - connection = Connection(opts.url, opts.connectionOptions); - connection.open(); - std::auto_ptr updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0); - Session session = connection.createSession(); - Receiver receiver = session.createReceiver(opts.address); - receiver.setCapacity(opts.capacity); - Message msg; - uint count = 0; - - while (!stopped) { - if (receiver.fetch(msg, Duration::SECOND)) { // msg retrieved - qpid::types::Variant::Map& properties = msg.getProperties(); - std::string groupId = properties[opts.groupKey]; - uint groupSeq = properties[SN]; - bool eof = properties[EOS]; - - QPID_LOG(trace, "RECVING GROUPID=[" << groupId << "] seq=" << groupSeq << " eos=" << eof << " name=" << name); - - qpid::sys::usleep(10); - - if (!checker.checkSequence( groupId, groupSeq, name )) { - ostringstream msg; - msg << "Check sequence failed. Group=" << groupId << " rcvd seq=" << groupSeq << " expected=" << checker.getNextExpectedSequence( groupId ); - testFailed( msg.str() ); - break; - } else if (eof) { - if (!checker.eraseGroup( groupId, name )) { - ostringstream msg; - msg << "Erase group failed. Group=" << groupId << " rcvd seq=" << groupSeq; - testFailed( msg.str() ); - break; - } - } - - ++count; - if (opts.ackFrequency && (count % opts.ackFrequency == 0)) { - session.acknowledge(); - } - // Clear out message properties & content for next iteration. - msg = Message(); // TODO aconway 2010-12-01: should be done by fetch - } else if (checker.allMsgsConsumed()) // timed out, nothing else to do? - break; - } - session.acknowledge(); - session.close(); - connection.close(); - } catch(const std::exception& error) { - ostringstream msg; - msg << "consumer error: " << error.what(); - testFailed( msg.str() ); - connection.close(); - } - clientDone(); - QPID_LOG(trace, "Consuming client " << name << " completed."); - } -}; - - - -class Producer : public Client -{ - GroupChecker& checker; - GroupGenerator generator; - -public: - Producer(const std::string& n, const Options& o, GroupChecker& c) - : Client(n, o), checker(c), - generator( n, o.messages, o.groupSize, o.randomizeSize, o.interleave ) - {}; - virtual ~Producer() {}; - - void run() - { - Connection connection; - try { - connection = Connection(opts.url, opts.connectionOptions); - connection.open(); - std::auto_ptr updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0); - Session session = connection.createSession(); - Sender sender = session.createSender(opts.address); - if (opts.capacity) sender.setCapacity(opts.capacity); - Message msg; - msg.setDurable(opts.durable); - std::string groupId; - uint seq; - bool eos; - uint sent = 0; - - qpid::sys::AbsTime start = qpid::sys::now(); - int64_t interval = 0; - if (opts.sendRate) interval = qpid::sys::TIME_SEC/opts.sendRate; - - while (!stopped && generator.genGroup(groupId, seq, eos)) { - msg.getProperties()[opts.groupKey] = groupId; - msg.getProperties()[SN] = seq; - msg.getProperties()[EOS] = eos; - checker.sendingSequence( groupId, seq, eos, name ); - - sender.send(msg); - ++sent; - - if (opts.sendRate) { - qpid::sys::AbsTime waitTill(start, sent*interval); - int64_t delay = qpid::sys::Duration(qpid::sys::now(), waitTill); - if (delay > 0) qpid::sys::usleep(delay/qpid::sys::TIME_USEC); - } - } - session.sync(); - session.close(); - connection.close(); - } catch(const std::exception& error) { - ostringstream msg; - msg << "producer '" << name << "' error: " << error.what(); - testFailed(msg.str()); - connection.close(); - } - clientDone(); - QPID_LOG(trace, "Producing client " << name << " completed."); - } -}; - - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - int status = 0; - try { - Options opts; - if (opts.parse(argc, argv)) { - - GroupChecker state( opts.messages, - opts.receivers, - opts.senders, - opts.allowDuplicates); - std::vector clients; - - if (opts.randomizeSize) srand((unsigned int)qpid::sys::SystemInfo::getProcessId()); - - // fire off the producers && consumers - for (size_t j = 0; j < opts.senders; ++j) { - ostringstream name; - name << opts.prefix << "P_" << j; - clients.push_back(Client::shared_ptr(new Producer( name.str(), opts, state ))); - clients.back()->getThread() = qpid::sys::Thread(*clients.back()); - } - for (size_t j = 0; j < opts.receivers; ++j) { - ostringstream name; - name << opts.prefix << "C_" << j; - clients.push_back(Client::shared_ptr(new Consumer( name.str(), opts, state ))); - clients.back()->getThread() = qpid::sys::Thread(*clients.back()); - } - - // wait for all pubs/subs to finish.... or for consumers to fail or stall. - uint stalledTime = 0; - bool clientFailed = false; - while (!clientFailed && (!state.allMsgsPublished() || !state.allMsgsConsumed())) { - uint lastCount; - - lastCount = state.getConsumedTotal(); - qpid::sys::usleep( 1000000 ); - - // check each client for failures - for (std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { - QPID_LOG(debug, "Client " << (*i)->getName() << " state=" << (*i)->getState()); - if ((*i)->getState() == Client::FAILURE) { - QPID_LOG(error, argv[0] << ": test failed with client error: " << (*i)->getErrorMsg()); - clientFailed = true; - break; // exit test. - } - } - - // check for stalled consumers - if (!clientFailed && !state.allMsgsConsumed()) { - if (lastCount == state.getConsumedTotal()) { - if (++stalledTime >= opts.timeout) { - clientFailed = true; - break; // exit test - } - } else { - stalledTime = 0; - } - } - QPID_LOG(debug, "Consumed to date = " << state.getConsumedTotal() << - " Published to date = " << state.getPublishedTotal() << - " total=" << state.getTotalMessages()); - } - - if (clientFailed) { - if (stalledTime >= opts.timeout) { - QPID_LOG(error, argv[0] << ": test failed due to stalled consumer." ); - status = 2; - } else { - status = 1; - } - } - - // Wait for started threads. - for (std::vector::iterator i = clients.begin(); - i != clients.end(); ++i) { - (*i)->stop(); - (*i)->getThread().join(); - } - - if (opts.printReport && !status) state.print(std::cout); - } else status = 4; - } catch(const std::exception& error) { - QPID_LOG(error, argv[0] << ": " << error.what()); - status = 3; - } - QPID_LOG(trace, "TEST DONE [" << status << "]"); - - return status; -} diff --git a/qpid/cpp/src/tests/perfdist b/qpid/cpp/src/tests/perfdist deleted file mode 100755 index 4049b410ff..0000000000 --- a/qpid/cpp/src/tests/perfdist +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env 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. -# - - -# -# Distributed perftest. -# Runs perftest clients on multiple hosts using ssh. -# - -set -e -usage() { -cat < -- [ --- ] -Client & broker hosts can also be set in env vars CLIENTS and BROKERS. - -Run perftest clients on the client hosts against brokers on the broker -hosts Clients are assigned to client hosts round robin: publishers -first, then subscribers. If there are multiple brokers (for cluster -tests) clients connect to them round robin. - -Broker hosts can be listed with -b in perftest-args or after --- -at the end of the arguments. - -Error: $* -EOF -exit 1 -} - -TESTDIR=${TESTDIR:-$PWD} # Absolute path to test exes on all hosts. - -collect() { eval $COLLECT=\""\$$COLLECT $*"\"; } -NPUBS=1 -NSUBS=1 -COLLECT=ARGS -while test $# -gt 0; do - case $1 in - --publish|--subscribe|--setup|--control) usage "Don't pass perftest action flags: $1" ;; - --npubs) collect $1 $2; NPUBS=$2; shift 2 ;; - --nsubs) collect $1 $2; NSUBS=$2; shift 2 ;; - -s|--summary) collect $1; QUIET=yes; shift 1 ;; - -b|--broker) BROKERS="$BROKERS $2"; shift 2;; - --) COLLECT=CLIENTARG; shift ;; - ---) COLLECT=BROKERARG; shift;; - *) collect $1; shift ;; - esac -done - -CLIENTS=${CLIENTARG:-$CLIENTS} -if [ -z "$CLIENTS" ]; then usage "No client hosts listed after --"; fi -BROKERS=${BROKERARG:-$BROKERS} -if [ -z "$BROKERS" ]; then usage "No brokers specified"; fi - -PERFTEST="$TESTDIR/perftest $ARGS" - -CLIENTS=($CLIENTS) -BROKERS=($BROKERS) -start() { - CLIENT=${CLIENTS[i % ${#CLIENTS[*]}]} - BROKER=${BROKERS[i % ${#BROKERS[*]}]} - ARGS="$* --broker $BROKER" - cmd="ssh -n $CLIENT $PERFTEST $ARGS" - test -z "$QUIET" && echo "Client $i: $cmd" - $cmd & -} - -$PERFTEST --setup -b ${BROKERS[0]} -for (( i=0 ; i < $NPUBS ; ++i)); do start --publish; done -for (( ; i < $NPUBS+$NSUBS ; ++i)); do start --subscribe; done -$PERFTEST --control -b ${BROKERS[0]} diff --git a/qpid/cpp/src/tests/ping_broker b/qpid/cpp/src/tests/ping_broker deleted file mode 100755 index bdf48f3358..0000000000 --- a/qpid/cpp/src/tests/ping_broker +++ /dev/null @@ -1,134 +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. -# - -import os -from optparse import OptionParser, OptionGroup -import sys -import locale -import socket -import re -from qpid.messaging import Connection - -home = os.environ.get("QPID_TOOLS_HOME", os.path.normpath("/usr/share/qpid-tools")) -sys.path.append(os.path.join(home, "python")) - -from qpidtoollibs import BrokerAgent -from qpidtoollibs import Display, Header, Sorter, YN, Commas, TimeLong - - -class Config: - def __init__(self): - self._host = "localhost" - self._connTimeout = 10 - -config = Config() -conn_options = {} - -def OptionsAndArguments(argv): - """ Set global variables for options, return arguments """ - - global config - global conn_options - - usage = "%prog [options]" - - parser = OptionParser(usage=usage) - - parser.add_option("-b", "--broker", action="store", type="string", default="localhost", metavar="", - help="URL of the broker to query") - parser.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="", - help="Maximum time to wait for broker connection (in seconds)") - parser.add_option("--sasl-mechanism", action="store", type="string", metavar="", - help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD5, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.") - parser.add_option("--ssl-certificate", action="store", type="string", metavar="", help="Client SSL certificate (PEM Format)") - parser.add_option("--ssl-key", action="store", type="string", metavar="", help="Client SSL private key (PEM Format)") - parser.add_option("--ssl-trustfile", action="store", type="string", metavar="", help="List of trusted CAs (PEM Format)") - parser.add_option("--ssl-skip-hostname-check", action="store_true", - help="Do not validate hostname in peer certificate") - parser.add_option("--ha-admin", action="store_true", help="Allow connection to a HA backup broker.") - - opts, args = parser.parse_args(args=argv) - - config._host = opts.broker - config._connTimeout = opts.timeout - - if opts.sasl_mechanism: - conn_options['sasl_mechanisms'] = opts.sasl_mechanism - if opts.ssl_certificate: - conn_options['ssl_certfile'] = opts.ssl_certificate - if opts.ssl_key: - conn_options['ssl_key'] = opts.ssl_key - if opts.ssl_trustfile: - conn_options['ssl_trustfile'] = opts.ssl_trustfile - if opts.ssl_skip_hostname_check: - conn_options['ssl_skip_hostname_check'] = True - if opts.ha_admin: - conn_options['client_properties'] = {'qpid.ha-admin' : 1} - return args - -class BrokerManager: - def __init__(self): - self.brokerName = None - self.connection = None - self.broker = None - self.cluster = None - - def SetBroker(self, brokerUrl): - self.url = brokerUrl - self.connection = Connection.establish(self.url, **conn_options) - self.broker = BrokerAgent(self.connection) - - def Disconnect(self): - """ Release any allocated brokers. Ignore any failures as the tool is - shutting down. - """ - try: - connection.close() - except: - pass - - def Ping(self, args): - for sequence in range(10): - result = self.broker.echo(sequence, "ECHO BODY") - if result['sequence'] != sequence: - raise Exception("Invalid Sequence") - - -def main(argv=None): - - args = OptionsAndArguments(argv) - bm = BrokerManager() - - try: - bm.SetBroker(config._host) - bm.Ping(args) - bm.Disconnect() - return 0 - except KeyboardInterrupt: - print - except Exception,e: - print "Failed: %s - %s" % (e.__class__.__name__, e) - - bm.Disconnect() # try to deallocate brokers - return 1 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/qpid/cpp/src/tests/plano.py b/qpid/cpp/src/tests/plano.py deleted file mode 100644 index e76fba03eb..0000000000 --- a/qpid/cpp/src/tests/plano.py +++ /dev/null @@ -1,559 +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. -# - -from __future__ import print_function - -import atexit as _atexit -import codecs as _codecs -import fnmatch as _fnmatch -import getpass as _getpass -import os as _os -import random as _random -import re as _re -import shutil as _shutil -import subprocess as _subprocess -import sys as _sys -import tarfile as _tarfile -import tempfile as _tempfile -import traceback as _traceback - -# See documentation at http://www.ssorj.net/projects/plano.html - -def fail(message, *args): - error(message, *args) - - if isinstance(message, BaseException): - raise message - - raise Exception(message) - -def error(message, *args): - _print_message("Error", message, args, _sys.stderr) - -def warn(message, *args): - _print_message("Warn", message, args, _sys.stderr) - -def notice(message, *args): - _print_message(None, message, args, _sys.stdout) - -def debug(message, *args): - _print_message("Debug", message, args, _sys.stdout) - -def exit(message=None, *args): - if message is None: - _sys.exit() - - _print_message("Error", message, args, _sys.stderr) - - _sys.exit(1) - -def _print_message(category, message, args, file): - message = _format_message(category, message, args) - - print(message, file=file) - file.flush() - -def _format_message(category, message, args): - if isinstance(message, BaseException): - message = str(message) - - if message == "": - message = message.__class__.__name__ - - if category: - message = "{0}: {1}".format(category, message) - - if args: - message = message.format(*args) - - script = split(_sys.argv[0])[1] - message = "{0}: {1}".format(script, message) - - return message - -def flush(): - _sys.stdout.flush() - _sys.stderr.flush() - -absolute_path = _os.path.abspath -normalize_path = _os.path.normpath -exists = _os.path.exists -is_absolute = _os.path.isabs -is_dir = _os.path.isdir -is_file = _os.path.isfile -is_link = _os.path.islink - -join = _os.path.join -split = _os.path.split -split_extension = _os.path.splitext - -LINE_SEP = _os.linesep -PATH_SEP = _os.sep -PATH_VAR_SEP = _os.pathsep -ENV = _os.environ -ARGS = _sys.argv - -current_dir = _os.getcwd - -def home_dir(user=""): - return _os.path.expanduser("~{0}".format(user)) - -def parent_dir(path): - path = normalize_path(path) - parent, child = split(path) - - return parent - -def file_name(file): - file = normalize_path(file) - dir, name = split(file) - - return name - -def name_stem(file): - name = file_name(file) - - if name.endswith(".tar.gz"): - name = name[:-3] - - stem, ext = split_extension(name) - - return stem - -def name_extension(file): - name = file_name(file) - stem, ext = split_extension(name) - - return ext - -def read(file): - with _codecs.open(file, encoding="utf-8", mode="r") as f: - return f.read() - -def write(file, string): - with _codecs.open(file, encoding="utf-8", mode="w") as f: - f.write(string) - - return file - -def append(file, string): - with _codecs.open(file, encoding="utf-8", mode="a") as f: - f.write(string) - - return file - -def prepend(file, string): - orig = read(file) - prepended = string + orig - - return write(file, prepended) - -def touch(file): - return append(file, "") - -def tail(file, n): - return "".join(tail_lines(file, n)) - -def read_lines(file): - with _codecs.open(file, encoding="utf-8", mode="r") as f: - return f.readlines() - -def write_lines(file, lines): - with _codecs.open(file, encoding="utf-8", mode="r") as f: - f.writelines(lines) - - return file - -def append_lines(file, lines): - with _codecs.open(file, encoding="utf-8", mode="a") as f: - f.writelines(string) - - return file - -def prepend_lines(file, lines): - orig_lines = read_lines(file) - - with _codecs.open(file, encoding="utf-8", mode="w") as f: - f.writelines(lines) - f.writelines(orig_lines) - - return file - -# Derived from http://stackoverflow.com/questions/136168/get-last-n-lines-of-a-file-with-python-similar-to-tail -def tail_lines(file, n): - assert n >= 0 - - with _codecs.open(file, encoding="utf-8", mode="r") as f: - pos = n + 1 - lines = list() - - while len(lines) <= n: - try: - f.seek(-pos, 2) - except IOError: - f.seek(0) - break - finally: - lines = f.readlines() - - pos *= 2 - - return lines[-n:] - -_temp_dir = _tempfile.mkdtemp(prefix="plano.") - -def _get_temp_file(key): - assert not key.startswith("_") - - return join(_temp_dir, "_file_{0}".format(key)) - -def _remove_temp_dir(): - _shutil.rmtree(_temp_dir, ignore_errors=True) - -_atexit.register(_remove_temp_dir) - -def read_temp(key): - file = _get_temp_file(key) - return read(file) - -def write_temp(key, string): - file = _get_temp_file(key) - return write(file, string) - -def append_temp(key, string): - file = _get_temp_file(key) - return append(file, string) - -def prepend_temp(key, string): - file = _get_temp_file(key) - return prepend(file, string) - -def make_temp(key): - return append_temp(key, "") - -def open_temp(key, mode="r"): - file = _get_temp_file(key) - return _codecs.open(file, encoding="utf-8", mode=mode) - -# This one is deleted on process exit -def make_temp_dir(): - return _tempfile.mkdtemp(prefix="_dir_", dir=_temp_dir) - -# This one sticks around -def make_user_temp_dir(): - temp_dir = _tempfile.gettempdir() - user = _getpass.getuser() - user_temp_dir = join(temp_dir, user) - - return make_dir(user_temp_dir) - -def copy(from_path, to_path): - notice("Copying '{0}' to '{1}'", from_path, to_path) - - to_dir = parent_dir(to_path) - - if to_dir: - make_dir(to_dir) - - if is_dir(from_path): - _copytree(from_path, to_path, symlinks=True) - else: - _shutil.copy(from_path, to_path) - - return to_path - -def move(from_path, to_path): - notice("Moving '{0}' to '{1}'", from_path, to_path) - - _shutil.move(from_path, to_path) - - return to_path - -def rename(path, expr, replacement): - path = normalize_path(path) - parent_dir, name = split(path) - to_name = string_replace(name, expr, replacement) - to_path = join(parent_dir, to_name) - - notice("Renaming '{0}' to '{1}'", path, to_path) - - move(path, to_path) - - return to_path - -def remove(path): - notice("Removing '{0}'", path) - - if not exists(path): - return - - if is_dir(path): - _shutil.rmtree(path, ignore_errors=True) - else: - _os.remove(path) - - return path - -def make_link(source_path, link_file): - if exists(link_file): - assert read_link(link_file) == source_path - return - - _os.symlink(source_path, link_file) - - return link_file - -def read_link(file): - return _os.readlink(file) - -def find(dir, *patterns): - matched_paths = set() - - if not patterns: - patterns = ("*",) - - for root, dirs, files in _os.walk(dir): - for pattern in patterns: - matched_dirs = _fnmatch.filter(dirs, pattern) - matched_files = _fnmatch.filter(files, pattern) - - matched_paths.update([join(root, x) for x in matched_dirs]) - matched_paths.update([join(root, x) for x in matched_files]) - - return sorted(matched_paths) - -def find_any_one(dir, *patterns): - paths = find(dir, *patterns) - - if len(paths) == 0: - return - - return paths[0] - -def find_only_one(dir, *patterns): - paths = find(dir, *patterns) - - if len(paths) == 0: - return - - assert len(paths) == 1 - - return paths[0] - -# find_via_expr? - -def string_replace(string, expr, replacement, count=0): - return _re.sub(expr, replacement, string, count) - -def make_dir(dir): - if not exists(dir): - _os.makedirs(dir) - - return dir - -# Returns the current working directory so you can change it back -def change_dir(dir): - notice("Changing directory to '{0}'", dir) - - cwd = current_dir() - _os.chdir(dir) - return cwd - -def list_dir(dir, *patterns): - assert is_dir(dir) - - names = _os.listdir(dir) - - if not patterns: - return sorted(names) - - matched_names = set() - - for pattern in patterns: - matched_names.update(_fnmatch.filter(names, pattern)) - - return sorted(matched_names) - -class working_dir(object): - def __init__(self, dir): - self.dir = dir - self.prev_dir = None - - def __enter__(self): - self.prev_dir = change_dir(self.dir) - return self.dir - - def __exit__(self, type, value, traceback): - change_dir(self.prev_dir) - -def _init_call(command, args, kwargs): - if args: - command = command.format(*args) - - if "shell" not in kwargs: - kwargs["shell"] = True - - notice("Calling '{0}'", command) - - return command, kwargs - -def call(command, *args, **kwargs): - command, kwargs = _init_call(command, args, kwargs) - _subprocess.check_call(command, **kwargs) - -def call_for_output(command, *args, **kwargs): - command, kwargs = _init_call(command, args, kwargs) - return _subprocess_check_output(command, **kwargs) - -def make_archive(input_dir, output_dir, archive_stem): - temp_dir = make_temp_dir() - temp_input_dir = join(temp_dir, archive_stem) - - copy(input_dir, temp_input_dir) - make_dir(output_dir) - - output_file = "{0}.tar.gz".format(join(output_dir, archive_stem)) - output_file = absolute_path(output_file) - - with working_dir(temp_dir): - call("tar -czf {0} {1}", output_file, archive_stem) - - return output_file - -def extract_archive(archive_file, output_dir): - assert is_file(archive_file) - - if not exists(output_dir): - make_dir(output_dir) - - archive_file = absolute_path(archive_file) - - with working_dir(output_dir): - call("tar -xf {0}", archive_file) - - return output_dir - -def rename_archive(archive_file, new_archive_stem): - assert is_file(archive_file) - - if name_stem(archive_file) == new_archive_stem: - return - - temp_dir = make_temp_dir() - - extract_archive(archive_file, temp_dir) - - input_name = list_dir(temp_dir)[0] - input_dir = join(temp_dir, input_name) - output_file = make_archive(input_dir, temp_dir, new_archive_stem) - output_name = file_name(output_file) - archive_dir = parent_dir(archive_file) - new_archive_file = join(archive_dir, output_name) - - move(output_file, new_archive_file) - remove(archive_file) - - return new_archive_file - -def random_port(min=49152, max=65535): - return _random.randint(min, max) - -# Modified copytree impl that allows for already existing destination -# dirs -def _copytree(src, dst, symlinks=False, ignore=None): - """Recursively copy a directory tree using copy2(). - - If exception(s) occur, an Error is raised with a list of reasons. - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. - - The optional ignore argument is a callable. If given, it - is called with the `src` parameter, which is the directory - being visited by copytree(), and `names` which is the list of - `src` contents, as returned by os.listdir(): - - callable(src, names) -> ignored_names - - Since copytree() is called recursively, the callable will be - called once for each directory that is copied. It returns a - list of names relative to the `src` directory that should - not be copied. - - XXX Consider this example code rather than the ultimate tool. - - """ - names = _os.listdir(src) - if ignore is not None: - ignored_names = ignore(src, names) - else: - ignored_names = set() - - if not exists(dst): - _os.makedirs(dst) - errors = [] - for name in names: - if name in ignored_names: - continue - srcname = _os.path.join(src, name) - dstname = _os.path.join(dst, name) - try: - if symlinks and _os.path.islink(srcname): - linkto = _os.readlink(srcname) - _os.symlink(linkto, dstname) - elif _os.path.isdir(srcname): - _copytree(srcname, dstname, symlinks, ignore) - else: - # Will raise a SpecialFileError for unsupported file types - _shutil.copy2(srcname, dstname) - # catch the Error from the recursive copytree so that we can - # continue with other files - except _shutil.Error as err: - errors.extend(err.args[0]) - except EnvironmentError as why: - errors.append((srcname, dstname, str(why))) - try: - _shutil.copystat(src, dst) - except OSError as why: - if _shutil.WindowsError is not None and isinstance \ - (why, _shutil.WindowsError): - # Copying file access times may fail on Windows - pass - else: - errors.append((src, dst, str(why))) - if errors: - raise _shutil.Error(errors) - -# For Python 2.6 compatibility -def _subprocess_check_output(command, **kwargs): - kwargs["stdout"] = _subprocess.PIPE - - proc = _subprocess.Popen(command, **kwargs) - output = proc.communicate()[0] - exit_code = proc.poll() - - if exit_code not in (None, 0): - error = _subprocess.CalledProcessError(exit_code, command) - error.output = output - - raise error - - return output diff --git a/qpid/cpp/src/tests/policies.py b/qpid/cpp/src/tests/policies.py deleted file mode 100644 index 265a04557f..0000000000 --- a/qpid/cpp/src/tests/policies.py +++ /dev/null @@ -1,136 +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. -# - -from qpid.tests.messaging.implementation import * -from qpid.tests.messaging import VersionTest -from mgmt_1 import Mgmt - -class PoliciesTests (VersionTest): - """ - Tests for node policies with qpidd - """ - - def do_simple_queue_test(self, pattern, name, properties={}, autodeleted=True): - mgmt = self.create_connection("amqp0-10", True) - agent = Mgmt(mgmt) - agent.create('QueuePolicy', pattern, properties) - try: - snd = self.ssn.sender(name) - msgs = [Message(content=s, subject = s) for s in ['a','b','c','d']] - for m in msgs: snd.send(m) - snd.close() - - for expected in msgs: - rcv = self.ssn.receiver(name) - msg = rcv.fetch(0) - assert msg.content == expected.content, (msg.content, expected.content) - self.ssn.acknowledge() - rcv.close() #close after each message to ensure queue isn't deleted with messages in it - self.ssn.close() - self.conn.close() - - matched = [q for q in agent.list("Queue") if q['name'] == name] - if autodeleted: - # ensure that queue is no longer there (as empty and unused) - assert len(matched) == 0, (matched) - else: - # ensure that queue is still there though empty and unused - assert len(matched) == 1, (matched) - finally: - agent.delete('QueuePolicy', pattern) - mgmt.close() - - def test_queue(self): - self.do_simple_queue_test("queue-*", "queue-1") - - def test_queue_not_autodeleted(self): - self.do_simple_queue_test("permanent-queue-*", "permanent-queue-1", {'auto-delete':False}, False) - - def test_queue_manual_delete(self): - self.do_simple_queue_test("permanent-queue-*", "permanent-queue-1", {'qpid.lifetime-policy':'manual'}, False) - - def test_queue_delete_if_unused_and_empty(self): - self.do_simple_queue_test("queue-*", "queue-1", {'qpid.lifetime-policy':'delete-if-unused-and-empty'}, True) - - def do_simple_topic_test(self, pattern, name, properties={}, autodeleted=True): - mgmt = self.create_connection("amqp0-10", True) - agent = Mgmt(mgmt) - agent.create('TopicPolicy', pattern, properties) - try: - snd = self.ssn.sender(name) - rcv1 = self.ssn.receiver(name) - rcv2 = self.ssn.receiver(name) - - msgs = [Message(content=s, subject = s) for s in ['a','b','c','d']] - for m in msgs: snd.send(m) - - for rcv in [rcv1, rcv2]: - for expected in msgs: - msg = rcv.fetch(0) - assert msg.content == expected.content, (msg.content, expected.content) - self.ssn.acknowledge() - rcv1.close() - rcv2.close() - snd.close() - - matched = [e for e in agent.list("Exchange") if e['name'] == name] - if autodeleted: - # ensure that exchange is no longer there (as it is now unused) - assert len(matched) == 0, (matched) - else: - # ensure that exchange has not been autodeleted in spite of being unused - assert len(matched) == 1, (matched) - finally: - agent.delete('TopicPolicy', pattern) - mgmt.close() - - def test_topic(self): - self.do_simple_topic_test('fanout-*', 'fanout-1', {'exchange-type':'fanout'}) - - def test_topic_not_autodelete(self): - self.do_simple_topic_test('permanent-fanout-*', 'permanent-fanout-1', {'exchange-type':'fanout', 'auto-delete':False}, False) - - def test_topic_manual_delete(self): - self.do_simple_topic_test('permanent-fanout-*', 'permanent-fanout-1', {'exchange-type':'fanout', 'qpid.lifetime-policy':'manual'}, False) - - def test_topic_delete_if_unused(self): - self.do_simple_topic_test('fanout-*', 'fanout-1', {'exchange-type':'fanout', 'qpid.lifetime-policy':'delete-if-unused'}, True) - - def test_mgmt(self): - mgmt = self.create_connection("amqp0-10", True) - agent = Mgmt(mgmt) - agent.create('QueuePolicy', 'queue-*') - agent.create('QueuePolicy', 'alt.queue.*') - agent.create('TopicPolicy', 'topic-*') - try: - queues = [q['name'] for q in agent.list("QueuePolicy")] - topics = [t['name'] for t in agent.list("TopicPolicy")] - assert 'queue-*' in queues, (queues) - assert 'alt.queue.*' in queues, (queues) - - try: - agent.delete('TopicPolicy', 'queue-*') - assert False, ('Deletion of policy using wrong type should fail') - except: None - - finally: - agent.delete('QueuePolicy', 'queue-*') - agent.delete('QueuePolicy', 'alt.queue.*') - agent.delete('TopicPolicy', 'topic-*') - mgmt.close() diff --git a/qpid/cpp/src/tests/policy.acl b/qpid/cpp/src/tests/policy.acl deleted file mode 100644 index 4c13ac75c1..0000000000 --- a/qpid/cpp/src/tests/policy.acl +++ /dev/null @@ -1,20 +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. -# - -acl allow all all diff --git a/qpid/cpp/src/tests/publish.cpp b/qpid/cpp/src/tests/publish.cpp deleted file mode 100644 index 3f456e7588..0000000000 --- a/qpid/cpp/src/tests/publish.cpp +++ /dev/null @@ -1,135 +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 -#include -#include -#include -#include - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using namespace std; - -namespace qpid { -namespace tests { - -typedef vector StringSet; - -struct Args : public qpid::TestOptions { - uint size; - uint count; - bool durable; - string destination; - string routingKey; - bool summary; - bool id; - - Args() : size(256), count(1000), durable(true), routingKey("publish-consume"), summary(false), id(false) { - addOptions() - ("size", optValue(size, "N"), "message size") - ("count", optValue(count, "N"), "number of messages to publish") - ("durable", optValue(durable, "yes|no"), "use durable messages") - ("destination", optValue(destination, ""), "destination to publish to") - ("routing-key", optValue(routingKey, ""), "routing key to publish with") - ("summary,s", optValue(summary), "Output only the rate.") - ("id", optValue(id), "Add unique correlation ID"); - } -}; - -Args opts; - -struct Client -{ - Connection connection; - AsyncSession session; - - Client() - { - opts.open(connection); - session = connection.newSession(); - } - - // Cheap hex calculation, avoid expensive ostrstream and string - // creation to generate correlation ids in message loop. - char hex(char i) { return i<10 ? '0'+i : 'A'+i-10; } - void hex(char i, string& s) { - s[0]=hex(i>>24); s[1]=hex(i>>16); s[2]=hex(i>>8); s[3]=i; - } - - void publish() - { - AbsTime begin=now(); - Message msg(string(opts.size, 'X'), opts.routingKey); - string correlationId = "0000"; - if (opts.durable) - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - - for (uint i = 0; i < opts.count; i++) { - if (opts.id) { - hex(i+1, correlationId); - msg.getMessageProperties().setCorrelationId(correlationId); - } - session.messageTransfer(arg::destination=opts.destination, - arg::content=msg, - arg::acceptMode=1); - } - session.sync(); - AbsTime end=now(); - double secs(double(Duration(begin,end))/TIME_SEC); - if (opts.summary) cout << opts.count/secs << endl; - else cout << "Time: " << secs << "s Rate: " << opts.count/secs << endl; - } - - ~Client() - { - try{ - session.close(); - connection.close(); - } catch(const exception& e) { - cout << e.what() << endl; - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - Client client; - client.publish(); - return 0; - } catch(const exception& e) { - cout << e.what() << endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/qpid-analyze-trace b/qpid/cpp/src/tests/qpid-analyze-trace deleted file mode 100755 index 009fbc441c..0000000000 --- a/qpid/cpp/src/tests/qpid-analyze-trace +++ /dev/null @@ -1,258 +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. -# - -import sys -from datetime import datetime -from optparse import OptionParser - -# Version of this tool software -MAJOR_VERSION = 1 -MINOR_VERSION = 1 -# === Version history === -# 2011-11-16 1.1: Bugfixs: -# QPID-3623 - Incorrect handling of transactions -# QPID-3624 - Replace argparse lib with optparse so tool can be used on Python 2.6. -# 2011-11-07 1.0: Initial checkin -# QPID-3579: Initial version checked in - - -# AMQP 0-10 commands - these increment the command counter -EXEC_COMMANDS = ["ExecutionSync", "ExecutionResult", "ExecutionException", "MessageTransfer", "MessageAccept", - "MessageReject", "MessageRelease", "MessageAcquire", "MessageResume", "MessageSubscribe", - "MessageCancel", "MessageSetFlowMode", "MessageFlow", "MessageFlush", "MessageStop", "TxSelect", - "TxCommit", "TxRollback", "DtxSelect", "DtxStart", "DtxEnd", "DtxCommit", "DtxForget", "DtxGetTimeout", - "DtxPrepare", "DtxRecover", "DtxRollback", "DtxSetTimeout", "ExchangeDeclare", "ExchangeDelete", - "ExchangeQuery", "ExchangeBind", "ExchangeUnbind", "ExchangeBound", "QueueDeclare", "QueueDelete", - "QueuePurge", "QueueQuery", "FileQos", "FileQosOk", "FileConsume", "FileConsumeOk", "FileCancel", - "FileOpen", "FileOpenOk", "FileStage", "FilePublish", "FileReturn", "FileDeliver", "FileAck", - "FileReject", "StreamQos", "StreamQosOk", "StreamConsume", "StreamConsumeOk", "StreamCancel", - "StreamPublish", "StreamReturn", "StreamDeliver"] -HEADER_STR = " -line ----------timestamp -----------connection ssn recv send- txn-- operation---------->" - -PROGRESS_LINES_PER_DOT = 100000 - -class LogLevel: - CRITICAL = (1, "critical") - ERROR = (2, "error") - WARNING = (3, "warning") - NOTICE = (4, "notice") - INFO = (5, "info") - DEBUG = (6, "debug") - TRACE = (7, "trace") - @staticmethod - def get_level(level): - if level == LogLevel.CRITICAL[1]: return LogLevel.CRITICAL - if level == LogLevel.ERROR[1]: return LogLevel.ERROR - if level == LogLevel.WARNING[1]: return LogLevel.WARNING - if level == LogLevel.NOTICE[1]: return LogLevel.NOTICE - if level == LogLevel.INFO[1]: return LogLevel.INFO - if level == LogLevel.DEBUG[1]: return LogLevel.DEBUG - if level == LogLevel.TRACE[1]: return LogLevel.TRACE - raise Exception("Unknown log level: %s" % level) - -class LogLine: - def __init__(self, line_no, line): - self.line_no = line_no - self.timestamp = datetime.strptime(line[:19], "%Y-%m-%d %H:%M:%S") - self.level = LogLevel.get_level(line[20:].split(" ")[0]) - self.line = line[21 + len(self.level[1]):].strip() - self.cmd_cnt = None - self.txn_cnt = None - def __str__(self): - if self.contains("RECV"): cnt_str = "R" - else: cnt_str = " S" - if self.cmd_cnt is not None: cnt_str += str(self.cmd_cnt) - set_index = self.find("{") - header_index = self.find("header") - content_index = self.find("content") - if self.txn_cnt is None: - txn_cnt_str = "" - else: - txn_cnt_str = "T%d" % self.txn_cnt - if header_index != -1 and header_index < set_index: op_str = " + " + self.line[header_index:self.line.rfind("]")] - elif content_index != -1 and set_index == -1: op_str = " + " + self.line[content_index:self.line.rfind("]")] - else: op_str = self.line[set_index+1:self.line.rfind("}")] - return " %7d %19s %22s %3d %-10s %-5s %s" % (self.line_no, self.timestamp.isoformat(" "), - self.get_identifier_remote_addr(), self.get_channel(), - cnt_str, txn_cnt_str, op_str) - def contains(self, string): - return self.line.find(string) != -1 - def find(self, string): - return self.line.find(string) - def get_channel(self): - return int(self.get_named_value("channel")) - def get_identifier(self): - return self.line.partition("[")[2].partition("]")[0] - def get_identifier_remote_addr(self): - return self.get_identifier().partition("-")[2] - def get_named_value(self, name): - return self.line.partition("%s=" % name)[2].partition(";")[0] - def get_msg_accept_range(self): - str_nums = self.get_named_value("transfers").strip(" {[]}").split(",") - return range(int(str_nums[0]), int(str_nums[1]) + 1) - def is_log_level(self, level): - if self.level is None: return None - return level[0] == self.level[0] - def is_frame(self): - return self.contains("Frame[") - -class ConnectionProperty: - def __init__(self, line): - self.addr = line.get_identifier_remote_addr() - self.channel = line.get_channel() - self.ops = [line] - def add_op(self, line): - self.ops.append(line) - -class Connection(ConnectionProperty): - def __init__(self, line): - ConnectionProperty.__init__(self, line) - self.session_list = [] # Keeps session creation order - self.session_dict = {} # For looking up by channel no. - def __str__(self): - return "Connection %s (ops=%d; sessions=%d):" % (self.addr, len(self.ops), len(self.session_dict)) - def add_session(self, session): - self.session_list.append(session) - self.session_dict[session.channel] = session - def get_session(self, channel): - return self.session_dict[channel] - -class Session(ConnectionProperty): - def __init__(self, line): - ConnectionProperty.__init__(self, line) - self.name = line.get_named_value("name") - self.send_cnt = 0 - self.recv_cnt = 0 - self.txn_flag = False - self.txn_cnt = 0 - self.recv_cmds = {} # For looking up by cmd no - self.send_cmds = {} # For looking up by cmd no - def __str__(self): - if self.txn_flag: - return " + Session %d (name=%s send-cmds=%d recv-cmds=%d txns=%d):" % (self.channel, self.name, - self.send_cnt, self.recv_cnt, - self.txn_cnt) - return " + Session %d (name=%s send-cmds=%d recv-cmds=%d non-txn):" % (self.channel, self.name, self.send_cnt, - self.recv_cnt) - def incr_recv_cnt(self, line): - self.recv_cmds[self.recv_cnt] = line - self.recv_cnt += 1 - def incr_send_cnt(self, line): - self.send_cmds[self.send_cnt] = line - self.send_cnt += 1 - def set_send_txn_cnt(self, cmd): - self.send_cmds[cmd].txn_cnt = self.txn_cnt - -class TraceAnalysis: - def __init__(self): - self.connection_list = [] # Keeps connection creation order - self.connection_dict = {} # For looking up by connection address - parser = OptionParser(usage="%prog [options] trace-file", version="%%prog %d.%d" % (MAJOR_VERSION, MINOR_VERSION), - description="A tool to structure and display Qpid broker trace logs.") - parser.add_option("--connection-summary", action="store_true", default=False, dest="connection_summary", - help="Hide connection details, provide one-line summary") - parser.add_option("--session-summary", action="store_true", default=False, dest="session_summary", - help="Hide session details, provide one-line summary") - parser.add_option("--summary", "-s", action="store_true", default=False, dest="summary", - help="Hide both connection and session details. Equivalent to --connection-summary and" - "--session-summary") - self.opts, self.args = parser.parse_args() - if len(self.args) == 0: raise Exception("Missing trace-file argument") - def analyze_trace(self): - lcnt = 0 - print "Reading trace file %s:" % self.args[0] - log_file = open(self.args[0], "r") - try: - for fline in log_file: - lcnt += 1 - try: - lline = LogLine(lcnt, fline) - if lline.is_log_level(LogLevel.TRACE) and lline.is_frame(): - if lline.contains("{ConnectionStartBody"): - conn = Connection(lline) - self.connection_list.append(conn) - self.connection_dict[conn.addr] = conn - elif lline.contains("{Connection"): - self.connection_dict[lline.get_identifier_remote_addr()].add_op(lline) - elif lline.contains("{SessionAttachBody"): - ssn = Session(lline) - self.connection_dict[ssn.addr].add_session(ssn) - else: - ssn = self.connection_dict[lline.get_identifier_remote_addr()].get_session(lline.get_channel()) - ssn.add_op(lline) - if lline.line[lline.find("{") + 1 : lline.find("Body")] in EXEC_COMMANDS: - if lline.contains("RECV"): - lline.cmd_cnt = ssn.recv_cnt - if ssn.txn_flag: - if lline.contains("MessageAcceptBody"): - lline.txn_cnt = ssn.txn_cnt - for cmd in lline.get_msg_accept_range(): - ssn.set_send_txn_cnt(cmd) - if lline.contains("MessageTransferBody"): lline.txn_cnt = ssn.txn_cnt - ssn.incr_recv_cnt(lline) - elif lline.contains("SEND") or lline.contains("SENT"): - lline.cmd_cnt = ssn.send_cnt - ssn.incr_send_cnt(lline) - # TODO: This treatment will probably break down for DTX - if lline.contains("xSelectBody"): - ssn.txn_flag = True - elif lline.contains("xCommitBody") or lline.contains("xRollbackBody"): - lline.txn_cnt = ssn.txn_cnt - ssn.txn_cnt += 1 - except KeyboardInterrupt, e: raise e - except: pass - if (lcnt + 1) % PROGRESS_LINES_PER_DOT == 0: - sys.stdout.write(".") - sys.stdout.flush() - finally: log_file.close() - if lcnt > PROGRESS_LINES_PER_DOT: print - print "Read and analyzed", lcnt, "lines." - def print_analysis(self): - if len(self.connection_list) > 0: - for c in self.connection_list: - print - print c - if not self.opts.connection_summary and not self.opts.summary: - print HEADER_STR - for o in c.ops: - print o - for s in c.session_list: - print s - if not self.opts.session_summary and not self.opts.summary: - print HEADER_STR - for o in s.ops: - print o - else: - print "No trace-level entries found in log." - -def check_python_version(major, minor, micro): - if sys.version_info < (major, minor, micro): - print "Incorrect Python version: %s found; >= %d.%d.%d needed." % (sys.version.split()[0], major, minor, micro) - sys.exit(-1) - -# === Main program === - -if __name__ == '__main__': - check_python_version(2, 4, 0) - t = TraceAnalysis() - t.analyze_trace() - t.print_analysis() - \ No newline at end of file diff --git a/qpid/cpp/src/tests/qpid-client-test.cpp b/qpid/cpp/src/tests/qpid-client-test.cpp deleted file mode 100644 index 9198324f93..0000000000 --- a/qpid/cpp/src/tests/qpid-client-test.cpp +++ /dev/null @@ -1,139 +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. - * - */ - -/** - * This file provides a simple test (and example) of basic - * functionality including declaring an exchange and a queue, binding - * these together, publishing a message and receiving that message - * asynchronously. - */ - -#include - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" - - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; -using std::string; - -namespace qpid { -namespace tests { - -struct Args : public TestOptions { - uint msgSize; - bool verbose; - - Args() : TestOptions("Simple test of Qpid c++ client; sends and receives a single message."), msgSize(26), verbose(false) - { - addOptions() - ("size", optValue(msgSize, "N"), "message size") - ("verbose", optValue(verbose), "print out some status messages"); - } -}; - -const std::string chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - -std::string generateData(uint size) -{ - if (size < chars.length()) { - return chars.substr(0, size); - } - std::string data; - for (uint i = 0; i < (size / chars.length()); i++) { - data += chars; - } - data += chars.substr(0, size % chars.length()); - return data; -} - -void print(const std::string& text, const Message& msg) -{ - std::cout << text; - if (msg.getData().size() > 16) { - std::cout << msg.getData().substr(0, 16) << "..."; - } else { - std::cout << msg.getData(); - } - std::cout << std::endl; -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - Args opts; - opts.parse(argc, argv); - - //Connect to the broker: - Connection connection; - opts.open(connection); - if (opts.verbose) std::cout << "Opened connection." << std::endl; - - //Create and open a session on the connection through which - //most functionality is exposed: - Session session = connection.newSession(); - if (opts.verbose) std::cout << "Opened session." << std::endl; - - - //'declare' the exchange and the queue, which will create them - //as they don't exist - session.exchangeDeclare(arg::exchange="MyExchange", arg::type="direct"); - if (opts.verbose) std::cout << "Declared exchange." << std::endl; - session.queueDeclare(arg::queue="MyQueue", arg::autoDelete=true, arg::exclusive=true); - if (opts.verbose) std::cout << "Declared queue." << std::endl; - - //now bind the queue to the exchange - session.exchangeBind(arg::exchange="MyExchange", arg::queue="MyQueue", arg::bindingKey="MyKey"); - if (opts.verbose) std::cout << "Bound queue to exchange." << std::endl; - - //create and send a message to the exchange using the routing - //key we bound our queue with: - Message msgOut(generateData(opts.msgSize)); - msgOut.getDeliveryProperties().setRoutingKey("MyKey"); - session.messageTransfer(arg::destination="MyExchange", arg::content=msgOut, arg::acceptMode=1); - if (opts.verbose) print("Published message: ", msgOut); - - // Using the SubscriptionManager, get the message from the queue. - SubscriptionManager subs(session); - Message msgIn = subs.get("MyQueue"); - if (msgIn.getData() == msgOut.getData()) - if (opts.verbose) std::cout << "Received the exepected message." << std::endl; - - //close the session & connection - session.close(); - if (opts.verbose) std::cout << "Closed session." << std::endl; - connection.close(); - if (opts.verbose) std::cout << "Closed connection." << std::endl; - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/qpid-cluster-benchmark b/qpid/cpp/src/tests/qpid-cluster-benchmark deleted file mode 100755 index f20ac6ac30..0000000000 --- a/qpid/cpp/src/tests/qpid-cluster-benchmark +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Benchmark script for comparing cluster performance. - -# Default options -MESSAGES="-m 10000" -REPEAT="--repeat 10" -QUEUES="-q 6" -SENDERS="-s 3" -RECEIVERS="-r 3" -BROKERS= # Local broker -CLIENT_HOSTS= # No ssh, all clients are local -# Connection options -TCP_NODELAY=false -RECONNECT=true -HEARTBEAT=1 - -while getopts "m:f:n:b:q:s:r:c:h:i:txyv-" opt; do - case $opt in - b) BROKERS="-b $OPTARG";; - c) CLIENT_HOSTS="-c $OPTARG";; - h) HEARTBEAT=$OPTARG;; - i) RECONNECT=$OPTARG;; - m) MESSAGES="-m $OPTARG";; - n) REPEAT="--repeat $OPTARG";; - q) QUEUES="-q $OPTARG";; - r) RECEIVERS="-r $OPTARG";; - s) SENDERS="-s $OPTARG";; - t) TCP_NODELAY=true;; - v) OPTS="--verbose";; - x) SAVE_RECEIVED="--save-received";; - y) NO_DELETE="--no-delete";; - -) break ;; - *) echo "Unknown option"; exit 1;; - esac -done -shift $(($OPTIND-1)) - -CONNECTION_OPTIONS="--connection-options {tcp-nodelay:$TCP_NODELAY,reconnect:$RECONNECT,heartbeat:$HEARTBEAT}" - -BROKER=$(echo $BROKERS | sed s/,.*//) -run_test() { echo $*; shift; "$@"; echo; echo; echo; } - -OPTS="$OPTS $REPEAT $BROKERS --summarize $QUEUES $SENDERS $RECEIVERS $MESSAGES $CLIENT_HOSTS $SAVE_RECEIVED $CONNECTION_OPTIONS $NO_DELETE" - -run_test "Benchmark:" qpid-cpp-benchmark $OPTS "$@" diff --git a/qpid/cpp/src/tests/qpid-cpp-benchmark b/qpid/cpp/src/tests/qpid-cpp-benchmark deleted file mode 100755 index 3a5419de5e..0000000000 --- a/qpid/cpp/src/tests/qpid-cpp-benchmark +++ /dev/null @@ -1,366 +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. -# - -import optparse, time, re, os - -try: - import qpid_messaging as qm -except ImportError: - qpid_messaging = None - import qpid.messaging as qm - -from threading import Thread -from subprocess import Popen, PIPE, STDOUT - -op = optparse.OptionParser(usage="usage: %prog [options]", - description="simple performance benchmarks") -op.add_option("-b", "--broker", default=[], action="append", type="str", - help="url of broker(s) to connect to, round robin on multiple brokers") -op.add_option("-c", "--client-host", default=[], action="append", type="str", - help="host(s) to run clients on via ssh, round robin on mulple hosts") -op.add_option("-q", "--queues", default=1, type="int", metavar="N", - help="create N queues (default %default)") -op.add_option("-s", "--senders", default=1, type="int", metavar="N", - help="start N senders per queue (default %default)") -op.add_option("-r", "--receivers", default=1, type="int", metavar="N", - help="start N receivers per queue (default %default)") -op.add_option("-m", "--messages", default=100000, type="int", metavar="N", - help="send N messages per sender (default %default)") -op.add_option("--queue-name", default="benchmark", metavar="NAME", - help="base name for queues (default %default)") -op.add_option("--send-rate", default=0, metavar="N", - help="send rate limited to N messages/second, 0 means no limit (default %default)") -op.add_option("--receive-rate", default=0, metavar="N", - help="receive rate limited to N messages/second, 0 means no limit (default %default)") -op.add_option("--content-size", default=1024, type="int", metavar="BYTES", - help="message size in bytes (default %default)") -op.add_option("--ack-frequency", default=100, metavar="N", type="int", - help="receiver ack's every N messages, 0 means unconfirmed (default %default)") -op.add_option("--tx", default=0, metavar="N", type="int", - help="Transaction batch size, 0 means no transactions") -op.add_option("--no-report-header", dest="report_header", default=True, - action="store_false", help="don't print header on report") -op.add_option("--summarize", default=False, action="store_true", - help="print summary statistics for multiple senders/receivers: total throughput, average latency") -op.add_option("--repeat", default=1, metavar="N", help="repeat N times", type="int") -op.add_option("--send-option", default=[], action="append", type="str", - help="Additional option for sending addresses") -op.add_option("--receive-option", default=[], action="append", type="str", - help="Additional option for receiving addresses") -op.add_option("--create-option", default=[], action="append", type="str", - help="Additional option for creating addresses") -op.add_option("--send-arg", default=[], action="append", type="str", - help="Additional argument for qpid-send") -op.add_option("--receive-arg", default=[], action="append", type="str", - help="Additional argument for qpid-receive") -op.add_option("--no-timestamp", dest="timestamp", default=True, - action="store_false", help="don't add a timestamp, no latency results") -op.add_option("--sequence", dest="sequence", default=False, - action="store_true", help="add a sequence number to each message") -op.add_option("--connection-options", type="str", - help="Connection options for senders & receivers") -op.add_option("--durable", default=False, action="store_true", - help="Use durable queues and messages") -op.add_option("-t", "--timeout", default=1.0, type="float", metavar="SECONDS", - help="Timeout for fetch operations (default %default)") -op.add_option("--save-received", default=False, action="store_true", - help="Save received message content to files -receiver-.msg") -op.add_option("--verbose", default=False, action="store_true", - help="Show commands executed") -op.add_option("--fill-drain", default=False, action="store_true", - help="First fill the queues, then drain them") -op.add_option("--qpid-send-path", default="", type="str", metavar="PATH", - help="path to qpid-send binary") -op.add_option("--qpid-receive-path", default="", type="str", metavar="PATH", - help="path to qpid-receive binary") - -single_quote_re = re.compile("'") -def posix_quote(string): - """ Quote a string for use as an argument in a posix shell""" - return "'" + single_quote_re.sub("\\'", string) + "'"; - -def ssh_command(host, command): - """ Convert command into an ssh command on host with quoting""" - return ["ssh", host] + [posix_quote(arg) for arg in command] - -class Clients: - def __init__(self): self.clients=[] - - def add(self, client): - self.clients.append(client) - return client - - def kill(self): - for c in self.clients: - try: c.kill() - except: pass - -class PopenCommand(Popen): - """Like Popen but you can query for the command""" - def __init__(self, command, *args, **kwargs): - self.command = command - Popen.__init__(self, command, *args, **kwargs) - -clients = Clients() - -def start_receive(queue, index, opts, ready_queue, broker, host): - address_opts=opts.receive_option - if opts.durable: address_opts += ["node:{durable:true}"] - address="%s;{%s}"%(queue,",".join(address_opts)) - msg_total=opts.senders*opts.messages - messages = msg_total/opts.receivers; - if (index < msg_total%opts.receivers): messages += 1 - if (messages == 0): return None - command = [os.path.join(opts.qpid_receive_path, "qpid-receive"), - "-b", broker, - "-a", address, - "-m", str(messages), - "--forever", - "--print-content=no", - "--receive-rate", str(opts.receive_rate), - "--report-total", - "--ack-frequency", str(opts.ack_frequency), - "--ready-address", "%s;{create:always}"%ready_queue, - "--report-header=no", - "--tx=%s" % opts.tx - ] - if opts.save_received: - command += ["--save-content=%s-receiver-%s.msg"%(queue,index)] - command += opts.receive_arg - if opts.connection_options: - command += ["--connection-options",opts.connection_options] - if host: command = ssh_command(host, command) - if opts.verbose: print "Receiver: ", command - return clients.add(PopenCommand(command, stdout=PIPE, stderr=PIPE)) - -def start_send(queue, opts, broker, host): - address="%s;{%s}"%(queue,",".join(opts.send_option + ["create:always"])) - command = [os.path.join(opts.qpid_send_path, "qpid-send"), - "-b", broker, - "-a", address, - "--messages", str(opts.messages), - "--content-size", str(opts.content_size), - "--send-rate", str(opts.send_rate), - "--report-total", - "--report-header=no", - "--timestamp=%s"%(opts.timestamp and "yes" or "no"), - "--sequence=%s"%(opts.sequence and "yes" or "no"), - "--durable=%d" % opts.durable, - "--tx=%s" % opts.tx - ] - command += opts.send_arg - if opts.connection_options: - command += ["--connection-options",opts.connection_options] - if host: command = ssh_command(host, command) - if opts.verbose: print "Sender: ", command - return clients.add(PopenCommand(command, stdout=PIPE, stderr=PIPE)) - -def error_msg(out, err): - return ("\n[stdout]\n%s\n[stderr]\n%s[end]"%(out, err)) - -def first_line(p): - out,err=p.communicate() - if p.returncode != 0: - raise Exception("Process exit %d: %s"%(p.returncode, error_msg(out,err))) - return out.split("\n")[0] - -def connect(broker, opts): - if opts.connection_options: - copts = dict([kv.strip().split(":") for kv in opts.connection_options.strip("{}").split(",")]) - else: - copts = {} - return qm.Connection.establish(broker, **copts) - -def drain(queue, session, opts): - """ - Drain a queue to make sure it is empty. Throw away the messages. - """ - if opts.verbose: print "Draining", queue - r = session.receiver(queue, capacity=1000) - n = 0 - try: - while True: - # FIXME aconway 2014-11-21: activemq broker does not respect the drain flag - # so fetch on an empty queue will hang forever, use get with timeout instead. - # r.fetch(timeout=0) - m = qm.Message() - r.get(timeout=opts.timeout) - n += 1 - if n % 500 == 0: r.session.acknowledge() - r.session.acknowledge() - except qm.Empty: - pass - r.close() - if opts.verbose: print "Drained", queue, n - -def clear_queues(queues, brokers, opts): - c = connect(brokers[0], opts) - for q in queues: - s = c.session() - need_drain = False - try: - s.sender("%s;{delete:always}"%(q)).close() - if opts.verbose: print "Deleted", q - except qm.NotFound: - s = c.session() - except qm.AddressError: - need_drain = True # AMQP 1.0 does not support delete, drain instead. - s = c.session() - address_opts = ["create:always"] - if opts.durable: address_opts += ["node:{durable:true}"] - address = "%s;{%s}"%(q, ",".join(opts.create_option + address_opts)) - if opts.verbose: print "Declaring", address - s.sender(address) - if need_drain: drain(q, s, opts) - c.close() - -def print_header(timestamp): - if timestamp: latency_header="\tl-min\tl-max\tl-avg\ttotal-tp" - else: latency_header="" - print "send-tp\trecv-tp%s"%latency_header - -def parse(parser, lines): # Parse sender/receiver output - return [map(lambda p: p[0](p[1]), zip(parser,line.split())) for line in lines] - -def parse_senders(senders): - return parse([int],[first_line(p) for p in senders]) - -def parse_receivers(receivers): - return parse([int,float,float,float],[first_line(p) for p in receivers if p]) - -def print_data(send_stats, recv_stats, total_tp): - for send,recv in map(None, send_stats, recv_stats): - line="" - if send: line += "%d"%send[0] - if recv: - line += "\t%d"%recv[0] - if len(recv) == 4: line += "\t%.2f\t%.2f\t%.2f"%tuple(recv[1:]) - if total_tp is not None: - line += "\t%d"%total_tp - total_tp = None - print line - -def print_summary(send_stats, recv_stats, total_tp): - def avg(s): sum(s) / len(s) - send_tp = sum([l[0] for l in send_stats]) - recv_tp = sum([l[0] for l in recv_stats]) - summary = "%d\t%d"%(send_tp, recv_tp) - if recv_stats and len(recv_stats[0]) == 4: - l_min = sum(l[1] for l in recv_stats)/len(recv_stats) - l_max = sum(l[2] for l in recv_stats)/len(recv_stats) - l_avg = sum(l[3] for l in recv_stats)/len(recv_stats) - summary += "\t%.2f\t%.2f\t%.2f"%(l_min, l_max, l_avg) - summary += "\t%d"%total_tp - print summary - - -class ReadyReceiver: - """A receiver for ready messages""" - def __init__(self, queue, broker, opts): - self.connection = connect(broker, opts) - self.receiver = self.connection.session().receiver(queue) - self.receiver.session.sync() - self.timeout=opts.timeout - - def wait(self, receivers): - try: - for i in receivers: self.receiver.fetch(self.timeout) - self.receiver.session.acknowledge() - self.connection.close() - except qm.Empty: - for r in receivers: - if (r.poll() is not None): - out,err=r.communicate() - raise Exception("Receiver error: %s\n%s" % - (" ".join(r.command), error_msg(out,err))) - raise Exception("Timed out waiting for receivers to be ready") - -def flatten(l): - return sum(map(lambda s: re.split(re.compile("\s*,\s*|\s+"), s), l), []) - -class RoundRobin: - def __init__(self,items): - self.items = items - self.index = 0 - - def next(self): - if not self.items: return None - ret = self.items[self.index] - self.index = (self.index+1)%len(self.items) - return ret - -def main(): - opts, args = op.parse_args() - opts.client_host = flatten(opts.client_host) - if not opts.broker: - if opts.client_host: - raise Exception("--broker must be specified if --client_host is.") - opts.broker = ["127.0.0.1"] # Deafult to local broker - opts.broker = flatten(opts.broker) - brokers = RoundRobin(opts.broker) - client_hosts = RoundRobin(opts.client_host) - send_out = "" - receive_out = "" - ready_queue="%s-ready"%(opts.queue_name) - queues = ["%s-%s"%(opts.queue_name, i) for i in xrange(opts.queues)] - try: - for i in xrange(opts.repeat): - clear_queues(queues+[ready_queue], opts.broker, opts) - ready_receiver = ReadyReceiver(ready_queue, opts.broker[0], opts) - - def start_receivers(): - return [ start_receive(q, j, opts, ready_queue, brokers.next(), client_hosts.next()) - for q in queues for j in xrange(opts.receivers) ] - - - def start_senders(): - return [ start_send(q, opts,brokers.next(), client_hosts.next()) - for q in queues for j in xrange(opts.senders) ] - - if opts.report_header and i == 0: print_header(opts.timestamp) - - if opts.fill_drain: - # First fill the queues, then drain them - start = time.time() - senders = start_senders() - for p in senders: - if p: p.wait() - receivers = start_receivers() - for p in receivers: - if p: p.wait() - else: - # Run senders and receivers in parallel - receivers = start_receivers() - ready_receiver.wait(filter(None, receivers)) # Wait for receivers ready - start = time.time() - senders = start_senders() - for p in senders + receivers: - if p: p.wait() - - total_sent = opts.queues * opts.senders * opts.messages - total_tp = total_sent / (time.time()-start) - send_stats=parse_senders(senders) - recv_stats=parse_receivers(receivers) - if opts.summarize: print_summary(send_stats, recv_stats, total_tp) - else: print_data(send_stats, recv_stats, total_tp) - finally: clients.kill() # No strays - -if __name__ == "__main__": main() - diff --git a/qpid/cpp/src/tests/qpid-ctrl b/qpid/cpp/src/tests/qpid-ctrl deleted file mode 100755 index 4246c57898..0000000000 --- a/qpid/cpp/src/tests/qpid-ctrl +++ /dev/null @@ -1,120 +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. -# - -import optparse -from qpid.messaging import * -from qpid.util import URL -from qpid.log import enable, DEBUG, WARN - -def nameval(st): - idx = st.find("=") - if idx >= 0: - name = st[0:idx] - value = st[idx+1:] - else: - name = st - value = None - return name, value - -def list_map_entries(m): - r = "" - for t in m: - r += "%s=%s " % (t, m[t]) - return r - -def get_qmfv2_result(m): - if m.properties['x-amqp-0-10.app-id'] == 'qmf2': - if m.properties['qmf.opcode'] == '_method_response': - return m.content['_arguments'] - elif m.properties['qmf.opcode'] == '_exception': - raise Exception("Error: %s" % list_map_entries(m.content['_values'])) - else: raise Exception("Invalid response received, unexpected opcode: %s" % m) - else: raise Exception("Invalid response received, not a qmfv2 method: %s" % m) - - -parser = optparse.OptionParser(usage="usage: %prog [options] COMMAND ...", - description="Invoke the specified command.") -parser.add_option("-b", "--broker", default="localhost", - help="connect to specified BROKER (default %default)") -parser.add_option("-c", "--class", dest="qmfclass", default="broker", - help="class of object on which command is being invoked (default %default)") -parser.add_option("-p", "--package", default="org.apache.qpid.broker", - help="package of object on which command is being invoked (default %default)") -parser.add_option("-i", "--id", default="amqp-broker", - help="identifier of object on which command is being invoked (default %default)") -parser.add_option("-a", "--address", default="qmf.default.direct/broker", - help="address to send commands to (default %default)") -parser.add_option("-t", "--timeout", type="float", default=5, - help="timeout in seconds to wait for response before exiting (default %default)") -parser.add_option("-v", dest="verbose", action="store_true", - help="enable logging") - -opts, args = parser.parse_args() - -if opts.verbose: - enable("qpid", DEBUG) -else: - enable("qpid", WARN) - -if args: - command = args.pop(0) -else: - parser.error("command is required") - - -conn = Connection(opts.broker) -try: - conn.open() - ssn = conn.session() - snd = ssn.sender(opts.address) - reply_to = "qmf.default.direct/%s; {node: {type: topic}}" % str(uuid4()) - rcv = ssn.receiver(reply_to) - - object_name = "%s:%s:%s" % (opts.package, opts.qmfclass, opts.id) - method_name = command - arguments = {} - for a in args: - name, val = nameval(a) - if val[0] == '{' or val[0] == '[': - arguments[name] = eval(val) - else: - arguments[name] = val - content = { - "_object_id": {"_object_name": object_name}, - "_method_name": method_name, - "_arguments": arguments - } - msg = Message(reply_to=reply_to, content=content) - msg.properties["x-amqp-0-10.app-id"] = "qmf2" - msg.properties["qmf.opcode"] = "_method_request" - snd.send(msg) - - try: - print list_map_entries(get_qmfv2_result(rcv.fetch(timeout=opts.timeout))) - except Empty: - print "No response received!" - except Exception, e: - print e -except ReceiverError, e: - print e -except KeyboardInterrupt: - pass - -conn.close() diff --git a/qpid/cpp/src/tests/qpid-latency-test.cpp b/qpid/cpp/src/tests/qpid-latency-test.cpp deleted file mode 100644 index a03963467b..0000000000 --- a/qpid/cpp/src/tests/qpid-latency-test.cpp +++ /dev/null @@ -1,480 +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 -#include -#include -#include -#include -#include - -#include "TestOptions.h" -#include "qpid/sys/Thread.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/sys/Time.h" - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - -namespace qpid { -namespace tests { - -typedef std::vector StringSet; - -struct Args : public qpid::TestOptions { - uint size; - uint count; - uint rate; - bool sync; - uint reportFrequency; - uint timeLimit; - uint concurrentConnections; - uint prefetch; - uint ack; - bool cumulative; - bool csv; - bool durable; - string base; - bool singleConnect; - - Args() : size(256), count(1000), rate(0), reportFrequency(1000), - timeLimit(0), concurrentConnections(1), - prefetch(100), ack(0), - durable(false), base("latency-test"), singleConnect(false) - - { - addOptions() - - ("size", optValue(size, "N"), "message size") - ("concurrentTests", optValue(concurrentConnections, "N"), "number of concurrent test setups, will create another publisher,\ - subcriber, queue, and connections") - ("single-connection", optValue(singleConnect, "yes|no"), "Use one connection for multiple sessions.") - ("count", optValue(count, "N"), "number of messages to send") - ("rate", optValue(rate, "N"), "target message rate (causes count to be ignored)") - ("sync", optValue(sync), "send messages synchronously") - ("report-frequency", optValue(reportFrequency, "N"), - "number of milliseconds to wait between reports (ignored unless rate specified)") - ("time-limit", optValue(timeLimit, "N"), - "test duration, in seconds") - ("prefetch", optValue(prefetch, "N"), "prefetch count (0 implies no flow control, and no acking)") - ("ack", optValue(ack, "N"), "Ack frequency in messages (defaults to half the prefetch value)") - ("durable", optValue(durable, "yes|no"), "use durable messages") - ("csv", optValue(csv), "print stats in csv format (rate,min,max,avg)") - ("cumulative", optValue(cumulative), "cumulative stats in csv format") - ("queue-base-name", optValue(base, ""), "base name for queues"); - } -}; - -const std::string chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - -Args opts; -double c_min, c_avg, c_max; -Connection globalConnection; - -uint64_t current_time() -{ - return Duration::FromEpoch(); -} - -struct Stats -{ - Mutex lock; - uint count; - double minLatency; - double maxLatency; - double totalLatency; - - Stats(); - void update(double l); - void print(); - void reset(); -}; - -class Client : public Runnable -{ -protected: - Connection* connection; - Connection localConnection; - AsyncSession session; - Thread thread; - string queue; - -public: - Client(const string& q); - virtual ~Client(); - - void start(); - void join(); - void run(); - virtual void test() = 0; -}; - -class Receiver : public Client, public MessageListener -{ - SubscriptionManager mgr; - uint count; - Stats& stats; - -public: - Receiver(const string& queue, Stats& stats); - void test(); - void received(Message& msg); - Stats getStats(); - uint getCount() { return count; } - void stop() { mgr.stop(); mgr.cancel(queue); } -}; - - -class Sender : public Client -{ - string generateData(uint size); - void sendByRate(); - void sendByCount(); - Receiver& receiver; - const string data; - -public: - Sender(const string& queue, Receiver& receiver); - void test(); -}; - - -class Test -{ - const string queue; - Stats stats; - Receiver receiver; - Sender sender; - AbsTime begin; - -public: - Test(const string& q) : queue(q), receiver(queue, stats), sender(queue, receiver), begin(now()) {} - void start(); - void join(); - void report(); -}; - - -Client::Client(const string& q) : queue(q) -{ - if (opts.singleConnect){ - connection = &globalConnection; - if (!globalConnection.isOpen()) opts.open(globalConnection); - }else{ - connection = &localConnection; - opts.open(localConnection); - } - session = connection->newSession(); -} - -void Client::start() -{ - thread = Thread(this); -} - -void Client::join() -{ - thread.join(); -} - -void Client::run() -{ - try{ - test(); - } catch(const std::exception& e) { - std::cout << "Error in receiver: " << e.what() << std::endl; - } -} - -Client::~Client() -{ - try{ - session.close(); - connection->close(); - } catch(const std::exception& e) { - std::cout << "Error in receiver: " << e.what() << std::endl; - } -} - -Receiver::Receiver(const string& q, Stats& s) : Client(q), mgr(session), count(0), stats(s) -{ - session.queueDeclare(arg::queue=queue, arg::durable=opts.durable, arg::autoDelete=true); - uint msgCount = session.queueQuery(arg::queue=queue).get().getMessageCount(); - if (msgCount) { - std::cout << "Warning: found " << msgCount << " msgs on " << queue << ". Purging..." << std::endl; - session.queuePurge(arg::queue=queue); - session.sync(); - } - SubscriptionSettings settings; - if (opts.prefetch) { - settings.autoAck = (opts.ack ? opts.ack : (opts.prefetch / 2)); - settings.flowControl = FlowControl::messageWindow(opts.prefetch); - } else { - settings.acceptMode = ACCEPT_MODE_NONE; - settings.flowControl = FlowControl::unlimited(); - } - mgr.subscribe(*this, queue, settings); -} - -void Receiver::test() -{ - mgr.run(); - mgr.cancel(queue); -} - -void Receiver::received(Message& msg) -{ - ++count; - uint64_t receivedAt = current_time(); - uint64_t sentAt = msg.getDeliveryProperties().getTimestamp(); - - stats.update(((double) (receivedAt - sentAt)) / TIME_MSEC); - - if (!opts.rate && count >= opts.count) { - mgr.stop(); - } -} - -void Stats::update(double latency) -{ - Mutex::ScopedLock l(lock); - count++; - minLatency = std::min(minLatency, latency); - maxLatency = std::max(maxLatency, latency); - totalLatency += latency; -} - -Stats::Stats() : count(0), minLatency(std::numeric_limits::max()), maxLatency(0), totalLatency(0) {} - -void Stats::print() -{ - static bool already_have_stats = false; - uint value; - - if (opts.rate) - value = opts.rate; - else - value = opts.count; - Mutex::ScopedLock l(lock); - double aux_avg = (totalLatency / count); - if (!opts.cumulative) { - if (!opts.csv) { - if (count) { - std::cout << "Latency(ms): min=" << minLatency << ", max=" << - maxLatency << ", avg=" << aux_avg; - } else { - std::cout << "Stalled: no samples for interval"; - } - } else { - if (count) { - std::cout << value << "," << minLatency << "," << maxLatency << - "," << aux_avg; - } else { - std::cout << value << "," << minLatency << "," << maxLatency << - ", Stalled"; - } - } - } else { - if (count) { - if (already_have_stats) { - c_avg = (c_min + aux_avg) / 2; - if (c_min > minLatency) c_min = minLatency; - if (c_max < maxLatency) c_max = maxLatency; - } else { - c_avg = aux_avg; - c_min = minLatency; - c_max = maxLatency; - already_have_stats = true; - } - std::cout << value << "," << c_min << "," << c_max << - "," << c_avg; - } else { - std::cout << "Stalled: no samples for interval"; - } - } -} - -void Stats::reset() -{ - Mutex::ScopedLock l(lock); - count = 0; - totalLatency = maxLatency = 0; - minLatency = std::numeric_limits::max(); -} - -Sender::Sender(const string& q, Receiver& receiver) : Client(q), receiver(receiver), data(generateData(opts.size)) {} - -void Sender::test() -{ - if (opts.rate) sendByRate(); - else sendByCount(); -} - -void Sender::sendByCount() -{ - Message msg(data, queue); - if (opts.durable) { - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - - for (uint i = 0; i < opts.count; i++) { - uint64_t sentAt(current_time()); - msg.getDeliveryProperties().setTimestamp(sentAt); - async(session).messageTransfer(arg::content=msg, arg::acceptMode=1); - if (opts.sync) session.sync(); - } - session.sync(); -} - -void Sender::sendByRate() -{ - Message msg(data, queue); - if (opts.durable) { - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - uint64_t interval = TIME_SEC/opts.rate; - int64_t timeLimit = opts.timeLimit * TIME_SEC; - uint64_t sent = 0; - AbsTime start = now(); - AbsTime last = start; - while (true) { - AbsTime sentAt=now(); - msg.getDeliveryProperties().setTimestamp(Duration::FromEpoch()); - async(session).messageTransfer(arg::content=msg, arg::acceptMode=1); - if (opts.sync) session.sync(); - ++sent; - if (Duration(last, sentAt) > (opts.reportFrequency*TIME_MSEC)) { - Duration t(start, now()); - //check rate actually achieved thus far - if (t/TIME_SEC) { - uint actualRate = sent / (t/TIME_SEC); - //report inability to stay within 1% of desired rate - if (actualRate < opts.rate && opts.rate - actualRate > opts.rate/100) { - std::cerr << "WARNING: Desired send rate: " << opts.rate << ", actual send rate: " << actualRate << std::endl; - } - } - last = sentAt; - } - - AbsTime waitTill(start, sent*interval); - Duration delay(sentAt, waitTill); - if (delay > 0) - sys::usleep(delay / TIME_USEC); - if (timeLimit != 0 && Duration(start, now()) > timeLimit) { - session.sync(); - receiver.stop(); - break; - } - } -} - -string Sender::generateData(uint size) -{ - if (size < chars.length()) { - return chars.substr(0, size); - } - std::string data; - for (uint i = 0; i < (size / chars.length()); i++) { - data += chars; - } - data += chars.substr(0, size % chars.length()); - return data; -} - - -void Test::start() -{ - receiver.start(); - begin = AbsTime(now()); - sender.start(); -} - -void Test::join() -{ - sender.join(); - receiver.join(); - AbsTime end = now(); - Duration time(begin, end); - double msecs(time / TIME_MSEC); - if (!opts.csv) { - std::cout << "Sent " << receiver.getCount() << " msgs through " << queue - << " in " << msecs << "ms (" << (receiver.getCount() * 1000 / msecs) << " msgs/s) "; - } - stats.print(); - std::cout << std::endl; -} - -void Test::report() -{ - stats.print(); - std::cout << std::endl; - stats.reset(); -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - if (opts.cumulative) - opts.csv = true; - - Connection localConnection; - AsyncSession session; - - boost::ptr_vector tests(opts.concurrentConnections); - for (uint i = 0; i < opts.concurrentConnections; i++) { - std::ostringstream out; - out << opts.base << "-" << (i+1); - tests.push_back(new Test(out.str())); - } - for (boost::ptr_vector::iterator i = tests.begin(); i != tests.end(); i++) { - i->start(); - } - if (opts.rate && !opts.timeLimit) { - while (true) { - qpid::sys::usleep(opts.reportFrequency * 1000); - //print latency report: - for (boost::ptr_vector::iterator i = tests.begin(); i != tests.end(); i++) { - i->report(); - } - } - } else { - for (boost::ptr_vector::iterator i = tests.begin(); i != tests.end(); i++) { - i->join(); - } - } - - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/qpid-perftest.cpp b/qpid/cpp/src/tests/qpid-perftest.cpp deleted file mode 100644 index b26b76015f..0000000000 --- a/qpid/cpp/src/tests/qpid-perftest.cpp +++ /dev/null @@ -1,760 +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 "TestOptions.h" -#include "qpid/OptionsTemplates.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Completion.h" -#include "qpid/client/Message.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -using namespace std; -using namespace qpid; -using namespace client; -using namespace sys; -using boost::lexical_cast; -using boost::bind; - -namespace qpid { -namespace tests { - -enum Mode { SHARED, FANOUT, TOPIC }; -const char* modeNames[] = { "shared", "fanout", "topic" }; - -// istream/ostream ops so Options can read/display Mode. -istream& operator>>(istream& in, Mode& mode) { - string s; - in >> s; - int i = find(modeNames, modeNames+3, s) - modeNames; - if (i >= 3) throw Exception("Invalid mode: "+s); - mode = Mode(i); - return in; -} - -ostream& operator<<(ostream& out, Mode mode) { - return out << modeNames[mode]; -} - -struct Opts : public TestOptions { - - // Actions - bool setup, control, publish, subscribe; - - // Queue policy - uint32_t queueMaxCount; - uint64_t queueMaxSize; - std::string baseName; - bool queueDurable; - - // Publisher - size_t pubs; - size_t count ; - size_t size; - size_t headers; - bool confirm; - bool durable; - bool uniqueData; - bool syncPub; - - // Subscriber - size_t subs; - size_t ack; - - // General - size_t qt; - bool singleConnect; - size_t iterations; - Mode mode; - bool summary; - uint32_t intervalSub; - uint32_t intervalPub; - size_t tx; - size_t txPub; - size_t txSub; - bool commitAsync; - - static const std::string helpText; - - Opts() : - TestOptions(helpText), - setup(false), control(false), publish(false), subscribe(false), baseName("qpid-perftest"), - pubs(1), count(500000), size(1024), headers(0), confirm(true), durable(false), uniqueData(false), syncPub(false), - subs(1), ack(0), - qt(1),singleConnect(false), iterations(1), mode(SHARED), summary(false), - intervalSub(0), intervalPub(0), tx(0), txPub(0), txSub(0), commitAsync(false) - { - addOptions() - ("setup", optValue(setup), "Create shared queues.") - ("control", optValue(control), "Run test, print report.") - ("publish", optValue(publish), "Publish messages.") - ("subscribe", optValue(subscribe), "Subscribe for messages.") - - ("mode", optValue(mode, "shared|fanout|topic"), "Test mode." - "\nshared: --qt queues, --npubs publishers and --nsubs subscribers per queue.\n" - "\nfanout: --npubs publishers, --nsubs subscribers, fanout exchange." - "\ntopic: --qt topics, --npubs publishers and --nsubs subscribers per topic.\n") - - ("npubs", optValue(pubs, "N"), "Create N publishers.") - ("count", optValue(count, "N"), "Each publisher sends N messages.") - ("size", optValue(size, "BYTES"), "Size of messages in bytes.") - ("headers", optValue(headers, "N"), "Number of headers to add to each message.") - ("pub-confirm", optValue(confirm, "yes|no"), "Publisher use confirm-mode.") - ("durable", optValue(durable, "yes|no"), "Publish messages as durable.") - ("unique-data", optValue(uniqueData, "yes|no"), "Make data for each message unique.") - ("sync-publish", optValue(syncPub, "yes|no"), "Wait for confirmation of each message before sending the next one.") - - ("nsubs", optValue(subs, "N"), "Create N subscribers.") - ("sub-ack", optValue(ack, "N"), "N>0: Subscriber acks batches of N.\n" - "N==0: Subscriber uses unconfirmed mode") - - ("qt", optValue(qt, "N"), "Create N queues or topics.") - ("single-connection", optValue(singleConnect, "yes|no"), "Use one connection for multiple sessions.") - - ("iterations", optValue(iterations, "N"), "Desired number of iterations of the test.") - ("summary,s", optValue(summary), "Summary output: pubs/sec subs/sec transfers/sec Mbytes/sec") - - ("queue-max-count", optValue(queueMaxCount, "N"), "queue policy: count to trigger 'flow to disk'") - ("queue-max-size", optValue(queueMaxSize, "N"), "queue policy: accumulated size to trigger 'flow to disk'") - ("base-name", optValue(baseName, "NAME"), "base name used for queues or topics") - ("queue-durable", optValue(queueDurable, "N"), "Make queue durable (implied if durable set)") - - ("interval_sub", optValue(intervalSub, "ms"), ">=0 delay between msg consume") - ("interval_pub", optValue(intervalPub, "ms"), ">=0 delay between msg publish") - - ("tx", optValue(tx, "N"), "if non-zero, the transaction batch size for publishing and consuming") - ("pub-tx", optValue(txPub, "N"), "if non-zero, the transaction batch size for publishing") - ("async-commit", optValue(commitAsync, "yes|no"), "Don't wait for completion of commit") - ("sub-tx", optValue(txSub, "N"), "if non-zero, the transaction batch size for consuming"); - } - - // Computed values - size_t totalPubs; - size_t totalSubs; - size_t transfers; - size_t subQuota; - - void parse(int argc, char** argv) { - TestOptions::parse(argc, argv); - switch (mode) { - case SHARED: - if (subs != 0 && count % subs) { - count += subs - (count % subs); - cout << "WARNING: Adjusted --count to " << count - << " the next multiple of --nsubs" << endl; - } - totalPubs = pubs*qt; - totalSubs = subs*qt; - subQuota = subs == 0 ? subs:(pubs*count)/subs; - break; - case FANOUT: - if (qt != 1) cerr << "WARNING: Fanout mode, ignoring --qt=" - << qt << endl; - qt=1; - totalPubs = pubs; - totalSubs = subs; - subQuota = totalPubs*count; - break; - case TOPIC: - totalPubs = pubs*qt; - totalSubs = subs*qt; - subQuota = pubs*count; - break; - } - transfers=(totalPubs*count) + (totalSubs*subQuota); - if (tx) { - if (txPub) { - cerr << "WARNING: Using overriden tx value for publishers: " << txPub << std::endl; - } else { - txPub = tx; - } - if (txSub) { - cerr << "WARNING: Using overriden tx value for subscribers: " << txSub << std::endl; - } else { - txSub = tx; - } - } - } -}; - -const std::string Opts::helpText= -"There are two ways to use qpid-perftest: single process or multi-process.\n\n" -"If none of the --setup, --publish, --subscribe or --control options\n" -"are given qpid-perftest will run a single-process test.\n" -"For a multi-process test first run:\n" -" qpid-perftest --setup \n" -"and wait for it to complete. The remaining process should run concurrently::\n" -"Run --npubs times: qpid-perftest --publish \n" -"Run --nsubs times: qpid-perftest --subscribe \n" -"Run once: qpid-perftest --control \n" -"Note the must be identical for all processes.\n"; - -Opts opts; -Connection globalConnection; - -std::string fqn(const std::string& name) -{ - ostringstream fqn; - fqn << opts.baseName << "_" << name; - return fqn.str(); -} - -struct Client : public Runnable { - Connection* connection; - Connection localConnection; - AsyncSession session; - Thread thread; - - Client() { - if (opts.singleConnect){ - connection = &globalConnection; - if (!globalConnection.isOpen()) opts.open(globalConnection); - }else{ - connection = &localConnection; - opts.open(localConnection); - } - session = connection->newSession(); - } - - ~Client() { - try { - if (connection->isOpen()) { - session.close(); - connection->close(); - } - } catch (const std::exception& e) { - std::cerr << "Error in shutdown: " << e.what() << std::endl; - } - } -}; - -struct Setup : public Client { - - void queueInit(string name, bool durable=false, const framing::FieldTable& settings=framing::FieldTable()) { - session.queueDeclare(arg::queue=name, arg::durable=durable, arg::arguments=settings); - session.queuePurge(arg::queue=name); - session.sync(); - } - - void run() { - queueInit(fqn("pub_start")); - queueInit(fqn("pub_done")); - queueInit(fqn("sub_ready")); - queueInit(fqn("sub_done")); - if (opts.iterations > 1) queueInit(fqn("sub_iteration")); - if (opts.mode==SHARED) { - framing::FieldTable settings;//queue policy settings - settings.setInt("qpid.max_count", opts.queueMaxCount); - settings.setInt("qpid.max_size", opts.queueMaxSize); - for (size_t i = 0; i < opts.qt; ++i) { - ostringstream qname; - qname << opts.baseName << i; - queueInit(qname.str(), opts.durable || opts.queueDurable, settings); - } - } - } -}; - -void expect(string actual, string expect) { - if (expect != actual) - throw Exception("Expecting "+expect+" but received "+actual); - -} - -double secs(Duration d) { return double(d)/TIME_SEC; } -double secs(AbsTime start, AbsTime finish) { - return secs(Duration(start,finish)); -} - - -// Collect rates & print stats. -class Stats { - vector values; - double sum; - - public: - Stats() : sum(0) {} - - // Functor to collect rates. - void operator()(const string& data) { - try { - double d=lexical_cast(data); - values.push_back(d); - sum += d; - } catch (const std::exception&) { - throw Exception("Bad report: "+data); - } - } - - double mean() const { - return sum/values.size(); - } - - double stdev() const { - if (values.size() <= 1) return 0; - double avg = mean(); - double ssq = 0; - for (vector::const_iterator i = values.begin(); - i != values.end(); ++i) { - double x=*i; - x -= avg; - ssq += x*x; - } - return sqrt(ssq/(values.size()-1)); - } - - ostream& print(ostream& out) { - ostream_iterator o(out, "\n"); - copy(values.begin(), values.end(), o); - out << "Average: " << mean(); - if (values.size() > 1) - out << " (std.dev. " << stdev() << ")"; - return out << endl; - } -}; - - -// Manage control queues, collect and print reports. -struct Controller : public Client { - - SubscriptionManager subs; - - Controller() : subs(session) {} - - /** Process messages from queue by applying a functor. */ - void process(size_t n, string queue, - boost::function msgFn) - { - if (!opts.summary) - cout << "Processing " << n << " messages from " - << queue << " " << flush; - LocalQueue lq; - subs.setFlowControl(n, SubscriptionManager::UNLIMITED, false); - subs.subscribe(lq, queue); - for (size_t i = 0; i < n; ++i) { - if (!opts.summary) cout << "." << flush; - msgFn(lq.pop().getData()); - } - if (!opts.summary) cout << " done." << endl; - } - - void process(size_t n, LocalQueue lq, string queue, - boost::function msgFn) - { - session.messageFlow(queue, 0, n); - if (!opts.summary) - cout << "Processing " << n << " messages from " - << queue << " " << flush; - for (size_t i = 0; i < n; ++i) { - if (!opts.summary) cout << "." << flush; - msgFn(lq.pop().getData()); - } - if (!opts.summary) cout << " done." << endl; - } - - void send(size_t n, string queue, string data) { - if (!opts.summary) - cout << "Sending " << data << " " << n << " times to " << queue - << endl; - Message msg(data, queue); - for (size_t i = 0; i < n; ++i) - session.messageTransfer(arg::content=msg, arg::acceptMode=1); - } - - void run() { // Controller - try { - // Wait for subscribers to be ready. - process(opts.totalSubs, fqn("sub_ready"), boost::bind(expect, _1, "ready")); - - LocalQueue pubDone; - LocalQueue subDone; - subs.setFlowControl(0, SubscriptionManager::UNLIMITED, false); - subs.subscribe(pubDone, fqn("pub_done")); - subs.subscribe(subDone, fqn("sub_done")); - - double txrateTotal(0); - double mbytesTotal(0); - double pubRateTotal(0); - double subRateTotal(0); - - for (size_t j = 0; j < opts.iterations; ++j) { - AbsTime start=now(); - send(opts.totalPubs, fqn("pub_start"), "start"); // Start publishers - if (j) { - send(opts.totalSubs, fqn("sub_iteration"), "next"); // Start subscribers on next iteration - } - - Stats pubRates; - Stats subRates; - - process(opts.totalPubs, pubDone, fqn("pub_done"), boost::ref(pubRates)); - process(opts.totalSubs, subDone, fqn("sub_done"), boost::ref(subRates)); - - AbsTime end=now(); - double time=secs(start, end); - if (time <= 0.0) { - throw Exception("ERROR: Test completed in zero seconds. Try again with a larger message count."); - } - double txrate=opts.transfers/time; - double mbytes=(txrate*opts.size)/(1024*1024); - - if (!opts.summary) { - cout << endl << "Total " << opts.transfers << " transfers of " - << opts.size << " bytes in " - << time << " seconds." << endl; - cout << endl << "Publish transfers/sec: " << endl; - pubRates.print(cout); - cout << endl << "Subscribe transfers/sec: " << endl; - subRates.print(cout); - cout << endl - << "Total transfers/sec: " << txrate << endl - << "Total Mbytes/sec: " << mbytes << endl; - } - else { - cout << pubRates.mean() << "\t" - << subRates.mean() << "\t" - << txrate << "\t" - << mbytes << endl; - } - - txrateTotal += txrate; - mbytesTotal += mbytes; - pubRateTotal += pubRates.mean(); - subRateTotal += subRates.mean(); - } - if (opts.iterations > 1) { - cout << "Averages: "<< endl - << (pubRateTotal / opts.iterations) << "\t" - << (subRateTotal / opts.iterations) << "\t" - << (txrateTotal / opts.iterations) << "\t" - << (mbytesTotal / opts.iterations) << endl; - } - } - catch (const std::exception& e) { - cout << "Controller exception: " << e.what() << endl; - } - } -}; - - -struct PublishThread : public Client { - string destination; - string routingKey; - - PublishThread() {}; - - PublishThread(string key, string dest=string()) { - destination=dest; - routingKey=key; - } - - void run() { // Publisher - try { - string data; - size_t offset(0); - if (opts.uniqueData) { - offset = 5; - data += "data:";//marker (requested for latency testing tool scripts) - data += string(sizeof(size_t), 'X');//space for seq no - data += session.getId().str(); - if (opts.size > data.size()) { - data += string(opts.size - data.size(), 'X'); - } else if(opts.size < data.size()) { - cout << "WARNING: Increased --size to " << data.size() - << " to honour --unique-data" << endl; - } - } else { - size_t msgSize=max(opts.size, sizeof(size_t)); - data = string(msgSize, 'X'); - } - - Message msg(data, routingKey); - if (opts.durable) - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - if (opts.headers) { - for (size_t i = 0; i < opts.headers; ++i) { - std::stringstream h; - h << "hdr" << i; - msg.getMessageProperties().getApplicationHeaders().setString(h.str(), h.str()); - } - } - - if (opts.txPub){ - session.txSelect(); - } - SubscriptionManager subs(session); - LocalQueue lq; - subs.setFlowControl(0, SubscriptionManager::UNLIMITED, false); - Subscription cs = subs.subscribe(lq, fqn("pub_start")); - - for (size_t j = 0; j < opts.iterations; ++j) { - cs.grantMessageCredit(1); - expect(lq.pop().getData(), "start"); - AbsTime start=now(); - for (size_t i=0; i(msg.getData()).replace(offset, sizeof(size_t), - reinterpret_cast(&i), sizeof(size_t)); - if (opts.syncPub) { - sync(session).messageTransfer( - arg::destination=destination, - arg::content=msg, - arg::acceptMode=1); - } else { - session.messageTransfer( - arg::destination=destination, - arg::content=msg, - arg::acceptMode=1); - } - if (opts.txPub && ((i+1) % opts.txPub == 0)){ - if (opts.commitAsync){ - session.txCommit(); - } else { - sync(session).txCommit(); - } - } - if (opts.intervalPub) - qpid::sys::usleep(opts.intervalPub*1000); - } - if (opts.confirm) session.sync(); - AbsTime end=now(); - double time=secs(start,end); - if (time <= 0.0) { - throw Exception("ERROR: Test completed in zero seconds. Try again with a larger message count."); - } - - // Send result to controller. - Message report(lexical_cast(opts.count/time), fqn("pub_done")); - session.messageTransfer(arg::content=report, arg::acceptMode=1); - if (opts.txPub){ - sync(session).txCommit(); - } - } - session.close(); - } - catch (const std::exception& e) { - cout << "PublishThread exception: " << e.what() << endl; - } - } -}; - -struct SubscribeThread : public Client { - - string queue; - - SubscribeThread() {} - - SubscribeThread(string q) { queue = q; } - - SubscribeThread(string key, string ex) { - queue=session.getId().str(); // Unique name. - session.queueDeclare(arg::queue=queue, - arg::exclusive=true, - arg::autoDelete=true, - arg::durable=opts.durable); - session.exchangeBind(arg::queue=queue, - arg::exchange=ex, - arg::bindingKey=key); - } - - void verify(bool cond, const char* test, uint32_t expect, uint32_t actual) { - if (!cond) { - Message error( - QPID_MSG("Sequence error: expected n" << test << expect << " but got " << actual), - "sub_done"); - session.messageTransfer(arg::content=error, arg::acceptMode=1); - throw Exception(error.getData()); - } - } - - void run() { // Subscribe - try { - if (opts.txSub) sync(session).txSelect(); - SubscriptionManager subs(session); - SubscriptionSettings settings; - settings.autoAck = opts.txSub ? opts.txSub : opts.ack; - settings.acceptMode = (opts.txSub || opts.ack ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE); - settings.flowControl = FlowControl::messageCredit(opts.subQuota); - LocalQueue lq; - Subscription subscription = subs.subscribe(lq, queue, settings); - // Notify controller we are ready. - session.messageTransfer(arg::content=Message("ready", fqn("sub_ready")), arg::acceptMode=1); - if (opts.txSub) { - if (opts.commitAsync) session.txCommit(); - else sync(session).txCommit(); - } - - LocalQueue iterationControl; - if (opts.iterations > 1) { - subs.subscribe(iterationControl, fqn("sub_iteration"), SubscriptionSettings(FlowControl::messageCredit(0))); - } - - for (size_t j = 0; j < opts.iterations; ++j) { - if (j > 0) { - //need to wait here until all subs are done - session.messageFlow(fqn("sub_iteration"), 0, 1); - iterationControl.pop(); - - //need to allocate some more credit for subscription - session.messageFlow(queue, 0, opts.subQuota); - } - Message msg; - AbsTime start=now(); - size_t expect=0; - for (size_t i = 0; i < opts.subQuota; ++i) { - msg=lq.pop(); - if (opts.txSub && ((i+1) % opts.txSub == 0)) { - if (opts.commitAsync) session.txCommit(); - else sync(session).txCommit(); - } - if (opts.intervalSub) - qpid::sys::usleep(opts.intervalSub*1000); - // TODO aconway 2007-11-23: check message order for. - // multiple publishers. Need an array of counters, - // one per publisher and a publisher ID in the - // message. Careful not to introduce a lot of overhead - // here, e.g. no std::map, std::string etc. - // - // For now verify order only for a single publisher. - size_t offset = opts.uniqueData ? 5 /*marker is 'data:'*/ : 0; - size_t n; - memcpy (&n, reinterpret_cast(msg.getData().data() + offset), - sizeof(n)); - if (opts.pubs == 1) { - if (opts.subs == 1 || opts.mode == FANOUT) verify(n==expect, "==", expect, n); - else verify(n>=expect, ">=", expect, n); - expect = n+1; - } - } - if (opts.txSub || opts.ack) - subscription.accept(subscription.getUnaccepted()); - if (opts.txSub) { - if (opts.commitAsync) session.txCommit(); - else sync(session).txCommit(); - } - AbsTime end=now(); - - // Report to publisher. - Message result(lexical_cast(opts.subQuota/secs(start,end)), - fqn("sub_done")); - session.messageTransfer(arg::content=result, arg::acceptMode=1); - if (opts.txSub) sync(session).txCommit(); - } - session.close(); - } - catch (const std::exception& e) { - cout << "SubscribeThread exception: " << e.what() << endl; - } - } -}; - -} - -template po::value_semantic* create_value(tests::Mode& val, const std::string& arg); - -} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) { - int exitCode = 0; - boost::ptr_vector subs(opts.subs); - boost::ptr_vector pubs(opts.pubs); - - try { - opts.parse(argc, argv); - - string exchange; - switch (opts.mode) { - case FANOUT: exchange="amq.fanout"; break; - case TOPIC: exchange="amq.topic"; break; - case SHARED: break; - } - - bool singleProcess= - (!opts.setup && !opts.control && !opts.publish && !opts.subscribe); - if (singleProcess) - opts.setup = opts.control = opts.publish = opts.subscribe = true; - - if (opts.setup) Setup().run(); // Set up queues - - // Start pubs/subs for each queue/topic. - for (size_t i = 0; i < opts.qt; ++i) { - ostringstream key; - key << opts.baseName << i; // Queue or topic name. - if (opts.publish) { - size_t n = singleProcess ? opts.pubs : 1; - for (size_t j = 0; j < n; ++j) { - pubs.push_back(new PublishThread(key.str(), exchange)); - pubs.back().thread=Thread(pubs.back()); - } - } - if (opts.subscribe) { - size_t n = singleProcess ? opts.subs : 1; - for (size_t j = 0; j < n; ++j) { - if (opts.mode==SHARED) - subs.push_back(new SubscribeThread(key.str())); - else - subs.push_back(new SubscribeThread(key.str(),exchange)); - subs.back().thread=Thread(subs.back()); - } - } - } - - if (opts.control) Controller().run(); - } - catch (const std::exception& e) { - cout << endl << e.what() << endl; - exitCode = 1; - } - - // Wait for started threads. - if (opts.publish) { - for (boost::ptr_vector::iterator i=pubs.begin(); - i != pubs.end(); - ++i) - i->thread.join(); - } - - if (opts.subscribe) { - for (boost::ptr_vector::iterator i=subs.begin(); - i != subs.end(); - ++i) - i->thread.join(); - } - return exitCode; -} diff --git a/qpid/cpp/src/tests/qpid-ping.cpp b/qpid/cpp/src/tests/qpid-ping.cpp deleted file mode 100644 index 40e6a0f671..0000000000 --- a/qpid/cpp/src/tests/qpid-ping.cpp +++ /dev/null @@ -1,94 +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 -#include -#include "qpid/messaging/Duration.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace qpid::messaging; -using qpid::types::Uuid; - -namespace { - -struct PingOptions : public qpid::Options { - string url; - string address; - string message; - string connectionOptions; - double timeout; // Timeout in seconds. - bool quiet; // No output - - PingOptions() : - url("127.0.0.1"), - address(Uuid(true).str()+";{create:always}"), - message(Uuid(true).str()), - timeout(1), - quiet(false) - { - using qpid::optValue; - addOptions() - ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to.") - ("address,a", qpid::optValue(address, "ADDRESS"), "address to use.") - ("message,m", optValue(message, "MESSAGE"), "message text to send.") - ("connection-options", optValue(connectionOptions, "OPTIONS"), "options for the connection.") - ("timeout,t", optValue(timeout, "SECONDS"), "Max time to wait.") - ("quiet,q", optValue(quiet), "Don't print anything to stderr/stdout."); - } -}; - -} // namespace - -int main(int argc, char** argv) { - Connection connection; - try { - PingOptions opts; - opts.parse(argc, argv); - connection = Connection(opts.url, opts.connectionOptions); - connection.open(); - if (!opts.quiet) cout << "Opened connection." << endl; - Session s = connection.createSession(); - s.createSender(opts.address).send(Message(opts.message)); - if (!opts.quiet) cout << "Sent message." << endl; - Message m = s.createReceiver(opts.address). - fetch(Duration(uint64_t(opts.timeout*1000))); - if (m.getContent() != opts.message) - throw qpid::Exception(qpid::Msg() << "Expected " << opts.message - << " but received " << m.getContent()); - if (!opts.quiet) cout << "Received message." << endl; - connection.close(); - return 0; - } catch (const exception& e) { - cerr << "Error: " << e.what() << endl; - connection.close(); - return 1; - } -} diff --git a/qpid/cpp/src/tests/qpid-receive.cpp b/qpid/cpp/src/tests/qpid-receive.cpp deleted file mode 100644 index eeb425f7b3..0000000000 --- a/qpid/cpp/src/tests/qpid-receive.cpp +++ /dev/null @@ -1,299 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "qpid/sys/Time.h" -#include "TestOptions.h" -#include "Statistics.h" - -#include -#include - -using namespace qpid::messaging; -using namespace qpid::types; -using namespace std; - -namespace qpid { -namespace tests { - -struct Options : public qpid::Options -{ - bool help; - std::string url; - std::string address; - std::string connectionOptions; - int64_t timeout; - bool forever; - uint messages; - bool ignoreDuplicates; - bool verifySequence; - bool checkRedelivered; - uint capacity; - uint ackFrequency; - uint tx; - uint rollbackFrequency; - bool printContent; - bool printContentObjectType; - bool printHeaders; - bool failoverUpdates; - qpid::log::Options log; - bool reportTotal; - uint reportEvery; - bool reportHeader; - string readyAddress; - uint receiveRate; - std::string replyto; - bool noReplies; - - Options(const std::string& argv0=std::string()) - : qpid::Options("Options"), - help(false), - url("127.0.0.1"), - timeout(0), - forever(false), - messages(0), - ignoreDuplicates(false), - verifySequence(false), - checkRedelivered(false), - capacity(1000), - ackFrequency(100), - tx(0), - rollbackFrequency(0), - printContent(true), - printContentObjectType(false), - printHeaders(false), - failoverUpdates(false), - log(argv0), - reportTotal(false), - reportEvery(0), - reportHeader(true), - receiveRate(0), - noReplies(false) - { - addOptions() - ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to") - ("address,a", qpid::optValue(address, "ADDRESS"), "address to receive from") - ("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection") - ("timeout", qpid::optValue(timeout, "TIMEOUT"), "timeout in seconds to wait before exiting") - ("forever,f", qpid::optValue(forever), "ignore timeout and wait forever") - ("messages,m", qpid::optValue(messages, "N"), "Number of messages to receive; 0 means receive indefinitely") - ("ignore-duplicates", qpid::optValue(ignoreDuplicates), "Detect and ignore duplicates (by checking 'sn' header)") - ("verify-sequence", qpid::optValue(verifySequence), "Verify there are no gaps in the message sequence (by checking 'sn' header)") - ("check-redelivered", qpid::optValue(checkRedelivered), "Fails with exception if a duplicate is not marked as redelivered (only relevant when ignore-duplicates is selected)") - ("capacity", qpid::optValue(capacity, "N"), "Pre-fetch window (0 implies no pre-fetch)") - ("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)") - ("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)") - ("rollback-frequency", qpid::optValue(rollbackFrequency, "N"), "rollback frequency (0 implies no transaction will be rolledback)") - ("print-content", qpid::optValue(printContent, "yes|no"), "print out message content") - ("print-object-type", qpid::optValue(printContentObjectType, "yes|no"), "print a description of the content's object type if relevant") - ("print-headers", qpid::optValue(printHeaders, "yes|no"), "print out message headers") - ("failover-updates", qpid::optValue(failoverUpdates), "Listen for membership updates distributed via amq.failover") - ("report-total", qpid::optValue(reportTotal), "Report total throughput and latency statistics") - ("report-every", qpid::optValue(reportEvery,"N"), "Report throughput and latency statistics every N messages.") - ("report-header", qpid::optValue(reportHeader, "yes|no"), "Headers on report.") - ("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); - } - - Duration getTimeout() - { - if (forever) return Duration::FOREVER; - else return Duration::SECOND*timeout; - - } - bool parse(int argc, char** argv) - { - try { - qpid::Options::parse(argc, argv); - if (address.empty()) throw qpid::Exception("Address must be specified!"); - qpid::log::Logger::instance().configure(log); - if (help) { - std::cout << *this << std::endl << std::endl - << "Drains messages from the specified address" << std::endl; - return false; - } else { - return true; - } - } catch (const std::exception& e) { - std::cerr << *this << std::endl << std::endl << e.what() << std::endl; - return false; - } - } -}; - -const string EOS("eos"); -const string SN("sn"); - -/** Check for duplicate or dropped messages by sequence number */ -class SequenceTracker -{ - public: - SequenceTracker(const Options& o) : opts(o), lastSn(0) {} - - /** Return true if the message should be procesed, false if it should be ignored. */ - bool track(Message& message) { - if (!(opts.verifySequence || opts.ignoreDuplicates)) - return true; // Not checking sequence numbers. - uint sn = message.getProperties()[SN]; - bool duplicate = (sn <= lastSn); - bool dropped = (sn > lastSn+1); - if (opts.verifySequence && dropped) - throw Exception(QPID_MSG("Gap in sequence numbers " << lastSn << "-" << sn)); - bool ignore = duplicate && opts.ignoreDuplicates; - if (ignore && opts.checkRedelivered && !message.getRedelivered()) - throw qpid::Exception("duplicate sequence number received, message not marked as redelivered!"); - if (!duplicate) lastSn = sn; - return !ignore; - } - - private: - const Options& opts; - uint lastSn; -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - Connection connection; - try { - Options opts; - if (opts.parse(argc, argv)) { - connection = Connection(opts.url, opts.connectionOptions); - connection.open(); - std::auto_ptr updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0); - Session session = opts.tx ? connection.createTransactionalSession() : connection.createSession(); - Receiver receiver = session.createReceiver(opts.address); - receiver.setCapacity(opts.messages == 0 ? opts.capacity : std::min(opts.capacity, opts.messages)); - Message msg; - uint count = 0; - uint txCount = 0; - SequenceTracker sequenceTracker(opts); - Duration timeout = opts.getTimeout(); - bool done = false; - Reporter reporter(std::cout, opts.reportEvery, opts.reportHeader); - if (!opts.readyAddress.empty()) { - session.createSender(opts.readyAddress).send(msg); - if (opts.tx) - session.commit(); - } - // For receive rate calculation - qpid::sys::AbsTime start = qpid::sys::now(); - int64_t interval = 0; - if (opts.receiveRate) interval = qpid::sys::TIME_SEC/opts.receiveRate; - - std::map replyTo; - - while (!done && receiver.fetch(msg, timeout)) { - reporter.message(msg); - if (sequenceTracker.track(msg)) { - if (msg.getContent() == EOS) { - done = true; - } else { - ++count; - 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; - if (msg.getPriority()) std::cout << "Priority: " << ((uint) msg.getPriority()) << std::endl; - if (msg.getDurable()) std::cout << "Durable: true" << std::endl; - if (msg.getRedelivered()) std::cout << "Redelivered: true" << std::endl; - std::cout << "Properties: " << msg.getProperties() << std::endl; - if (msg.getContentType().size()) std::cout << "ContentType: " << msg.getContentType() << std::endl; - std::cout << std::endl; - } - if (opts.printContent) { - if (!msg.getContentObject().isVoid()) { - if (opts.printContentObjectType) { - std::cout << "[Object: " << getTypeName(msg.getContentObject().getType()) << "]" << std::endl; - } - std::cout << msg.getContentObject() << std::endl; - } else { - std::cout << msg.getContent() << std::endl; - } - } - if (opts.messages && count >= opts.messages) done = true; - } - } - if (opts.tx && (count % opts.tx == 0)) { - if (opts.rollbackFrequency && (++txCount % opts.rollbackFrequency == 0)) { - session.rollback(); - } else { - session.commit(); - } - } else if (opts.ackFrequency && (count % opts.ackFrequency == 0)) { - session.acknowledge(); - } - 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()); - s.setCapacity(opts.capacity); - replyTo[msg.getReplyTo().str()] = s; - } - msg.setReplyTo(Address(opts.replyto)); - s.send(msg); - } - if (opts.receiveRate) { - qpid::sys::AbsTime waitTill(start, count*interval); - int64_t delay = qpid::sys::Duration(qpid::sys::now(), waitTill); - if (delay > 0) qpid::sys::usleep(delay/qpid::sys::TIME_USEC); - } - } - if (opts.reportTotal) reporter.report(); - if (opts.tx) { - if (opts.rollbackFrequency && (++txCount % opts.rollbackFrequency == 0)) { - session.rollback(); - } else { - session.commit(); - } - } else if (opts.ackFrequency) { - session.acknowledge(); - } - session.close(); - connection.close(); - return 0; - } - return 1; - } catch(const std::exception& error) { - std::cerr << "qpid-receive: " << error.what() << std::endl; - connection.close(); - return 1; - } -} diff --git a/qpid/cpp/src/tests/qpid-send.cpp b/qpid/cpp/src/tests/qpid-send.cpp deleted file mode 100644 index 1f4e25e5c1..0000000000 --- a/qpid/cpp/src/tests/qpid-send.cpp +++ /dev/null @@ -1,469 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "TestOptions.h" -#include "Statistics.h" - -#include -#include -#include - -using std::string; -using std::ios_base; - -using qpid::messaging::Address; -using qpid::messaging::Connection; -using qpid::messaging::Duration; -using qpid::messaging::FailoverUpdates; -using qpid::messaging::Message; -using qpid::messaging::Receiver; -using qpid::messaging::Session; -using qpid::messaging::Sender; -using qpid::types::Exception; -using qpid::types::Uuid; -using qpid::types::Variant; - -namespace qpid { -namespace tests { - -typedef std::vector string_vector; - -struct Options : public qpid::Options -{ - bool help; - std::string url; - std::string connectionOptions; - std::string address; - uint messages; - std::string id; - std::string replyto; - uint sendEos; - bool durable; - uint ttl; - uint priority; - std::string userid; - bool autouserid; - std::string correlationid; - string_vector properties; - string_vector entries; - std::string contentString; - uint contentSize; - bool contentStdin; - uint tx; - uint rollbackFrequency; - uint capacity; - bool failoverUpdates; - qpid::log::Options log; - bool reportTotal; - uint reportEvery; - bool reportHeader; - uint sendRate; - bool sequence; - bool timestamp; - std::string groupKey; - std::string groupPrefix; - uint groupSize; - bool groupRandSize; - uint groupInterleave; - - Options(const std::string& argv0=std::string()) - : qpid::Options("Options"), - help(false), - url("127.0.0.1"), - messages(1), - sendEos(0), - durable(false), - ttl(0), - priority(0), - autouserid(false), - contentString(), - contentSize(0), - contentStdin(false), - tx(0), - rollbackFrequency(0), - capacity(1000), - failoverUpdates(false), - log(argv0), - reportTotal(false), - reportEvery(0), - reportHeader(true), - sendRate(0), - sequence(true), - timestamp(true), - groupPrefix("GROUP-"), - groupSize(10), - groupRandSize(false), - groupInterleave(1) - { - addOptions() - ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to") - ("address,a", qpid::optValue(address, "ADDRESS"), "address to send to") - ("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection") - ("messages,m", qpid::optValue(messages, "N"), "stop after N messages have been sent, 0 means no limit") - ("id,i", qpid::optValue(id, "ID"), "use the supplied id instead of generating one") - ("reply-to", qpid::optValue(replyto, "REPLY-TO"), "specify reply-to address") - ("send-eos", qpid::optValue(sendEos, "N"), "Send N EOS messages to mark end of input") - ("durable", qpid::optValue(durable, "yes|no"), "Mark messages as durable.") - ("ttl", qpid::optValue(ttl, "msecs"), "Time-to-live for messages, in milliseconds") - ("priority", qpid::optValue(priority, "PRIORITY"), "Priority for messages (higher value implies higher priority)") - ("property,P", qpid::optValue(properties, "NAME=VALUE"), "specify message property") - ("correlation-id", qpid::optValue(correlationid, "ID"), "correlation-id for message") - ("user-id", qpid::optValue(userid, "USERID"), "userid for message") - ("auto-user-id", qpid::optValue(autouserid, "yes| no"), "set userid for message based on authenticated identity") - ("content-string", qpid::optValue(contentString, "CONTENT"), "use CONTENT as message content") - ("content-size", qpid::optValue(contentSize, "N"), "create an N-byte message content") - ("content-map,M", qpid::optValue(entries, "NAME=VALUE"), "specify entry for map content") - ("content-stdin", qpid::optValue(contentStdin), "read message content from stdin, one line per message") - ("capacity", qpid::optValue(capacity, "N"), "size of the senders outgoing message queue") - ("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)") - ("rollback-frequency", qpid::optValue(rollbackFrequency, "N"), "rollback frequency (0 implies no transaction will be rolledback)") - ("failover-updates", qpid::optValue(failoverUpdates), "Listen for membership updates distributed via amq.failover") - ("report-total", qpid::optValue(reportTotal), "Report total throughput statistics") - ("report-every", qpid::optValue(reportEvery,"N"), "Report throughput statistics every N messages") - ("report-header", qpid::optValue(reportHeader, "yes|no"), "Headers on report.") - ("send-rate", qpid::optValue(sendRate,"N"), "Send at rate of N messages/second. 0 means send as fast as possible.") - ("sequence", qpid::optValue(sequence, "yes|no"), "Add a sequence number messages property (required for duplicate/lost message detection)") - ("timestamp", qpid::optValue(timestamp, "yes|no"), "Add a time stamp messages property (required for latency measurement)") - ("group-key", qpid::optValue(groupKey, "KEY"), "Generate groups of messages using message header 'KEY' to hold the group identifier") - ("group-prefix", qpid::optValue(groupPrefix, "STRING"), "Generate group identifers with 'STRING' prefix (if group-key specified)") - ("group-size", qpid::optValue(groupSize, "N"), "Number of messages per a group (if group-key specified)") - ("group-randomize-size", qpid::optValue(groupRandSize), "Randomize the number of messages per group to [1...group-size] (if group-key specified)") - ("group-interleave", qpid::optValue(groupInterleave, "N"), "Simultaineously interleave messages from N different groups (if group-key specified)") - ("help", qpid::optValue(help), "print this usage statement"); - add(log); - } - - bool parse(int argc, char** argv) - { - try { - qpid::Options::parse(argc, argv); - if (address.empty()) throw qpid::Exception("Address must be specified!"); - qpid::log::Logger::instance().configure(log); - if (help) { - std::cout << *this << std::endl << std::endl - << "Sends messages to the specified address" << std::endl; - return false; - } else { - return true; - } - } catch (const std::exception& e) { - std::cerr << *this << std::endl << std::endl << e.what() << std::endl; - return false; - } - } - - static bool nameval(const std::string& in, std::string& name, std::string& value) - { - std::string::size_type i = in.find("="); - if (i == std::string::npos) { - name = in; - return false; - } else { - name = in.substr(0, i); - if (i+1 < in.size()) { - value = in.substr(i+1); - return true; - } else { - return false; - } - } - } - - static void setProperty(Message& message, const std::string& property) - { - std::string name; - std::string value; - if (nameval(property, name, value)) { - message.getProperties()[name].parse(value); - } else { - message.getProperties()[name] = Variant(); - } - } - - void setProperties(Message& message) const - { - for (string_vector::const_iterator i = properties.begin(); i != properties.end(); ++i) { - setProperty(message, *i); - } - } - - void setEntries(Variant::Map& content) const - { - for (string_vector::const_iterator i = entries.begin(); i != entries.end(); ++i) { - std::string name; - std::string value; - if (nameval(*i, name, value)) { - content[name] = value; - } else { - content[name] = Variant(); - } - } - } -}; - -const string EOS("eos"); -const string SN("sn"); -const string TS("ts"); - -class ContentGenerator { - public: - virtual ~ContentGenerator() {} - virtual bool setContent(Message& msg) = 0; - void setContentObject(Message& msg, const std::string& content, const std::string& encoding=std::string("utf8")) - { - Variant& obj = msg.getContentObject(); - obj = content; - obj.setEncoding(encoding); - } -}; - - -class GetlineContentGenerator : public ContentGenerator { - public: - virtual bool setContent(Message& msg) { - string content; - bool got = !!getline(std::cin, content); - if (got) { - setContentObject(msg, content); - } - return got; - } -}; - -class FixedContentGenerator : public ContentGenerator { - public: - FixedContentGenerator(const string& s) : content(s) {} - virtual bool setContent(Message& msg) { - setContentObject(msg, content); - return true; - } - private: - std::string content; -}; - -class MapContentGenerator : public ContentGenerator { - public: - MapContentGenerator(const Options& opt) : opts(opt) {} - virtual bool setContent(Message& msg) { - msg.getContentObject() = qpid::types::Variant::Map(); - opts.setEntries(msg.getContentObject().asMap()); - return true; - } - private: - const Options& opts; -}; - -// tag each generated message with a group identifer -// -class GroupGenerator { - public: - GroupGenerator(const std::string& key, - const std::string& prefix, - const uint size, - const bool randomize, - const uint interleave) - : groupKey(key), groupPrefix(prefix), groupSize(size), - randomizeSize(randomize), groupSuffix(0) - { - if (randomize) srand((unsigned int)qpid::sys::SystemInfo::getProcessId()); - - for (uint i = 0; i < 1 || i < interleave; ++i) { - newGroup(); - } - current = groups.begin(); - } - - void setGroupInfo(Message &msg) - { - if (current == groups.end()) - current = groups.begin(); - msg.getProperties()[groupKey] = current->id; - // std::cout << "SENDING GROUPID=[" << current->id << "]" << std::endl; - if (++(current->count) == current->size) { - newGroup(); - groups.erase(current++); - } else - ++current; - } - - private: - const std::string& groupKey; - const std::string& groupPrefix; - const uint groupSize; - const bool randomizeSize; - - uint groupSuffix; - - struct GroupState { - std::string id; - const uint size; - uint count; - GroupState( const std::string& i, const uint s ) - : id(i), size(s), count(0) {} - }; - typedef std::list GroupList; - GroupList groups; - GroupList::iterator current; - - void newGroup() { - std::ostringstream groupId(groupPrefix, ios_base::out|ios_base::ate); - groupId << groupSuffix++; - uint size = (randomizeSize) ? (rand() % groupSize) + 1 : groupSize; - // std::cout << "New group: GROUPID=[" << groupId.str() << "] size=" << size << std::endl; - GroupState group( groupId.str(), size ); - groups.push_back( group ); - } -}; - -}} // namespace qpid::tests - -using qpid::tests::Options; -using qpid::tests::Reporter; -using qpid::tests::Throughput; -using qpid::tests::ContentGenerator; -using qpid::tests::GroupGenerator; -using qpid::tests::GetlineContentGenerator; -using qpid::tests::MapContentGenerator; -using qpid::tests::FixedContentGenerator; -using qpid::tests::SN; -using qpid::tests::TS; -using qpid::tests::EOS; - -int main(int argc, char ** argv) -{ - Connection connection; - try { - Options opts; - if (opts.parse(argc, argv)) { - connection = Connection(opts.url, opts.connectionOptions); - connection.open(); - std::auto_ptr updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0); - Session session = opts.tx ? connection.createTransactionalSession() : connection.createSession(); - Sender sender = session.createSender(opts.address); - if (opts.capacity) sender.setCapacity(opts.capacity); - Message msg; - msg.setDurable(opts.durable); - if (opts.ttl) { - msg.setTtl(Duration(opts.ttl)); - } - if (opts.priority) { - msg.setPriority(opts.priority); - } - if (!opts.replyto.empty()) { - msg.setReplyTo(Address(opts.replyto)); - } - if (!opts.userid.empty()) msg.setUserId(opts.userid); - else if (opts.autouserid) msg.setUserId(connection.getAuthenticatedUsername()); - if (!opts.id.empty()) msg.setMessageId(opts.id); - if (!opts.correlationid.empty()) msg.setCorrelationId(opts.correlationid); - opts.setProperties(msg); - uint sent = 0; - uint txCount = 0; - Reporter reporter(std::cout, opts.reportEvery, opts.reportHeader); - - std::auto_ptr contentGen; - if (opts.contentStdin) { - opts.messages = 0; // Don't limit # messages sent. - contentGen.reset(new GetlineContentGenerator); - } - else if (opts.entries.size() > 0) - contentGen.reset(new MapContentGenerator(opts)); - else if (opts.contentSize > 0) - contentGen.reset(new FixedContentGenerator(string(opts.contentSize, 'X'))); - else - contentGen.reset(new FixedContentGenerator(opts.contentString)); - - std::auto_ptr groupGen; - if (!opts.groupKey.empty()) - groupGen.reset(new GroupGenerator(opts.groupKey, - opts.groupPrefix, - opts.groupSize, - opts.groupRandSize, - opts.groupInterleave)); - - qpid::sys::AbsTime start = qpid::sys::now(); - int64_t interval = 0; - if (opts.sendRate) interval = qpid::sys::TIME_SEC/opts.sendRate; - - while (contentGen->setContent(msg)) { - ++sent; - if (opts.sequence) - msg.getProperties()[SN] = sent; - if (groupGen.get()) - groupGen->setGroupInfo(msg); - - if (opts.timestamp) - msg.getProperties()[TS] = int64_t( - qpid::sys::Duration::FromEpoch()); - sender.send(msg); - reporter.message(msg); - - if (opts.tx && (sent % opts.tx == 0)) { - if (opts.rollbackFrequency && - (++txCount % opts.rollbackFrequency == 0)) - session.rollback(); - else - session.commit(); - } - if (opts.messages && sent >= opts.messages) break; - - if (opts.sendRate) { - qpid::sys::AbsTime waitTill(start, sent*interval); - int64_t delay = qpid::sys::Duration(qpid::sys::now(), waitTill); - if (delay > 0) qpid::sys::usleep(delay/qpid::sys::TIME_USEC); - } - } - if (opts.reportTotal) reporter.report(); - for (uint i = opts.sendEos; i > 0; --i) { - if (opts.sequence) - msg.getProperties()[SN] = ++sent; - msg.setContent(EOS); //TODO: add in ability to send digest or similar - sender.send(msg); - } - if (opts.tx) { - if (opts.rollbackFrequency && (++txCount % opts.rollbackFrequency == 0)) { - session.rollback(); - } else { - session.commit(); - } - } - session.sync(); - session.close(); - connection.close(); - return 0; - } - return 1; - } catch(const std::exception& error) { - std::cerr << "qpid-send: " << error.what() << std::endl; - connection.close(); - return 1; - } -} diff --git a/qpid/cpp/src/tests/qpid-src-rinstall b/qpid/cpp/src/tests/qpid-src-rinstall deleted file mode 100755 index c7473e9197..0000000000 --- a/qpid/cpp/src/tests/qpid-src-rinstall +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -# -# Licensed to the Apache Software Foundation (ASF) under onemake -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Copy the source tree and run "make install" on each of $HOSTS -# Must be run in a configured qpid build directory. - -absdir() { echo `cd $1 && pwd`; } - -test -f config.status || { echo "Not in a configured build directory."; } -CONFIGURE=`./config.status -V | grep '^configured by' | sed 's/^configured by \([^,]*\),.*$/\1/'` -CONFIG_OPTIONS=`./config.status -V | grep 'with options' | sed 's/^.*with options "\([^"]*\)".*$/\1/'` -set -ex -rsynchosts `absdir $(dirname $CONFIGURE)/..` # Copy cpp srcdir and siblings. -allhosts -bo rbuild.log "mkdir -p $PWD && cd $PWD && { test -f config.status || $CONFIGURE $CONFIG_OPTIONS; } && make && make -j1 install" diff --git a/qpid/cpp/src/tests/qpid-stream.cpp b/qpid/cpp/src/tests/qpid-stream.cpp deleted file mode 100644 index f02a484750..0000000000 --- a/qpid/cpp/src/tests/qpid-stream.cpp +++ /dev/null @@ -1,193 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace qpid::messaging; -using namespace qpid::types; - -namespace qpid { -namespace tests { - -struct Args : public qpid::Options -{ - std::string url; - std::string address; - uint size; - uint rate; - bool durable; - uint receiverCapacity; - uint senderCapacity; - uint ackFrequency; - - Args() : - url("amqp:tcp:127.0.0.1:5672"), - address("test-queue"), - size(512), - rate(1000), - durable(false), - receiverCapacity(0), - senderCapacity(0), - ackFrequency(1) - { - addOptions() - ("url", qpid::optValue(url, "URL"), "Url to connect to.") - ("address", qpid::optValue(address, "ADDRESS"), "Address to stream messages through.") - ("size", qpid::optValue(size, "bytes"), "Message size in bytes (content only, not headers).") - ("rate", qpid::optValue(rate, "msgs/sec"), "Rate at which to stream messages.") - ("durable", qpid::optValue(durable, "true|false"), "Mark messages as durable.") - ("sender-capacity", qpid::optValue(senderCapacity, "N"), "Credit window (0 implies infinite window)") - ("receiver-capacity", qpid::optValue(receiverCapacity, "N"), "Credit window (0 implies infinite window)") - ("ack-frequency", qpid::optValue(ackFrequency, "N"), - "Ack frequency (0 implies none of the messages will get accepted)"); - } -}; - -Args opts; - -const std::string TS = "ts"; - -uint64_t timestamp(const qpid::sys::AbsTime& time) -{ - qpid::sys::Duration t(qpid::sys::EPOCH, time); - return t; -} - -struct Client : qpid::sys::Runnable -{ - virtual ~Client() {} - virtual void doWork(Session&) = 0; - - void run() - { - Connection connection(opts.url); - try { - connection.open(); - Session session = connection.createSession(); - doWork(session); - session.close(); - connection.close(); - } catch(const std::exception& error) { - std::cout << error.what() << std::endl; - connection.close(); - } - } - - qpid::sys::Thread thread; - - void start() { thread = qpid::sys::Thread(this); } - void join() { thread.join(); } -}; - -struct Publish : Client -{ - void doWork(Session& session) - { - Sender sender = session.createSender(opts.address); - if (opts.senderCapacity) sender.setCapacity(opts.senderCapacity); - Message msg(std::string(opts.size, 'X')); - uint64_t interval = qpid::sys::TIME_SEC / opts.rate; - uint64_t sent = 0, missedRate = 0; - qpid::sys::AbsTime start = qpid::sys::now(); - while (true) { - qpid::sys::AbsTime sentAt = qpid::sys::now(); - msg.getProperties()[TS] = timestamp(sentAt); - sender.send(msg); - ++sent; - qpid::sys::AbsTime waitTill(start, sent*interval); - qpid::sys::Duration delay(sentAt, waitTill); - if (delay < 0) { - ++missedRate; - } else { - qpid::sys::usleep(delay / qpid::sys::TIME_USEC); - } - } - } -}; - -struct Consume : Client -{ - void doWork(Session& session) - { - Message msg; - uint64_t received = 0; - double minLatency = std::numeric_limits::max(); - double maxLatency = 0; - double totalLatency = 0; - Receiver receiver = session.createReceiver(opts.address); - if (opts.receiverCapacity) receiver.setCapacity(opts.receiverCapacity); - while (receiver.fetch(msg)) { - ++received; - if (opts.ackFrequency && (received % opts.ackFrequency == 0)) { - session.acknowledge(); - } - //calculate latency - uint64_t receivedAt = timestamp(qpid::sys::now()); - uint64_t sentAt = msg.getProperties()[TS].asUint64(); - double latency = ((double) (receivedAt - sentAt)) / qpid::sys::TIME_MSEC; - - //update avg, min & max - minLatency = std::min(minLatency, latency); - maxLatency = std::max(maxLatency, latency); - totalLatency += latency; - - if (received % opts.rate == 0) { - std::cout << "count=" << received - << ", avg=" << (totalLatency/received) - << ", min=" << minLatency - << ", max=" << maxLatency << std::endl; - } - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - Publish publish; - Consume consume; - publish.start(); - consume.start(); - consume.join(); - publish.join(); - return 0; - } catch(const std::exception& error) { - std::cout << error.what() << std::endl; - } - return 1; -} - - diff --git a/qpid/cpp/src/tests/qpid-topic-listener.cpp b/qpid/cpp/src/tests/qpid-topic-listener.cpp deleted file mode 100644 index c42e76d760..0000000000 --- a/qpid/cpp/src/tests/qpid-topic-listener.cpp +++ /dev/null @@ -1,209 +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. - * - */ - -/** - * This file provides one half of a test and example of a pub-sub - * style of interaction. See qpid-topic-publisher.cpp for the other half, - * in which the logic for publishing is defined. - * - * This file contains the listener logic. A listener will subscribe to - * a logical 'topic'. It will count the number of messages it receives - * and the time elapsed between the first one and the last one. It - * recognises two types of 'special' message that tell it to (a) send - * a report containing this information, (b) shutdown (i.e. stop - * listening). - */ - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/Session.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/FieldValue.h" -#include -#include - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using namespace qpid::framing; -using namespace std; - -namespace qpid { -namespace tests { - -/** - * A message listener implementation in which the runtime logic is - * defined. - */ -class Listener : public MessageListener{ - Session session; - SubscriptionManager& mgr; - const string responseQueue; - const bool transactional; - bool init; - int count; - AbsTime start; - - void shutdown(); - void report(); -public: - Listener(const Session& session, SubscriptionManager& mgr, const string& reponseQueue, bool tx); - virtual void received(Message& msg); - Subscription subscription; -}; - -/** - * A utility class for managing the options passed in. - */ -struct Args : public qpid::TestOptions { - int ack; - bool transactional; - bool durable; - int prefetch; - string statusqueue; - - Args() : ack(0), transactional(false), durable(false), prefetch(0) { - addOptions() - ("ack", optValue(ack, "MODE"), "Ack frequency in messages (defaults to half the prefetch value)") - ("transactional", optValue(transactional), "Use transactions") - ("durable", optValue(durable), "subscribers should use durable queues") - ("prefetch", optValue(prefetch, "N"), "prefetch count (0 implies no flow control, and no acking)") - ("status-queue", optValue(statusqueue, "QUEUE-NAME"), "Message queue to put status messages on"); - } -}; - -Listener::Listener(const Session& s, SubscriptionManager& m, const string& _responseq, bool tx) : - session(s), mgr(m), responseQueue(_responseq), transactional(tx), init(false), count(0){} - -void Listener::received(Message& message){ - if(!init){ - start = now(); - count = 0; - init = true; - cout << "Batch started." << endl; - } - string type = message.getHeaders().getAsString("TYPE"); - - if(string("TERMINATION_REQUEST") == type){ - shutdown(); - }else if(string("REPORT_REQUEST") == type){ - subscription.accept(subscription.getUnaccepted()); // Accept everything upto this point - cout <<"Batch ended, sending report." << endl; - //send a report: - report(); - init = false; - }else if (++count % 1000 == 0){ - cout <<"Received " << count << " messages." << endl; - } -} - -void Listener::shutdown(){ - mgr.stop(); -} - -void Listener::report(){ - AbsTime finish = now(); - Duration time(start, finish); - stringstream reportstr; - reportstr << "Received " << count << " messages in " - << time/TIME_MSEC << " ms."; - Message msg(reportstr.str(), responseQueue); - msg.getHeaders().setString("TYPE", "REPORT"); - session.messageTransfer(arg::destination="amq.direct", arg::content=msg, arg::acceptMode=1); - if(transactional){ - sync(session).txCommit(); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -/** - * The main routine creates a Listener instance and sets it up to - * consume from a private queue bound to the exchange with the - * appropriate topic name. - */ -int main(int argc, char** argv){ - try{ - Args args; - args.parse(argc, argv); - if(args.help) - cout << args << endl; - else { - Connection connection; - args.open(connection); - AsyncSession session = connection.newSession(); - - //declare exchange, queue and bind them: - session.queueDeclare(arg::queue="response"); - std::string control = "control_" + session.getId().str(); - if (args.durable) { - session.queueDeclare(arg::queue=control, arg::durable=true); - } else { - session.queueDeclare(arg::queue=control, arg::exclusive=true, arg::autoDelete=true); - } - session.exchangeBind(arg::exchange="amq.topic", arg::queue=control, arg::bindingKey="topic_control"); - - //set up listener - SubscriptionManager mgr(session); - Listener listener(session, mgr, "response", args.transactional); - SubscriptionSettings settings; - if (args.prefetch) { - settings.autoAck = (args.ack ? args.ack : (args.prefetch / 2)); - settings.flowControl = FlowControl::messageCredit(args.prefetch); - } else { - settings.acceptMode = ACCEPT_MODE_NONE; - settings.flowControl = FlowControl::unlimited(); - } - listener.subscription = mgr.subscribe(listener, control, settings); - session.sync(); - - if( args.statusqueue.length() > 0 ) { - stringstream msg_str; - msg_str << "qpid-topic-listener: " << qpid::sys::SystemInfo::getProcessId(); - session.messageTransfer(arg::content=Message(msg_str.str(), args.statusqueue)); - cout << "Ready status put on queue '" << args.statusqueue << "'" << endl; - } - - if (args.transactional) { - session.txSelect(); - } - - cout << "qpid-topic-listener: listening..." << endl; - mgr.run(); - if (args.durable) { - session.queueDelete(arg::queue=control); - } - session.close(); - cout << "closing connection" << endl; - connection.close(); - } - return 0; - } catch (const std::exception& error) { - cout << "qpid-topic-listener: " << error.what() << endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/qpid-topic-publisher.cpp b/qpid/cpp/src/tests/qpid-topic-publisher.cpp deleted file mode 100644 index f9107b90d0..0000000000 --- a/qpid/cpp/src/tests/qpid-topic-publisher.cpp +++ /dev/null @@ -1,230 +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. - * - */ - -/** - * This file provides one half of a test and example of a pub-sub - * style of interaction. See qpid-topic-listener.cpp for the other half, in - * which the logic for subscribers is defined. - * - * This file contains the publisher logic. The publisher will send a - * number of messages to the exchange with the appropriate routing key - * for the logical 'topic'. Once it has done this it will then send a - * request that each subscriber report back with the number of message - * it has received and the time that elapsed between receiving the - * first one and receiving the report request. Once the expected - * number of reports are received, it sends out a request that each - * subscriber shutdown. - */ - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include -#include - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using namespace std; - -namespace qpid { -namespace tests { - -/** - * The publishing logic is defined in this class. It implements - * message listener and can therfore be used to receive messages sent - * back by the subscribers. - */ -class Publisher { - AsyncSession session; - SubscriptionManager mgr; - LocalQueue queue; - const string controlTopic; - const bool transactional; - const bool durable; - - string generateData(int size); - -public: - Publisher(const AsyncSession& session, const string& controlTopic, bool tx, bool durable); - int64_t publish(int msgs, int listeners, int size); - void terminate(); -}; - -/** - * A utility class for managing the options passed in to the test - */ -struct Args : public TestOptions { - int messages; - int subscribers; - bool transactional; - bool durable; - int batches; - int delay; - int size; - string statusqueue; - - Args() : messages(1000), subscribers(1), - transactional(false), durable(false), - batches(1), delay(0), size(256) - { - addOptions() - ("messages", optValue(messages, "N"), "how many messages to send") - ("subscribers", optValue(subscribers, "N"), "how many subscribers to expect reports from") - ("transactional", optValue(transactional), "client should use transactions") - ("durable", optValue(durable), "messages should be durable") - ("batches", optValue(batches, "N"), "how many batches to run") - ("delay", optValue(delay, "SECONDS"), "Causes a delay between each batch") - ("size", optValue(size, "BYTES"), "size of the published messages") - ("status-queue", optValue(statusqueue, "QUEUE-NAME"), "Message queue to read status messages from"); - } -}; - -Publisher::Publisher(const AsyncSession& _session, const string& _controlTopic, bool tx, bool d) : - session(_session), mgr(session), controlTopic(_controlTopic), transactional(tx), durable(d) -{ - mgr.subscribe(queue, "response"); -} - -int64_t Publisher::publish(int msgs, int listeners, int size){ - Message msg(generateData(size), controlTopic); - if (durable) { - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - AbsTime start = now(); - - for(int i = 0; i < msgs; i++){ - session.messageTransfer(arg::content=msg, arg::destination="amq.topic", arg::acceptMode=1); - } - //send report request - Message reportRequest("", controlTopic); - reportRequest.getHeaders().setString("TYPE", "REPORT_REQUEST"); - session.messageTransfer(arg::content=reportRequest, arg::destination="amq.topic", arg::acceptMode=1); - if(transactional){ - sync(session).txCommit(); - } - //wait for a response from each listener (TODO, could log these) - for (int i = 0; i < listeners; i++) { - Message report = queue.pop(); - } - - if(transactional){ - sync(session).txCommit(); - } - - AbsTime finish = now(); - return Duration(start, finish); -} - -string Publisher::generateData(int size){ - string data; - for(int i = 0; i < size; i++){ - data += ('A' + (i / 26)); - } - return data; -} - -void Publisher::terminate(){ - //send termination request - Message terminationRequest("", controlTopic); - terminationRequest.getHeaders().setString("TYPE", "TERMINATION_REQUEST"); - session.messageTransfer(arg::content=terminationRequest, arg::destination="amq.topic", arg::acceptMode=1); - if(transactional){ - session.txCommit(); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) { - try{ - Args args; - args.parse(argc, argv); - if(args.help) - cout << args << endl; - else { - Connection connection; - args.open(connection); - AsyncSession session = connection.newSession(); - - // If status-queue is defined, wait for all expected listeners to join in before we start - if( args.statusqueue.length() > 0 ) { - cout << "Waiting for " << args.subscribers << " listeners..." << endl; - SubscriptionManager statusSubs(session); - LocalQueue statusQ; - statusSubs.subscribe(statusQ, args.statusqueue); - for (int i = 0; i < args.subscribers; i++) { - Message m = statusQ.get(); - if( m.getData().find("topic_listener: ", 0) == 0 ) { - cout << "Listener " << (i+1) << " of " << args.subscribers - << " is ready (pid " << m.getData().substr(16, m.getData().length() - 16) - << ")" << endl; - } else { - throw Exception(QPID_MSG("Unexpected message received on status queue: " << m.getData())); - } - } - } - - if (args.transactional) { - session.txSelect(); - } - session.queueDeclare(arg::queue="response"); - session.exchangeBind(arg::exchange="amq.direct", arg::queue="response", arg::bindingKey="response"); - - Publisher publisher(session, "topic_control", args.transactional, args.durable); - - int batchSize(args.batches); - int64_t max(0); - int64_t min(0); - int64_t sum(0); - for(int i = 0; i < batchSize; i++){ - if(i > 0 && args.delay) qpid::sys::sleep(args.delay); - int64_t msecs = - publisher.publish(args.messages, - args.subscribers, - args.size) / TIME_MSEC; - if(!max || msecs > max) max = msecs; - if(!min || msecs < min) min = msecs; - sum += msecs; - cout << "Completed " << (i+1) << " of " << batchSize - << " in " << msecs << "ms" << endl; - } - publisher.terminate(); - int64_t avg = sum / batchSize; - if(batchSize > 1){ - cout << batchSize << " batches completed. avg=" << avg << - ", max=" << max << ", min=" << min << endl; - } - session.close(); - connection.close(); - } - return 0; - }catch(exception& error) { - cout << error.what() << endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/qpid-txtest.cpp b/qpid/cpp/src/tests/qpid-txtest.cpp deleted file mode 100644 index 59ab905af7..0000000000 --- a/qpid/cpp/src/tests/qpid-txtest.cpp +++ /dev/null @@ -1,342 +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 -#include -#include -#include -#include -#include - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/Thread.h" - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - -namespace qpid { -namespace tests { - -typedef std::vector StringSet; - -struct Args : public qpid::TestOptions { - bool init, transfer, check;//actions - uint size; - bool durable; - uint queues; - string base; - uint msgsPerTx; - uint txCount; - uint totalMsgCount; - bool dtx; - bool quiet; - - Args() : init(true), transfer(true), check(true), - size(256), durable(true), queues(2), - base("tx-test"), msgsPerTx(1), txCount(1), totalMsgCount(10), - dtx(false), quiet(false) - { - addOptions() - - ("init", optValue(init, "yes|no"), "Declare queues and populate one with the initial set of messages.") - ("transfer", optValue(transfer, "yes|no"), "'Move' messages from one queue to another using transactions to ensure no message loss.") - ("check", optValue(check, "yes|no"), "Check that the initial messages are all still available.") - ("size", optValue(size, "N"), "message size") - ("durable", optValue(durable, "yes|no"), "use durable messages") - ("queues", optValue(queues, "N"), "number of queues") - ("queue-base-name", optValue(base, ""), "base name for queues") - ("messages-per-tx", optValue(msgsPerTx, "N"), "number of messages transferred per transaction") - ("tx-count", optValue(txCount, "N"), "number of transactions per 'agent'") - ("total-messages", optValue(totalMsgCount, "N"), "total number of messages in 'circulation'") - ("dtx", optValue(dtx, "yes|no"), "use distributed transactions") - ("quiet", optValue(quiet), "reduce output from test"); - } -}; - -const std::string chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - -std::string generateData(uint size) -{ - if (size < chars.length()) { - return chars.substr(0, size); - } - std::string data; - for (uint i = 0; i < (size / chars.length()); i++) { - data += chars; - } - data += chars.substr(0, size % chars.length()); - return data; -} - -void generateSet(const std::string& base, uint count, StringSet& collection) -{ - for (uint i = 0; i < count; i++) { - std::ostringstream out; - out << base << "-" << (i+1); - collection.push_back(out.str()); - } -} - -Args opts; - -struct Client -{ - Connection connection; - AsyncSession session; - - Client() - { - opts.open(connection); - session = connection.newSession(); - } - - ~Client() - { - try{ - session.close(); - connection.close(); - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - } - } -}; - -struct Transfer : public Client, public Runnable -{ - std::string src; - std::string dest; - Thread thread; - framing::Xid xid; - - Transfer(const std::string& to, const std::string& from) : src(to), dest(from), xid(0x4c414e47, "", from) {} - - void run() - { - try { - - if (opts.dtx) session.dtxSelect(); - else session.txSelect(); - SubscriptionManager subs(session); - - LocalQueue lq; - SubscriptionSettings settings(FlowControl::messageWindow(opts.msgsPerTx)); - settings.autoAck = 0; // Disabled - Subscription sub = subs.subscribe(lq, src, settings); - - for (uint t = 0; t < opts.txCount; t++) { - Message in; - Message out("", dest); - if (opts.dtx) { - setNewXid(xid); - session.dtxStart(arg::xid=xid); - } - for (uint m = 0; m < opts.msgsPerTx; m++) { - in = lq.pop(); - std::string& data = in.getData(); - if (data.size() != opts.size) { - std::ostringstream oss; - oss << "Message size incorrect: size=" << in.getData().size() << "; expected " << opts.size; - throw std::runtime_error(oss.str()); - } - out.setData(data); - out.getMessageProperties().setCorrelationId(in.getMessageProperties().getCorrelationId()); - out.getDeliveryProperties().setDeliveryMode(in.getDeliveryProperties().getDeliveryMode()); - session.messageTransfer(arg::content=out, arg::acceptMode=1); - } - sub.accept(sub.getUnaccepted()); - if (opts.dtx) { - session.dtxEnd(arg::xid=xid); - session.dtxPrepare(arg::xid=xid); - session.dtxCommit(arg::xid=xid); - } else { - session.txCommit(); - } - session.sync(); - } - } catch(const std::exception& e) { - std::cout << "Transfer interrupted: " << e.what() << std::endl; - } - } - - void setNewXid(framing::Xid& xid) { - framing::Uuid uuid(true); - xid.setGlobalId(uuid.str()); - } -}; - -struct Controller : public Client -{ - StringSet ids; - StringSet queues; - - Controller() - { - generateSet(opts.base, opts.queues, queues); - generateSet("msg", opts.totalMsgCount, ids); - } - - void init() - { - //declare queues - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - session.queueDeclare(arg::queue=*i, arg::durable=opts.durable); - session.sync(); - } - - Message msg(generateData(opts.size), *queues.begin()); - if (opts.durable) { - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - - //publish messages - for (StringSet::iterator i = ids.begin(); i != ids.end(); i++) { - msg.getMessageProperties().setCorrelationId(*i); - session.messageTransfer(arg::content=msg, arg::acceptMode=1); - } - } - - void transfer() - { - boost::ptr_vector agents(opts.queues); - //launch transfer agents - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - StringSet::iterator next = i + 1; - if (next == queues.end()) next = queues.begin(); - - if (!opts.quiet) std::cout << "Transfering from " << *i << " to " << *next << std::endl; - agents.push_back(new Transfer(*i, *next)); - agents.back().thread = Thread(agents.back()); - } - - for (boost::ptr_vector::iterator i = agents.begin(); i != agents.end(); i++) { - i->thread.join(); - } - } - - int check() - { - SubscriptionManager subs(session); - - // Recover DTX transactions (if any) - if (opts.dtx) { - framing::DtxRecoverResult dtxRes = session.dtxRecover().get(); - const framing::Array& xidArr = dtxRes.getInDoubt(); - std::vector inDoubtXids(xidArr.size()); - std::transform(xidArr.begin(), xidArr.end(), inDoubtXids.begin(), framing::Array::get); - - if (inDoubtXids.size()) { - if (!opts.quiet) std::cout << "Recovering DTX in-doubt transaction(s):" << std::endl; - framing::StructHelper decoder; - framing::Xid xid; - // abort even, commit odd transactions - for (unsigned i = 0; i < inDoubtXids.size(); i++) { - decoder.decode(xid, inDoubtXids[i]); - if (!opts.quiet) std::cout << (i%2 ? " * aborting " : " * committing "); - xid.print(std::cout); - std::cout << std::endl; - if (i%2) { - session.dtxRollback(arg::xid=xid); - } else { - session.dtxCommit(arg::xid=xid); - } - } - } - } - - StringSet drained; - //drain each queue and verify the correct set of messages are available - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - //subscribe, allocate credit and flushn - LocalQueue lq; - SubscriptionSettings settings(FlowControl::unlimited(), ACCEPT_MODE_NONE); - subs.subscribe(lq, *i, settings); - session.messageFlush(arg::destination=*i); - session.sync(); - - uint count(0); - while (!lq.empty()) { - Message m = lq.pop(); - //add correlation ids of received messages to drained - drained.push_back(m.getMessageProperties().getCorrelationId()); - ++count; - } - if (!opts.quiet) std::cout << "Drained " << count << " messages from " << *i << std::endl; - } - - sort(ids.begin(), ids.end()); - sort(drained.begin(), drained.end()); - - //check that drained == ids - StringSet missing; - set_difference(ids.begin(), ids.end(), drained.begin(), drained.end(), back_inserter(missing)); - - StringSet extra; - set_difference(drained.begin(), drained.end(), ids.begin(), ids.end(), back_inserter(extra)); - - if (missing.empty() && extra.empty()) { - std::cout << "All expected messages were retrieved." << std::endl; - return 0; - } else { - if (!missing.empty()) { - std::cout << "The following ids were missing:" << std::endl; - for (StringSet::iterator i = missing.begin(); i != missing.end(); i++) { - std::cout << " '" << *i << "'" << std::endl; - } - } - if (!extra.empty()) { - std::cout << "The following extra ids were encountered:" << std::endl; - for (StringSet::iterator i = extra.begin(); i != extra.end(); i++) { - std::cout << " '" << *i << "'" << std::endl; - } - } - return 1; - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - Controller controller; - if (opts.init) controller.init(); - if (opts.transfer) controller.transfer(); - if (opts.check) return controller.check(); - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - } - return 2; -} diff --git a/qpid/cpp/src/tests/qpid-txtest2.cpp b/qpid/cpp/src/tests/qpid-txtest2.cpp deleted file mode 100644 index 58c48f9a8d..0000000000 --- a/qpid/cpp/src/tests/qpid-txtest2.cpp +++ /dev/null @@ -1,363 +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 -#include -#include -#include -#include -#include - -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Session.h" -#include -#include -#include -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" - -using namespace qpid::messaging; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -typedef std::vector StringSet; - -struct Options : public qpid::Options { - bool help; - bool init, transfer, check;//actions - uint size; - bool durable; - uint queues; - std::string base; - uint msgsPerTx; - uint txCount; - uint totalMsgCount; - bool dtx; - uint capacity; - std::string url; - std::string connectionOptions; - qpid::log::Options log; - uint port; - bool quiet; - double fetchTimeout; - - Options() : help(false), init(true), transfer(true), check(true), - size(256), durable(true), queues(2), - base("tx"), msgsPerTx(1), txCount(5), totalMsgCount(10), - capacity(1000), url("localhost"), port(0), quiet(false), fetchTimeout(5) - { - addOptions() - ("init", qpid::optValue(init, "yes|no"), "Declare queues and populate one with the initial set of messages.") - ("transfer", qpid::optValue(transfer, "yes|no"), "'Move' messages from one queue to another using transactions to ensure no message loss.") - ("check", qpid::optValue(check, "yes|no"), "Check that the initial messages are all still available.") - ("size", qpid::optValue(size, "N"), "message size") - ("durable", qpid::optValue(durable, "yes|no"), "use durable messages") - ("queues", qpid::optValue(queues, "N"), "number of queues") - ("queue-base-name", qpid::optValue(base, ""), "base name for queues") - ("messages-per-tx", qpid::optValue(msgsPerTx, "N"), "number of messages transferred per transaction") - ("tx-count", qpid::optValue(txCount, "N"), "number of transactions per 'agent'") - ("total-messages", qpid::optValue(totalMsgCount, "N"), "total number of messages in 'circulation'") - ("capacity", qpid::optValue(capacity, "N"), "Pre-fetch window (0 implies no pre-fetch)") - ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to") - ("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection") - ("port,p", qpid::optValue(port, "PORT"), "(for test compatibility only, use broker option instead)") - ("quiet", qpid::optValue(quiet), "reduce output from test") - ("fetch-timeout", qpid::optValue(fetchTimeout, "SECONDS"), "Timeout for transactional fetch") - ("help", qpid::optValue(help), "print this usage statement"); - add(log); - } - - bool parse(int argc, char** argv) - { - try { - qpid::Options::parse(argc, argv); - if (port) { - if (url == "localhost") { - std::stringstream u; - u << url << ":" << port; - url = u.str(); - } else { - std::cerr << *this << std::endl << std::endl - << "--port and --broker should not be specified together; specify full url in --broker option" << std::endl; - return false; - } - - } - qpid::log::Logger::instance().configure(log); - if (help) { - std::cout << *this << std::endl << std::endl - << "Transactionally moves messages between queues" << std::endl; - return false; - } - if (totalMsgCount < msgsPerTx) { - totalMsgCount = msgsPerTx; // Must have at least msgsPerTx total messages. - } - return true; - } catch (const std::exception& e) { - std::cerr << *this << std::endl << std::endl << e.what() << std::endl; - return false; - } - } -}; - -const std::string chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - -std::string generateData(uint size) -{ - if (size < chars.length()) { - return chars.substr(0, size); - } - std::string data; - for (uint i = 0; i < (size / chars.length()); i++) { - data += chars; - } - data += chars.substr(0, size % chars.length()); - return data; -} - -void generateSet(const std::string& base, uint count, StringSet& collection) -{ - for (uint i = 0; i < count; i++) { - std::ostringstream digits; - digits << count; - std::ostringstream out; - out << base << "-" << std::setw(digits.str().size()) << std::setfill('0') << (i+1); - collection.push_back(out.str()); - } -} - -struct Client -{ - const Options& opts; - Connection connection; - Session session; - - Client(const Options& o, bool transactional=false) : opts(o), connection(opts.url, opts.connectionOptions) - { - connection.open(); - session = transactional ? connection.createTransactionalSession() : connection.createSession(); - } - - virtual ~Client() - { - try { - session.sync(); - session.close(); - connection.close(); - } catch(const std::exception& e) { - std::cout << "Client shutdown: " << e.what() << std::endl; - } - } -}; - -struct TransactionalClient : Client -{ - TransactionalClient(const Options& o) : Client(o, true) {} - virtual ~TransactionalClient() {} -}; - -struct Transfer : public TransactionalClient, public Runnable -{ - const std::string target; - const std::string source; - Thread thread; - bool failed; - - Transfer(const std::string& to, const std::string& from, const Options& opts) : TransactionalClient(opts), target(to), source(from), failed(false) {} - - void run() - { - try { - - Sender sender(session.createSender(target)); - Receiver receiver(session.createReceiver(source)); - receiver.setCapacity(opts.capacity); - for (uint t = 0; t < opts.txCount;) { - std::ostringstream id; - id << source << ">" << target << ":" << t+1; - try { - for (uint m = 0; m < opts.msgsPerTx; m++) { - Message msg = receiver.fetch(Duration::SECOND*uint64_t(opts.fetchTimeout)); - if (msg.getContentSize() != opts.size) { - std::ostringstream oss; - oss << "Message size incorrect: size=" << msg.getContentSize() << "; expected " << opts.size; - throw std::runtime_error(oss.str()); - } - sender.send(msg); - } - session.commit(); - t++; - if (!opts.quiet) std::cout << "Transaction " << id.str() << " of " << opts.txCount << " committed successfully" << std::endl; - } catch (const TransactionAborted&) { - std::cout << "Transaction " << id.str() << " of " << opts.txCount << " was aborted and will be retried" << std::endl; - session = connection.createTransactionalSession(); - sender = session.createSender(target); - receiver = session.createReceiver(source); - receiver.setCapacity(opts.capacity); - } - } - sender.close(); - receiver.close(); - } catch(const std::exception& e) { - failed = true; - QPID_LOG(error, "Transfer " << source << " to " << target << " interrupted: " << e.what()); - } - } -}; - -namespace { -const std::string CREATE_DURABLE("; {create:always, node:{durable:True}}"); -const std::string CREATE_NON_DURABLE("; {create:always}"); -} - -struct Controller : public Client -{ - StringSet ids; - StringSet queues; - - Controller(const Options& opts) : Client(opts) - { - generateSet(opts.base, opts.queues, queues); - generateSet("msg", opts.totalMsgCount, ids); - } - - void init() - { - Message msg(generateData(opts.size)); - msg.setDurable(opts.durable); - - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - std::string address = *i + (opts.durable ? CREATE_DURABLE : CREATE_NON_DURABLE); - - // Clear out any garbage on queues. - Receiver receiver = session.createReceiver(address); - Message rmsg; - uint count(0); - while (receiver.fetch(rmsg, Duration::IMMEDIATE)) ++count; - session.acknowledge(); - receiver.close(); - if (!opts.quiet) std::cout << "Cleaned up " << count << " messages from " << *i << std::endl; - - Sender sender = session.createSender(address); - if (i == queues.begin()) { - for (StringSet::iterator i = ids.begin(); i != ids.end(); i++) { - msg.setCorrelationId(*i); - sender.send(msg); - } - } - sender.close(); - } - } - - void transfer() - { - boost::ptr_vector agents(opts.queues); - //launch transfer agents - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - StringSet::iterator next = i + 1; - if (next == queues.end()) next = queues.begin(); - - if (!opts.quiet) std::cout << "Transfering from " << *i << " to " << *next << std::endl; - agents.push_back(new Transfer(*i, *next, opts)); - agents.back().thread = Thread(agents.back()); - } - - for (boost::ptr_vector::iterator i = agents.begin(); i != agents.end(); i++) - i->thread.join(); - for (boost::ptr_vector::iterator i = agents.begin(); i != agents.end(); i++) - if (i->failed) - throw std::runtime_error("Transfer agents failed"); - } - - int check() - { - StringSet drained; - //drain each queue and verify the correct set of messages are available - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - Receiver receiver = session.createReceiver(*i); - uint count(0); - Message msg; - while (receiver.fetch(msg, Duration::IMMEDIATE)) { - //add correlation ids of received messages to drained - drained.push_back(msg.getCorrelationId()); - ++count; - } - session.acknowledge(); - receiver.close(); - if (!opts.quiet) std::cout << "Drained " << count << " messages from " << *i << std::endl; - } - sort(ids.begin(), ids.end()); - sort(drained.begin(), drained.end()); - - //check that drained == ids - StringSet missing; - set_difference(ids.begin(), ids.end(), drained.begin(), drained.end(), back_inserter(missing)); - - StringSet extra; - set_difference(drained.begin(), drained.end(), ids.begin(), ids.end(), back_inserter(extra)); - - if (missing.empty() && extra.empty()) { - std::cout << "All expected messages were retrieved." << std::endl; - return 0; - } else { - if (!missing.empty()) { - std::cout << "The following ids were missing:" << std::endl; - for (StringSet::iterator i = missing.begin(); i != missing.end(); i++) { - std::cout << " '" << *i << "'" << std::endl; - } - } - if (!extra.empty()) { - std::cout << "The following extra ids were encountered:" << std::endl; - for (StringSet::iterator i = extra.begin(); i != extra.end(); i++) { - std::cout << " '" << *i << "'" << std::endl; - } - } - return 1; - } - } -}; -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - Options opts; - if (opts.parse(argc, argv)) { - Controller controller(opts); - if (opts.init) controller.init(); - if (opts.transfer) controller.transfer(); - if (opts.check) return controller.check(); - return 0; - } - return 1; - } catch(const std::exception& e) { - std::cerr << argv[0] << ": " << e.what() << std::endl; - } - return 2; -} diff --git a/qpid/cpp/src/tests/qpidd-empty.conf b/qpid/cpp/src/tests/qpidd-empty.conf deleted file mode 100644 index cf3f19fba0..0000000000 --- a/qpid/cpp/src/tests/qpidd-empty.conf +++ /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. -# - -# An empty configuration file. -# Used when running tests to avoid picking up configuration -# installed in the default place. diff --git a/qpid/cpp/src/tests/qpidd-p0 b/qpid/cpp/src/tests/qpidd-p0 deleted file mode 100755 index 1f7807afd2..0000000000 --- a/qpid/cpp/src/tests/qpidd-p0 +++ /dev/null @@ -1,46 +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. -# - -# Wrapper script to allocate a port and fork a broker to listen on it. -# -# Instead of this: -# qpidd --port 0 -# do this: -# qpidd-p0 -# -# The port is bound by python code, and then handed over to the broker via the -# --socket-fd option. This avoids problems with the qpidd --port 0 option which -# ocassional fails with an "address in use" error. It's not clear why --port 0 -# doesn't work, it may be to do with the way qpidd binds a port to multiple -# addresses on a multi-homed host. -# - -import subprocess, socket, time, os, sys - -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(("", 0)) -s.listen(5) -port = s.getsockname()[1] -print port -sys.stdout.flush() -if len(sys.argv) > 1: - cmd = sys.argv[1:] + ["--socket-fd", str(s.fileno()), "--listen-disable=tcp"] - os.execvp(sys.argv[1], cmd) diff --git a/qpid/cpp/src/tests/qpidd_qmfv2_tests.py b/qpid/cpp/src/tests/qpidd_qmfv2_tests.py deleted file mode 100755 index 2b45cb6eea..0000000000 --- a/qpid/cpp/src/tests/qpidd_qmfv2_tests.py +++ /dev/null @@ -1,278 +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. -# - -# Runs QMF tests against a broker running with QMFv1 disabled. This forces the -# broker to use QMFv2 only. This is necessary as if there is a bug in V2, some -# V1 operations may hide that (esp. asynchonous notifications) - - -import sys, shutil, os -from time import sleep -from brokertest import * -from qpid.messaging import Message -try: import qmf.console -except: print "Cannot import module qmf.console, skipping tests"; exit(0); - -import qpid.messaging, brokertest -brokertest.qm = qpid.messaging # TODO aconway 2014-04-04: Tests fail with SWIG client. - -class ConsoleTest(BrokerTest): - """ - Test QMFv2 support using the qmf.console library. - """ - PUB_INTERVAL=1 - - def setUp(self): - BrokerTest.setUp(self) - - 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 _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())) - - def _create_queue( self, q_name, args={} ): - broker = self.qmf_session.getObjects(_class="broker")[0] - result = broker.create("queue", q_name, args, False) - self.assertEqual(result.status, 0, result) - - - def _test_method_call(self): - """ Verify method calls work, and check the behavior of getObjects() - call - """ - self._myStartQmf( self.broker ) - self._create_queue( "fleabag", {"auto-delete":True} ) - - qObj = None - queues = self.qmf_session.getObjects(_class="queue") - for q in queues: - if q.name == "fleabag": - qObj = q - break - self.assertNotEqual(qObj, None, "Failed to get queue object") - #print qObj - - 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 = [] - self.newclass = [] - self.agents = [] - self.events = [] - self.updates = {} # holds the objects by OID - self.heartbeats = [] - - def brokerInfo(self, broker): - #print "brokerInfo:", broker - self.broker_info.append(broker) - def brokerConnected(self, broker): - #print "brokerConnected:", broker - self.broker_conn.append(broker) - def newPackage(self, name): - #print "newPackage:", name - self.newpackage.append(name) - def newClass(self, kind, classKey): - #print "newClass:", kind, classKey - self.newclass.append( (kind, classKey) ) - def newAgent(self, agent): - #print "newAgent:", agent - self.agents.append( agent ) - def event(self, broker, event): - #print "EVENT %s" % event - self.events.append(event) - 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): - assert len(record.getStatistics()), "objectStats() invoked with no properties?" - self._handle_obj_update(record) - - handler = 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 - self.broker.send_message( "fleabag", Message("Hi") ) - # and we should get a few heartbeats - sleep(self.PUB_INTERVAL) - self.broker.send_message( "fleabag", Message("Hi") ) - sleep(self.PUB_INTERVAL) - self.broker.send_message( "fleabag", Message("Hi") ) - sleep(self.PUB_INTERVAL * 2) - - assert handler.broker_info, "No BrokerInfo callbacks received" - assert handler.broker_conn, "No BrokerConnected callbacks received" - assert handler.newpackage, "No NewPackage callbacks received" - assert handler.newclass, "No NewClass callbacks received" - assert handler.agents, "No NewAgent callbacks received" - assert handler.events, "No event callbacks received" - assert handler.updates, "No updates received" - assert handler.heartbeats, "No heartbeat callbacks received" - - # now verify updates for queue "fleabag" were received, and the - # msgDepth statistic is correct - - msgs = 0 - for o in handler.updates.itervalues(): - key = o.getClassKey() - if key and key.getClassName() == "queue" and o.name == "fleabag": - assert o.msgDepth, "No update to msgDepth statistic!" - msgs = o.msgDepth - break - assert msgs == 3, "msgDepth statistics not accurate!" - - # 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() - self.xmtList = {} - self.rcvList = {} - - def methodResponse(self, broker, seq, response): - self.cv.acquire() - try: - self.rcvList[seq] = response - finally: - self.cv.release() - - def request(self, broker, count): - self.count = count - for idx in range(count): - self.cv.acquire() - try: - seq = broker.echo(idx, "Echo Message", _async = True) - self.xmtList[seq] = idx - finally: - self.cv.release() - - def check(self): - if self.count != len(self.xmtList): - return "fail (attempted send=%d, actual sent=%d)" % (self.count, len(self.xmtList)) - lost = 0 - mismatched = 0 - for seq in self.xmtList: - value = self.xmtList[seq] - if seq in self.rcvList: - result = self.rcvList.pop(seq) - if result.sequence != value: - mismatched += 1 - else: - lost += 1 - spurious = len(self.rcvList) - if lost == 0 and mismatched == 0 and spurious == 0: - return "pass" - else: - return "fail (lost=%d, mismatch=%d, spurious=%d)" % (lost, mismatched, spurious) - - handler = 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) - os.execvp("qpid-python-test", - ["qpid-python-test", "-m", "qpidd_qmfv2_tests"] + sys.argv[1:]) - diff --git a/qpid/cpp/src/tests/queue_flow_limit_tests.py b/qpid/cpp/src/tests/queue_flow_limit_tests.py deleted file mode 100644 index 83e31e979b..0000000000 --- a/qpid/cpp/src/tests/queue_flow_limit_tests.py +++ /dev/null @@ -1,376 +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. -# - -import sys -from qpid.testlib import TestBase010 -from qpid.messaging import Connection -from threading import Thread -from time import sleep, time -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) - else: - raise AttributeError - - def _create_queue(self, name, - stop_count=None, resume_count=None, - stop_size=None, resume_size=None, - max_size=None, max_count=None): - """ Create a queue with the given flow settings via the queue.declare - command. - """ - args={} - if (stop_count is not None): - args["qpid.flow_stop_count"] = stop_count; - if (resume_count is not None): - args["qpid.flow_resume_count"] = resume_count; - if (stop_size is not None): - args["qpid.flow_stop_size"] = stop_size; - if (resume_size is not None): - args["qpid.flow_resume_size"] = resume_size; - if (max_size is not None): - args["qpid.max_size"] = max_size; - if (max_count is not None): - args["qpid.max_count"] = max_count; - - broker = self.qmf.getObjects(_class="broker")[0] - rc = broker.create( "queue", name, args, True ) - self.assertEqual(rc.status, 0, rc) - - qs = self.qmf.getObjects(_class="queue") - for i in qs: - if i.name == name: - # verify flow settings - if (stop_count is not None): - self.assertEqual(i.arguments.get("qpid.flow_stop_count"), stop_count) - if (resume_count is not None): - self.assertEqual(i.arguments.get("qpid.flow_resume_count"), resume_count) - if (stop_size is not None): - self.assertEqual(i.arguments.get("qpid.flow_stop_size"), stop_size) - if (resume_size is not None): - self.assertEqual(i.arguments.get("qpid.flow_resume_size"), resume_size) - if (max_size is not None): - self.assertEqual(i.arguments.get("qpid.max_size"), max_size) - if (max_count is not None): - self.assertEqual(i.arguments.get("qpid.max_count"), max_count) - self.failIf(i.flowStopped) - return i.getObjectId() - self.fail("Unable to create queue '%s'" % name) - return None - - - def _delete_queue(self, name): - """ Delete a named queue - """ - broker = self.qmf.getObjects(_class="broker")[0] - rc = broker.delete( "queue", name, {} ) - self.assertEqual(rc.status, 0, rc) - - - def _start_qpid_send(self, queue, count, content="X", capacity=100): - """ Use the qpid-send client to generate traffic to a queue. - """ - command = "qpid-send" + \ - " -b" + " %s:%s" % (self.broker.host, self.broker.port) \ - + " -a " + str(queue) \ - + " --messages " + str(count) \ - + " --content-string " + str(content) \ - + " --capacity " + str(capacity) - return popen(command) - - def _start_qpid_receive(self, queue, count, timeout=5): - """ Use the qpid-receive client to consume from a queue. - Note well: prints one line of text to stdout for each consumed msg. - """ - command = "qpid-receive" + \ - " -b " + "%s:%s" % (self.broker.host, self.broker.port) \ - + " -a " + str(queue) \ - + " --messages " + str(count) \ - + " --timeout " + str(timeout) \ - + " --print-content yes" - return popen(command) - - def test_qpid_config_cmd(self): - """ Test the qpid-config command's ability to configure a queue's flow - control thresholds. - """ - tool = environ.get("QPID_CONFIG_EXEC") - if tool: - command = tool + \ - " --broker=%s:%s " % (self.broker.host, self.broker.port) \ - + "add queue test01 --flow-stop-count=999" \ - + " --flow-resume-count=55 --flow-stop-size=5000000" \ - + " --flow-resume-size=100000" - cmd = popen(command) - rc = cmd.close() - self.assertEqual(rc, None) - - # now verify the settings - self.startQmf(); - qs = self.qmf.getObjects(_class="queue") - for i in qs: - if i.name == "test01": - self.assertEqual(i.arguments.get("qpid.flow_stop_count"), 999) - self.assertEqual(i.arguments.get("qpid.flow_resume_count"), 55) - self.assertEqual(i.arguments.get("qpid.flow_stop_size"), 5000000) - self.assertEqual(i.arguments.get("qpid.flow_resume_size"), 100000) - self.failIf(i.flowStopped) - break; - self.assertEqual(i.name, "test01") - self._delete_queue("test01") - - - def test_flow_count(self): - """ Create a queue with count-based flow limit. Spawn several - producers which will exceed the limit. Verify limit exceeded. Consume - all messages. Verify flow control released. - """ - self.startQmf(); - oid = self._create_queue("test-q", stop_count=373, resume_count=229) - self.assertEqual(self.qmf.getObjects(_objectId=oid)[0].flowStoppedCount, 0) - - sndr1 = self._start_qpid_send("test-q", count=1213, content="XXX", capacity=50); - sndr2 = self._start_qpid_send("test-q", count=797, content="Y", capacity=13); - sndr3 = self._start_qpid_send("test-q", count=331, content="ZZZZZ", capacity=149); - totalMsgs = 1213 + 797 + 331 - - # wait until flow control is active - deadline = time() + self._timeout - while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \ - time() < deadline: - pass - self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStopped) - depth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - self.assertGreater(depth, 373) - - # now wait until the enqueues stop happening - ensure that - # not all msgs have been sent (senders are blocked) - sleep(1) - newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - while depth != newDepth: - depth = newDepth; - sleep(1) - newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - self.assertGreater(totalMsgs, depth) - - # drain the queue - rcvr = self._start_qpid_receive("test-q", - count=totalMsgs) - count = 0; - x = rcvr.readline() # prints a line for each received msg - while x: - count += 1; - x = rcvr.readline() - - sndr1.close(); - sndr2.close(); - sndr3.close(); - rcvr.close(); - - self.assertEqual(count, totalMsgs) - self.failIf(self.qmf.getObjects(_objectId=oid)[0].flowStopped) - self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStoppedCount) - - self._delete_queue("test-q") - - - def test_flow_size(self): - """ Create a queue with size-based flow limit. Spawn several - producers which will exceed the limit. Verify limit exceeded. Consume - all messages. Verify flow control released. - """ - self.startQmf(); - oid = self._create_queue("test-q", stop_size=351133, resume_size=251143) - - sndr1 = self._start_qpid_send("test-q", count=1699, content="X"*439, capacity=53); - sndr2 = self._start_qpid_send("test-q", count=1129, content="Y"*631, capacity=13); - sndr3 = self._start_qpid_send("test-q", count=881, content="Z"*823, capacity=149); - totalMsgs = 1699 + 1129 + 881 - - # wait until flow control is active - deadline = time() + self._timeout - while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \ - time() < deadline: - pass - self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStopped) - self.assertGreater(self.qmf.getObjects(_objectId=oid)[0].byteDepth, 351133) - - # now wait until the enqueues stop happening - ensure that - # not all msgs have been sent (senders are blocked) - depth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - sleep(1) - newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - while depth != newDepth: - depth = newDepth; - sleep(1) - newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - self.assertGreater(totalMsgs, depth) - - # drain the queue - rcvr = self._start_qpid_receive("test-q", - count=totalMsgs) - count = 0; - x = rcvr.readline() # prints a line for each received msg - while x: - count += 1; - x = rcvr.readline() - - sndr1.close(); - sndr2.close(); - sndr3.close(); - rcvr.close(); - - self.assertEqual(count, totalMsgs) - self.failIf(self.qmf.getObjects(_objectId=oid)[0].flowStopped) - - self._delete_queue("test-q") - - - def verify_limit(self, testq): - """ run a limit check against the testq object - """ - - testq.mgmt = self.qmf.getObjects(_objectId=testq.oid)[0] - - # 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() + self._timeout - while (not testq.mgmt.flowStopped) and time() < deadline: - testq.mgmt.update() - - self.failUnless(testq.verifyStopped()) - - # now consume enough messages to drop below the flow resume point, and - # verify flow control is released. - rcvr = self._start_qpid_receive(testq.mgmt.name, count=testq.consumeCount) - rcvr.readlines() # prints a line for each received msg - rcvr.close(); - - # we should now be below the resume threshold - self.failUnless(testq.verifyResumed()) - - self._delete_queue(testq.mgmt.name) - sndr1.close(); - - - def test_default_flow_count(self): - """ Create a queue with count-based size limit, and verify the computed - thresholds using the broker's default ratios. - """ - class TestQ: - def __init__(self, oid): - # Use the broker-wide default flow thresholds of 80%/70% (see - # run_queue_flow_limit_tests) to base the thresholds off the - # queue's max_count configuration parameter - # max_count == 1000 -> stop == 800, resume == 700 - self.oid = oid - self.sendCount = 1000 - self.consumeCount = 301 # (send - resume) + 1 to reenable flow - self.content = "X" - self.mgmt = None - def verifyStopped(self): - self.mgmt.update() - return self.mgmt.flowStopped and (self.mgmt.msgDepth > 800) - def verifyResumed(self): - self.mgmt.update() - return (not self.mgmt.flowStopped) and (self.mgmt.msgDepth < 700) - - self.startQmf(); - oid = self._create_queue("test-X", max_count=1000) - self.verify_limit(TestQ(oid)) - - - def test_default_flow_size(self): - """ Create a queue with byte-based size limit, and verify the computed - thresholds using the broker's default ratios. - """ - class TestQ: - def __init__(self, oid): - # Use the broker-wide default flow thresholds of 80%/70% (see - # run_queue_flow_limit_tests) to base the thresholds off the - # queue's max_count configuration parameter - # max_size == 10000 -> stop == 8000 bytes, resume == 7000 bytes - self.oid = oid - self.sendCount = 2000 - self.consumeCount = 601 # (send - resume) + 1 to reenable flow - self.content = "XXXXX" # 5 bytes per message sent. - self.mgmt = None - def verifyStopped(self): - self.mgmt.update() - return self.mgmt.flowStopped and (self.mgmt.byteDepth > 8000) - def verifyResumed(self): - self.mgmt.update() - return (not self.mgmt.flowStopped) and (self.mgmt.byteDepth < 7000) - - self.startQmf(); - oid = self._create_queue("test-Y", max_size=10000) - self.verify_limit(TestQ(oid)) - - - def test_blocked_queue_delete(self): - """ Verify that blocked senders are unblocked when a queue that is flow - controlled is deleted. - """ - - class BlockedSender(Thread): - def __init__(self, tester, queue, count, capacity=10): - self.tester = tester - self.queue = queue - self.count = count - self.capacity = capacity - Thread.__init__(self) - self.done = False - self.start() - def run(self): - # spawn qpid-send - p = self.tester._start_qpid_send(self.queue, - self.count, - self.capacity) - p.close() # waits for qpid-send to complete - self.done = True - - self.startQmf(); - oid = self._create_queue("kill-q", stop_size=10, resume_size=2) - q = self.qmf.getObjects(_objectId=oid)[0] - self.failIf(q.flowStopped) - - sender = BlockedSender(self, "kill-q", count=100) - # wait for flow control - deadline = time() + self._timeout - while (not q.flowStopped) and time() < deadline: - q.update() - - self.failUnless(q.flowStopped) - self.failIf(sender.done) # sender blocked - - self._delete_queue("kill-q") - sender.join(5) - self.failIf(sender.isAlive()) - self.failUnless(sender.done) - - - - diff --git a/qpid/cpp/src/tests/queue_redirect.py b/qpid/cpp/src/tests/queue_redirect.py deleted file mode 100644 index 8a7b4c244b..0000000000 --- a/qpid/cpp/src/tests/queue_redirect.py +++ /dev/null @@ -1,317 +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. -# - -import sys -import qpid -from qpid.util import connect -from qpid.connection import Connection -from qpid.datatypes import uuid4 -from qpid.testlib import TestBase010 -from qmf.console import Session -from qpid.datatypes import Message -import qpid.messaging -from time import sleep -from os import environ, popen - -class ACLFile: - def __init__(self, policy='data_dir/policy.acl'): - self.f = open(policy,'w') - - def write(self,line): - self.f.write(line) - - def close(self): - self.f.close() - -class QueueredirectTests(TestBase010): - - def get_session(self, user, passwd): - socket = connect(self.broker.host, self.broker.port) - connection = Connection (sock=socket, username=user, password=passwd, - mechanism="PLAIN") - connection.start() - return connection.session(str(uuid4())) - - def reload_acl(self): - result = None - try: - self.broker_access.reloadAclFile() - except Exception, e: - result = str(e) - return result - - def get_acl_file(self): - return ACLFile(self.config.defines.get("policy-file", "data_dir/policy.acl")) - - def setUp(self): - aclf = self.get_acl_file() - aclf.write('acl allow all all\n') - aclf.close() - TestBase010.setUp(self) - self.startBrokerAccess() - self.reload_acl() - - def tearDown(self): - aclf = self.get_acl_file() - aclf.write('acl allow all all\n') - aclf.close() - self.reload_acl() - TestBase010.tearDown(self) - - - def redirect(self, srcQueue, tgtQueue, expectPass, failMessage): - try: - result = {} - result = self.broker_access.Redirect(srcQueue, tgtQueue) - if not expectPass: - self.fail("src:" + srcQueue + ", tgt:" + tgtQueue + " - " + failMessage) - except Exception, e: - if expectPass: - self.fail("src:" + srcQueue + ", tgt:" + tgtQueue + " - " + failMessage) - - def create_queue(self, session, name, autoDelete): - try: - session.queue_declare(queue=name, auto_delete=autoDelete) - except Exception, e: - self.fail("Should allow create queue " + name) - - def _start_qpid_send(self, queue, count, content="X", capacity=100): - """ Use the qpid-send client to generate traffic to a queue. - """ - command = "qpid-send" + \ - " -b" + " %s:%s" % (self.broker.host, self.broker.port) \ - + " -a " + str(queue) \ - + " --messages " + str(count) \ - + " --content-string " + str(content) \ - + " --capacity " + str(capacity) - return popen(command) - - def _start_qpid_receive(self, queue, count, timeout=5): - """ Use the qpid-receive client to consume from a queue. - Note well: prints one line of text to stdout for each consumed msg. - """ - command = "qpid-receive" + \ - " -b " + "%s:%s" % (self.broker.host, self.broker.port) \ - + " -a " + str(queue) \ - + " --messages " + str(count) \ - + " --timeout " + str(timeout) \ - + " --print-content yes" - return popen(command) - - - - #===================================== - # QT queue tests - #===================================== - - def test_010_deny_backing_up_a_nonexistant_queue(self): - session = self.get_session('bob','bob') - self.redirect("A010", "A010", False, "Should not allow redirect to non-existent queue A010") - session.close() - - def test_020_deny_destroy_redirect(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A020", False) - self.redirect("A020", "", False, "Should not allow destroying redirect") - session.close() - - def test_030_deny_redirecting_to_nonexistent_queue(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A030", False) - self.redirect("A030", "Axxx", False, "Should not allow redirect with non-existent queue Axxx") - session.close() - - def test_040_deny_queue_redirecting_to_itself(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A040", False) - self.redirect("A040", "A040", False, "Should not allow redirect with itself") - session.close() - - def test_050_deny_redirecting_autodelete_queue(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A050", True) - self.create_queue(session, "B050", False) - self.redirect("A050", "B050", False, "Should not allow redirect with autodelete source queue") - self.redirect("B050", "A050", False, "Should not allow redirect with autodelete target queue") - session.close() - - def test_100_create_redirect_queue_pair(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A100", False) - self.create_queue(session, "B100", False) - self.redirect("A100", "B100", True, "Should allow redirect") - session.close() - - def test_110_deny_adding_second_redirect_to_queue(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A110", False) - self.create_queue(session, "B110", False) - self.create_queue(session, "C110", False) - self.redirect("A110", "B110", True, "Should allow redirect") - self.redirect("A110", "C110", False, "Should deny second redirect") - self.redirect("C110", "B110", False, "Should deny second redirect") - session.close() - - def test_120_verify_redirect_to_target(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A120", False) - self.create_queue(session, "B120", False) - - # Send messages to original queue - sndr1 = self._start_qpid_send("A120", count=5, content="A120-before-rebind"); - sndr1.close() - - # redirect - self.redirect("A120", "B120", True, "Should allow redirect") - - # Send messages to original queue - sndr2 = self._start_qpid_send("A120", count=3, content="A120-after-rebind"); - sndr2.close() - - # drain the queue - rcvr = self._start_qpid_receive("A120", - count=5) - count = 0; - x = rcvr.readline() # prints a line for each received msg - while x: -# print "Read from A120 " + x - count += 1; - x = rcvr.readline() - - self.assertEqual(count, 5) - - # drain the queue - rcvrB = self._start_qpid_receive("B120", - count=3) - count = 0; - x = rcvrB.readline() # prints a line for each received msg - while x: -# print "Read from B120 " + x - count += 1; - x = rcvrB.readline() - - self.assertEqual(count, 3) - - ###session.close() - - def test_140_verify_redirect_to_source(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A140", False) - self.create_queue(session, "B140", False) - - # Send messages to target queue - these go onto B - sndr1 = self._start_qpid_send("B140", count=5, content="B140-before-rebind"); - sndr1.close() - - # redirect - self.redirect("A140", "B140", True, "Should allow redirect") - - # Send messages to target queue - these go onto A - sndr2 = self._start_qpid_send("B140", count=3, content="B140-after-rebind"); - sndr2.close() - - # drain the queue - rcvr = self._start_qpid_receive("B140", count=5) - count = 0; - x = rcvr.readline() # prints a line for each received msg - while x: - # print "Read from B140 " + x - count += 1; - x = rcvr.readline() - - self.assertEqual(count, 5) - - # drain the queue - rcvrB = self._start_qpid_receive("A140", count=3) - count = 0; - x = rcvrB.readline() # prints a line for each received msg - while x: - # print "Read from A140 " + x - count += 1; - x = rcvrB.readline() - - self.assertEqual(count, 3) - - ###session.close() - - def test_150_queue_deletion_destroys_redirect(self): - session = self.get_session('bob','bob') - self.create_queue(session, "A150", False) - self.create_queue(session, "B150", False) - self.create_queue(session, "C150", False) - - # redirect - self.redirect("A150", "B150", True, "Should allow redirect") - - self.redirect("A150", "C150", False, "A is already redirected") - - alice = BrokerAdmin(self.config.broker, "bob", "bob") - alice.delete_queue("B150") #should pass - - self.redirect("A150", "C150", True, "Should allow redirect") - session.close() - -############################################################################################## -class BrokerAdmin: - def __init__(self, broker, username=None, password=None): - self.connection = qpid.messaging.Connection(broker) - if username: - self.connection.username = username - self.connection.password = password - self.connection.sasl_mechanisms = "PLAIN" - self.connection.open() - self.session = self.connection.session() - self.sender = self.session.sender("qmf.default.direct/broker") - self.reply_to = "responses-#; {create:always}" - self.receiver = self.session.receiver(self.reply_to) - - def invoke(self, method, arguments): - content = { - "_object_id": {"_object_name": "org.apache.qpid.broker:broker:amqp-broker"}, - "_method_name": method, - "_arguments": arguments - } - request = qpid.messaging.Message(reply_to=self.reply_to, content=content) - request.properties["x-amqp-0-10.app-id"] = "qmf2" - request.properties["qmf.opcode"] = "_method_request" - self.sender.send(request) - response = self.receiver.fetch() - self.session.acknowledge() - if response.properties['x-amqp-0-10.app-id'] == 'qmf2': - if response.properties['qmf.opcode'] == '_method_response': - return response.content['_arguments'] - elif response.properties['qmf.opcode'] == '_exception': - raise Exception(response.content['_values']) - else: raise Exception("Invalid response received, unexpected opcode: %s" % response.properties['qmf.opcode']) - else: raise Exception("Invalid response received, not a qmfv2 method: %s" % response.properties['x-amqp-0-10.app-id']) - - def create_exchange(self, name, exchange_type=None, options={}): - properties = options - if exchange_type: properties["exchange_type"] = exchange_type - self.invoke("create", {"type": "exchange", "name":name, "properties":properties}) - - def create_queue(self, name, properties={}): - self.invoke("create", {"type": "queue", "name":name, "properties":properties}) - - def delete_exchange(self, name): - self.invoke("delete", {"type": "exchange", "name":name}) - - def delete_queue(self, name): - self.invoke("delete", {"type": "queue", "name":name}) diff --git a/qpid/cpp/src/tests/receiver.cpp b/qpid/cpp/src/tests/receiver.cpp deleted file mode 100644 index f1b462d6e4..0000000000 --- a/qpid/cpp/src/tests/receiver.cpp +++ /dev/null @@ -1,140 +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 -#include -#include -#include -#include -#include "TestOptions.h" - -#include -#include - - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; - -using namespace std; - -namespace qpid { -namespace tests { - -struct Args : public qpid::TestOptions -{ - string queue; - uint messages; - bool ignoreDuplicates; - uint creditWindow; - uint ackFrequency; - bool browse; - - Args() : queue("test-queue"), messages(0), ignoreDuplicates(false), creditWindow(0), ackFrequency(1), browse(false) - { - addOptions() - ("queue", qpid::optValue(queue, "QUEUE NAME"), "Queue from which to request messages") - ("messages", qpid::optValue(messages, "N"), "Number of messages to receive; 0 means receive indefinitely") - ("ignore-duplicates", qpid::optValue(ignoreDuplicates), "Detect and ignore duplicates (by checking 'sn' header)") - ("credit-window", qpid::optValue(creditWindow, "N"), "Credit window (0 implies infinite window)") - ("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)") - ("browse", qpid::optValue(browse), "Browse rather than consuming"); - } -}; - -const string EOS("eos"); -const string SN("sn"); - -class Receiver : public MessageListener, public FailoverManager::Command -{ - public: - Receiver(const string& queue, uint messages, bool ignoreDuplicates, uint creditWindow, uint ackFrequency, bool browse); - void received(Message& message); - void execute(AsyncSession& session, bool isRetry); - private: - const string queue; - const uint count; - const bool skipDups; - SubscriptionSettings settings; - Subscription subscription; - uint processed; - uint lastSn; - - bool isDuplicate(Message& message); -}; - -Receiver::Receiver(const string& q, uint messages, bool ignoreDuplicates, uint creditWindow, uint ackFrequency, bool browse) : - queue(q), count(messages), skipDups(ignoreDuplicates), processed(0), lastSn(0) -{ - if (browse) settings.acquireMode = ACQUIRE_MODE_NOT_ACQUIRED; - if (creditWindow) settings.flowControl = FlowControl::messageWindow(creditWindow); - settings.autoAck = ackFrequency; -} - -void Receiver::received(Message& message) -{ - if (!(skipDups && isDuplicate(message))) { - bool eos = message.getData() == EOS; - if (!eos) std::cout << message.getData() << std::endl; - if (eos || ++processed == count) subscription.cancel(); - } -} - -bool Receiver::isDuplicate(Message& message) -{ - uint sn = message.getHeaders().getAsInt(SN); - if (lastSn < sn) { - lastSn = sn; - return false; - } else { - return true; - } -} - -void Receiver::execute(AsyncSession& session, bool /*isRetry*/) -{ - SubscriptionManager subs(session); - subscription = subs.subscribe(*this, queue, settings); - subs.run(); - if (settings.autoAck) { - subscription.accept(subscription.getUnaccepted()); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - Args opts; - try { - opts.parse(argc, argv); - FailoverManager connection(opts.con); - Receiver receiver(opts.queue, opts.messages, opts.ignoreDuplicates, opts.creditWindow, opts.ackFrequency, opts.browse); - connection.execute(receiver); - connection.close(); - return 0; - } catch(const std::exception& error) { - std::cerr << "Failure: " << error.what() << std::endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/reject_release.py b/qpid/cpp/src/tests/reject_release.py deleted file mode 100644 index d072b8aa78..0000000000 --- a/qpid/cpp/src/tests/reject_release.py +++ /dev/null @@ -1,65 +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. -# - -from qpid.tests.messaging.implementation import * -from qpid.tests.messaging import VersionTest - -class RejectReleaseTests (VersionTest): - """ - Tests for reject and release with qpidd - """ - def test_reject(self): - name = str(uuid4()) - snd = self.ssn.sender("%s; {create:always, node:{properties:{alternate-exchange:amq.fanout}}}" % name) - rcv = self.ssn.receiver(name) - rcv2 = self.ssn.receiver("amq.fanout") - - msgs = [Message(content=s, subject = s) for s in ['a','b','c','d']] - - for m in msgs: snd.send(m) - - for expected in msgs: - msg = rcv.fetch(0) - assert msg.content == expected.content - self.ssn.reject(msg) - - for expected in msgs: - msg = rcv2.fetch(0) - assert msg.content == expected.content - - def test_release(self): - snd = self.ssn.sender("#") - rcv = self.ssn.receiver(snd.target) - - msgs = [Message(content=s, subject = s) for s in ['a','b','c','d']] - - for m in msgs: snd.send(m) - - msg = rcv.fetch(0) - assert msg.content == "a" - self.ssn.release(msg) - - msg = rcv.fetch(0) - assert msg.content == "a" - self.ssn.acknowledge(msg) - - msg = rcv.fetch(0) - assert msg.content == "b" - self.ssn.release(msg) - diff --git a/qpid/cpp/src/tests/replaying_sender.cpp b/qpid/cpp/src/tests/replaying_sender.cpp deleted file mode 100644 index a5549bfdf2..0000000000 --- a/qpid/cpp/src/tests/replaying_sender.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 -#include -#include -#include -#include -#include - -#include -#include - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; - -using namespace std; - -namespace qpid { -namespace tests { - -class Sender : public FailoverManager::Command -{ - public: - Sender(const std::string& queue, uint count, uint reportFreq); - void execute(AsyncSession& session, bool isRetry); - uint getSent(); - - void setVerbosity ( int v ) { verbosity = v; } - void setPersistence ( int p ) { persistence = p; } - - private: - MessageReplayTracker sender; - const uint count; - uint sent; - const uint reportFrequency; - Message message; - int verbosity; - int persistence; - string queueName; -}; - -Sender::Sender(const std::string& queue, uint count_, uint reportFreq ) - : sender(10), - count(count_), - sent(0), - reportFrequency(reportFreq), - verbosity(0), - persistence(0), - queueName ( queue ) -{ - message.getDeliveryProperties().setRoutingKey(queueName.c_str()); -} - -const string SN("sn"); - -void Sender::execute(AsyncSession& session, bool isRetry) -{ - if (verbosity > 0) - std::cout << "replaying_sender " << (isRetry ? "first " : "re-") << "connect." << endl; - if (isRetry) sender.replay(session); - else sender.init(session); - while (sent < count) { - stringstream message_data; - message_data << ++sent; - message.setData(message_data.str()); - message.getHeaders().setInt(SN, sent); - if ( persistence ) - message.getDeliveryProperties().setDeliveryMode(PERSISTENT); - - sender.send(message); - if (count > reportFrequency && !(sent % reportFrequency)) { - if ( verbosity > 0 ) - std::cout << "Sender sent " - << sent - << " of " - << count - << " on queue " - << queueName - << std::endl; - } - } - message.setData("That's all, folks!"); - sender.send(message); - - if ( verbosity > 0 ) - std::cout << "SENDER COMPLETED\n"; -} - -uint Sender::getSent() -{ - return sent; -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - ConnectionSettings settings; - - if ( argc != 8 ) - { - std::cerr << "Usage: replaying_sender host port n_messages report_frequency verbosity persistence queue_name\n"; - return 1; - } - - settings.host = argv[1]; - settings.port = atoi(argv[2]); - int n_messages = atoi(argv[3]); - int reportFrequency = atoi(argv[4]); - int verbosity = atoi(argv[5]); - int persistence = atoi(argv[6]); - char * queue_name = argv[7]; - - FailoverManager connection(settings); - Sender sender(queue_name, n_messages, reportFrequency ); - sender.setVerbosity ( verbosity ); - sender.setPersistence ( persistence ); - try { - connection.execute ( sender ); - if ( verbosity > 0 ) - { - std::cout << "Sender finished. Sent " - << sender.getSent() - << " messages on queue " - << queue_name - << endl; - } - connection.close(); - return 0; - } - catch(const std::exception& error) - { - cerr << "Sender (host: " - << settings.host - << " port: " - << settings.port - << " ) " - << " Failed: " - << error.what() - << std::endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/resuming_receiver.cpp b/qpid/cpp/src/tests/resuming_receiver.cpp deleted file mode 100644 index 2e22a7c572..0000000000 --- a/qpid/cpp/src/tests/resuming_receiver.cpp +++ /dev/null @@ -1,193 +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 -#include -#include -#include - -#include -#include - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; - -using namespace std; - - - -namespace qpid { -namespace tests { - -class Listener : public MessageListener, - public FailoverManager::Command, - public FailoverManager::ReconnectionStrategy -{ - public: - Listener ( int report_frequency = 1000, - int verbosity = 0, - char const * queue_name = "message_queue" ); - void received(Message& message); - void execute(AsyncSession& session, bool isRetry); - void check(); - void editUrlList(vector& urls); - private: - Subscription subscription; - uint count; - vector received_twice; - uint lastSn; - bool gaps; - uint reportFrequency; - int verbosity; - bool done; - string queueName; -}; - - -Listener::Listener ( int freq, int verbosity, char const * name ) - : count(0), - lastSn(0), - gaps(false), - reportFrequency(freq), - verbosity(verbosity), - done(false), - queueName ( name ) -{} - -const std::string SN("sn"); - -void Listener::received(Message & message) -{ - if (message.getData() == "That's all, folks!") - { - done = true; - if(verbosity > 0 ) - { - cout << "Shutting down listener for " - << message.getDestination() << endl; - - cout << "Listener received " - << count - << " messages (" - << received_twice.size() - << " received_twice)" - << endl; - - } - subscription.cancel(); - if ( verbosity > 0 ) - cout << "LISTENER COMPLETED\n"; - - if ( ! gaps ) { - cout << "no gaps were detected\n"; - cout << received_twice.size() << " messages were received twice.\n"; - } - else { - cout << "gaps detected\n"; - for ( unsigned int i = 0; i < received_twice.size(); ++ i ) - cout << "received_twice " - << received_twice[i] - << endl; - } - } else { - uint sn = message.getHeaders().getAsInt(SN); - if (lastSn < sn) { - if (sn - lastSn > 1) { - cerr << "Error: gap in sequence between " << lastSn << " and " << sn << endl; - gaps = true; - } - lastSn = sn; - ++count; - if ( ! ( count % reportFrequency ) ) { - if ( verbosity > 0 ) - cout << "Listener has received " - << count - << " messages on queue " - << queueName - << endl; - } - } else { - received_twice.push_back ( sn ); - } - } -} - -void Listener::check() -{ - if (gaps) throw Exception("Detected gaps in sequence; messages appear to have been lost."); -} - -void Listener::execute(AsyncSession& session, bool isRetry) { - if (verbosity > 0) - cout << "resuming_receiver " << (isRetry ? "first " : "re-") << "connect." << endl; - if (!done) { - SubscriptionManager subs(session); - subscription = subs.subscribe(*this, queueName); - subs.run(); - } -} - -void Listener::editUrlList(vector& urls) -{ - /** - * A more realistic algorithm would be to search through the list - * for prefered hosts and ensure they come first in the list. - */ - if (urls.size() > 1) rotate(urls.begin(), urls.begin() + 1, urls.end()); -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - ConnectionSettings settings; - - if ( argc != 6 ) - { - cerr << "Usage: resuming_receiver host port report_frequency verbosity queue_name\n"; - return 1; - } - - settings.host = argv[1]; - settings.port = atoi(argv[2]); - int reportFrequency = atoi(argv[3]); - int verbosity = atoi(argv[4]); - char * queue_name = argv[5]; - - Listener listener ( reportFrequency, verbosity, queue_name ); - FailoverManager connection(settings, &listener); - - try { - connection.execute(listener); - connection.close(); - listener.check(); - return 0; - } catch(const exception& error) { - cerr << "Receiver failed: " << error.what() << endl; - } - return 1; -} - - - diff --git a/qpid/cpp/src/tests/ring_queue_test b/qpid/cpp/src/tests/ring_queue_test deleted file mode 100755 index 410ea30eb8..0000000000 --- a/qpid/cpp/src/tests/ring_queue_test +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env 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. -# - -# Test script for validating the behaviour of a ring queue - -QUEUE_NAME=ring-queue -LIMIT=100 -DURABLE=0 -MESSAGES=10000 -SENDERS=1 -RECEIVERS=1 -CONCURRENT=0 -BROKER_URL="-b ${QPID_BROKER:-localhost}:${QPID_PORT:-5672}" - -setup() { - if [[ $DURABLE -gt 0 ]]; then - EXTRA_ARGS=" --durable" - fi - qpid-config $BROKER_URL add queue $QUEUE_NAME --max-queue-count $LIMIT --limit-policy ring $EXTRA_ARGS -} - -send() { - datagen --count $MESSAGES | tee sender_${QUEUE_NAME}_${1} | sender --durable $DURABLE --routing-key $QUEUE_NAME -} - -receive() { - #TODO: allow a variety of receiver options to be passed in (ack-frequency, credit-window etc) - receiver --queue $QUEUE_NAME > receiver_${QUEUE_NAME}_${1} -} - -cleanup() { - rm -f sender_${QUEUE_NAME}_* receiver_${QUEUE_NAME}_* - qpid-config $BROKER_URL del queue $QUEUE_NAME --force -} - -log() { - echo $1 -} - -fail() { - echo $1 - FAILED=1 -} - -validate() { - if [[ $RECEIVERS -eq 0 ]]; then - #queue should have $LIMIT messages on it, but need to send an eos also - sender --routing-key $QUEUE_NAME --send-eos 1 < /dev/null - received=$(receiver --queue $QUEUE_NAME --browse | wc -l) - if [[ received -eq $(( $LIMIT - 1)) ]]; then - log "queue contains $LIMIT messages as expected" - else - fail "queue does not contain the expected $LIMIT messages (received $received)" - fi - elif [[ $CONCURRENT -eq 0 ]]; then - #sum of length of all output files should be equal to $LIMIT - $RECEIVERS (1 eos message each) - received=$(cat receiver_${QUEUE_NAME}_* | wc -l) - expected=$(( $LIMIT - $RECEIVERS )) - if [[ $received -eq $expected ]]; then - log "received $LIMIT messages as expected" - else - fail "received $received messages, expected $expected" - fi - #if there were only a single sender and receiver (executed serially) we can check the - #actual received contents - if [[ $RECEIVERS -eq 1 ]] && [[ $SENDERS -eq 1 ]]; then - tail -n $(($LIMIT - 1)) sender_${QUEUE_NAME}_1 | diff - receiver_${QUEUE_NAME}_1 || FAILED=1 - if [[ $FAILED -eq 1 ]]; then - fail "did not receive expected messages" - else - log "received messages matched expectations" - fi - fi - else - #multiple receivers, concurrent with senders; ring queue functionality cannot be validated in this case - if [[ $(cat receiver_${QUEUE_NAME}_* | wc -l) -le $(cat sender_${QUEUE_NAME}_* | wc -l) ]]; then - log "sent at least as many messages as were received" - else - #Note: if any receiver was browsing, this would be valid (would need to add 'sort | uniq') - # to pipeline above - fail "received more messages than were sent" - fi - fi - - if [[ $FAILED ]]; then - echo $(basename $0): FAILED - exit 1 - else - cleanup - fi -} - -run_test() { - if [[ $CONCURRENT -eq 0 ]]; then - echo "Starting $SENDERS senders followed by $RECEIVERS receivers " - else - echo "Starting $SENDERS senders concurrently with $RECEIVERS receivers" - fi - for ((i=1; i <= $SENDERS; i++)); do - send $i & - sender_pids[$i]=$! - done - if [[ $CONCURRENT -eq 0 ]] && [[ $RECEIVERS -gt 0 ]]; then - wait - sender --routing-key $QUEUE_NAME --send-eos $RECEIVERS < /dev/null - fi - for ((i=1; i <= $RECEIVERS; i++)); do - receive $i & - done - if [[ $CONCURRENT -gt 0 ]]; then - for ((i=1; i <= $SENDERS; i++)); do - wait ${sender_pids[$i]} - done - sender --routing-key $QUEUE_NAME --send-eos $RECEIVERS < /dev/null - fi - wait -} - -usage() { - cat < the name of the queue to use - -s the number of senders to start - -r the number of receivers to start - -l the limit for the ring queue - -m the number of messages to send - -c if specified, receivers will run concurrently with senders - -d if specified the queue and messages will be durable -EOF - exit 1 -} - -while getopts "s:r:m:u:dch" opt ; do - case $opt in - q) QUEUE_NAME=$OPTARG ;; - l) LIMIT=$OPTARG ;; - s) SENDERS=$OPTARG ;; - r) RECEIVERS=$OPTARG ;; - m) MESSAGES=$OPTARG ;; - d) DURABLE=1 ;; - c) CONCURRENT=1 ;; - h) usage;; - ?) usage;; - esac -done - -if [[ $SENDERS -gt 0 ]]; then - setup - run_test - validate -else - echo "Nothing can be done if there are no senders" -fi - diff --git a/qpid/cpp/src/tests/run.py b/qpid/cpp/src/tests/run.py deleted file mode 100755 index 9b74ba4d30..0000000000 --- a/qpid/cpp/src/tests/run.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python - -from common import * - -call(" ".join(ARGS[1:])) - diff --git a/qpid/cpp/src/tests/run_acl_tests b/qpid/cpp/src/tests/run_acl_tests deleted file mode 100755 index dc6b9e8272..0000000000 --- a/qpid/cpp/src/tests/run_acl_tests +++ /dev/null @@ -1,70 +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. -# - -from common import * - -policy_file = join(BUILD_DIR, "src", "tests", "policy.acl") -broker_args = "--acl-file {0}".format(policy_file) - -broker_port = start_broker("broker", broker_args, "--log-enable debug+:acl") -broker_i_port = start_broker("broker_i", broker_args, "--connection-limit-per-ip 2") -broker_u_port = start_broker("broker_u", broker_args, "--connection-limit-per-user 2") -broker_q_port = start_broker("broker_q", broker_args, "--max-queues-per-user 2") - -run_broker_tests(broker_port, "-m acl", - "-Dport-i={0}".format(broker_i_port), - "-Dport-u={0}".format(broker_u_port), - "-Dport-q={0}".format(broker_q_port), - "-Dpolicy-file={0}".format(policy_file)) - -# Test interaction of authentication and link creation - -broker_1_port = start_broker("broker_1") -broker_2_port = start_broker("broker_2") - -configure_broker(broker_1_port, "add exchange topic fed.topic") -configure_broker(broker_2_port, "add exchange topic fed.topic") - -connect_brokers("dynamic add", - "localhost:{0}".format(broker_1_port), - "localhost:{0}".format(broker_2_port), - "fed.topic") - -sasl_config_dir = join(BUILD_DIR, "src", "tests", "sasl_config") -broker_args = "--auth yes --sasl-config {0}".format(sasl_config_dir) - -broker_3_port = start_broker("broker_3", broker_args, auth_disabled=False) -broker_4_port = start_broker("broker_4", broker_args, auth_disabled=False) - -configure_broker(broker_3_port, "add exchange topic fed.topic") -configure_broker(broker_4_port, "add exchange topic fed.topic") - -try: - connect_brokers("dynamic add", - "localhost:{0}".format(broker_3_port), - "localhost:{0}".format(broker_4_port), - "fed.topic") - - fail("Broker with no ACLs but auth enabled did not deny link creation") -except: - pass - -check_results() diff --git a/qpid/cpp/src/tests/run_cli_tests b/qpid/cpp/src/tests/run_cli_tests deleted file mode 100755 index 2d2eabacb2..0000000000 --- a/qpid/cpp/src/tests/run_cli_tests +++ /dev/null @@ -1,63 +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. -# - -# Run the cli-utility tests - -from common import * - -cli_dir = join(SOURCE_DIR, "management", "python", "bin") - -xquery = """ -let $w := ./weather -return $w/station = 'Raleigh-Durham International Airport (KRDU)' - and $w/temperature_f > 50 - and $w/temperature_f - $w/dewpoint > 5 - and $w/wind_speed_mph > 7 - and $w/wind_speed_mph < 20 -""" -xquery_file = write(join(WORK_DIR, "xquery_file"), xquery) - -# If the xml lib is present, use it. if not, disable any tests which -# look like they're xml related. -# -# If we start supporting xml on windows, it will need something -# similar here. - -if XML_LIB is not None: - broker_args = "--load-module {0}".format(XML_LIB) - test_args = "" -else: - notice("Ignoring XML tests") - - broker_args = "" - test_args = "--ignore=*xml*" - -local_port = start_broker("local", broker_args) -remote_port = start_broker("remote", broker_args) - -run_broker_tests(local_port, - "-m cli_tests", - "-Dremote-port={0}".format(remote_port), - "-Dcli-dir={0}".format(cli_dir), - "-Dxquery-file={0}".format(xquery_file), - test_args) - -check_results() diff --git a/qpid/cpp/src/tests/run_client_tests b/qpid/cpp/src/tests/run_client_tests deleted file mode 100755 index 76c46ef949..0000000000 --- a/qpid/cpp/src/tests/run_client_tests +++ /dev/null @@ -1,30 +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. -# - -from common import * - -port = start_broker("broker") - -ENV["QPID_PORT"] = str(port) - -call_with_valgrind("qpid-client-test --verbose") - -check_results() diff --git a/qpid/cpp/src/tests/run_federation_tests b/qpid/cpp/src/tests/run_federation_tests deleted file mode 100755 index 1b37fe604a..0000000000 --- a/qpid/cpp/src/tests/run_federation_tests +++ /dev/null @@ -1,60 +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. -# - -from common import * - -common_args = "--log-enable=debug+:Bridge" -module_args = None -test_args = "-i *_xml" - -sys_test_args = [ - "-i federation_sys.A_Long*", - "-i federation_sys.B_Long*", - "-i federation_sys.C_*", - "-i federation_sys.D_*", - "-i federation_sys.E_*", - "-i federation_sys.F_*", - "-i federation_sys.G_*", - "-i federation_sys.H_*", -] - -if XML_LIB is not None: - module_args = "--load-module {0}".format(XML_LIB) - test_args = None - -local_port = start_broker("local", common_args, module_args, "--federation-tag LOCAL") -remote_port = start_broker("remote", common_args, module_args, "--federation-tag REMOTE") -remote_b1 = start_broker("remote_b1", common_args, module_args, "--federation-tag REMOTE_B1") -remote_b2 = start_broker("remote_b2", common_args, module_args, "--federation-tag REMOTE_B2") - -run_broker_tests(local_port, "-m federation", - "-Dremote-port={0}".format(remote_port), - "-Dextra-brokers='{0} {1}'".format(remote_b1, remote_b2), - test_args) - -run_broker_tests(local_port, "-m headers_federation", "-Dremote-port={0}".format(remote_port)) - -run_broker_tests(remote_port, "-m federation_sys", - "-Dlocal-port={0}".format(local_port), - "-Dremote-port={0}".format(remote_port), - *sys_test_args) - -check_results() diff --git a/qpid/cpp/src/tests/run_flow_control_tests b/qpid/cpp/src/tests/run_flow_control_tests deleted file mode 100755 index 5158fb2c47..0000000000 --- a/qpid/cpp/src/tests/run_flow_control_tests +++ /dev/null @@ -1,28 +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. -# - -from common import * - -port = start_broker("broker", "--default-flow-stop-threshold=80 --default-flow-resume-threshold=70") - -run_broker_tests(port, "-m queue_flow_limit_tests") - -check_results() diff --git a/qpid/cpp/src/tests/run_ha_tests b/qpid/cpp/src/tests/run_ha_tests deleted file mode 100755 index 6f87fdaceb..0000000000 --- a/qpid/cpp/src/tests/run_ha_tests +++ /dev/null @@ -1,37 +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. -# - -from common import * - -# ENV["QPID_USE_SWIG_CLIENT"] = "1" # XXX is this necessary? - -# XXX These tests hang, and I can't figure out why -# -i *tx_block_threads - -# ENV["QPID_NO_MODULE_DIR"] = "1" # Don't accidentally load installed modules -# ENV["QPID_DATA_DIR"] = "" -# ENV["QPID_CONFIG"] = join(BUILD_DIR, "src", "tests", "qpidd-empty.conf") -# ENV["QPID_PORT"] = "" -# ENV["QPID_LOG_TO_FILE"] = join(BUILD_DIR, "src", "tests", "gah.log") - -call("qpid-python-test -m ha_tests -DOUTDIR={0}", WORK_DIR) - -check_results() diff --git a/qpid/cpp/src/tests/run_idle_timeout_tests b/qpid/cpp/src/tests/run_idle_timeout_tests deleted file mode 100755 index 08c7966518..0000000000 --- a/qpid/cpp/src/tests/run_idle_timeout_tests +++ /dev/null @@ -1,26 +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. -# - -from common import * - -call("qpid-python-test -m idle_timeout_tests -DOUTDIR={0}", WORK_DIR) - -check_results() diff --git a/qpid/cpp/src/tests/run_interlink_tests b/qpid/cpp/src/tests/run_interlink_tests deleted file mode 100755 index f7d8bb8589..0000000000 --- a/qpid/cpp/src/tests/run_interlink_tests +++ /dev/null @@ -1,26 +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. -# - -from common import * - -call("qpid-python-test -m interlink_tests -DOUTDIR={0}", WORK_DIR) - -check_results() diff --git a/qpid/cpp/src/tests/run_interop_tests b/qpid/cpp/src/tests/run_interop_tests deleted file mode 100755 index 7507c6a99f..0000000000 --- a/qpid/cpp/src/tests/run_interop_tests +++ /dev/null @@ -1,35 +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. -# - -from common import * - -python_swig_module = join(BUILD_DIR, "bindings", "qpid", "python", "qpid_messaging.py") - -if exists(python_swig_module): - port = start_broker("broker", "--load-module {0}".format(AMQP_LIB)) - - ENV["QPID_INTEROP_URL"] = "localhost:{0}".format(port) - - call("qpid-python-test -m interop_tests -DOUTDIR={0}", WORK_DIR) -else: - warn("Skipping tests: 1.0 messaging client not found") - -check_results() diff --git a/qpid/cpp/src/tests/run_ipv6_tests b/qpid/cpp/src/tests/run_ipv6_tests deleted file mode 100755 index 55212257a9..0000000000 --- a/qpid/cpp/src/tests/run_ipv6_tests +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env 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. -# - -source env.sh - -# Check whether we have any globally configured IPv6 addresses -# - if not then we can't run the tests because ipv6 lookups won't -# work within the qpid code. This is a deliberate feature to avoid -# getting addresses that can't be routed by the machine. - -if ip -f inet6 -o addr | cut -f 9 -s -d' ' | grep global > /dev/null ; then - echo "IPv6 addresses configured - continuing" -else - echo "No global IPv6 addresses configured - skipping test" - exit 0 -fi - - -CONFIG=$(dirname $0)/qpidd-empty.conf -TEST_HOSTNAME=::1 -COUNT=10 - -trap cleanup EXIT - -error() { echo $*; exit 1; } - -# Don't need --no-module-dir or --no-data-dir as they are set as env vars in env.sh -COMMON_OPTS="--interface [::1] --daemon --auth no --config $CONFIG" - -# Record all broker ports started -unset PORTS -declare -a PORTS - -# Start new brokers: -# $1 must be integer -# $2 = extra opts -# Append used ports to PORTS variable -start_brokers() { - local -a ports - for (( i=0; $i<$1; i++)) do - ports[$i]=$(qpidd --port 0 $COMMON_OPTS $2) - done - PORTS=( ${PORTS[@]} ${ports[@]} ) -} - -stop_brokers() { - for port in "${PORTS[@]}"; - do - qpidd -qp $port - done - PORTS=() -} - -cleanup() { - stop_brokers -} - -start_brokers 1 -PORT=${PORTS[0]} -echo "Started IPv6 smoke perftest on broker port $PORT" - -## Test connection via connection settings -qpid-perftest --count ${COUNT} --port ${PORT} -b $TEST_HOSTNAME --summary - -## Test connection with a URL -URL="amqp:[$TEST_HOSTNAME]:$PORT" - -qpid-send -b $URL --content-string=hello -a "foo;{create:always}" -MSG=`qpid-receive -b $URL -a "foo;{create:always}" --messages 1` -test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; } - -stop_brokers - -# Federation smoke test follows - -# Start 2 brokers - -start_brokers 2 -echo "Started Federated brokers on ports ${PORTS[*]}" -# Make broker urls -BROKER0="[::1]:${PORTS[0]}" -BROKER1="[::1]:${PORTS[1]}" -TEST_QUEUE=ipv6-fed-test - -qpid-config -b $BROKER0 add queue $TEST_QUEUE -qpid-config -b $BROKER1 add queue $TEST_QUEUE -qpid-route dynamic add $BROKER1 $BROKER0 amq.direct -qpid-config -b $BROKER1 bind amq.direct $TEST_QUEUE $TEST_QUEUE -qpid-route route map $BROKER1 - -datagen --count 100 | tee rdata-in | - ./qpid-send -b amqp:$BROKER0 -a amq.direct/$TEST_QUEUE --content-stdin -qpid-receive -b amqp:$BROKER1 -a $TEST_QUEUE --print-content yes -m 0 > rdata-out - -cmp rdata-in rdata-out || { echo "Federated data over IPv6 does not compare"; exit 1; } - -stop_brokers -rm rdata-in rdata-out diff --git a/qpid/cpp/src/tests/run_logging_tests b/qpid/cpp/src/tests/run_logging_tests deleted file mode 100755 index 2ebcc5c902..0000000000 --- a/qpid/cpp/src/tests/run_logging_tests +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env 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. -# - -set -eu - -source env.sh - -export WORK_DIR=$(mktemp -d $PWD/run_logging_tests_XXXX) - -exit_code=0 - -dynamic_log_hires_timestamp || exit_code=1 -dynamic_log_level_test || exit_code=1 - -if (( exit_code != 0 )); then - echo "Logging test failures" - exit $exit_code -fi - -rm -rf $WORK_DIR diff --git a/qpid/cpp/src/tests/run_long_federation_sys_tests b/qpid/cpp/src/tests/run_long_federation_sys_tests deleted file mode 100644 index ab8b5646ec..0000000000 --- a/qpid/cpp/src/tests/run_long_federation_sys_tests +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env 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 federation system tests (long version). - -USE_LONG_TEST=1 ./run_federation_sys_tests $@ diff --git a/qpid/cpp/src/tests/run_msg_group_tests b/qpid/cpp/src/tests/run_msg_group_tests deleted file mode 100755 index 17bc49794c..0000000000 --- a/qpid/cpp/src/tests/run_msg_group_tests +++ /dev/null @@ -1,47 +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. -# - -from common import * - -port = start_broker("broker") - -commands = [ - "qpid-config -b {0} add queue group-queue --group-header=My-Group-Id --shared-groups", - "msg_group_test -b {0} -a group-queue --group-key My-Group-Id --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 3", - "msg_group_test -b {0} -a group-queue --group-key My-Group-Id --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 7 --randomize-group-size", - "qpid-config -b {0} add queue group-queue-two --group-header=My-Group-Id --shared-groups", - "msg_group_test -b {0} -a group-queue --group-key My-Group-Id --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 3 --randomize-group-size", - "msg_group_test -b {0} -a group-queue-two --group-key My-Group-Id --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 5", - "msg_group_test -b {0} -a group-queue --group-key My-Group-Id --messages 59 --group-size 5 --receivers 2 --senders 3 --capacity 1 --ack-frequency 3 --randomize-group-size", - "qpid-config -b {0} del queue group-queue-two --force", - "msg_group_test -b {0} -a group-queue --group-key My-Group-Id --messages 59 --group-size 3 --receivers 2 --senders 3 --capacity 1 --ack-frequency 1 --randomize-group-size", - "msg_group_test -b {0} -a group-queue --group-key My-Group-Id --messages 211 --group-size 13 --receivers 2 --senders 3 --capacity 47 --ack-frequency 79 --interleave 53", - "msg_group_test -b {0} -a group-queue --group-key My-Group-Id --messages 10000 --group-size 1 --receivers 0 --senders 1", - "msg_group_test -b {0} -a group-queue --group-key My-Group-Id --messages 10000 --receivers 5 --senders 0", - "qpid-config -b {0} del queue group-queue --force", -] - -address = "localhost:{0}".format(port) - -for command in commands: - call(command, address) - -check_results() diff --git a/qpid/cpp/src/tests/run_msg_group_tests_soak b/qpid/cpp/src/tests/run_msg_group_tests_soak deleted file mode 100755 index 68a16793f3..0000000000 --- a/qpid/cpp/src/tests/run_msg_group_tests_soak +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env 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. -# - -# Script to run a sequence of long-running message group tests via -# make - -source env.sh - -#set port to connect to via env var -test -s qpidd.port && QPID_PORT=`cat qpidd.port` - -#trap cleanup INT TERM QUIT - -QUEUE_NAME="group-queue" -GROUP_KEY="My-Group-Id" - -BROKER_URL="${QPID_BROKER:-localhost}:${QPID_PORT:-5672}" - -run_test() { - $@ -} - -##set -x - -declare -i i=0 -declare -a tests -tests=("qpid-config -b $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups" - "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 47 --ack-frequency 97" - "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 79 --ack-frequency 79" - "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 97 --ack-frequency 47" - "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 40000 --receivers 0 --senders 5 --group-size 13 --randomize-group-size" - "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 200000 --receivers 3 --senders 0 --capacity 23 --ack-frequency 7" - "qpid-config -b $BROKER_URL del queue $QUEUE_NAME --force") - -while [ -n "${tests[i]}" ]; do - run_test ${tests[i]} - RETCODE=$? - if test x$RETCODE != x0; then - echo "FAILED message group test. Failed command: \"${tests[i]}\""; - exit 1; - fi - i+=1 -done diff --git a/qpid/cpp/src/tests/run_paged_queue_tests b/qpid/cpp/src/tests/run_paged_queue_tests deleted file mode 100755 index f13a7747a3..0000000000 --- a/qpid/cpp/src/tests/run_paged_queue_tests +++ /dev/null @@ -1,45 +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. -# - -from common import * - -port = start_broker("broker", "--paging-dir={0}".format(join(WORK_DIR, "pqtest_data"))) - -messages = 1000 -address = "onepage; {create: always, node:{x-declare:{arguments:{'qpid.paging':True,'qpid.max_pages_loaded':1}}}}" - -call_with_valgrind("qpid-send --messages {0} --content-size 1024 --broker localhost:{1} --address \"{2}\"", - messages, port, address) - -output = call_for_output_with_valgrind("qpid-receive --address onepage --messages {0} --broker localhost:{1}", - messages, port) - -received = len(output.splitlines()) - -if received != messages: - fail("Single page test failed: received {0} messages, expected {1}", received, messages) - -option = "node:{x-declare:{arguments:{'qpid.paging':True,'qpid.max_size':0,'qpid.max_count':0,'qpid.flow_stop_size':0,'qpid.flow_resume_size':0,'qpid.flow_stop_count':0,'qpid.flow_resume_count':0}}}" - -call("qpid-cpp-benchmark --broker localhost:{0} --create-option \"{1}\"", port, option) -call("qpid-cpp-benchmark --broker localhost:{0} --create-option \"{1}\" --fill-drain", port, option) - -check_results() diff --git a/qpid/cpp/src/tests/run_performance_tests b/qpid/cpp/src/tests/run_performance_tests deleted file mode 100755 index 31da852c34..0000000000 --- a/qpid/cpp/src/tests/run_performance_tests +++ /dev/null @@ -1,28 +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. -# - -from common import * - -port = start_broker("broker") - -call_with_valgrind("qpid-perftest --summary --count 100 --port {0}", port) - -check_results() diff --git a/qpid/cpp/src/tests/run_python_tests b/qpid/cpp/src/tests/run_python_tests deleted file mode 100755 index 53a9aa54f5..0000000000 --- a/qpid/cpp/src/tests/run_python_tests +++ /dev/null @@ -1,67 +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. -# - -from common import * - -load_module_arg = None - -if AMQP_LIB is not None: - load_module_arg = "--load-module {0}".format(AMQP_LIB) - -acl_file = join(BUILD_DIR, "src", "tests", "policy.acl") -acl_file_arg = "--acl-file {0}".format(acl_file) - -port = start_broker("broker", load_module_arg, acl_file_arg) - -# Native python tests - -run_broker_tests(port, "-m qpid_tests.broker_0_10 -m qpid.tests") - -# Swigged python tests - -python_swig_module = join(BUILD_DIR, "bindings", "qpid", "python", "qpid_messaging.py") - -if exists(python_swig_module): - failing_tests = join(BUILD_DIR, "src", "tests", "failing-amqp0-10-python-tests") - - ENV["QPID_USE_SWIG_CLIENT"] = "1" - - run_broker_tests(port, - "-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", - "-I {0}".format(failing_tests)) - - if AMQP_LIB is not None: - failing_tests = join(BUILD_DIR, "src", "tests", "failing-amqp1.0-python-tests") - - run_broker_tests(port, - "--define=\"protocol_version=amqp1.0\"", - "--define=\"policy_file={0}\"".format(acl_file), - "-m qpid_tests.broker_1_0", - "-m qpid_tests.broker_0_10.new_api", - "-m assertions -m reject_release -m misc -m policies -m acl_1", - "-I {0}".format(failing_tests)) -else: - warn("Skipping tests for swigged python client: swigged module not found") - -check_results() diff --git a/qpid/cpp/src/tests/run_qmf_tests b/qpid/cpp/src/tests/run_qmf_tests deleted file mode 100755 index 3d474d2893..0000000000 --- a/qpid/cpp/src/tests/run_qmf_tests +++ /dev/null @@ -1,26 +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. -# - -from common import * - -call("qpid-python-test -m qpidd_qmfv2_tests -DOUTDIR={0}", WORK_DIR) - -check_results() diff --git a/qpid/cpp/src/tests/run_queue_redirect_tests b/qpid/cpp/src/tests/run_queue_redirect_tests deleted file mode 100644 index 881f1ea5f1..0000000000 --- a/qpid/cpp/src/tests/run_queue_redirect_tests +++ /dev/null @@ -1,30 +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. -# - -from common import * - -policy_file = join(BUILD_DIR, "src", "tests", "policy.acl") - -port = start_broker("broker", "--acl-file {0}".format(policy_file), "--log-enable debug+:Model") - -run_broker_tests(port, "-m queue_redirect", "-Dpolicy-file={0}".format(policy_file)) - -check_results() diff --git a/qpid/cpp/src/tests/run_ring_queue_tests b/qpid/cpp/src/tests/run_ring_queue_tests deleted file mode 100755 index fbd6b0dff8..0000000000 --- a/qpid/cpp/src/tests/run_ring_queue_tests +++ /dev/null @@ -1,30 +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. -# - -from common import * - -ENV["QPID_PORT"] = start_broker("broker") - -call("ring_queue_test -c -s 4 -r 4") -call("ring_queue_test -s 4 -r 0") -call("ring_queue_test -s 1 -r 1") - -check_results() diff --git a/qpid/cpp/src/tests/run_sasl_tests b/qpid/cpp/src/tests/run_sasl_tests deleted file mode 100755 index 7ce92a232b..0000000000 --- a/qpid/cpp/src/tests/run_sasl_tests +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env 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. -# - -set -eu - -source env.sh - -export WORK_DIR=$(mktemp -d $PWD/run_sasl_tests_XXXX) - -echo "Created work dir '${WORK_DIR}'" - -min_sasl_version=131350 # Sasl version 2.1.22 -sasl_version=$(sasl_version) - -if (( $sasl_version < min_sasl_version )); then - echo "Sasl version is too old; found $version; require $min_version or greater" - echo "SKIPPING" - exit 0 -fi - -exit_code=0 - -function fail { - echo "FAILED! ${1}" - exit_code=1 -} - -echo "# Running sasl_fed" -sasl_fed || fail "Test sasl_fed failed" -echo "# Running sasl_fed_ex dynamic" -sasl_fed_ex dynamic || fail "Test sasl_fed_ex dynamic failed" -echo "# Running sasl_fed_ex link" -sasl_fed_ex link || fail "Test sasl_fed_ex link failed" -echo "# Running sasl_fed_ex queue" -sasl_fed_ex queue || fail "Test sasl_fed_ex queue failed" -echo "# Running sasl_fed_ex route" -sasl_fed_ex route || fail "Test sasl_fed_ex route failed" -echo "# Running sasl_no_dir" -sasl_no_dir || fail "Test sasl_no_dir failed" - -if (( exit_code != 0 )); then - echo "SASL test failures" - exit $exit_code -fi - -rm -rf $WORK_DIR diff --git a/qpid/cpp/src/tests/run_ssl_tests b/qpid/cpp/src/tests/run_ssl_tests deleted file mode 100755 index 896893eb3d..0000000000 --- a/qpid/cpp/src/tests/run_ssl_tests +++ /dev/null @@ -1,329 +0,0 @@ -#!/usr/bin/env 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 a simple test over SSL - -source env.sh - -#set -x - -CONFIG=$(dirname $0)/qpidd-empty.conf -TEST_CERT_DIR=`pwd`/test_cert_dir -CERT_DB=${TEST_CERT_DIR}/test_cert_db -CERT_PW_FILE=`pwd`/cert.password -TEST_HOSTNAME=127.0.0.1 -TEST_CLIENT_CERT=rumplestiltskin -CA_PEM_FILE=${TEST_CERT_DIR}/ca_cert.pem -OTHER_CA_CERT_DB=${TEST_CERT_DIR}/x_ca_cert_db -OTHER_CA_PEM_FILE=${TEST_CERT_DIR}/other_ca_cert.pem -PY_PING_BROKER=$SOURCE_DIR/src/tests/ping_broker -COUNT=10 - -if [[ -a $AMQP_LIB ]] ; then - MODULES="--load-module $AMQP_LIB" -fi - -trap cleanup EXIT - -error() { echo $*; exit 1; } - -# create the test certificate database -# $1 = string used as Subject in server's certificate -# $2 = string used as SubjectAlternateName (SAN) in server's certificate -create_certs() { - - local CERT_SUBJECT=${1:-"CN=${TEST_HOSTNAME},O=MyCo,ST=Massachusetts,C=US"} - local CERT_SAN=${2:-"*.server.com"} - - mkdir -p ${TEST_CERT_DIR} - rm -rf ${TEST_CERT_DIR}/* - - # Set Up a CA with a self-signed Certificate - # - mkdir -p ${CERT_DB} - certutil -N -d ${CERT_DB} -f ${CERT_PW_FILE} - certutil -S -d ${CERT_DB} -n "Test-CA" -s "CN=Test-CA,O=MyCo,ST=Massachusetts,C=US" -t "CT,," -x -f ${CERT_PW_FILE} -z /bin/sh >/dev/null 2>&1 - certutil -L -d ${CERT_DB} -n "Test-CA" -a -o ${CERT_DB}/rootca.crt -f ${CERT_PW_FILE} - #certutil -L -d ${CERT_DB} -f ${CERT_PW_FILE} - - # create server certificate signed by Test-CA - # - certutil -R -d ${CERT_DB} -s "${CERT_SUBJECT}" -o ${TEST_CERT_DIR}/server.req -f ${CERT_PW_FILE} -z /bin/sh > /dev/null 2>&1 - certutil -C -d ${CERT_DB} -c "Test-CA" -8 "${CERT_SAN}" -i ${TEST_CERT_DIR}/server.req -o ${TEST_CERT_DIR}/server.crt -f ${CERT_PW_FILE} -m ${RANDOM} - certutil -A -d ${CERT_DB} -n ${TEST_HOSTNAME} -i ${TEST_CERT_DIR}/server.crt -t "Pu,," - - # create a certificate to identify the client - # - certutil -R -d ${CERT_DB} -s "CN=${TEST_CLIENT_CERT}" -o ${TEST_CERT_DIR}/client.req -f ${CERT_PW_FILE} -z /bin/sh > /dev/null 2>&1 - certutil -C -d ${CERT_DB} -c "Test-CA" -8 "*.client.com" -i ${TEST_CERT_DIR}/client.req -o ${TEST_CERT_DIR}/client.crt -f ${CERT_PW_FILE} -m ${RANDOM} - certutil -A -d ${CERT_DB} -n ${TEST_CLIENT_CERT} -i ${TEST_CERT_DIR}/client.crt -t "Pu,," - ### - #certutil -N -d ${SERVER_CERT_DIR} -f ${CERT_PW_FILE} - #certutil -S -d ${SERVER_CERT_DIR} -n ${TEST_HOSTNAME} -s "CN=${TEST_HOSTNAME}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil - #certutil -S -d ${SERVER_CERT_DIR} -n ${TEST_CLIENT_CERT} -s "CN=${TEST_CLIENT_CERT}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil - - # Set up a separate DB with its own CA for testing failure to validate scenario - # - mkdir -p ${OTHER_CA_CERT_DB} - certutil -N -d ${OTHER_CA_CERT_DB} -f ${CERT_PW_FILE} - certutil -S -d ${OTHER_CA_CERT_DB} -n "Other-Test-CA" -s "CN=Another Test CA,O=MyCo,ST=Massachusetts,C=US" -t "CT,," -x -f ${CERT_PW_FILE} -z /bin/sh >/dev/null 2>&1 - certutil -L -d ${OTHER_CA_CERT_DB} -n "Other-Test-CA" -a -o ${OTHER_CA_CERT_DB}/rootca.crt -f ${CERT_PW_FILE} - #certutil -L -d ${OTHER_CA_CERT_DB} -f ${CERT_PW_FILE} -} - -delete_certs() { - if [[ -e ${TEST_CERT_DIR} ]] ; then - rm -rf ${TEST_CERT_DIR} - fi -} - -# Don't need --no-module-dir or --no-data-dir as they are set as env vars in env.sh -COMMON_OPTS="--daemon --config $CONFIG --ssl-cert-db $CERT_DB --ssl-cert-password-file $CERT_PW_FILE --ssl-cert-name $TEST_HOSTNAME" - -# Start new brokers: -# $1 must be integer -# $2 = extra opts -# Append used ports to PORTS variable -start_brokers() { - local -a ports - for (( i=0; $i<$1; i++)) do - ports[$i]=$(qpidd --port 0 --interface 127.0.0.1 $COMMON_OPTS $2) || error "Could not start broker $i" - done - PORTS=( ${PORTS[@]} ${ports[@]} ) -} - -# Stop single broker: -# $1 is number of broker to stop (0 based) -stop_broker() { - qpidd -qp ${PORTS[$1]} - - # Remove from ports array - unset PORTS[$1] -} - -stop_brokers() { - for port in "${PORTS[@]}"; - do - qpidd -qp $port - done - PORTS=() -} - -pick_port() { - # We need a fixed port to set --cluster-url. Use qpidd to pick a free port. - PICK=`qpidd --no-module-dir --listen-disable ssl -dp0` - qpidd --no-module-dir -qp $PICK - echo $PICK -} - -cleanup() { - stop_brokers - delete_certs - rm -f ${CERT_PW_FILE} -} - -start_ssl_broker() { - start_brokers 1 "--transport ssl --ssl-port 0 --require-encryption --auth no $MODULES" -} - -start_ssl_mux_broker() { - qpidd $COMMON_OPTS --port $1 --ssl-port $1 --auth no - PORTS=( ${PORTS[@]} $1 ) -} - -sasl_config_dir=$BUILD_DIR/src/tests/sasl_config - -start_authenticating_broker() { - start_brokers 1 "--transport ssl --ssl-port 0 --require-encryption --ssl-sasl-no-dict --ssl-require-client-authentication --auth yes --sasl-config=${sasl_config_dir} $MODULES" -} - -ssl_cluster_broker() { # $1 = port - start_brokers 1 "--ssl-port $1 --auth no --load-module $CLUSTER_LIB --cluster-name ssl_test.$HOSTNAME.$$ --cluster-url amqp:ssl:$TEST_HOSTNAME:$1" - - # Wait for broker to be ready - qpid-ping -Pssl -b $TEST_HOSTNAME:$1 -q || { echo "Cannot connect to broker on $1"; exit 1; } -} - -CERTUTIL=$(type -p certutil) -if [[ !(-x $CERTUTIL) ]] ; then - echo "No certutil, skipping ssl test"; - exit 0; -fi - -if [[ !(-e ${CERT_PW_FILE}) ]] ; then - echo password > ${CERT_PW_FILE} -fi -delete_certs -create_certs || error "Could not create test certificate database" - -start_ssl_broker -PORT=${PORTS[0]} -echo "Running SSL test on port $PORT" -export QPID_NO_MODULE_DIR=1 -export QPID_SSL_CERT_DB=${CERT_DB} -export QPID_SSL_CERT_PASSWORD_FILE=${CERT_PW_FILE} - -## Test connection via connection settings -qpid-perftest --count ${COUNT} --port ${PORT} -P ssl -b $TEST_HOSTNAME --summary - -## Test connection with a URL -URL=amqp:ssl:$TEST_HOSTNAME:$PORT -qpid-send -b $URL --content-string=hello -a "foo;{create:always}" -MSG=`qpid-receive -b $URL -a "foo;{create:always}" --messages 1` -test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; } - -if [[ -a $AMQP_LIB ]] ; then - echo "Testing ssl over AMQP 1.0" - qpid-send --connection-options '{protocol:amqp1.0}' -b $URL --content-string=hello -a "foo;{create:always}" - MSG=`qpid-receive --connection-options '{protocol:amqp1.0}' -b $URL -a "foo;{create:always}" --messages 1` - test "$MSG" = "hello" || { echo "receive failed for AMQP 1.0 '$MSG' != 'hello'"; exit 1; } -fi - -## Test connection with a combination of URL and connection options (in messaging API) -URL=$TEST_HOSTNAME:$PORT -qpid-send -b $URL --connection-options '{transport:ssl,heartbeat:2}' --content-string='hello again' -a "foo;{create:always}" -MSG=`qpid-receive -b $URL --connection-options '{transport:ssl,heartbeat:2}' -a "foo;{create:always}" --messages 1` -test "$MSG" = "hello again" || { echo "receive failed '$MSG' != 'hello again'"; exit 1; } - -## Test using the Python client -if test -d $PYTHON_DIR; then - echo "Testing Non-Authenticating with Python Client..." - URL=amqps://$TEST_HOSTNAME:$PORT - if `$PY_PING_BROKER -b $URL`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi -else - echo "Skipping python part of ssl_test, no python dir." -fi - -#### Client Authentication tests - -start_authenticating_broker -PORT2=${PORTS[1]} -echo "Running SSL client authentication test on port $PORT2" -URL=amqp:ssl:$TEST_HOSTNAME:$PORT2 - -## See if you can set the SSL cert-name for the connection -qpid-send -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" --content-string=hello -a "bar;{create:always}" -MSG2=`qpid-receive -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" -a "bar;{create:always}" --messages 1` -test "$MSG2" = "hello" || { echo "receive failed '$MSG2' != 'hello'"; exit 1; } - -## Make sure that connect fails with an invalid SSL cert-name -qpid-send -b $URL --connection-options "{ssl-cert-name: pignose }" --content-string=hello -a "baz;{create:always}" 2>/dev/null 1>/dev/null -MSG3=`qpid-receive -b $URL --connection-options "{ssl-cert-name: pignose }" -a "baz;{create:always}" --messages 1 2>/dev/null` -test "$MSG3" = "" || { echo "receive succeeded without valid ssl cert '$MSG3' != ''"; exit 1; } - -stop_brokers - -# Test ssl muxed with plain TCP on the same connection - -# Test a specified port number - since tcp/ssl are the same port don't need to specify --transport ssl -PORT=`pick_port` -start_ssl_mux_broker $PORT || error "Could not start broker" -echo "Running SSL/TCP mux test on fixed port $PORT" - -## Test connection via connection settings -qpid-perftest --count ${COUNT} --port ${PORT} -P ssl -b $TEST_HOSTNAME --summary || error "SSL connection failed!" -qpid-perftest --count ${COUNT} --port ${PORT} -P tcp -b $TEST_HOSTNAME --summary || error "TCP connection failed!" - -# Test a broker chosen port - since ssl chooses port need to use --transport ssl here -start_ssl_broker -PORT=${PORTS[0]} -echo "Running SSL/TCP mux test on random port $PORT" - -## Test connection via connection settings -qpid-perftest --count ${COUNT} --port ${PORT} -P ssl -b $TEST_HOSTNAME --summary || error "SSL connection failed!" -qpid-perftest --count ${COUNT} --port ${PORT} -P tcp -b $TEST_HOSTNAME --summary || error "TCP connection failed!" - -stop_brokers - -### Additional tests that require 'openssl' and 'pk12util' to be installed (optional) - -PK12UTIL=$(type -p pk12util) -if [[ !(-x $PK12UTIL) ]] ; then - echo >&2 "'pk12util' command not available, skipping remaining tests" - exit 0 -fi - -OPENSSL=$(type -p openssl) -if [[ !(-x $OPENSSL) ]] ; then - echo >&2 "'openssl' command not available, skipping remaining tests" - exit 0 -fi - -## verify python version > 2.5 (only 2.6+ does certificate checking) -PY_VERSION=$(python -c "import sys; print hex(sys.hexversion)") -if (( PY_VERSION < 0x02060000 )); then - echo >&2 "Detected python version < 2.6 - skipping certificate verification tests" - exit 0 -fi - -echo "Testing Certificate validation and Authentication with the Python Client..." - -# extract the CA's certificate as a PEM file -get_ca_certs() { - $PK12UTIL -o ${TEST_CERT_DIR}/CA_pk12.out -d ${CERT_DB} -n "Test-CA" -w ${CERT_PW_FILE} -k ${CERT_PW_FILE} > /dev/null - $OPENSSL pkcs12 -in ${TEST_CERT_DIR}/CA_pk12.out -out ${CA_PEM_FILE} -nokeys -passin file:${CERT_PW_FILE} >/dev/null - $PK12UTIL -o ${TEST_CERT_DIR}/other_CA_pk12.out -d ${OTHER_CA_CERT_DB} -n "Other-Test-CA" -w ${CERT_PW_FILE} -k ${CERT_PW_FILE} > /dev/null - $OPENSSL pkcs12 -in ${TEST_CERT_DIR}/other_CA_pk12.out -out ${OTHER_CA_PEM_FILE} -nokeys -passin file:${CERT_PW_FILE} >/dev/null -} - -get_ca_certs || error "Could not extract CA certificates as PEM files" -start_ssl_broker -PORT=${PORTS[0]} -URL=amqps://$TEST_HOSTNAME:$PORT -# verify the python client can authenticate the broker using the CA -if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE}`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi -# verify the python client fails to authenticate the broker when using the other CA -if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${OTHER_CA_PEM_FILE} > /dev/null 2>&1`; then { echo " Failed"; exit 1; }; else echo " Passed"; fi -stop_brokers - -# create a certificate without matching TEST_HOSTNAME, should fail to verify - -create_certs "O=MyCo" "*.${TEST_HOSTNAME}.com" || error "Could not create server test certificate" -get_ca_certs || error "Could not extract CA certificates as PEM files" -start_ssl_broker -PORT=${PORTS[0]} -URL=amqps://$TEST_HOSTNAME:$PORT -if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE} > /dev/null 2>&1`; then { echo " Failed"; exit 1; }; else echo " Passed"; fi -# but disabling the check for the hostname should pass -if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE} --ssl-skip-hostname-check`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi -stop_brokers - -# test SubjectAltName parsing - -if (( PY_VERSION >= 0x02070300 )); then -# python 2.7.3+ supports SubjectAltName extraction -# create a certificate with TEST_HOSTNAME only in SAN, should verify OK - create_certs "O=MyCo" "*.foo.com,${TEST_HOSTNAME},*xyz.com" || error "Could not create server test certificate" - get_ca_certs || error "Could not extract CA certificates as PEM files" - start_ssl_broker - PORT=${PORTS[0]} - URL=amqps://$TEST_HOSTNAME:$PORT - if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE}`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi - stop_brokers - - create_certs "O=MyCo" "*${TEST_HOSTNAME}" || error "Could not create server test certificate" - get_ca_certs || error "Could not extract CA certificates as PEM files" - start_ssl_broker - PORT=${PORTS[0]} - URL=amqps://$TEST_HOSTNAME:$PORT - if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE}`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi - stop_brokers -fi diff --git a/qpid/cpp/src/tests/run_store_tests.ps1 b/qpid/cpp/src/tests/run_store_tests.ps1 deleted file mode 100644 index f85e158cc0..0000000000 --- a/qpid/cpp/src/tests/run_store_tests.ps1 +++ /dev/null @@ -1,132 +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. -# - -# Run the store tests. -# There are two sets of tests: -# 1. A subset of the normal broker python tests, dtx and persistence, but -# run again with the desired store loaded. -# 2. store.py, which tests recovering things across broker restarts. - -$test_store = $args[0] -if ($test_store -ne "MSSQL" -and $test_store -ne "MSSQL-CLFS") { - "Invalid store test type $test_store - must be MSSQL or MSSQL-CLFS" - exit 1 -} - -$srcdir = Split-Path $myInvocation.InvocationName - -. .\env.ps1 - -if (!(Test-Path $PYTHON_DIR -pathType Container)) { - "Skipping store tests as python libs not found" - exit 1 -} - -# Test runs from the tests directory but the broker executable is one level -# up, and most likely in a subdirectory from there based on what build type. -# Look around for it before trying to start it. -$subs = "Debug","Release","MinSizeRel","RelWithDebInfo" -foreach ($sub in $subs) { - $prog = "..\$sub\qpidd.exe" - if (Test-Path $prog) { - break - } -} -if (!(Test-Path $prog)) { - "Cannot locate qpidd.exe" - exit 1 -} - -# The store to test is the same build type as the broker. -$store_dir = "..\qpid\store\$sub" -if (!([string]::Compare($sub, "Debug", $True))) { - $suffix = "d" -} - -$stamp = Get-Date -format %dMMMyyyy_HHmmss -$env:STORE_LIB="$store_dir\store$suffix.dll" -if ($test_store -eq "MSSQL") { - $test_store_module="$store_dir\mssql_store$suffix.dll" - $env:STORE_SQL_LIB=$test_store_module - $env:STORE_CATALOG="store_recovery_sql_test_$stamp" - $cat1="store_sql_test_$stamp" - $out = "sql_store_test_$stamp" -} -else { - $test_store_module="$store_dir\msclfs_store$suffix.dll" - $env:STORE_SQL_CLFS_LIB=$test_store_module - $env:STORE_CATALOG="store_recovery_clfs_test_$stamp" - $cat1="store_clfs_test_$stamp" - $out = "clfs_store_test_$stamp" -} - -$FAILCODE = 0 - -# Test 1... re-run some of the regular python broker tests against a broker -# with the store module loaded. -$cmdline = "$prog --auth=no --port=0 --log-to-file qpidd-store.log --no-module-dir --load-module $env:STORE_LIB --load-module $test_store_module --catalog $cat1 | foreach { set-content qpidd-store.port `$_ }" -$cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline) -. $srcdir\background.ps1 $cmdblock - -$wait_time = 0 -while (!(Test-Path qpidd-store.port) -and ($wait_time -lt 90)) { - Start-Sleep 2 - $wait_time += 2 -} -if (!(Test-Path qpidd-store.port)) { - "Time out waiting for broker to start" - exit 1 -} -set-item -path env:QPID_PORT -value (get-content -path qpidd-store.port -totalcount 1) -Remove-Item qpidd-store.port - -$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py\qpid_tests\broker_0_10" -$env:PYTHONPATH="$PYTHON_TEST_DIR;$srcdir;$env:PYTHONPATH" -python $PYTHON_DIR/qpid-python-test -m dtx -m persistence -b localhost:$env:QPID_PORT $fails $tests -$RETCODE=$LASTEXITCODE -if ($RETCODE -ne 0) { - $FAILCODE = 1 -} - -# Piping the output makes the script wait for qpidd to finish. -Invoke-Expression "$prog --quit --port $env:QPID_PORT" | Write-Output - - -# Test 2... store.py starts/stops/restarts its own brokers - -$tests = "*" -$env:QPIDD_EXEC="$prog" -$env:STORE_LIB="$store_dir\store$suffix.dll" -if ($test_store -eq "MSSQL") { - $env:STORE_SQL_LIB="$store_dir\mssql_store$suffix.dll" - $env:STORE_CATALOG="store_recovery_sql_test_$stamp" - $out = "sql_store_test_$stamp" -} -else { - $env:STORE_SQL_CLFS_LIB="$store_dir\msclfs_store$suffix.dll" - $env:STORE_CATALOG="store_recovery_clfs_test_$stamp" - $out = "clfs_store_test_$stamp" -} -Invoke-Expression "python $PYTHON_DIR/qpid-python-test -m store -D OUTDIR=$out $tests" | Out-Default -$RETCODE=$LASTEXITCODE -if ($RETCODE -ne 0) { - "FAIL $test_store store tests" - $FAILCODE = 1 -} -exit $FAILCODE diff --git a/qpid/cpp/src/tests/run_topic_tests b/qpid/cpp/src/tests/run_topic_tests deleted file mode 100755 index f34b8044ba..0000000000 --- a/qpid/cpp/src/tests/run_topic_tests +++ /dev/null @@ -1,30 +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. -# - -# Quick and quiet topic test for make test - -from common import * - -ENV["QPID_PORT"] = start_broker("broker") - -call_with_valgrind("topictest -s2 -m2 -b1") - -check_results() diff --git a/qpid/cpp/src/tests/run_transaction_tests b/qpid/cpp/src/tests/run_transaction_tests deleted file mode 100755 index d0c8a8a5c0..0000000000 --- a/qpid/cpp/src/tests/run_transaction_tests +++ /dev/null @@ -1,30 +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. -# - -from common import * - -port1 = start_broker("broker1") -port2 = start_broker("broker2") - -call_with_valgrind("qpid-txtest --queues 4 --tx-count 10 --quiet --port {0}", port1) -call_with_valgrind("qpid-txtest2 --queues 4 --tx-count 10 --quiet --port {0}", port2) - -check_results() diff --git a/qpid/cpp/src/tests/run_unit_tests b/qpid/cpp/src/tests/run_unit_tests deleted file mode 100755 index 8e81fe73a0..0000000000 --- a/qpid/cpp/src/tests/run_unit_tests +++ /dev/null @@ -1,39 +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. -# - -from common import * - -# Options for boost test framework - -if "BOOST_TEST_SHOW_PROGRESS" not in ENV: - ENV["BOOST_TEST_SHOW_PROGRESS"] = "yes" - -if "BOOST_TEST_CATCH_SYSTEM_ERRORS" not in ENV: - ENV["BOOST_TEST_CATCH_SYSTEM_ERRORS"] = "no" - -if WINDOWS: - ENV["QPID_SSL_CERT_STORE_LOCATION"] = "LocalMachine" - ENV["QPID_SSL_CERT_NAME"] = "localhost" - ENV["QPID_SSL_PORT"] = "0" - -call_with_valgrind("unit_test") - -check_results() diff --git a/qpid/cpp/src/tests/run_windows_store_tests b/qpid/cpp/src/tests/run_windows_store_tests deleted file mode 100644 index 900d0fc1a7..0000000000 --- a/qpid/cpp/src/tests/run_windows_store_tests +++ /dev/null @@ -1,61 +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. -# - -from common import * - -store_lib = join(BUILD_DIR, "src", "qpid", "store", "RelWithDebInfo", "store.dll") -store_sql_lib = join(BUILD_DIR, "src", "qpid", "store", "RelWithDebInfo", "mssql_store.dll") -store_clfs_lib = join(BUILD_DIR, "src", "qpid", "store", "RelWithDebInfo", "msclfs_store.dll") - -if exists(store_sql_lib): - port = start_broker("broker_sql", - "--load-module {0}".format(store_lib), - "--load-module {0}".format(store_sql_lib)) - - run_broker_tests(port, - "-m qpid_tests.broker_0_10.dtx", - "-m qpid_tests.broker_0_10.persistence") - - stop_broker(port) - -if exists(store_clfs_lib): - port = start_broker("broker_clfs", - "--load-module {0}".format(store_lib), - "--load-module {0}".format(store_clfs_lib)) - - run_broker_tests(port, - "-m qpid_tests.broker_0_10.dtx", - "-m qpid_tests.broker_0_10.persistence") - - stop_broker(port) - -ENV["STORE_SQL_LIB"] = store_sql_lib -ENV["STORE_SQL_CLFS_LIB"] = store_clfs_lib - -if exists(store_sql_lib): - ENV["STORE_CATALOG"] = join(WORK_DIR, "store_recovery_sql_test") - call("qpid-python-test -m store -DOUTDIR={0}", WORK_DIR) - -if exists(store_clfs_lib): - ENV["STORE_CATALOG"] = join(WORK_DIR, "store_recovery_clfs_test") - call("qpid-python-test -m store -DOUTDIR={0}", WORK_DIR) - -check_results() diff --git a/qpid/cpp/src/tests/sasl_fed b/qpid/cpp/src/tests/sasl_fed deleted file mode 100755 index 8491d428be..0000000000 --- a/qpid/cpp/src/tests/sasl_fed +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env 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. -# - -set -eu - -WORK_DIR=$WORK_DIR/sasl_fed -mkdir $WORK_DIR - -sasl_config_dir=$BUILD_DIR/src/tests/sasl_config - -# Create ACL file to allow links -echo acl allow all all > $WORK_DIR/sasl_fed.acl - -echo "Starting broker 1" - -qpidd \ - -p 0 --interface 127.0.0.1 \ - --data-dir $WORK_DIR/data_1 \ - --auth=yes \ - --mgmt-enable=yes \ - --log-enable info+ \ - --log-source yes \ - --log-to-file $WORK_DIR/qpidd_1.log \ - --sasl-config=$sasl_config_dir \ - --acl-file $WORK_DIR/sasl_fed.acl \ - -d > $WORK_DIR/broker_1_port - -broker_1_port=$(cat $WORK_DIR/broker_1_port) - -echo "Starting broker 2" - -qpidd \ - -p 0 --interface 127.0.0.1 \ - --data-dir $WORK_DIR/data_2 \ - --auth=yes \ - --mgmt-enable=yes \ - --log-enable info+ \ - --log-source yes \ - --log-to-file $WORK_DIR/qpidd_2.log \ - --sasl-config=$sasl_config_dir \ - --acl-file $WORK_DIR/sasl_fed.acl \ - -d > $WORK_DIR/broker_2_port - -broker_2_port=$(cat $WORK_DIR/broker_2_port) - -function stop_brokers { - qpidd --port $broker_1_port --quit - qpidd --port $broker_2_port --quit -} - -trap stop_brokers EXIT - -sleep 2 - -# I am not randomizing these names, because the test creates its own brokers. -QUEUE_NAME=sasl_fed_queue -ROUTING_KEY=sasl_fed_queue -EXCHANGE_NAME=sasl_fedex - -echo "Adding exchanges" - -qpid-config -b localhost:$broker_1_port add exchange direct $EXCHANGE_NAME -qpid-config -b localhost:$broker_2_port add exchange direct $EXCHANGE_NAME - -echo "Adding queues" - -qpid-config -b localhost:$broker_1_port add queue $QUEUE_NAME -qpid-config -b localhost:$broker_2_port add queue $QUEUE_NAME - -sleep 5 - -echo "Creating bindings" - -qpid-config -b localhost:$broker_1_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY -qpid-config -b localhost:$broker_2_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY - -sleep 5 - -echo "Adding routes" - -qpid-route route add zag/zag@localhost:$broker_2_port zag/zag@localhost:$broker_1_port $EXCHANGE_NAME $ROUTING_KEY "" "" DIGEST-MD5 - -sleep 5 - -n_messages=100 - -echo "Sending 100 messages to $broker_1_port " - -datagen --count $n_messages | sender --mechanism DIGEST-MD5 --username zag --password zag --exchange $EXCHANGE_NAME --routing-key $ROUTING_KEY --port $broker_1_port - -sleep 5 - -echo "Examining Broker $broker_1_port" - -broker_1_message_count=$(qpid-stat -q -b localhost:$broker_1_port | grep sasl_fed_queue | awk '{print $2}') - -echo "Examining Broker $broker_2_port" - -broker_2_message_count=$(qpid-stat -q -b localhost:$broker_2_port | grep sasl_fed_queue | awk '{print $2}') - -if (( $broker_2_message_count != $n_messages )); then - echo "Expected ${n_messages} and received ${broker_2_message_count}" - exit 1 -fi diff --git a/qpid/cpp/src/tests/sasl_fed_ex b/qpid/cpp/src/tests/sasl_fed_ex deleted file mode 100755 index cc70246683..0000000000 --- a/qpid/cpp/src/tests/sasl_fed_ex +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env 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. -# - -#=============================================================================== -# These tests create federated links between two brokers using SASL security. -# The SASL mechanism used is EXTERNAL, which is satisfied by SSL -# transport-layer security. -#=============================================================================== - -set -eu - -if (( $# != 1 )); then - # These are the four different ways of creating links ( or routes+links ) - # that the qpid-route command provides. - echo "Usage: $(basename $0) dynamic|link|queue|route" - exit 1 -fi - -qpid_route_method=$1 - -WORK_DIR="${WORK_DIR}/sasl_fed_ex_${qpid_route_method}" -mkdir $WORK_DIR - -CERT_DIR=$WORK_DIR/test_cert_db -CERT_PW_FILE=$WORK_DIR/cert.password -TEST_HOSTNAME=127.0.0.1 - -create_certs() { - # Create certificate and key databases with single, simple, - # self-signed certificate in it - mkdir ${CERT_DIR} - certutil -N -d ${CERT_DIR} -f ${CERT_PW_FILE} - certutil -S -d ${CERT_DIR} -n ${TEST_HOSTNAME} -s "CN=${TEST_HOSTNAME}" -t "CT,," -x -f ${CERT_PW_FILE} -z /bin/sh 2> /dev/null -} - -CERTUTIL=$(type -p certutil) || : - -if [[ ! -x $CERTUTIL ]]; then - echo "No certutil, skipping ssl test" - exit 0 -fi - -create_certs 2> /dev/null - -if (( $? != 0 )); then - echo "Could not create test certificate" - exit 1 -fi - -sasl_config_dir=$BUILD_DIR/src/tests/sasl_config - -SRC_SSL_PORT=6667 -DST_SSL_PORT=6666 - -SRC_SSL_PORT_2=6668 -DST_SSL_PORT_2=6669 - -SRC_TCP_PORT=5801 -DST_TCP_PORT=5807 - -SRC_TCP_PORT_2=5802 -DST_TCP_PORT_2=5803 - -export QPID_SSL_CERT_NAME=${TEST_HOSTNAME} - -export QPID_NO_MODULE_DIR=1 -export QPID_SSL_CERT_DB=${CERT_DIR} -export QPID_SSL_CERT_PASSWORD_FILE=${CERT_PW_FILE} -export QPID_SSL_CERT_NAME=${TEST_HOSTNAME} - -####################################### -# Understanding this Plumbing -####################################### -# 1. when you establish the route with qpid-route, -# here is the best termiology to use: -# -# qpid-route route add DST SRC -# -# 2. DST will connect to SRC through the ssl port of SRC. -# -# 3. sender client connects to the tcp port of SRC. -# -# 4. sender specifies mechanism ANONYMOUS. -# -# 5. DST pulls messages off the temp queue on SRC to itself. -# - -COMMON_BROKER_OPTIONS=" \ - --ssl-sasl-no-dict \ - --sasl-config $sasl_config_dir \ - --ssl-require-client-authentication \ - --auth yes \ - --ssl-cert-db $CERT_DIR \ - --ssl-cert-password-file $CERT_PW_FILE \ - --ssl-cert-name $TEST_HOSTNAME \ - --no-data-dir \ - --no-module-dir \ - --mgmt-enable yes \ - --log-enable info+ \ - --log-source yes \ - --daemon" - -function start_brokers { - # vanilla brokers -------------------------------- - echo "Starting SRC broker" - qpidd \ - --port=${SRC_TCP_PORT} \ - --ssl-port ${SRC_SSL_PORT} \ - ${COMMON_BROKER_OPTIONS} \ - --log-to-file $WORK_DIR/qpidd_src.log 2> /dev/null - - broker_ports[0]=${SRC_TCP_PORT} - - echo "Starting DST broker" - qpidd \ - --port=${DST_TCP_PORT} \ - --ssl-port ${DST_SSL_PORT} \ - ${COMMON_BROKER_OPTIONS} \ - --log-to-file $WORK_DIR/qpidd_dst.log 2> /dev/null - - broker_ports[1]=${DST_TCP_PORT} -} - -function halt_brokers { - n_brokers=${#broker_ports[@]} - echo "Halting ${n_brokers} brokers" - for i in $(seq 0 $((${n_brokers} - 1))); do - halt_port=${broker_ports[$i]} - echo "Halting broker $i on port ${halt_port}" - qpidd --port ${halt_port} --quit - done -} - -start_brokers -trap halt_brokers EXIT - -# I am not randomizing these names, because this test creates its own brokers. -QUEUE_NAME=sasl_fed_queue -ROUTING_KEY=sasl_fed_queue -EXCHANGE_NAME=sasl_fedex - -echo "Add exchanges" -qpid-config -b localhost:${SRC_TCP_PORT} add exchange direct $EXCHANGE_NAME -qpid-config -b localhost:${DST_TCP_PORT} add exchange direct $EXCHANGE_NAME - -echo "Add queues" -qpid-config -b localhost:${SRC_TCP_PORT} add queue $QUEUE_NAME -qpid-config -b localhost:${DST_TCP_PORT} add queue $QUEUE_NAME - -echo "Create bindings" -qpid-config -b localhost:${SRC_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY -qpid-config -b localhost:${DST_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY - -# -# NOTE: The SRC broker *must* be referred to as $TEST_HOSTNAME, and not as "localhost". -# It must be referred to by the exact string given as the Common Name (CN) in the cert, -# which was created in the function create_certs, above. - -#---------------------------------------------------------------- -# Use qpid-route to create the link, or the link+route, depending -# on which of its several methods was requested. -#---------------------------------------------------------------- -if [[ $qpid_route_method == "dynamic" ]]; then - echo "Dynamic add" - qpid-route -t ssl dynamic add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME "" "" EXTERNAL || : -elif [[ $qpid_route_method == "link" ]]; then - echo "Link add" - qpid-route -t ssl link add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} EXTERNAL || : -elif [[ $qpid_route_method == "queue" ]]; then - echo "Queue add" - qpid-route -t ssl queue add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME $ROUTING_KEY EXTERNAL || : -elif [[ $qpid_route_method == "route" ]]; then - echo "Route add" - qpid-route -t ssl route add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME $ROUTING_KEY "" "" EXTERNAL || : -else - echo "Unknown method: |${qpid_route_method}|" - echo "Choices are: dynamic|link|queue|route " - halt_brokers - exit 1 -fi - -# I don't know how to avoid this sleep yet. It has to come after route-creation -# to avoid false negatives. -sleep 5 - -# Look only at the transport field, which should be "ssl". -echo "Check the link" -link_status=$(qpid-route link list localhost:${DST_TCP_PORT} | tail -1 | awk '{print $3}') - -sleep 1 - -if [[ ! $link_status ]]; then - echo "Link status is empty" - echo "Result: fail" - exit 2 -fi - -if [[ $link_status == "ssl" ]]; then - echo "Result: good" - exit 0 -fi - -echo "Link status has a bad value: ${link_status}" -echo "Result: fail" -exit 3 diff --git a/qpid/cpp/src/tests/sasl_no_dir b/qpid/cpp/src/tests/sasl_no_dir deleted file mode 100755 index 30d8434079..0000000000 --- a/qpid/cpp/src/tests/sasl_no_dir +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env 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. -# - -set -eu - -sasl_config_dir=$BUILD_DIR/not_there_at_all - -WORK_DIR=$WORK_DIR/sasl_no_dir -mkdir $WORK_DIR - -LOG_FILE=$WORK_DIR/qpidd.log - -echo "Starting broker" -qpidd \ - -p 0 --interface 127.0.0.1 \ - --no-data-dir \ - --auth=yes \ - --mgmt-enable=yes \ - --log-enable info+ \ - --log-source yes \ - --log-to-file ${LOG_FILE} \ - --sasl-config=$sasl_config_dir \ - -d 2> /dev/null 1> $WORK_DIR/broker_port || : - -# If it works right, the output will look something like this: ( two lines long ) -# Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112) -# 2011-10-13 14:07:00 critical qpidd.cpp:83: Unexpected error: Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112) - -result=$(cat ${LOG_FILE} | grep "sasl_set_path failed: no such directory" | wc -l) - -if (( $result == 2 )); then - echo "Result: success" - exit 0 -fi - -broker_port=$(cat $WORK_DIR/broker_port) -qpidd --port ${broker_port} --quit - -echo "Result: fail" -exit 1 diff --git a/qpid/cpp/src/tests/sasl_test_setup.sh b/qpid/cpp/src/tests/sasl_test_setup.sh deleted file mode 100755 index 1416759da7..0000000000 --- a/qpid/cpp/src/tests/sasl_test_setup.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env 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. -# - -source env.sh - -test -x $SASLPASSWD2 || { echo Skipping SASL test, saslpasswd2 not found; exit 0; } - -mkdir -p sasl_config - -# Create configuration file. -cat > sasl_config/qpidd.conf < - -#include "sasl/sasl.h" - - -/* - Some tests need to distinguish between different versions of - SASL. This encodes and outputs the version number as an integer - for easy use in testing scripts. -*/ - -int -main ( ) -{ - // I assume that these are 8-bit quantities.... - int sasl_version = (SASL_VERSION_MAJOR << 16) + - (SASL_VERSION_MINOR << 8) + - SASL_VERSION_STEP; - - std::cout << sasl_version << std::endl; - - return 0; -} - - - - diff --git a/qpid/cpp/src/tests/sender.cpp b/qpid/cpp/src/tests/sender.cpp deleted file mode 100644 index 063b5e87dc..0000000000 --- a/qpid/cpp/src/tests/sender.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "TestOptions.h" - -#include "qpid/messaging/Message.h" // Only for Statistics -#include "Statistics.h" - -#include -#include - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; - -using namespace std; - -namespace qpid { -namespace tests { - -struct Args : public qpid::TestOptions -{ - string destination; - string key; - uint sendEos; - bool durable; - uint ttl; - string lvqMatchValue; - string lvqMatchFile; - bool reportTotal; - int reportEvery; - bool reportHeader; - - Args() : - key("test-queue"), sendEos(0), durable(false), ttl(0), - reportTotal(false), - reportEvery(0), - reportHeader(true) - { - addOptions() - ("exchange", qpid::optValue(destination, "EXCHANGE"), "Exchange to send messages to") - ("routing-key", qpid::optValue(key, "KEY"), "Routing key to add to messages") - ("send-eos", qpid::optValue(sendEos, "N"), "Send N EOS messages to mark end of input") - ("durable", qpid::optValue(durable, "true|false"), "Mark messages as durable.") - ("ttl", qpid::optValue(ttl, "msecs"), "Time-to-live for messages, in milliseconds") - ("lvq-match-value", qpid::optValue(lvqMatchValue, "KEY"), "The value to set for the LVQ match key property") - ("lvq-match-file", qpid::optValue(lvqMatchFile, "FILE"), "A file containing values to set for the LVQ match key property") - ("report-total", qpid::optValue(reportTotal), "Report total throughput statistics") - ("report-every", qpid::optValue(reportEvery,"N"), "Report throughput statistics every N messages") - ("report-header", qpid::optValue(reportHeader, "yes|no"), "Headers on report.") - ; - } -}; - -const string EOS("eos"); - -class Sender : public FailoverManager::Command -{ - public: - Sender(Reporter& reporter, const std::string& destination, const std::string& key, uint sendEos, bool durable, uint ttl, - const std::string& lvqMatchValue, const std::string& lvqMatchFile); - void execute(AsyncSession& session, bool isRetry); - - private: - Reporter& reporter; - messaging::Message dummyMessage; - const std::string destination; - MessageReplayTracker sender; - Message message; - const uint sendEos; - uint sent; - std::ifstream lvqMatchValues; -}; - -Sender::Sender(Reporter& rep, const std::string& dest, const std::string& key, uint eos, bool durable, uint ttl, const std::string& lvqMatchValue, const std::string& lvqMatchFile) : - reporter(rep), destination(dest), sender(10), message("", key), sendEos(eos), sent(0) , lvqMatchValues(lvqMatchFile.c_str()) -{ - if (durable){ - message.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - - if (ttl) { - message.getDeliveryProperties().setTtl(ttl); - } - - if (!lvqMatchValue.empty()) { - message.getHeaders().setString(QueueOptions::strLVQMatchProperty, lvqMatchValue); - } -} - -void Sender::execute(AsyncSession& session, bool isRetry) -{ - if (isRetry) sender.replay(session); - else sender.init(session); - string data; - while (getline(std::cin, data)) { - message.setData(data); - //message.getHeaders().setInt("SN", ++sent); - string matchKey; - if (lvqMatchValues && getline(lvqMatchValues, matchKey)) { - message.getHeaders().setString(QueueOptions::strLVQMatchProperty, matchKey); - } - reporter.message(dummyMessage); // For statistics - sender.send(message, destination); - } - for (uint i = sendEos; i > 0; --i) { - message.setData(EOS); - sender.send(message, destination); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - Args opts; - try { - opts.parse(argc, argv); - Reporter reporter(std::cout, opts.reportEvery, opts.reportHeader); - FailoverManager connection(opts.con); - Sender sender(reporter, opts.destination, opts.key, opts.sendEos, opts.durable, opts.ttl, opts.lvqMatchValue, opts.lvqMatchFile); - connection.execute(sender); - connection.close(); - if (opts.reportTotal) reporter.report(); - return 0; - } catch(const std::exception& error) { - std::cout << "Failed: " << error.what() << std::endl; - } - return 1; -} diff --git a/qpid/cpp/src/tests/shlibtest.cpp b/qpid/cpp/src/tests/shlibtest.cpp deleted file mode 100644 index 5655eb7e64..0000000000 --- a/qpid/cpp/src/tests/shlibtest.cpp +++ /dev/null @@ -1,34 +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. - * - */ - -namespace qpid { -namespace tests { - -int* loaderData = 0; -extern "C" -#ifdef WIN32 -__declspec(dllexport) -#endif -void callMe(int *i) { loaderData=i; } - -struct OnUnload { ~OnUnload() { *loaderData=42; } }; -OnUnload unloader; // For destructor. - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/ssl_test b/qpid/cpp/src/tests/ssl_test deleted file mode 100755 index 7c85087ad1..0000000000 --- a/qpid/cpp/src/tests/ssl_test +++ /dev/null @@ -1,335 +0,0 @@ -#!/usr/bin/env 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 a simple test over SSL - -source env.sh - -#set -x - -CONFIG=$(dirname $0)/qpidd-empty.conf -TEST_CERT_DIR=`pwd`/test_cert_dir -CERT_DB=${TEST_CERT_DIR}/test_cert_db -CERT_PW_FILE=`pwd`/cert.password -TEST_HOSTNAME=127.0.0.1 -TEST_CLIENT_CERT=rumplestiltskin -CA_PEM_FILE=${TEST_CERT_DIR}/ca_cert.pem -OTHER_CA_CERT_DB=${TEST_CERT_DIR}/x_ca_cert_db -OTHER_CA_PEM_FILE=${TEST_CERT_DIR}/other_ca_cert.pem -PY_PING_BROKER=$SOURCE_DIR/src/tests/ping_broker -COUNT=10 - -if [[ -a $AMQP_LIB ]] ; then - MODULES="--load-module $AMQP_LIB" -fi - -trap cleanup EXIT - -error() { echo $*; exit 1; } - -# create the test certificate database -# $1 = string used as Subject in server's certificate -# $2 = string used as SubjectAlternateName (SAN) in server's certificate -create_certs() { - - local CERT_SUBJECT=${1:-"CN=${TEST_HOSTNAME},O=MyCo,ST=Massachusetts,C=US"} - local CERT_SAN=${2:-"*.server.com"} - - mkdir -p ${TEST_CERT_DIR} - rm -rf ${TEST_CERT_DIR}/* - - # Set Up a CA with a self-signed Certificate - # - mkdir -p ${CERT_DB} - certutil -N -d ${CERT_DB} -f ${CERT_PW_FILE} - certutil -S -d ${CERT_DB} -n "Test-CA" -s "CN=Test-CA,O=MyCo,ST=Massachusetts,C=US" -t "CT,," -x -f ${CERT_PW_FILE} -z /bin/sh >/dev/null 2>&1 - certutil -L -d ${CERT_DB} -n "Test-CA" -a -o ${CERT_DB}/rootca.crt -f ${CERT_PW_FILE} - #certutil -L -d ${CERT_DB} -f ${CERT_PW_FILE} - - # create server certificate signed by Test-CA - # - certutil -R -d ${CERT_DB} -s "${CERT_SUBJECT}" -o ${TEST_CERT_DIR}/server.req -f ${CERT_PW_FILE} -z /bin/sh > /dev/null 2>&1 - certutil -C -d ${CERT_DB} -c "Test-CA" -8 "${CERT_SAN}" -i ${TEST_CERT_DIR}/server.req -o ${TEST_CERT_DIR}/server.crt -f ${CERT_PW_FILE} -m ${RANDOM} - certutil -A -d ${CERT_DB} -n ${TEST_HOSTNAME} -i ${TEST_CERT_DIR}/server.crt -t "Pu,," - - # create a certificate to identify the client - # - certutil -R -d ${CERT_DB} -s "CN=${TEST_CLIENT_CERT}" -o ${TEST_CERT_DIR}/client.req -f ${CERT_PW_FILE} -z /bin/sh > /dev/null 2>&1 - certutil -C -d ${CERT_DB} -c "Test-CA" -8 "*.client.com" -i ${TEST_CERT_DIR}/client.req -o ${TEST_CERT_DIR}/client.crt -f ${CERT_PW_FILE} -m ${RANDOM} - certutil -A -d ${CERT_DB} -n ${TEST_CLIENT_CERT} -i ${TEST_CERT_DIR}/client.crt -t "Pu,," - ### - #certutil -N -d ${SERVER_CERT_DIR} -f ${CERT_PW_FILE} - #certutil -S -d ${SERVER_CERT_DIR} -n ${TEST_HOSTNAME} -s "CN=${TEST_HOSTNAME}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil - #certutil -S -d ${SERVER_CERT_DIR} -n ${TEST_CLIENT_CERT} -s "CN=${TEST_CLIENT_CERT}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil - - # Set up a separate DB with its own CA for testing failure to validate scenario - # - mkdir -p ${OTHER_CA_CERT_DB} - certutil -N -d ${OTHER_CA_CERT_DB} -f ${CERT_PW_FILE} - certutil -S -d ${OTHER_CA_CERT_DB} -n "Other-Test-CA" -s "CN=Another Test CA,O=MyCo,ST=Massachusetts,C=US" -t "CT,," -x -f ${CERT_PW_FILE} -z /bin/sh >/dev/null 2>&1 - certutil -L -d ${OTHER_CA_CERT_DB} -n "Other-Test-CA" -a -o ${OTHER_CA_CERT_DB}/rootca.crt -f ${CERT_PW_FILE} - #certutil -L -d ${OTHER_CA_CERT_DB} -f ${CERT_PW_FILE} -} - -delete_certs() { - if [[ -e ${TEST_CERT_DIR} ]] ; then - rm -rf ${TEST_CERT_DIR} - fi -} - -# Don't need --no-module-dir or --no-data-dir as they are set as env vars in env.sh -COMMON_OPTS="--daemon --config $CONFIG --ssl-cert-db $CERT_DB --ssl-cert-password-file $CERT_PW_FILE --ssl-cert-name $TEST_HOSTNAME" - -# Start new brokers: -# $1 must be integer -# $2 = extra opts -# Append used ports to PORTS variable -start_brokers() { - local -a ports - for (( i=0; $i<$1; i++)) do - ports[$i]=$(qpidd --port 0 --interface 127.0.0.1 $COMMON_OPTS $2) || error "Could not start broker $i" - done - PORTS=( ${PORTS[@]} ${ports[@]} ) -} - -# Stop single broker: -# $1 is number of broker to stop (0 based) -stop_broker() { - qpidd -qp ${PORTS[$1]} - - # Remove from ports array - unset PORTS[$1] -} - -stop_brokers() { - for port in "${PORTS[@]}"; - do - qpidd -qp $port - done - PORTS=() -} - -pick_port() { - # We need a fixed port to set --cluster-url. Use qpidd to pick a free port. - PICK=`qpidd --no-module-dir --listen-disable ssl -dp0` - qpidd --no-module-dir -qp $PICK - echo $PICK -} - -cleanup() { - stop_brokers - delete_certs - rm -f ${CERT_PW_FILE} -} - -start_ssl_broker() { - start_brokers 1 "--transport ssl --ssl-port 0 --require-encryption --auth no $MODULES" -} - -start_ssl_mux_broker() { - qpidd $COMMON_OPTS --port $1 --ssl-port $1 --auth no - PORTS=( ${PORTS[@]} $1 ) -} - -sasl_config_dir=$BUILD_DIR/src/tests/sasl_config - -start_authenticating_broker() { - start_brokers 1 "--transport ssl --ssl-port 0 --require-encryption --ssl-sasl-no-dict --ssl-require-client-authentication --auth yes --sasl-config=${sasl_config_dir} $MODULES" -} - -ssl_cluster_broker() { # $1 = port - start_brokers 1 "--ssl-port $1 --auth no --load-module $CLUSTER_LIB --cluster-name ssl_test.$HOSTNAME.$$ --cluster-url amqp:ssl:$TEST_HOSTNAME:$1" - - # Wait for broker to be ready - qpid-ping -Pssl -b $TEST_HOSTNAME:$1 -q || { echo "Cannot connect to broker on $1"; exit 1; } -} - -CERTUTIL=$(type -p certutil) -if [[ !(-x $CERTUTIL) ]] ; then - echo "No certutil, skipping ssl test"; - exit 0; -fi - -if [[ !(-e ${CERT_PW_FILE}) ]] ; then - echo password > ${CERT_PW_FILE} -fi -delete_certs -create_certs || error "Could not create test certificate database" - -start_ssl_broker -PORT=${PORTS[0]} -echo "Running SSL test on port $PORT" -export QPID_NO_MODULE_DIR=1 -export QPID_SSL_CERT_DB=${CERT_DB} -export QPID_SSL_CERT_PASSWORD_FILE=${CERT_PW_FILE} - -## Test connection via connection settings -qpid-perftest --count ${COUNT} --port ${PORT} -P ssl -b $TEST_HOSTNAME --summary - -## Test connection with a URL -URL=amqp:ssl:$TEST_HOSTNAME:$PORT -qpid-send -b $URL --content-string=hello -a "foo;{create:always}" -MSG=`qpid-receive -b $URL -a "foo;{create:always}" --messages 1` -test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; } - -if [[ -a $AMQP_LIB ]] ; then - echo "Testing ssl over AMQP 1.0" - qpid-send --connection-options '{protocol:amqp1.0}' -b $URL --content-string=hello -a "foo;{create:always}" - MSG=`qpid-receive --connection-options '{protocol:amqp1.0}' -b $URL -a "foo;{create:always}" --messages 1` - test "$MSG" = "hello" || { echo "receive failed for AMQP 1.0 '$MSG' != 'hello'"; exit 1; } -fi - -## Test connection with a combination of URL and connection options (in messaging API) -URL=$TEST_HOSTNAME:$PORT -qpid-send -b $URL --connection-options '{transport:ssl,heartbeat:2}' --content-string='hello again' -a "foo;{create:always}" -MSG=`qpid-receive -b $URL --connection-options '{transport:ssl,heartbeat:2}' -a "foo;{create:always}" --messages 1` -test "$MSG" = "hello again" || { echo "receive failed '$MSG' != 'hello again'"; exit 1; } - -## Test using the Python client -if test -d $PYTHON_DIR; then - echo "Testing Non-Authenticating with Python Client..." - URL=amqps://$TEST_HOSTNAME:$PORT - if `$PY_PING_BROKER -b $URL`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi -else - echo "Skipping python part of ssl_test, no python dir." -fi - -#### Client Authentication tests - -start_authenticating_broker -PORT2=${PORTS[1]} -echo "Running SSL client authentication test on port $PORT2" -URL=amqp:ssl:$TEST_HOSTNAME:$PORT2 - -## See if you can set the SSL cert-name for the connection -qpid-send -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" --content-string=hello -a "bar;{create:always}" -MSG2=`qpid-receive -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" -a "bar;{create:always}" --messages 1` -test "$MSG2" = "hello" || { echo "receive failed '$MSG2' != 'hello'"; exit 1; } - - -## Make sure that connect fails with an invalid SSL cert-name -qpid-send -b $URL --connection-options "{ssl-cert-name: pignose }" --content-string=hello -a "baz;{create:always}" 2>/dev/null 1>/dev/null -MSG3=`qpid-receive -b $URL --connection-options "{ssl-cert-name: pignose }" -a "baz;{create:always}" --messages 1 2>/dev/null` -test "$MSG3" = "" || { echo "receive succeeded without valid ssl cert '$MSG3' != ''"; exit 1; } - -## Set the userid in the message to the authenticated username -./qpid-send -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" --auto-user-id true --content-string=hello -a "bar;{create:always}" -RECEIVED_USER=`./qpid-receive -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" -a "bar;{create:always}" --messages 1 --print-headers true | awk '/UserId/{print $2}'` -test "$RECEIVED_USER" = $TEST_CLIENT_CERT || { echo "user id not as expected: $RECEIVED_USER"; exit 1; } - -stop_brokers - -# Test ssl muxed with plain TCP on the same connection - -# Test a specified port number - since tcp/ssl are the same port don't need to specify --transport ssl -PORT=`pick_port` -start_ssl_mux_broker $PORT || error "Could not start broker" -echo "Running SSL/TCP mux test on fixed port $PORT" - -## Test connection via connection settings -qpid-perftest --count ${COUNT} --port ${PORT} -P ssl -b $TEST_HOSTNAME --summary || error "SSL connection failed!" -qpid-perftest --count ${COUNT} --port ${PORT} -P tcp -b $TEST_HOSTNAME --summary || error "TCP connection failed!" - -# Test a broker chosen port - since ssl chooses port need to use --transport ssl here -start_ssl_broker -PORT=${PORTS[0]} -echo "Running SSL/TCP mux test on random port $PORT" - -## Test connection via connection settings -qpid-perftest --count ${COUNT} --port ${PORT} -P ssl -b $TEST_HOSTNAME --summary || error "SSL connection failed!" -qpid-perftest --count ${COUNT} --port ${PORT} -P tcp -b $TEST_HOSTNAME --summary || error "TCP connection failed!" - -stop_brokers - -### Additional tests that require 'openssl' and 'pk12util' to be installed (optional) - -PK12UTIL=$(type -p pk12util) -if [[ !(-x $PK12UTIL) ]] ; then - echo >&2 "'pk12util' command not available, skipping remaining tests" - exit 0 -fi - -OPENSSL=$(type -p openssl) -if [[ !(-x $OPENSSL) ]] ; then - echo >&2 "'openssl' command not available, skipping remaining tests" - exit 0 -fi - -## verify python version > 2.5 (only 2.6+ does certificate checking) -PY_VERSION=$(python -c "import sys; print hex(sys.hexversion)") -if (( PY_VERSION < 0x02060000 )); then - echo >&2 "Detected python version < 2.6 - skipping certificate verification tests" - exit 0 -fi - -echo "Testing Certificate validation and Authentication with the Python Client..." - -# extract the CA's certificate as a PEM file -get_ca_certs() { - $PK12UTIL -o ${TEST_CERT_DIR}/CA_pk12.out -d ${CERT_DB} -n "Test-CA" -w ${CERT_PW_FILE} -k ${CERT_PW_FILE} > /dev/null - $OPENSSL pkcs12 -in ${TEST_CERT_DIR}/CA_pk12.out -out ${CA_PEM_FILE} -nokeys -passin file:${CERT_PW_FILE} >/dev/null - $PK12UTIL -o ${TEST_CERT_DIR}/other_CA_pk12.out -d ${OTHER_CA_CERT_DB} -n "Other-Test-CA" -w ${CERT_PW_FILE} -k ${CERT_PW_FILE} > /dev/null - $OPENSSL pkcs12 -in ${TEST_CERT_DIR}/other_CA_pk12.out -out ${OTHER_CA_PEM_FILE} -nokeys -passin file:${CERT_PW_FILE} >/dev/null -} - -get_ca_certs || error "Could not extract CA certificates as PEM files" -start_ssl_broker -PORT=${PORTS[0]} -URL=amqps://$TEST_HOSTNAME:$PORT -# verify the python client can authenticate the broker using the CA -if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE}`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi -# verify the python client fails to authenticate the broker when using the other CA -if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${OTHER_CA_PEM_FILE} > /dev/null 2>&1`; then { echo " Failed"; exit 1; }; else echo " Passed"; fi -stop_brokers - -# create a certificate without matching TEST_HOSTNAME, should fail to verify - -create_certs "O=MyCo" "*.${TEST_HOSTNAME}.com" || error "Could not create server test certificate" -get_ca_certs || error "Could not extract CA certificates as PEM files" -start_ssl_broker -PORT=${PORTS[0]} -URL=amqps://$TEST_HOSTNAME:$PORT -if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE} > /dev/null 2>&1`; then { echo " Failed"; exit 1; }; else echo " Passed"; fi -# but disabling the check for the hostname should pass -if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE} --ssl-skip-hostname-check`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi -stop_brokers - -# test SubjectAltName parsing - -if (( PY_VERSION >= 0x02070300 )); then -# python 2.7.3+ supports SubjectAltName extraction -# create a certificate with TEST_HOSTNAME only in SAN, should verify OK - create_certs "O=MyCo" "*.foo.com,${TEST_HOSTNAME},*xyz.com" || error "Could not create server test certificate" - get_ca_certs || error "Could not extract CA certificates as PEM files" - start_ssl_broker - PORT=${PORTS[0]} - URL=amqps://$TEST_HOSTNAME:$PORT - if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE}`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi - stop_brokers - - create_certs "O=MyCo" "*${TEST_HOSTNAME}" || error "Could not create server test certificate" - get_ca_certs || error "Could not extract CA certificates as PEM files" - start_ssl_broker - PORT=${PORTS[0]} - URL=amqps://$TEST_HOSTNAME:$PORT - if `${PY_PING_BROKER} -b $URL --ssl-trustfile=${CA_PEM_FILE}`; then echo " Passed"; else { echo " Failed"; exit 1; }; fi - stop_brokers -fi diff --git a/qpid/cpp/src/tests/store.py b/qpid/cpp/src/tests/store.py deleted file mode 100755 index 5c1934dded..0000000000 --- a/qpid/cpp/src/tests/store.py +++ /dev/null @@ -1,214 +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. -# - -import errno, os, time -from brokertest import * -from qpid import compat, session -from qpid.util import connect -from qpid.connection import Connection -from qpid.datatypes import Message, uuid4 -from qpid.queue import Empty - -class StoreTests(BrokerTest): - - XA_RBROLLBACK = 1 - XA_RBTIMEOUT = 2 - XA_OK = 0 - tx_counter = 0 - - def configure(self, config): - self.config = config - self.defines = self.config.defines - BrokerTest.configure(self, config) - - def setup_connection(self): - socket = connect(self._broker.host(), self._broker.port()) - return Connection(sock=socket) - - def setup_session(self): - self.conn.start() - return self.conn.session(str(uuid4())) - - def start_session(self): - self.conn = self.setup_connection() - self.ssn = self.setup_session() - - def setUp(self): - BrokerTest.setUp(self) - self._broker = self.broker() - self.start_session() - - def cycle_broker(self): - # tearDown resets working dir; change it back after. - d = os.getcwd() - BrokerTest.tearDown(self) - os.chdir(d) - self._broker = None - self._broker = self.broker() - self.conn = self.setup_connection() - self.ssn = self.setup_session() - - def xid(self, txid): - StoreTests.tx_counter += 1 - branchqual = "v%s" % StoreTests.tx_counter - return self.ssn.xid(format=0, global_id=txid, branch_id=branchqual) - - def testDurableExchange(self): - try: - self.ssn.exchange_delete(exchange="DE1") - except: - # restart the session busted from the exception - self.start_session() - - self.ssn.exchange_declare(exchange="DE1", type="direct", durable=True) - response = self.ssn.exchange_query(name="DE1") - self.assert_(response.durable) - self.assert_(not response.not_found) - - # Cycle the broker and make sure the exchange recovers - self.cycle_broker() - response = self.ssn.exchange_query(name="DE1") - self.assert_(response.durable) - self.assert_(not response.not_found) - - self.ssn.exchange_delete(exchange="DE1") - - def testDurableQueues(self): - try: - self.ssn.queue_delete(queue="DQ1") - except: - self.start_session() - - self.ssn.queue_declare(queue="DQ1", durable=True) - response = self.ssn.queue_query(queue="DQ1") - self.assertEqual("DQ1", response.queue) - self.assert_(response.durable) - - # Cycle the broker and make sure the queue recovers - self.cycle_broker() - response = self.ssn.queue_query(queue="DQ1") - self.assertEqual("DQ1", response.queue) - self.assert_(response.durable) - - self.ssn.queue_delete(queue="DQ1") - - def testDurableBindings(self): - try: - self.ssn.exchange_unbind(queue="DB_Q1", exchange="DB_E1", binding_key="K1") - except: - self.start_session() - try: - self.ssn.exchange_delete(exchange="DB_E1") - except: - self.start_session() - try: - self.ssn.queue_delete(queue="DB_Q1") - except: - self.start_session() - - self.ssn.queue_declare(queue="DB_Q1", durable=True) - self.ssn.exchange_declare(exchange="DB_E1", type="direct", durable=True) - self.ssn.exchange_bind(exchange="DB_E1", queue="DB_Q1", binding_key="K1") - - # Queue up 2 messages, one with non-zero body, one with zero-length. - # 2 = delivery_mode.persistent - dp = self.ssn.delivery_properties(routing_key="DB_Q1", delivery_mode=2) - self.ssn.message_transfer(message=Message(dp, "normal message")) - self.ssn.message_transfer(message=Message(dp, "")) - - # Cycle the broker and make sure the binding recovers - self.cycle_broker() - response = self.ssn.exchange_bound(exchange="DB_E1", queue="DB_Q1", binding_key="K1") - self.assert_(not response.exchange_not_found) - self.assert_(not response.queue_not_found) - self.assert_(not response.queue_not_matched) - self.assert_(not response.key_not_matched) - - # Are the messages still there? - self.ssn.message_subscribe(destination="msgs", queue="DB_Q1", accept_mode=1, acquire_mode=0) - self.ssn.message_flow(unit = 1, value = 0xFFFFFFFFL, destination = "msgs") - self.ssn.message_flow(unit = 0, value = 10, destination = "msgs") - message_arrivals = self.ssn.incoming("msgs") - try: - message_arrivals.get(timeout=1) - message_arrivals.get(timeout=1) - except Empty: - assert False, 'Durable message(s) not recovered' - - self.ssn.exchange_unbind(queue="DB_Q1", exchange="DB_E1", binding_key="K1") - self.ssn.exchange_delete(exchange="DB_E1") - self.ssn.queue_delete(queue="DB_Q1") - - def testDtxRecoverPrepared(self): - try: - self.ssn.exchange_unbind(queue="Dtx_Q", exchange="Dtx_E", binding_key="Dtx") - except: - self.start_session() - try: - self.ssn.exchange_delete(exchange="Dtx_E") - except: - self.start_session() - try: - self.ssn.queue_delete(queue="Dtx_Q") - except: - self.start_session() - - self.ssn.queue_declare(queue="Dtx_Q", auto_delete=False, durable=True) - self.ssn.exchange_declare(exchange="Dtx_E", type="direct", durable=True) - self.ssn.exchange_bind(exchange="Dtx_E", queue="Dtx_Q", binding_key="Dtx") - txid = self.xid("DtxRecoverPrepared") - self.ssn.dtx_select() - self.ssn.dtx_start(xid=txid) - # 2 = delivery_mode.persistent - dp = self.ssn.delivery_properties(routing_key="Dtx_Q", delivery_mode=2) - self.ssn.message_transfer(message=Message(dp, "transactional message")) - self.ssn.dtx_end(xid=txid) - self.assertEqual(self.XA_OK, self.ssn.dtx_prepare(xid=txid).status) - # Cycle the broker and make sure the xid is there, the message is not - # queued. - self.cycle_broker() - # The txid should be recovered and in doubt - xids = self.ssn.dtx_recover().in_doubt - xid_matched = False - for x in xids: - self.assertEqual(txid.format, x.format) - self.assertEqual(txid.global_id, x.global_id) - self.assertEqual(txid.branch_id, x.branch_id) - xid_matched = True - self.assert_(xid_matched) - self.ssn.message_subscribe(destination="dtx_msgs", queue="Dtx_Q", accept_mode=1, acquire_mode=0) - self.ssn.message_flow(unit = 1, value = 0xFFFFFFFFL, destination = "dtx_msgs") - self.ssn.message_flow(unit = 0, value = 10, destination = "dtx_msgs") - message_arrivals = self.ssn.incoming("dtx_msgs") - try: - message_arrivals.get(timeout=1) - assert False, 'Message present in queue before commit' - except Empty: pass - self.ssn.dtx_select() - self.assertEqual(self.XA_OK, self.ssn.dtx_commit(xid=txid, one_phase=False).status) - try: - msg = message_arrivals.get(timeout=1) - self.assertEqual("transactional message", msg.body) - except Empty: - assert False, 'Message should be present after dtx commit but is not' - - self.ssn.exchange_unbind(queue="Dtx_Q", exchange="Dtx_E", binding_key="Dtx") - self.ssn.exchange_delete(exchange="Dtx_E") - self.ssn.queue_delete(queue="Dtx_Q") diff --git a/qpid/cpp/src/tests/test_store.cpp b/qpid/cpp/src/tests/test_store.cpp deleted file mode 100644 index 14aee7b648..0000000000 --- a/qpid/cpp/src/tests/test_store.cpp +++ /dev/null @@ -1,339 +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. - * - */ - - -/**@file - * - * Message store for tests, with two roles: - * - * 1. Dump store events to a text file that can be compared to expected event - * sequence - * - * 2. Emulate hard-to-recreate conditions such as asynchronous completion delays - * or store errors. - * - * Messages with specially formatted contents trigger various actions. - * See class Action below for available actions and message format.. - * - */ - -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/amqp_0_10/MessageTransfer.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Thread.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/RefCounted.h" -#include "qpid/Msg.h" -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace boost; -using namespace qpid; -using namespace qpid::broker; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -namespace { - -bool startswith(const string& s, const string& prefix) { - return s.compare(0, prefix.size(), prefix) == 0; -} - -void split(const string& s, vector& result, const char* sep=" \t\n") { - size_t i = s.find_first_not_of(sep); - while (i != string::npos) { - size_t j = s.find_first_of(sep, i); - if (j == string::npos) { - result.push_back(s.substr(i)); - break; - } - result.push_back(s.substr(i, j-i)); - i = s.find_first_not_of(sep, j); - } -} - -} - -/** - * Action message format is TEST_STORE_DO [...]: [...] - * - * A list of store can be included so the action only executes on one of - * the named stores. This is useful in a cluster setting where the same message - * is replicated to all broker's stores but should only trigger an action on - * specific ones. If no is given, execute on any store. - * - */ -class Action { - public: - /** Available actions */ - enum ActionEnum { - NONE, - THROW, ///< Throw an exception from enqueue - DELAY, ///< Delay completion, takes an ID string to complete. - COMPLETE, ///< Complete a previously delayed message, takes ID - - N_ACTIONS // Count of actions, must be last - }; - - string name; - ActionEnum index; - vector storeNames, args; - - Action(const string& s) { - index = NONE; - if (!startswith(s, PREFIX)) return; - size_t colon = s.find_first_of(":"); - if (colon == string::npos) return; - assert(colon >= PREFIX.size()); - split(s.substr(PREFIX.size(), colon-PREFIX.size()), storeNames); - split(s.substr(colon+1), args); - if (args.empty()) return; - for (size_t i = 0; i < N_ACTIONS; ++i) { - if (args[0] == ACTION_NAMES[i]) { - name = args[0]; - index = ActionEnum(i); - args.erase(args.begin()); - break; - } - } - } - - bool executeIn(const string& storeName) { - return storeNames.empty() || - find(storeNames.begin(), storeNames.end(), storeName) !=storeNames.end(); - } - - private: - static string PREFIX; - static const char* ACTION_NAMES[N_ACTIONS]; -}; - -string Action::PREFIX("TEST_STORE_DO"); - -const char* Action::ACTION_NAMES[] = { "none", "throw", "delay", "complete" }; - - -struct TestStoreOptions : public Options { - - string name; - string dump; - string events; - - 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-events", optValue(events, "FILE"), - "File to log events, 1 line per event.") - ; - } -}; - - -class TestStore : public NullMessageStore { - public: - TestStore(const TestStoreOptions& opts, Broker& broker_) - : options(opts), name(opts.name), broker(broker_) - { - QPID_LOG(info, "TestStore name=" << name - << " dump=" << options.dump - << " events=" << options.events) - - 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)); - } - - // Dummy transaction context. - struct TxContext : public TPCTransactionContext { - static int nextId; - string id; - TxContext() : id(lexical_cast(nextId++)) {} - TxContext(string xid) : id(xid) {} - }; - - static string getId(const TransactionContext& tx) { - const TxContext* tc = dynamic_cast(&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 begin() { - auto_ptr tx(new TxContext()); - log(Msg() << "id << ">"); - return auto_ptr(tx); - } - - auto_ptr begin(const std::string& xid) { - auto_ptr tx(new TxContext(xid)); - log(Msg() << "id << ">"); - return auto_ptr(tx); - } - - string getContent(const intrusive_ptr& msg) { - intrusive_ptr enc( - dynamic_pointer_cast(msg)); - return enc->getContent(); - } - - void enqueue(TransactionContext* tx, - const boost::intrusive_ptr& pmsg, - const PersistableQueue& queue) - { - ostringstream o; - string data = getContent(pmsg); - o << ""; - log(o.str()); - - // Dump the message if there is a dump file. - if (dump.get()) { - *dump << "Message(" << data.size() << "): " << data << endl; - } - string logPrefix = "TestStore "+name+": "; - Action action(data); - bool doComplete = true; - if (action.index && action.executeIn(name)) { - switch (action.index) { - - case Action::THROW: - throw Exception(logPrefix + data); - break; - - case Action::DELAY: { - if (action.args.empty()) { - QPID_LOG(error, logPrefix << "async-id needs argument: " << data); - break; - } - asyncIds[action.args[0]] = pmsg; - QPID_LOG(debug, logPrefix << "delayed completion " << action.args[0]); - doComplete = false; - break; - } - - case Action::COMPLETE: { - if (action.args.empty()) { - QPID_LOG(error, logPrefix << "complete-id needs argument: " << data); - break; - } - AsyncIds::iterator i = asyncIds.find(action.args[0]); - if (i != asyncIds.end()) { - i->second->enqueueComplete(); - QPID_LOG(debug, logPrefix << "completed " << action.args[0]); - asyncIds.erase(i); - } else { - QPID_LOG(info, logPrefix << "not found for completion " << action.args[0]); - } - break; - } - - default: - QPID_LOG(error, logPrefix << "unknown action: " << data); - } - } - if (doComplete) pmsg->enqueueComplete(); - } - - void dequeue(TransactionContext* tx, - const boost::intrusive_ptr& msg, - const PersistableQueue& queue) - { - QPID_LOG(debug, "TestStore dequeue " << queue.getName()); - ostringstream o; - o<< ""; - log(o.str()); - } - - void prepare(TPCTransactionContext& txn) { - log(Msg() << ""); - } - - void commit(TransactionContext& txn) { - log(Msg() << ""); - } - - void abort(TransactionContext& txn) { - log(Msg() << ""); - } - - - private: - typedef map > AsyncIds; - - TestStoreOptions options; - string name; - Broker& broker; - vector threads; - std::auto_ptr dump; - std::auto_ptr events; - AsyncIds asyncIds; -}; - -int TestStore::TxContext::nextId(1); - -struct TestStorePlugin : public Plugin { - - TestStoreOptions options; - - Options* getOptions() { return &options; } - - void earlyInitialize (Plugin::Target& target) - { - Broker* broker = dynamic_cast(&target); - if (!broker) return; - boost::shared_ptr p(new TestStore(options, *broker)); - broker->setStore (p); - } - - void initialize(qpid::Plugin::Target&) {} -}; - -static TestStorePlugin pluginInstance; - -}} // namespace qpid::tests diff --git a/qpid/cpp/src/tests/test_tools.h b/qpid/cpp/src/tests/test_tools.h deleted file mode 100644 index d006246299..0000000000 --- a/qpid/cpp/src/tests/test_tools.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef TEST_TOOLS_H -#define TEST_TOOLS_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/Logger.h" - -#include // Include before boost/test headers. -#include -#include -#include -#include -#include -#include -#include -#include - -// Print a sequence -template std::ostream& seqPrint(std::ostream& o, const T& seq) { - std::copy(seq.begin(), seq.end(), std::ostream_iterator(o, " ")); - return o; -} - -// Compare sequences -template -bool seqEqual(const T& a, const U& b) { - typename T::const_iterator i = a.begin(); - typename U::const_iterator j = b.begin(); - while (i != a.end() && j != b.end() && *i == *j) { ++i; ++j; } - return (i == a.end()) && (j == b.end()); -} - -// ostream and == operators so we can compare vectors and sets with -// boost::assign::list_of with BOOST_CHECK_EQUALS -namespace std { // In namespace std so boost can find them. - -template -ostream& operator<<(ostream& o, const vector& v) { return seqPrint(o, v); } - -template -ostream& operator<<(ostream& o, const set& v) { return seqPrint(o, v); } - -template -ostream& operator<<(ostream& o, const boost::assign_detail::generic_list& l) { return seqPrint(o, l); } - -template -bool operator == (const vector& a, const boost::assign_detail::generic_list& b) { return seqEqual(a, b); } - -template -bool operator == (const boost::assign_detail::generic_list& b, const vector& a) { return seqEqual(a, b); } - -template -bool operator == (const set& a, const boost::assign_detail::generic_list& b) { return seqEqual(a, b); } - -template -bool operator == (const boost::assign_detail::generic_list& b, const set& a) { return seqEqual(a, b); } -} - -namespace qpid { -namespace tests { - -/** Check if types of two objects (as given by typeinfo::name()) match. */ -#define BOOST_CHECK_TYPEID_EQUAL(a,b) BOOST_CHECK_EQUAL(typeid(a).name(),typeid(b).name()) - -/** - * Supress all logging in a scope, restore to previous configuration in destructor. - */ -struct ScopedSuppressLogging { - typedef qpid::log::Logger Logger; - ScopedSuppressLogging(Logger& l=Logger::instance()) : logger(l), opts(l.getOptions()) { l.clear(); } - ~ScopedSuppressLogging() { logger.configure(opts); } - Logger& logger; - qpid::log::Options opts; -}; - -inline std::string getLibPath(const char* envName, const char* defaultPath = 0) { - const char* p = std::getenv(envName); - if (p != 0) - return p; - if (defaultPath == 0) { - std::ostringstream msg; - msg << "Environment variable " << envName << " not set."; - throw std::runtime_error(msg.str()); - } - return defaultPath; -} - -}} // namespace qpid::tests - -#endif /*!TEST_TOOLS_H*/ - diff --git a/qpid/cpp/src/tests/topictest b/qpid/cpp/src/tests/topictest deleted file mode 100755 index 13f38120b3..0000000000 --- a/qpid/cpp/src/tests/topictest +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env 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 C++ topic test - -# Clean up old log files -rm -f subscriber_*.log - -# Defaults values -SUBSCRIBERS=10 -MESSAGES=2000 -BATCHES=10 - -while getopts "s:m:b:h:t" opt ; do - case $opt in - s) SUBSCRIBERS=$OPTARG ;; - m) MESSAGES=$OPTARG ;; - b) BATCHES=$OPTARG ;; - h) HOST=-h$OPTARG ;; - t) TRANSACTIONAL="--transactional --durable" ;; - ?) - echo "Usage: %0 [-s ] [-m ]" - exit 1 - ;; - esac -done - -subscribe() { - echo Start subscriber $1 - LOG="subscriber_$1.log" - qpid-topic-listener $TRANSACTIONAL > $LOG 2>&1 && rm -f $LOG -} - -publish() { - qpid-topic-publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS $HOST $TRANSACTIONAL -} - -for ((i=$SUBSCRIBERS ; i--; )); do - subscribe $i & -done -# FIXME aconway 2007-03-27: Hack around startup race. Fix topic test. -sleep 2 -publish 2>&1 || exit 1 diff --git a/qpid/cpp/src/tests/topictest.ps1 b/qpid/cpp/src/tests/topictest.ps1 deleted file mode 100644 index f15b2d452c..0000000000 --- a/qpid/cpp/src/tests/topictest.ps1 +++ /dev/null @@ -1,73 +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. -# - -# Parameters with default values: s (subscribers) m (messages) b (batches) -# h (host) t (false; use transactions) -param ( - [int]$subscribers = 10, - [int]$message_count = 2000, - [int]$batches = 10, - [string]$broker, - [switch] $t # transactional -) - -# Run the C++ topic test -[string]$me = $myInvocation.InvocationName -$srcdir = Split-Path $me -#$srcdir = Split-Path $myInvocation.InvocationName - -# Clean up old log files -Get-Item subscriber_*.log | Remove-Item - -if ($t) { - $transactional = "--transactional --durable" -} - -# Find which subdir the exes are in -. $srcdir\find_prog.ps1 .\qpid-topic-listener.exe - -function subscribe { - param ([int]$num, [string]$sub) - "Start subscriber $num" - $LOG = "subscriber_$num.log" - $cmdline = ".\$sub\qpid-topic-listener $transactional > $LOG 2>&1 - if (`$LastExitCode -ne 0) { Remove-Item $LOG }" - $cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline) - . $srcdir\background.ps1 $cmdblock -} - -function publish { - param ([string]$sub) - Invoke-Expression ".\$sub\qpid-topic-publisher --messages $message_count --batches $batches --subscribers $subscribers $host $transactional" 2>&1 -} - -if ($broker.length) { - $broker = "-h$broker" -} - -$i = $subscribers -while ($i -gt 0) { - subscribe $i $sub - $i-- -} - -# FIXME aconway 2007-03-27: Hack around startup race. Fix topic test. -Start-Sleep 2 -publish $sub -exit $LastExitCode diff --git a/qpid/cpp/src/tests/txjob.cpp b/qpid/cpp/src/tests/txjob.cpp deleted file mode 100644 index 29394c3415..0000000000 --- a/qpid/cpp/src/tests/txjob.cpp +++ /dev/null @@ -1,102 +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 -#include -#include - -#include "TestOptions.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/FailoverManager.h" -#include "qpid/client/Message.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/sys/Thread.h" - -using namespace qpid::client; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -struct Args : public qpid::TestOptions -{ - std::string workQueue; - std::string source; - std::string dest; - uint messages; - uint jobs; - bool quit; - bool declareQueues; - - Args() : workQueue("txshift-control"), source("txshift-1"), dest("txshift-2"), messages(0), jobs(0), - quit(false), declareQueues(false) - { - addOptions() - ("messages", qpid::optValue(messages, "N"), "Number of messages to shift") - ("jobs", qpid::optValue(jobs, "N"), "Number of shift jobs to request") - ("source", qpid::optValue(source, "QUEUE NAME"), "source queue from which messages will be shifted") - ("dest", qpid::optValue(dest, "QUEUE NAME"), "dest queue to which messages will be shifted") - ("work-queue", qpid::optValue(workQueue, "QUEUE NAME"), "work queue from which to take instructions") - ("add-quit", qpid::optValue(quit), "add a 'quit' instruction to the queue (after any other jobs)") - ("declare-queues", qpid::optValue(declareQueues), "issue a declare for all queues"); - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -//TODO: might be nice to make this capable of failover as well at some -//point; for now its just for the setup phase. -int main(int argc, char** argv) -{ - Args opts; - try { - opts.parse(argc, argv); - Connection connection; - connection.open(opts.con); - Session session = connection.newSession(); - if (opts.declareQueues) { - session.queueDeclare(arg::queue=opts.workQueue); - session.queueDeclare(arg::queue=opts.source); - session.queueDeclare(arg::queue=opts.dest); - } - for (uint i = 0; i < opts.jobs; ++i) { - Message job("transfer", opts.workQueue); - job.getHeaders().setString("src", opts.source); - job.getHeaders().setString("dest", opts.dest); - job.getHeaders().setInt("count", opts.messages); - async(session).messageTransfer(arg::content=job); - } - - if (opts.quit) { - async(session).messageTransfer(arg::content=Message("quit", opts.workQueue)); - } - - session.sync(); - session.close(); - - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - return 1; - } -} diff --git a/qpid/cpp/src/tests/txshift.cpp b/qpid/cpp/src/tests/txshift.cpp deleted file mode 100644 index 6ec28c7233..0000000000 --- a/qpid/cpp/src/tests/txshift.cpp +++ /dev/null @@ -1,193 +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 -#include -#include - -#include "TestOptions.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/FailoverManager.h" -#include "qpid/client/Message.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Thread.h" - -using namespace qpid::client; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -struct Args : public qpid::TestOptions -{ - std::string workQueue; - uint workers; - - Args() : workQueue("txshift-control"), workers(1) - { - addOptions() - ("workers", qpid::optValue(workers, "N"), "Number of separate worker sessions to start") - ("work-queue", qpid::optValue(workQueue, "NAME"), "work queue from which to take instructions"); - } -}; - -struct Transfer : MessageListener -{ - std::string control; - std::string source; - std::string destination; - uint expected; - uint transfered; - SubscriptionSettings controlSettings; - Subscription controlSubscription; - SubscriptionSettings sourceSettings; - Subscription sourceSubscription; - - Transfer(const std::string control_) : control(control_), expected(0), transfered(0) {} - - void subscribeToSource(SubscriptionManager manager) - { - sourceSettings.autoAck = 0;//will accept once at the end of the batch - sourceSettings.flowControl = FlowControl::messageCredit(expected); - sourceSubscription = manager.subscribe(*this, source, sourceSettings); - QPID_LOG(info, "Subscribed to source: " << source << " expecting: " << expected); - } - - void subscribeToControl(SubscriptionManager manager) - { - controlSettings.flowControl = FlowControl::messageCredit(1); - controlSubscription = manager.subscribe(*this, control, controlSettings); - QPID_LOG(info, "Subscribed to job queue"); - } - - void received(Message& message) - { - QPID_LOG(debug, "received: " << message.getData() << " for " << message.getDestination()); - if (message.getDestination() == source) { - receivedFromSource(message); - } else if (message.getDestination() == control) { - receivedFromControl(message); - } else { - QPID_LOG(error, "Unexpected message: " << message.getData() << " to " << message.getDestination()); - } - } - - void receivedFromSource(Message& message) - { - QPID_LOG(debug, "transfering " << (transfered+1) << " of " << expected); - message.getDeliveryProperties().setRoutingKey(destination); - async(sourceSubscription.getSession()).messageTransfer(arg::content=message); - if (++transfered == expected) { - QPID_LOG(info, "completed job: " << transfered << " messages shifted from " << - source << " to " << destination); - sourceSubscription.accept(sourceSubscription.getUnaccepted()); - sourceSubscription.getSession().txCommit(); - sourceSubscription.cancel(); - //grant credit to allow broker to send us another control message - controlSubscription.grantMessageCredit(1); - } - } - - void receivedFromControl(Message& message) - { - if (message.getData() == "transfer") { - source = message.getHeaders().getAsString("src"); - destination = message.getHeaders().getAsString("dest"); - expected = message.getHeaders().getAsInt("count"); - transfered = 0; - QPID_LOG(info, "received transfer request: " << expected << " messages to be shifted from " << - source << " to " << destination); - subscribeToSource(controlSubscription.getSubscriptionManager()); - } else if (message.getData() == "quit") { - QPID_LOG(info, "received quit request"); - controlSubscription.cancel(); - } else { - std::cerr << "Rejecting invalid message: " << message.getData() << std::endl; - controlSubscription.getSession().messageReject(SequenceSet(message.getId())); - } - } - -}; - -struct Worker : FailoverManager::Command, Runnable -{ - FailoverManager& connection; - Transfer transfer; - Thread runner; - - Worker(FailoverManager& c, const std::string& controlQueue) : connection(c), transfer(controlQueue) {} - - void run() - { - connection.execute(*this); - } - - void start() - { - runner = Thread(this); - } - - void join() - { - runner.join(); - } - - void execute(AsyncSession& session, bool isRetry) - { - if (isRetry) QPID_LOG(info, "Retrying..."); - session.txSelect(); - SubscriptionManager subs(session); - transfer.subscribeToControl(subs); - subs.run(); - session.txCommit();//commit accept of control messages - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - Args opts; - try { - opts.parse(argc, argv); - FailoverManager connection(opts.con); - connection.connect(); - if (opts.workers == 1) { - Worker worker(connection, opts.workQueue); - worker.run(); - } else { - boost::ptr_vector workers; - for (uint i = 0; i < opts.workers; i++) { - workers.push_back(new Worker(connection, opts.workQueue)); - } - std::for_each(workers.begin(), workers.end(), boost::bind(&Worker::start, _1)); - std::for_each(workers.begin(), workers.end(), boost::bind(&Worker::join, _1)); - } - - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - return 1; - } -} diff --git a/qpid/cpp/src/tests/unit_test.cpp b/qpid/cpp/src/tests/unit_test.cpp deleted file mode 100644 index 00c61242e4..0000000000 --- a/qpid/cpp/src/tests/unit_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * - * 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. - * - */ - -// Defines test_main function to link with actual unit test code. -#define BOOST_AUTO_TEST_MAIN // Boost 1.33 -#define BOOST_TEST_MAIN -#include "unit_test.h" - diff --git a/qpid/cpp/src/tests/unit_test.h b/qpid/cpp/src/tests/unit_test.h deleted file mode 100644 index a11df2ff04..0000000000 --- a/qpid/cpp/src/tests/unit_test.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef QPIPD_TEST_UNIT_TEST_H_ -#define QPIPD_TEST_UNIT_TEST_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. - * - */ - -// Workaround so we can build against boost 1.33 and boost 1.34. -// Remove when we no longer need to support 1.33. -// -#include -#include // Must be inclued beofre boost/test headers. - -// #include the correct header file. -// -#if (BOOST_VERSION < 103400) -# include -#else -# include -#endif // BOOST_VERSION - -// Workarounds for BOOST_AUTO_TEST_CASE|SUITE|SUITE_END -// -#if (BOOST_VERSION < 103300) - -# define QPID_AUTO_TEST_SUITE(name) -# define QPID_AUTO_TEST_CASE(name) BOOST_AUTO_UNIT_TEST(name) -# define QPID_AUTO_TEST_SUITE_END() - -#elif (BOOST_VERSION < 103400) -// Note the trailing ';' -# define QPID_AUTO_TEST_SUITE(name) BOOST_AUTO_TEST_SUITE(name); -# define QPID_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END(); - -#endif // Workarounds for BOOST_AUTO_TEST_CASE|SUITE|SUITE_END - -// -// Default definitions for latest version of boost. -// - -#ifndef QPID_AUTO_TEST_SUITE -# define QPID_AUTO_TEST_SUITE(name) BOOST_AUTO_TEST_SUITE(name) -#endif - -#ifndef QPID_AUTO_TEST_CASE -# define QPID_AUTO_TEST_CASE(name) BOOST_AUTO_TEST_CASE(name) -#endif - -#ifndef QPID_FIXTURE_TEST_CASE -# define QPID_FIXTURE_TEST_CASE(name, f) BOOST_FIXTURE_TEST_CASE(name, f) -#endif - -#ifndef QPID_AUTO_TEST_SUITE_END -# define QPID_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END() -#endif - -#endif // !QPIPD_TEST_UNIT_TEST_H_ diff --git a/qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp b/qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp deleted file mode 100644 index 14f1e46606..0000000000 --- a/qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp +++ /dev/null @@ -1,78 +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. - * - */ - -// This file intends to prevent Windows from throwing up error boxes and -// offering to debug when serious errors happen. The errors are displayed -// on stderr instead. The purpose of this is to allow the tests to proceed -// scripted and catch the text for logging. If this behavior is desired, -// include this file with the executable being built. If the default -// behaviors are desired, don't include this file in the build. - -#if defined(_MSC_VER) -#include -#endif -#include -#include - -namespace qpid { -namespace tests { -namespace windows { - -// Instead of popping up a window for exceptions, just print something out -LONG _stdcall UnhandledExceptionFilter (PEXCEPTION_POINTERS pExceptionInfo) -{ - DWORD dwExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode; - - if (dwExceptionCode == EXCEPTION_ACCESS_VIOLATION) - std::cerr << "\nERROR: ACCESS VIOLATION\n" << std::endl; - else - std::cerr << "\nERROR: UNHANDLED EXCEPTION\n" << std::endl; - - return EXCEPTION_EXECUTE_HANDLER; -} - -struct redirect_errors_to_stderr { - redirect_errors_to_stderr (); -}; - -static redirect_errors_to_stderr block; - -redirect_errors_to_stderr::redirect_errors_to_stderr() -{ -#if defined(_MSC_VER) - _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE); - _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR); - _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR); - _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR); -#endif - - // Prevent the system from displaying the critical-error-handler - // and can't-open-file message boxes. - SetErrorMode(SEM_FAILCRITICALERRORS); - SetErrorMode(SEM_NOOPENFILEERRORBOX); - - // And this will catch all unhandled exceptions. - SetUnhandledExceptionFilter (&UnhandledExceptionFilter); -} - -}}} // namespace diff --git a/qpid/cpp/src/versions.cmake b/qpid/cpp/src/versions.cmake deleted file mode 100644 index ac20e9ed7f..0000000000 --- a/qpid/cpp/src/versions.cmake +++ /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. -# - -# Library Version Information (CURRENT.REVISION.AGE): -# -# CURRENT => API/ABI version. Bump this if the interface changes -# REVISION => Version of underlying implementation. -# Bump if implementation changes but API/ABI doesn't -# AGE => Number of API/ABI versions this is backward compatible with - -set (qmf_version 1.0.0) -set (qmf2_version 1.0.0) -set (qmfconsole_version 2.0.0) -set (qmfengine_version 1.1.0) -set (qpidbroker_version 2.0.0) -set (qpidclient_version 2.0.0) -set (qpidcommon_version 2.0.0) -set (qpidmessaging_version 2.0.0) -set (qpidtypes_version 1.0.0) -set (rdmawrap_version 2.0.0) -set (sslcommon_version 2.0.0) -set (legacystore_version 1.0.0) - -string(REGEX MATCH "[0-9]*" qmf_version_major ${qmf_version}) -string(REGEX MATCH "[0-9]*" qmf2_version_major ${qmf2_version}) -string(REGEX MATCH "[0-9]*" qmfconsole_version_major ${qmfconsole_version}) -string(REGEX MATCH "[0-9]*" qmfengine_version_major ${qmfengine_version}) -string(REGEX MATCH "[0-9]*" qpidbroker_version_major ${qpidbroker_version}) -string(REGEX MATCH "[0-9]*" qpidclient_version_major ${qpidclient_version}) -string(REGEX MATCH "[0-9]*" qpidcommon_version_major ${qpidcommon_version}) -string(REGEX MATCH "[0-9]*" qpidmessaging_version_major ${qpidmessaging_version}) -string(REGEX MATCH "[0-9]*" qpidtypes_version_major ${qpidtypes_version}) -string(REGEX MATCH "[0-9]*" rdmawrap_version_major ${rdmawrap_version}) -string(REGEX MATCH "[0-9]*" sslcommon_version_major ${sslcommon_version}) -string(REGEX MATCH "[0-9]*" legacystore_version_major ${legacystore_version}) diff --git a/qpid/cpp/src/windows/QpiddBroker.cpp b/qpid/cpp/src/windows/QpiddBroker.cpp deleted file mode 100644 index b383b7d6c7..0000000000 --- a/qpid/cpp/src/windows/QpiddBroker.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 "config.h" -#include "qpidd.h" -#include "SCM.h" -#include "qpid/Exception.h" -#include "qpid/Options.h" -#include "qpid/Plugin.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/windows/check.h" -#include "qpid/sys/Thread.h" -#include "qpid/broker/Broker.h" - -#include -#include -#include -#include - -namespace { - // This will accept args from the command line; augmented with service args. - std::vector cmdline_args; -} - -namespace qpid { -namespace broker { - -BootstrapOptions::BootstrapOptions(const char* argv0) - : qpid::Options("Options"), - common("", QPIDD_CONF_FILE, QPIDC_CONF_FILE), - module(QPIDD_MODULE_DIR), - log(argv0) -{ - add(common); - add(module); - add(log); -} - -void BootstrapOptions::usage() const { - std::cout << "Usage: qpidd [OPTIONS]" << std::endl << std::endl << *this << std::endl; -} - -// Local functions to set and get the pid via a LockFile. -namespace { - -const std::string TCP = "tcp"; - -// ShutdownEvent maintains an event that can be used to ask the broker -// to stop. Analogous to sending SIGTERM/SIGINT to the posix broker. -// The signal() method signals the event. -class ShutdownEvent { - public: - ShutdownEvent(int port); - ~ShutdownEvent(); - - void create(); - void open(); - void signal(); - - private: - std::string eventName; - - protected: - HANDLE event; -}; - -class ShutdownHandler : public ShutdownEvent, public qpid::sys::Runnable { - public: - ShutdownHandler(int port, const boost::intrusive_ptr& b) - : ShutdownEvent(port) { broker = b; } - - private: - virtual void run(); // Inherited from Runnable - boost::intrusive_ptr broker; -}; - -ShutdownEvent::ShutdownEvent(int port) : event(NULL) { - std::ostringstream name; - name << "qpidd_" << port << std::ends; - eventName = name.str(); -} - -void ShutdownEvent::create() { - // Auto-reset event in case multiple processes try to signal a - // broker that doesn't respond for some reason. Initially not signaled. - event = ::CreateEvent(NULL, false, false, eventName.c_str()); - QPID_WINDOWS_CHECK_NULL(event); -} - -void ShutdownEvent::open() { - // TODO: Might need to search Global\\ name if unadorned name fails - event = ::OpenEvent(EVENT_MODIFY_STATE, false, eventName.c_str()); - QPID_WINDOWS_CHECK_NULL(event); -} - -ShutdownEvent::~ShutdownEvent() { - ::CloseHandle(event); - event = NULL; -} - -void ShutdownEvent::signal() { - QPID_WINDOWS_CHECK_NOT(::SetEvent(event), 0); -} - - -void ShutdownHandler::run() { - if (event == NULL) - return; - ::WaitForSingleObject(event, INFINITE); - if (broker.get()) { - broker->shutdown(); - broker = 0; // Release the broker reference - } -} - -// Console control handler to properly handle ctl-c. -int ourPort; -BOOL CtrlHandler(DWORD ctl) -{ - ShutdownEvent shutter(ourPort); // We have to have set up the port before interrupting - shutter.open(); - shutter.signal(); - return ((ctl == CTRL_C_EVENT || ctl == CTRL_CLOSE_EVENT) ? TRUE : FALSE); -} - -template -class NamedSharedMemory { - std::string name; - HANDLE memory; - T* data; - -public: - NamedSharedMemory(const std::string&); - ~NamedSharedMemory(); - - T& create(); - T& get(); -}; - -template -NamedSharedMemory::NamedSharedMemory(const std::string& n) : - name(n), - memory(NULL), - data(0) -{} - -template -NamedSharedMemory::~NamedSharedMemory() { - if (data) - ::UnmapViewOfFile(data); - if (memory != NULL) - ::CloseHandle(memory); -} - -template -T& NamedSharedMemory::create() { - assert(memory == NULL); - - // Create named shared memory file - memory = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(T), name.c_str()); - QPID_WINDOWS_CHECK_NULL(memory); - - // Map file into memory - data = static_cast(::MapViewOfFile(memory, FILE_MAP_WRITE, 0, 0, 0)); - QPID_WINDOWS_CHECK_NULL(data); - - return *data; -} - -template -T& NamedSharedMemory::get() { - if (memory == NULL) { - // TODO: Might need to search Global\\ name if unadorned name fails - memory = ::OpenFileMapping(FILE_MAP_WRITE, FALSE, name.c_str()); - QPID_WINDOWS_CHECK_NULL(memory); - - data = static_cast(::MapViewOfFile(memory, FILE_MAP_WRITE, 0, 0, 0)); - QPID_WINDOWS_CHECK_NULL(data); - } - - return *data; -} - -std::string brokerInfoName(uint16_t port) -{ - std::ostringstream path; - path << "qpidd_info_" << port; - return path.str(); -} - -struct BrokerInfo { - DWORD pid; -}; - -// Service-related items. Only involved when running the broker as a Windows -// service. - -const std::string svcName = "qpidd"; -SERVICE_STATUS svcStatus; -SERVICE_STATUS_HANDLE svcStatusHandle = 0; - -// This function is only called when the broker is run as a Windows -// service. It receives control requests from Windows. -VOID WINAPI SvcCtrlHandler(DWORD control) -{ - switch(control) { - case SERVICE_CONTROL_STOP: - svcStatus.dwCurrentState = SERVICE_STOP_PENDING; - svcStatus.dwControlsAccepted = 0; - svcStatus.dwCheckPoint = 1; - svcStatus.dwWaitHint = 5000; // 5 secs. - ::SetServiceStatus(svcStatusHandle, &svcStatus); - CtrlHandler(CTRL_C_EVENT); - break; - - case SERVICE_CONTROL_INTERROGATE: - break; - - default: - break; - } -} - -VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) -{ - // The arguments can come from 2 places. Args set with the executable - // name when the service is installed come through main() and are now - // in cmdline_args. Arguments set in StartService come into argc/argv - // above; if they are set, argv[0] is the service name. Make command - // line args first; StartService args come later and can override - // command line args. - int all_argc = argc + cmdline_args.size(); - if (argc == 0 && !cmdline_args.empty()) - ++all_argc; // No StartService args, so need to add prog name argv[0] - const char **all_argv = new const char *[all_argc]; - if (all_argc > 0) { - int i = 0; - all_argv[i++] = argc > 0 ? argv[0] : svcName.c_str(); - for (size_t j = 0; j < cmdline_args.size(); ++j) - all_argv[i++] = cmdline_args[j].c_str(); - for (DWORD k = 1; k < argc; ++k) - all_argv[i++] = argv[k]; - } - - ::memset(&svcStatus, 0, sizeof(svcStatus)); - svcStatusHandle = ::RegisterServiceCtrlHandler(svcName.c_str(), - SvcCtrlHandler); - svcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - svcStatus.dwCheckPoint = 1; - svcStatus.dwWaitHint = 10000; // 10 secs. - svcStatus.dwCurrentState = SERVICE_START_PENDING; - ::SetServiceStatus(svcStatusHandle, &svcStatus); - // QpiddBroker class resets state to running. - svcStatus.dwWin32ExitCode = run_broker(all_argc, - const_cast(all_argv), - true); - svcStatus.dwCurrentState = SERVICE_STOPPED; - svcStatus.dwCheckPoint = 0; - svcStatus.dwWaitHint = 0; - ::SetServiceStatus(svcStatusHandle, &svcStatus); -} - -} // namespace - - -struct ProcessControlOptions : public qpid::Options { - bool quit; - bool check; - std::string transport; - - ProcessControlOptions() - : qpid::Options("Process control options"), - quit(false), - check(false), - transport(TCP) - { - addOptions() - ("check,c", qpid::optValue(check), "Prints the broker's process ID to stdout and returns 0 if the broker is running, otherwise returns 1") - ("transport", qpid::optValue(transport, "TRANSPORT"), "The transport for which to return the port") - ("quit,q", qpid::optValue(quit), "Tells the broker to shut down"); - } -}; - -struct ServiceOptions : public qpid::Options { - bool install; - bool start; - bool stop; - bool uninstall; - bool daemon; - std::string startType; - std::string startArgs; - std::string account; - std::string password; - std::string depends; - - ServiceOptions() - : qpid::Options("Service options"), - install(false), - start(false), - stop(false), - uninstall(false), - daemon(false), - startType("demand"), - startArgs(""), - account("NT AUTHORITY\\LocalService"), - password(""), - depends("") - { - addOptions() - ("install", qpid::optValue(install), "Install as service") - ("start-type", qpid::optValue(startType, "auto|demand|disabled"), "Service start type\nApplied at install time only.") - ("arguments", qpid::optValue(startArgs, "COMMAND LINE ARGS"), "Arguments to pass when service auto-starts") - ("account", qpid::optValue(account, "(LocalService)"), "Account to run as, default is LocalService\nApplied at install time only.") - ("password", qpid::optValue(password, "PASSWORD"), "Account password, if needed\nApplied at install time only.") - ("depends", qpid::optValue(depends, "(comma delimited list)"), "Names of services that must start before this service\nApplied at install time only.") - ("start", qpid::optValue(start), "Start the service.") - ("stop", qpid::optValue(stop), "Stop the service.") - ("uninstall", qpid::optValue(uninstall), "Uninstall the service."); - } -}; - -struct QpiddWindowsOptions : public QpiddOptionsPrivate { - ProcessControlOptions control; - ServiceOptions service; - QpiddWindowsOptions(QpiddOptions *parent) : QpiddOptionsPrivate(parent) { - parent->add(service); - parent->add(control); - } -}; - -QpiddOptions::QpiddOptions(const char* argv0) - : qpid::Options("Options"), - common("", QPIDD_CONF_FILE, QPIDC_CONF_FILE), - module(QPIDD_MODULE_DIR), - log(argv0) -{ - add(common); - add(module); - add(broker); - add(log); - - platform.reset(new QpiddWindowsOptions(this)); - qpid::Plugin::addOptions(*this); -} - -void QpiddOptions::usage() const { - std::cout << "Usage: qpidd [OPTIONS]" << std::endl << std::endl - << *this << std::endl; -} - -int QpiddBroker::execute (QpiddOptions *options) { - - // If running as a service, bump the status checkpoint to let SCM know - // we're still making progress. - if (svcStatusHandle != 0) { - svcStatus.dwCheckPoint++; - ::SetServiceStatus(svcStatusHandle, &svcStatus); - } - - // Options that affect a running daemon. - QpiddWindowsOptions *myOptions = - reinterpret_cast(options->platform.get()); - if (myOptions == 0) - throw qpid::Exception("Internal error obtaining platform options"); - - if (myOptions->service.install) { - // Handle start type - DWORD startType; - if (myOptions->service.startType.compare("demand") == 0) - startType = SERVICE_DEMAND_START; - else if (myOptions->service.startType.compare("auto") == 0) - startType = SERVICE_AUTO_START; - else if (myOptions->service.startType.compare("disabled") == 0) - startType = SERVICE_DISABLED; - else if (!myOptions->service.startType.empty()) - throw qpid::Exception("Invalid service start type: " + - myOptions->service.startType); - - // Install service and exit - qpid::windows::SCM manager; - manager.install(svcName, - "Apache Qpid Message Broker", - myOptions->service.startArgs, - startType, - myOptions->service.account, - myOptions->service.password, - myOptions->service.depends); - return 0; - } - - if (myOptions->service.start) { - qpid::windows::SCM manager; - manager.start(svcName); - return 0; - } - - if (myOptions->service.stop) { - qpid::windows::SCM manager; - manager.stop(svcName); - return 0; - } - - if (myOptions->service.uninstall) { - qpid::windows::SCM manager; - manager.uninstall(svcName); - return 0; - } - - if (myOptions->control.check || myOptions->control.quit) { - // Relies on port number being set via --port or QPID_PORT env variable. - NamedSharedMemory info(brokerInfoName(options->broker.port)); - int pid = info.get().pid; - if (pid < 0) - return 1; - if (myOptions->control.check) - std::cout << pid << std::endl; - if (myOptions->control.quit) { - ShutdownEvent shutter(options->broker.port); - shutter.open(); - shutter.signal(); - HANDLE brokerHandle = ::OpenProcess(SYNCHRONIZE, false, pid); - QPID_WINDOWS_CHECK_NULL(brokerHandle); - ::WaitForSingleObject(brokerHandle, INFINITE); - ::CloseHandle(brokerHandle); - } - return 0; - } - - boost::intrusive_ptr brokerPtr(new Broker(options->broker)); - - // Need the correct port number to use in the pid file name. - if (options->broker.port == 0) - options->broker.port = brokerPtr->getPort(myOptions->control.transport); - - BrokerInfo info; - info.pid = ::GetCurrentProcessId(); - - NamedSharedMemory sharedInfo(brokerInfoName(options->broker.port)); - sharedInfo.create() = info; - - // Allow the broker to receive a shutdown request via a qpidd --quit - // command. Note that when the broker is run as a service this operation - // should not be allowed. - ourPort = options->broker.port; - ShutdownHandler waitShut(ourPort, brokerPtr); - waitShut.create(); - qpid::sys::Thread waitThr(waitShut); // Wait for shutdown event - ::SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); - brokerPtr->accept(); - std::cout << options->broker.port << std::endl; - - // If running as a service, tell SCM we're up. There's still a chance - // that store recovery will drag out the time before the broker actually - // responds to requests, but integrating that mechanism with the SCM - // updating is probably more work than it's worth. - if (svcStatusHandle != 0) { - svcStatus.dwCheckPoint = 0; - svcStatus.dwWaitHint = 0; - svcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; - svcStatus.dwCurrentState = SERVICE_RUNNING; - ::SetServiceStatus(svcStatusHandle, &svcStatus); - } - - brokerPtr->run(); - waitShut.signal(); // In case we shut down some other way - waitThr.join(); - return 0; -} - -}} // namespace qpid::broker - -int main(int argc, char* argv[]) -{ - // If started as a service, notify the SCM we're up. Else just run. - // If as a service, StartServiceControlDispatcher doesn't return until - // the service is stopped. - SERVICE_TABLE_ENTRY dispatchTable[] = - { - { "", (LPSERVICE_MAIN_FUNCTION)qpid::broker::ServiceMain }, - { NULL, NULL } - }; - // Copy any command line args to be available in case we're started - // as a service. Pick these back up in ServiceMain. - for (int i = 1; i < argc; ++i) - cmdline_args.push_back(argv[i]); - - if (!StartServiceCtrlDispatcher(dispatchTable)) { - DWORD err = ::GetLastError(); - if (err == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) // Run as console - return qpid::broker::run_broker(argc, argv); - throw QPID_WINDOWS_ERROR(err); - } - return 0; -} diff --git a/qpid/cpp/src/windows/SCM.cpp b/qpid/cpp/src/windows/SCM.cpp deleted file mode 100644 index 2eeb143427..0000000000 --- a/qpid/cpp/src/windows/SCM.cpp +++ /dev/null @@ -1,332 +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/log/Statement.h" -#include "qpid/sys/windows/check.h" -#include "SCM.h" - -#pragma comment(lib, "advapi32.lib") - -namespace qpid { -namespace windows { - -namespace { - -// Container that will close a SC_HANDLE upon destruction. -class AutoServiceHandle { -public: - AutoServiceHandle(SC_HANDLE h_ = NULL) : h(h_) {} - ~AutoServiceHandle() { if (h != NULL) ::CloseServiceHandle(h); } - void release() { h = NULL; } - void reset(SC_HANDLE newHandle) - { - if (h != NULL) - ::CloseServiceHandle(h); - h = newHandle; - } - operator SC_HANDLE() const { return h; } - -private: - SC_HANDLE h; -}; - -} - -SCM::SCM() : scmHandle(NULL) -{ -} - -SCM::~SCM() -{ - if (NULL != scmHandle) - ::CloseServiceHandle(scmHandle); -} - -/** - * Install this executable as a service - */ -void SCM::install(const string& serviceName, - const string& serviceDesc, - const string& args, - DWORD startType, - const string& account, - const string& password, - const string& depends) -{ - // Handle dependent service name list; Windows wants a set of nul-separated - // names ending with a double nul. - string depends2 = depends; - if (!depends2.empty()) { - // CDL to null delimiter w/ trailing double null - size_t p = 0; - while ((p = depends2.find_first_of( ',', p)) != string::npos) - depends2.replace(p, 1, 1, '\0'); - depends2.push_back('\0'); - depends2.push_back('\0'); - } - -#if 0 - // I'm nervous about adding a user/password check here. Is this a - // potential attack vector, letting users check passwords without - // control? -Steve Huston, Feb 24, 2011 - - // Validate account, password - HANDLE hToken = NULL; - bool logStatus = false; - if (!account.empty() && !password.empty() && - !(logStatus = ::LogonUserA(account.c_str(), - "", - password.c_str(), - LOGON32_LOGON_NETWORK, - LOGON32_PROVIDER_DEFAULT, - &hToken ) != 0)) - std::cout << "warning: supplied account & password failed with LogonUser." << std::endl; - if (logStatus) - ::CloseHandle(hToken); -#endif - - // Get fully qualified .exe name - char myPath[MAX_PATH]; - DWORD myPathLength = ::GetModuleFileName(NULL, myPath, MAX_PATH); - QPID_WINDOWS_CHECK_NOT(myPathLength, 0); - string imagePath(myPath, myPathLength); - if (!args.empty()) - imagePath += " " + args; - - // Ensure there's a handle to the SCM database. - openSvcManager(); - - // Create the service - SC_HANDLE svcHandle; - svcHandle = ::CreateService(scmHandle, // SCM database - serviceName.c_str(), // name of service - serviceDesc.c_str(), // name to display - SERVICE_ALL_ACCESS, // desired access - SERVICE_WIN32_OWN_PROCESS, // service type - startType, // start type - SERVICE_ERROR_NORMAL, // error cntrl type - imagePath.c_str(), // path to service's binary w/ optional arguments - NULL, // no load ordering group - NULL, // no tag identifier - depends2.empty() ? NULL : depends2.c_str(), - account.empty() ? NULL : account.c_str(), // account name, or NULL for LocalSystem - password.empty() ? NULL : password.c_str()); // password, or NULL for none - QPID_WINDOWS_CHECK_NULL(svcHandle); - ::CloseServiceHandle(svcHandle); - QPID_LOG(info, "Service installed successfully"); -} - -/** - * - */ -void SCM::uninstall(const string& serviceName) -{ - // Ensure there's a handle to the SCM database. - openSvcManager(); - AutoServiceHandle svc(::OpenService(scmHandle, - serviceName.c_str(), - DELETE)); - QPID_WINDOWS_CHECK_NULL((SC_HANDLE)svc); - QPID_WINDOWS_CHECK_NOT(::DeleteService(svc), 0); - QPID_LOG(info, "Service deleted successfully."); -} - -/** - * Attempt to start the service. - */ -void SCM::start(const string& serviceName) -{ - // Ensure we have a handle to the SCM database. - openSvcManager(); - - // Get a handle to the service. - AutoServiceHandle svc(::OpenService(scmHandle, - serviceName.c_str(), - SERVICE_ALL_ACCESS)); - QPID_WINDOWS_CHECK_NULL(svc); - - // Check the status in case the service is not stopped. - DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING); - if (state == SERVICE_STOP_PENDING) - throw qpid::Exception("Timed out waiting for running service to stop."); - - // Attempt to start the service. - QPID_WINDOWS_CHECK_NOT(::StartService(svc, 0, NULL), 0); - - QPID_LOG(info, "Service start pending..."); - - // Check the status until the service is no longer start pending. - state = waitForStateChangeFrom(svc, SERVICE_START_PENDING); - // Determine whether the service is running. - if (state == SERVICE_RUNNING) { - QPID_LOG(info, "Service started successfully"); - } - else { - throw qpid::Exception(QPID_MSG("Service not yet running; state now " << state)); - } -} - -/** - * - */ -void SCM::stop(const string& serviceName) -{ - // Ensure a handle to the SCM database. - openSvcManager(); - - // Get a handle to the service. - AutoServiceHandle svc(::OpenService(scmHandle, - serviceName.c_str(), - SERVICE_STOP | SERVICE_QUERY_STATUS | - SERVICE_ENUMERATE_DEPENDENTS)); - QPID_WINDOWS_CHECK_NULL(svc); - - // Make sure the service is not already stopped; if it's stop-pending, - // wait for it to finalize. - DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING); - if (state == SERVICE_STOPPED) { - QPID_LOG(info, "Service is already stopped"); - return; - } - - // If the service is running, dependencies must be stopped first. - std::auto_ptr deps; - DWORD numDeps = getDependentServices(svc, deps); - for (DWORD i = 0; i < numDeps; i++) - stop(deps.get()[i].lpServiceName); - - // Dependents stopped; send a stop code to the service. - SERVICE_STATUS_PROCESS ssp; - if (!::ControlService(svc, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp)) - throw qpid::Exception(QPID_MSG("Stopping " << serviceName << ": " << - qpid::sys::strError(::GetLastError()))); - - // Wait for the service to stop. - state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING); - if (state == SERVICE_STOPPED) - QPID_LOG(info, QPID_MSG("Service " << serviceName << - " stopped successfully.")); -} - -/** - * - */ -void SCM::openSvcManager() -{ - if (NULL != scmHandle) - return; - - scmHandle = ::OpenSCManager(NULL, // local computer - NULL, // ServicesActive database - SC_MANAGER_ALL_ACCESS); // Rights - QPID_WINDOWS_CHECK_NULL(scmHandle); -} - -DWORD SCM::waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState) -{ - SERVICE_STATUS_PROCESS ssStatus; - DWORD bytesNeeded; - DWORD waitTime; - if (!::QueryServiceStatusEx(svc, // handle to service - SC_STATUS_PROCESS_INFO, // information level - (LPBYTE)&ssStatus, // address of structure - sizeof(ssStatus), // size of structure - &bytesNeeded)) // size needed if buffer is too small - throw QPID_WINDOWS_ERROR(::GetLastError()); - - // Save the tick count and initial checkpoint. - DWORD startTickCount = ::GetTickCount(); - DWORD oldCheckPoint = ssStatus.dwCheckPoint; - - // Wait for the service to change out of the noted state. - while (ssStatus.dwCurrentState == originalState) { - // Do not wait longer than the wait hint. A good interval is - // one-tenth of the wait hint but not less than 1 second - // and not more than 10 seconds. - waitTime = ssStatus.dwWaitHint / 10; - if (waitTime < 1000) - waitTime = 1000; - else if (waitTime > 10000) - waitTime = 10000; - - ::Sleep(waitTime); - - // Check the status until the service is no longer stop pending. - if (!::QueryServiceStatusEx(svc, - SC_STATUS_PROCESS_INFO, - (LPBYTE) &ssStatus, - sizeof(ssStatus), - &bytesNeeded)) - throw QPID_WINDOWS_ERROR(::GetLastError()); - - if (ssStatus.dwCheckPoint > oldCheckPoint) { - // Continue to wait and check. - startTickCount = ::GetTickCount(); - oldCheckPoint = ssStatus.dwCheckPoint; - } else { - if ((::GetTickCount() - startTickCount) > ssStatus.dwWaitHint) - break; - } - } - return ssStatus.dwCurrentState; -} - -/** - * Get the services that depend on @arg svc. All dependent service info - * is returned in an array of ENUM_SERVICE_STATUS structures via @arg deps. - * - * @retval The number of dependent services. - */ -DWORD SCM::getDependentServices(SC_HANDLE svc, - std::auto_ptr& deps) -{ - DWORD bytesNeeded; - DWORD numEntries; - - // Pass a zero-length buffer to get the required buffer size. - if (::EnumDependentServices(svc, - SERVICE_ACTIVE, - 0, - 0, - &bytesNeeded, - &numEntries)) { - // If the Enum call succeeds, then there are no dependent - // services, so do nothing. - return 0; - } - - if (::GetLastError() != ERROR_MORE_DATA) - throw QPID_WINDOWS_ERROR((::GetLastError())); - - // Allocate a buffer for the dependencies. - deps.reset((LPENUM_SERVICE_STATUS)(new char[bytesNeeded])); - // Enumerate the dependencies. - if (!::EnumDependentServices(svc, - SERVICE_ACTIVE, - deps.get(), - bytesNeeded, - &bytesNeeded, - &numEntries)) - throw QPID_WINDOWS_ERROR((::GetLastError())); - return numEntries; -} - -} } // namespace qpid::windows diff --git a/qpid/cpp/src/windows/SCM.h b/qpid/cpp/src/windows/SCM.h deleted file mode 100644 index bdc73bc210..0000000000 --- a/qpid/cpp/src/windows/SCM.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef WINDOWS_SCM_H -#define WINDOWS_SCM_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 -#include -using std::string; - -#ifdef UNICODE -#undef UNICODE -#endif - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include - -namespace qpid { -namespace windows { - -/** - * @class SCM - * - * Access the Windows Service Control Manager. - */ -class SCM -{ -public: - SCM(); - ~SCM(); - - /** - * Install this executable as a service - * - * @param serviceName The name of the service - * @param serviceDesc Description of the service's purpose - * @param args The argument list to pass into the service - * @param startType The start type: SERVICE_DEMAND_START, - * SERVICE_AUTO_START, SERVICE_DISABLED - * @param account If not empty, the account name to install this - * service under - * @param password If not empty, the account password to install this - * service with - * @param depends If not empty, a comma delimited list of services - * that must start before this one - */ - void install(const string& serviceName, - const string& serviceDesc, - const string& args, - DWORD startType = SERVICE_DEMAND_START, - const string& account = "NT AUTHORITY\\LocalSystem", - const string& password = "", - const string& depends = ""); - - /** - * Uninstall this executable as a service - * - * @param serviceName the name of the service - */ - void uninstall(const string& serviceName); - - /** - * Start the specified service - * - * @param serviceName the name of the service - */ - void start(const string& serviceName); - - /** - * Stop the specified service - * - * @param serviceName the name of the service - */ - void stop(const string &serviceName); - -private: - SC_HANDLE scmHandle; - - void openSvcManager(); - DWORD waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState); - DWORD getDependentServices(SC_HANDLE svc, - std::auto_ptr& deps); - -}; - -}} // namespace qpid::windows - -#endif /* #ifndef WINDOWS_SCM_H */ diff --git a/qpid/cpp/src/windows/resources/qpid-icon.ico b/qpid/cpp/src/windows/resources/qpid-icon.ico deleted file mode 100644 index 112f5d8f1f..0000000000 Binary files a/qpid/cpp/src/windows/resources/qpid-icon.ico and /dev/null differ diff --git a/qpid/cpp/src/windows/resources/template-resource.rc b/qpid/cpp/src/windows/resources/template-resource.rc deleted file mode 100644 index 8ca0a90890..0000000000 --- a/qpid/cpp/src/windows/resources/template-resource.rc +++ /dev/null @@ -1,122 +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 "version-resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "windows.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "version-resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION ${winverFileVersionBinary} - PRODUCTVERSION ${winverProductVersionBinary} - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "${winverFileDescription}" - VALUE "FileVersion", "${winverFileVersionString}" - VALUE "LegalCopyright", "${winverLegalCopyright}" - VALUE "InternalName", "${winverInternalName}" - VALUE "OriginalFilename", "${winverOriginalFilename}" - VALUE "ProductName", "${winverProductName}" - VALUE "ProductVersion", "${winverProductVersionString}" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON1 ICON "qpid-icon.ico" - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/qpid/cpp/src/windows/resources/version-resource.h b/qpid/cpp/src/windows/resources/version-resource.h deleted file mode 100644 index bf942abbaf..0000000000 --- a/qpid/cpp/src/windows/resources/version-resource.h +++ /dev/null @@ -1,35 +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. -// - -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Preserved for common usage by any Qpid exe/dll. - -#define IDI_ICON1 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 104 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif -- cgit v1.2.1